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