Add synchronous callback support to important_file_writer.cc

This is required to support post-write callbacks which need to execute
even if Chrome is shutting down.

Carved out of https://codereview.chromium.org/2204943002/, new call will be used there.

BUG=624858

Review-Url: https://codereview.chromium.org/2299523003
Cr-Commit-Position: refs/heads/master@{#420102}
diff --git a/components/prefs/json_pref_store.h b/components/prefs/json_pref_store.h
index 047fe74..218b205 100644
--- a/components/prefs/json_pref_store.h
+++ b/components/prefs/json_pref_store.h
@@ -30,6 +30,7 @@
 class DictionaryValue;
 class FilePath;
 class HistogramBase;
+class JsonPrefStoreCallbackTest;
 class JsonPrefStoreLossyWriteTest;
 class SequencedTaskRunner;
 class SequencedWorkerPool;
@@ -106,10 +107,18 @@
   // cleanup that shouldn't otherwise alert observers.
   void RemoveValueSilently(const std::string& key, uint32_t flags);
 
-  // Registers |on_next_successful_write| to be called once, on the next
+  // Registers |on_next_successful_write_reply| to be called once, on the next
   // successful write event of |writer_|.
-  void RegisterOnNextSuccessfulWriteCallback(
-      const base::Closure& on_next_successful_write);
+  // |on_next_successful_write_reply| will be called on the thread from which
+  // this method is called and does not need to be thread safe.
+  void RegisterOnNextSuccessfulWriteReply(
+      const base::Closure& on_next_successful_write_reply);
+
+  // Registers |on_next_write_callback| to be called once synchronously, on the
+  // next write event of |writer_|.
+  // |on_next_write_callback| must be thread-safe.
+  void RegisterOnNextWriteSynchronousCallback(
+      const base::Callback<void(bool success)>& on_next_write_callback);
 
   void ClearMutableValues() override;
 
@@ -170,10 +179,24 @@
                            WriteCountHistogramTestMultiplePeriods);
   FRIEND_TEST_ALL_PREFIXES(base::JsonPrefStoreTest,
                            WriteCountHistogramTestPeriodWithGaps);
+  friend class base::JsonPrefStoreCallbackTest;
   friend class base::JsonPrefStoreLossyWriteTest;
 
   ~JsonPrefStore() override;
 
+  // If |write_success| is true, runs |on_next_successful_write_|.
+  // Otherwise, re-registers |on_next_successful_write_|.
+  void RunOrScheduleNextSuccessfulWriteCallback(bool write_success);
+
+  // Handles the result of a write with result |write_success|. Runs
+  // |on_next_write| callback on the current thread and posts
+  // |RunOrScheduleNextSuccessfulWriteCallback| on |reply_task_runner|.
+  static void PostWriteCallback(
+      const base::Callback<void(bool success)>& on_next_write_reply,
+      const base::Callback<void(bool success)>& on_next_write_callback,
+      scoped_refptr<base::SequencedTaskRunner> reply_task_runner,
+      bool write_success);
+
   // This method is called after the JSON file has been read.  It then hands
   // |value| (or an empty dictionary in some read error cases) to the
   // |pref_filter| if one is set. It also gives a callback pointing at
@@ -223,6 +246,10 @@
 
   std::set<std::string> keys_need_empty_value_;
 
+  bool has_pending_successful_write_reply_;
+  bool has_pending_write_callback_;
+  base::Closure on_next_successful_write_reply_;
+
   WriteCountHistogram write_count_histogram_;
 
   DISALLOW_COPY_AND_ASSIGN(JsonPrefStore);