summaryrefslogtreecommitdiff
path: root/base/files/important_file_writer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/files/important_file_writer.cc')
-rw-r--r--base/files/important_file_writer.cc61
1 files changed, 37 insertions, 24 deletions
diff --git a/base/files/important_file_writer.cc b/base/files/important_file_writer.cc
index b46846277b..28550ad52f 100644
--- a/base/files/important_file_writer.cc
+++ b/base/files/important_file_writer.cc
@@ -18,7 +18,7 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -57,18 +57,9 @@ void LogFailure(const FilePath& path, TempFileFailure failure_code,
// Helper function to call WriteFileAtomically() with a
// std::unique_ptr<std::string>.
-void WriteScopedStringToFileAtomically(
- const FilePath& path,
- std::unique_ptr<std::string> data,
- Closure before_write_callback,
- Callback<void(bool success)> after_write_callback) {
- if (!before_write_callback.is_null())
- before_write_callback.Run();
-
- bool result = ImportantFileWriter::WriteFileAtomically(path, *data);
-
- if (!after_write_callback.is_null())
- after_write_callback.Run(result);
+bool WriteScopedStringToFileAtomically(const FilePath& path,
+ std::unique_ptr<std::string> data) {
+ return ImportantFileWriter::WriteFileAtomically(path, *data);
}
} // namespace
@@ -103,7 +94,6 @@ bool ImportantFileWriter::WriteFileAtomically(const FilePath& path,
File tmp_file(tmp_file_path, File::FLAG_OPEN | File::FLAG_WRITE);
if (!tmp_file.IsValid()) {
LogFailure(path, FAILED_OPENING, "could not open temporary file");
- DeleteFile(tmp_file_path, false);
return false;
}
@@ -178,11 +168,8 @@ void ImportantFileWriter::WriteNow(std::unique_ptr<std::string> data) {
if (HasPendingWrite())
timer_.Stop();
- Closure task = Bind(&WriteScopedStringToFileAtomically, path_, Passed(&data),
- Passed(&before_next_write_callback_),
- Passed(&after_next_write_callback_));
-
- if (!task_runner_->PostTask(FROM_HERE, MakeCriticalClosure(task))) {
+ auto task = Bind(&WriteScopedStringToFileAtomically, path_, Passed(&data));
+ if (!PostWriteTask(task)) {
// Posting the task to background message loop is not expected
// to fail, but if it does, avoid losing data and just hit the disk
// on the current thread.
@@ -216,11 +203,37 @@ void ImportantFileWriter::DoScheduledWrite() {
serializer_ = nullptr;
}
-void ImportantFileWriter::RegisterOnNextWriteCallbacks(
- const Closure& before_next_write_callback,
- const Callback<void(bool success)>& after_next_write_callback) {
- before_next_write_callback_ = before_next_write_callback;
- after_next_write_callback_ = after_next_write_callback;
+void ImportantFileWriter::RegisterOnNextSuccessfulWriteCallback(
+ const Closure& on_next_successful_write) {
+ DCHECK(on_next_successful_write_.is_null());
+ on_next_successful_write_ = on_next_successful_write;
+}
+
+bool ImportantFileWriter::PostWriteTask(const Callback<bool()>& task) {
+ // TODO(gab): This code could always use PostTaskAndReplyWithResult and let
+ // ForwardSuccessfulWrite() no-op if |on_next_successful_write_| is null, but
+ // PostTaskAndReply causes memory leaks in tests (crbug.com/371974) and
+ // suppressing all of those is unrealistic hence we avoid most of them by
+ // using PostTask() in the typical scenario below.
+ if (!on_next_successful_write_.is_null()) {
+ return PostTaskAndReplyWithResult(
+ task_runner_.get(),
+ FROM_HERE,
+ MakeCriticalClosure(task),
+ Bind(&ImportantFileWriter::ForwardSuccessfulWrite,
+ weak_factory_.GetWeakPtr()));
+ }
+ return task_runner_->PostTask(
+ FROM_HERE,
+ MakeCriticalClosure(Bind(IgnoreResult(task))));
+}
+
+void ImportantFileWriter::ForwardSuccessfulWrite(bool result) {
+ DCHECK(CalledOnValidThread());
+ if (result && !on_next_successful_write_.is_null()) {
+ on_next_successful_write_.Run();
+ on_next_successful_write_.Reset();
+ }
}
} // namespace base