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_view> 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/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 29 class PrefFilter; 30 31 namespace base { 32 class FilePath; 33 class JsonPrefStoreCallbackTest; 34 class JsonPrefStoreLossyWriteTest; 35 class SequencedTaskRunner; 36 class WriteCallbacksObserver; 37 } // namespace base 38 39 // A writable PrefStore implementation that is used for user preferences. 40 class COMPONENTS_PREFS_EXPORT JsonPrefStore final 41 : public PersistentPrefStore, 42 public base::ImportantFileWriter::DataSerializer, 43 public base::ImportantFileWriter::BackgroundDataSerializer { 44 public: 45 struct ReadResult; 46 47 // A pair of callbacks to call before and after the preference file is written 48 // to disk. 49 using OnWriteCallbackPair = 50 std::pair<base::OnceClosure, base::OnceCallback<void(bool success)>>; 51 52 // |pref_filename| is the path to the file to read prefs from. It is incorrect 53 // to create multiple JsonPrefStore with the same |pref_filename|. 54 // |file_task_runner| is used for asynchronous reads and writes. It must 55 // have the base::TaskShutdownBehavior::BLOCK_SHUTDOWN and base::MayBlock() 56 // traits. Unless external tasks need to run on the same sequence as 57 // JsonPrefStore tasks, keep the default value. 58 // The initial read is done synchronously, the TaskPriority is thus only used 59 // for flushes to disks and BEST_EFFORT is therefore appropriate. Priority of 60 // remaining BEST_EFFORT+BLOCK_SHUTDOWN tasks is bumped by the ThreadPool on 61 // shutdown. However, some shutdown use cases happen without 62 // ThreadPoolInstance::Shutdown() (e.g. ChromeRestartRequest::Start() and 63 // BrowserProcessImpl::EndSession()) and we must thus unfortunately make this 64 // USER_VISIBLE until we solve https://crbug.com/747495 to allow bumping 65 // priority of a sequence on demand. 66 JsonPrefStore(const base::FilePath& pref_filename, 67 std::unique_ptr<PrefFilter> pref_filter = nullptr, 68 scoped_refptr<base::SequencedTaskRunner> file_task_runner = 69 base::ThreadPool::CreateSequencedTaskRunner( 70 {base::MayBlock(), base::TaskPriority::USER_VISIBLE, 71 base::TaskShutdownBehavior::BLOCK_SHUTDOWN}), 72 bool read_only = false); 73 74 JsonPrefStore(const JsonPrefStore&) = delete; 75 JsonPrefStore& operator=(const JsonPrefStore&) = delete; 76 77 // PrefStore overrides: 78 bool GetValue(std::string_view key, 79 const base::Value** result) const override; 80 base::Value::Dict GetValues() const override; 81 void AddObserver(PrefStore::Observer* observer) override; 82 void RemoveObserver(PrefStore::Observer* observer) override; 83 bool HasObservers() const override; 84 bool IsInitializationComplete() const override; 85 86 // PersistentPrefStore overrides: 87 bool GetMutableValue(std::string_view key, base::Value** result) override; 88 void SetValue(std::string_view key, 89 base::Value value, 90 uint32_t flags) override; 91 void SetValueSilently(std::string_view key, 92 base::Value value, 93 uint32_t flags) override; 94 void RemoveValue(std::string_view key, uint32_t flags) override; 95 bool ReadOnly() const override; 96 PrefReadError GetReadError() const override; 97 bool HasReadErrorDelegate() 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(std::string_view 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(std::string_view 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(std::string_view prefix) override; 117 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 AsWeakPtr()127 base::WeakPtr<JsonPrefStore> AsWeakPtr() { 128 return weak_ptr_factory_.GetWeakPtr(); 129 } 130 131 #if defined(UNIT_TEST) get_writer()132 base::ImportantFileWriter& get_writer() { return writer_; } 133 #endif 134 135 private: 136 friend class base::JsonPrefStoreCallbackTest; 137 friend class base::JsonPrefStoreLossyWriteTest; 138 friend class base::WriteCallbacksObserver; 139 140 ~JsonPrefStore() override; 141 142 // Perform pre-serialization bookkeeping common to either serialization flow 143 // (main thread or background thread). 144 void PerformPreserializationTasks(); 145 146 // If |write_success| is true, runs |on_next_successful_write_|. 147 // Otherwise, re-registers |on_next_successful_write_|. 148 void RunOrScheduleNextSuccessfulWriteCallback(bool write_success); 149 150 // Handles the result of a write with result |write_success|. Runs 151 // |on_next_write_callback| on the current thread and posts 152 // |on_next_write_reply| on |reply_task_runner|. 153 static void PostWriteCallback( 154 base::OnceCallback<void(bool success)> on_next_write_callback, 155 base::OnceCallback<void(bool success)> on_next_write_reply, 156 scoped_refptr<base::SequencedTaskRunner> reply_task_runner, 157 bool write_success); 158 159 // Registers the |callbacks| pair to be called once synchronously before and 160 // after, respectively, the next write event of |writer_|. 161 // Both callbacks must be thread-safe. 162 void RegisterOnNextWriteSynchronousCallbacks(OnWriteCallbackPair callbacks); 163 164 // This method is called after the JSON file has been read. It then hands 165 // |value| (or an empty dictionary in some read error cases) to the 166 // |pref_filter| if one is set. It also gives a callback pointing at 167 // FinalizeFileRead() to that |pref_filter_| which is then responsible for 168 // invoking it when done. If there is no |pref_filter_|, FinalizeFileRead() 169 // is invoked directly. 170 void OnFileRead(std::unique_ptr<ReadResult> read_result); 171 172 // ImportantFileWriter::DataSerializer overrides: 173 std::optional<std::string> SerializeData() override; 174 // ImportantFileWriter::BackgroundDataSerializer implementation. 175 base::ImportantFileWriter::BackgroundDataProducerCallback 176 GetSerializedDataProducerForBackgroundSequence() override; 177 178 // This method is called after the JSON file has been read and the result has 179 // potentially been intercepted and modified by |pref_filter_|. 180 // |initialization_successful| is pre-determined by OnFileRead() and should 181 // be used when reporting OnInitializationCompleted(). 182 // |schedule_write| indicates whether a write should be immediately scheduled 183 // (typically because the |pref_filter_| has already altered the |prefs|) -- 184 // this will be ignored if this store is read-only. 185 void FinalizeFileRead(bool initialization_successful, 186 base::Value::Dict prefs, 187 bool schedule_write); 188 189 // Schedule a write with the file writer as long as |flags| doesn't contain 190 // WriteablePrefStore::LOSSY_PREF_WRITE_FLAG. 191 void ScheduleWrite(uint32_t flags); 192 193 const base::FilePath path_; 194 const scoped_refptr<base::SequencedTaskRunner> file_task_runner_; 195 196 base::Value::Dict prefs_; 197 198 bool read_only_; 199 200 // Helper for safely writing pref data. 201 base::ImportantFileWriter writer_; 202 203 std::unique_ptr<PrefFilter> pref_filter_; 204 base::ObserverList<PrefStore::Observer, true> observers_; 205 206 // Optional so we can differentiate `nullopt` from `nullptr`. 207 std::optional<std::unique_ptr<ReadErrorDelegate>> error_delegate_; 208 209 bool initialized_; 210 bool filtering_in_progress_; 211 bool pending_lossy_write_; 212 PrefReadError read_error_; 213 214 std::set<std::string> keys_need_empty_value_; 215 216 bool has_pending_write_reply_ = true; 217 base::OnceClosure on_next_successful_write_reply_; 218 219 SEQUENCE_CHECKER(sequence_checker_); 220 221 base::WeakPtrFactory<JsonPrefStore> weak_ptr_factory_{this}; 222 }; 223 224 #endif // COMPONENTS_PREFS_JSON_PREF_STORE_H_ 225