1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_PREFS_JSON_PREF_STORE_H_ 6 #define COMPONENTS_PREFS_JSON_PREF_STORE_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <set> 12 #include <string> 13 14 #include "base/compiler_specific.h" 15 #include "base/files/file_path.h" 16 #include "base/files/important_file_writer.h" 17 #include "base/functional/callback_forward.h" 18 #include "base/gtest_prod_util.h" 19 #include "base/memory/weak_ptr.h" 20 #include "base/observer_list.h" 21 #include "base/sequence_checker.h" 22 #include "base/strings/string_piece.h" 23 #include "base/task/thread_pool.h" 24 #include "base/values.h" 25 #include "components/prefs/persistent_pref_store.h" 26 #include "components/prefs/pref_filter.h" 27 #include "components/prefs/prefs_export.h" 28 #include "third_party/abseil-cpp/absl/types/optional.h" 29 30 class PrefFilter; 31 32 namespace base { 33 class FilePath; 34 class JsonPrefStoreCallbackTest; 35 class JsonPrefStoreLossyWriteTest; 36 class SequencedTaskRunner; 37 class WriteCallbacksObserver; 38 } // namespace base 39 40 // A writable PrefStore implementation that is used for user preferences. 41 class COMPONENTS_PREFS_EXPORT JsonPrefStore 42 : public PersistentPrefStore, 43 public base::ImportantFileWriter::DataSerializer, 44 public base::ImportantFileWriter::BackgroundDataSerializer, 45 public base::SupportsWeakPtr<JsonPrefStore> { 46 public: 47 struct ReadResult; 48 49 // A pair of callbacks to call before and after the preference file is written 50 // to disk. 51 using OnWriteCallbackPair = 52 std::pair<base::OnceClosure, base::OnceCallback<void(bool success)>>; 53 54 // |pref_filename| is the path to the file to read prefs from. It is incorrect 55 // to create multiple JsonPrefStore with the same |pref_filename|. 56 // |file_task_runner| is used for asynchronous reads and writes. It must 57 // have the base::TaskShutdownBehavior::BLOCK_SHUTDOWN and base::MayBlock() 58 // traits. Unless external tasks need to run on the same sequence as 59 // JsonPrefStore tasks, keep the default value. 60 // The initial read is done synchronously, the TaskPriority is thus only used 61 // for flushes to disks and BEST_EFFORT is therefore appropriate. Priority of 62 // remaining BEST_EFFORT+BLOCK_SHUTDOWN tasks is bumped by the ThreadPool on 63 // shutdown. However, some shutdown use cases happen without 64 // ThreadPoolInstance::Shutdown() (e.g. ChromeRestartRequest::Start() and 65 // BrowserProcessImpl::EndSession()) and we must thus unfortunately make this 66 // USER_VISIBLE until we solve https://crbug.com/747495 to allow bumping 67 // priority of a sequence on demand. 68 JsonPrefStore(const base::FilePath& pref_filename, 69 std::unique_ptr<PrefFilter> pref_filter = nullptr, 70 scoped_refptr<base::SequencedTaskRunner> file_task_runner = 71 base::ThreadPool::CreateSequencedTaskRunner( 72 {base::MayBlock(), base::TaskPriority::USER_VISIBLE, 73 base::TaskShutdownBehavior::BLOCK_SHUTDOWN}), 74 bool read_only = false); 75 76 JsonPrefStore(const JsonPrefStore&) = delete; 77 JsonPrefStore& operator=(const JsonPrefStore&) = delete; 78 79 // PrefStore overrides: 80 bool GetValue(base::StringPiece key, 81 const base::Value** result) const override; 82 base::Value::Dict GetValues() const override; 83 void AddObserver(PrefStore::Observer* observer) override; 84 void RemoveObserver(PrefStore::Observer* observer) override; 85 bool HasObservers() const override; 86 bool IsInitializationComplete() const override; 87 88 // PersistentPrefStore overrides: 89 bool GetMutableValue(const std::string& key, base::Value** result) override; 90 void SetValue(const std::string& key, 91 base::Value value, 92 uint32_t flags) override; 93 void SetValueSilently(const std::string& key, 94 base::Value value, 95 uint32_t flags) override; 96 void RemoveValue(const std::string& key, uint32_t flags) override; 97 bool ReadOnly() const override; 98 PrefReadError GetReadError() const override; 99 // Note this method may be asynchronous if this instance has a |pref_filter_| 100 // in which case it will return PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE. 101 // See details in pref_filter.h. 102 PrefReadError ReadPrefs() override; 103 void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override; 104 void CommitPendingWrite( 105 base::OnceClosure reply_callback = base::OnceClosure(), 106 base::OnceClosure synchronous_done_callback = 107 base::OnceClosure()) override; 108 void SchedulePendingLossyWrites() override; 109 void ReportValueChanged(const std::string& key, uint32_t flags) override; 110 111 // Just like RemoveValue(), but doesn't notify observers. Used when doing some 112 // cleanup that shouldn't otherwise alert observers. 113 void RemoveValueSilently(const std::string& key, uint32_t flags); 114 115 // Just like RemoveValue(), but removes all the prefs that start with 116 // |prefix|. Used for pref-initialization cleanup. 117 void RemoveValuesByPrefixSilently(const std::string& prefix) override; 118 // Registers |on_next_successful_write_reply| to be called once, on the next 119 // successful write event of |writer_|. 120 // |on_next_successful_write_reply| will be called on the thread from which 121 // this method is called and does not need to be thread safe. 122 void RegisterOnNextSuccessfulWriteReply( 123 base::OnceClosure on_next_successful_write_reply); 124 125 void OnStoreDeletionFromDisk() override; 126 127 #if defined(UNIT_TEST) get_writer()128 base::ImportantFileWriter& get_writer() { return writer_; } 129 #endif 130 131 private: 132 friend class base::JsonPrefStoreCallbackTest; 133 friend class base::JsonPrefStoreLossyWriteTest; 134 friend class base::WriteCallbacksObserver; 135 136 ~JsonPrefStore() override; 137 138 // Perform pre-serialization bookkeeping common to either serialization flow 139 // (main thread or background thread). 140 void PerformPreserializationTasks(); 141 142 // If |write_success| is true, runs |on_next_successful_write_|. 143 // Otherwise, re-registers |on_next_successful_write_|. 144 void RunOrScheduleNextSuccessfulWriteCallback(bool write_success); 145 146 // Handles the result of a write with result |write_success|. Runs 147 // |on_next_write_callback| on the current thread and posts 148 // |on_next_write_reply| on |reply_task_runner|. 149 static void PostWriteCallback( 150 base::OnceCallback<void(bool success)> on_next_write_callback, 151 base::OnceCallback<void(bool success)> on_next_write_reply, 152 scoped_refptr<base::SequencedTaskRunner> reply_task_runner, 153 bool write_success); 154 155 // Registers the |callbacks| pair to be called once synchronously before and 156 // after, respectively, the next write event of |writer_|. 157 // Both callbacks must be thread-safe. 158 void RegisterOnNextWriteSynchronousCallbacks(OnWriteCallbackPair callbacks); 159 160 // This method is called after the JSON file has been read. It then hands 161 // |value| (or an empty dictionary in some read error cases) to the 162 // |pref_filter| if one is set. It also gives a callback pointing at 163 // FinalizeFileRead() to that |pref_filter_| which is then responsible for 164 // invoking it when done. If there is no |pref_filter_|, FinalizeFileRead() 165 // is invoked directly. 166 void OnFileRead(std::unique_ptr<ReadResult> read_result); 167 168 // ImportantFileWriter::DataSerializer overrides: 169 absl::optional<std::string> SerializeData() override; 170 // ImportantFileWriter::BackgroundDataSerializer implementation. 171 base::ImportantFileWriter::BackgroundDataProducerCallback 172 GetSerializedDataProducerForBackgroundSequence() override; 173 174 // This method is called after the JSON file has been read and the result has 175 // potentially been intercepted and modified by |pref_filter_|. 176 // |initialization_successful| is pre-determined by OnFileRead() and should 177 // be used when reporting OnInitializationCompleted(). 178 // |schedule_write| indicates whether a write should be immediately scheduled 179 // (typically because the |pref_filter_| has already altered the |prefs|) -- 180 // this will be ignored if this store is read-only. 181 void FinalizeFileRead(bool initialization_successful, 182 base::Value::Dict prefs, 183 bool schedule_write); 184 185 // Schedule a write with the file writer as long as |flags| doesn't contain 186 // WriteablePrefStore::LOSSY_PREF_WRITE_FLAG. 187 void ScheduleWrite(uint32_t flags); 188 189 const base::FilePath path_; 190 const scoped_refptr<base::SequencedTaskRunner> file_task_runner_; 191 192 base::Value::Dict prefs_; 193 194 bool read_only_; 195 196 // Helper for safely writing pref data. 197 base::ImportantFileWriter writer_; 198 199 std::unique_ptr<PrefFilter> pref_filter_; 200 base::ObserverList<PrefStore::Observer, true>::Unchecked observers_; 201 202 std::unique_ptr<ReadErrorDelegate> error_delegate_; 203 204 bool initialized_; 205 bool filtering_in_progress_; 206 bool pending_lossy_write_; 207 PrefReadError read_error_; 208 209 std::set<std::string> keys_need_empty_value_; 210 211 bool has_pending_write_reply_ = true; 212 base::OnceClosure on_next_successful_write_reply_; 213 214 SEQUENCE_CHECKER(sequence_checker_); 215 }; 216 217 #endif // COMPONENTS_PREFS_JSON_PREF_STORE_H_ 218