blob: 1a696052373ab356385d1ac434821c23bc5c7264 [file] [log] [blame]
brettw58cd1f12016-01-30 05:56:051// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
brettw066508682016-02-03 08:22:025#ifndef COMPONENTS_PREFS_JSON_PREF_STORE_H_
6#define COMPONENTS_PREFS_JSON_PREF_STORE_H_
brettw58cd1f12016-01-30 05:56:057
8#include <stdint.h>
9
dcheng5f043bc2016-04-22 19:09:0610#include <memory>
brettw58cd1f12016-01-30 05:56:0511#include <set>
12#include <string>
13
14#include "base/callback_forward.h"
15#include "base/compiler_specific.h"
16#include "base/files/file_path.h"
17#include "base/files/important_file_writer.h"
18#include "base/gtest_prod_util.h"
19#include "base/macros.h"
brettw58cd1f12016-01-30 05:56:0520#include "base/memory/weak_ptr.h"
21#include "base/observer_list.h"
gab6e1fb5352017-05-31 18:27:1222#include "base/sequence_checker.h"
Gabriel Charette44db1422018-08-06 11:19:3323#include "base/task/post_task.h"
brettwf00b9b42016-02-01 22:11:3824#include "components/prefs/persistent_pref_store.h"
fdoray5f4a7a0b2017-05-15 16:15:5825#include "components/prefs/pref_filter.h"
Brett Wilson5c6cf262017-09-09 02:05:5426#include "components/prefs/prefs_export.h"
brettw58cd1f12016-01-30 05:56:0527
28class PrefFilter;
29
30namespace base {
31class Clock;
32class DictionaryValue;
33class FilePath;
34class HistogramBase;
probergefc46ac12016-09-21 18:03:0035class JsonPrefStoreCallbackTest;
brettw58cd1f12016-01-30 05:56:0536class JsonPrefStoreLossyWriteTest;
37class SequencedTaskRunner;
probergec503d692016-09-28 19:51:0538class WriteCallbacksObserver;
brettw58cd1f12016-01-30 05:56:0539class Value;
40FORWARD_DECLARE_TEST(JsonPrefStoreTest, WriteCountHistogramTestBasic);
41FORWARD_DECLARE_TEST(JsonPrefStoreTest, WriteCountHistogramTestSinglePeriod);
42FORWARD_DECLARE_TEST(JsonPrefStoreTest, WriteCountHistogramTestMultiplePeriods);
43FORWARD_DECLARE_TEST(JsonPrefStoreTest, WriteCountHistogramTestPeriodWithGaps);
44}
45
46// A writable PrefStore implementation that is used for user preferences.
brettw066508682016-02-03 08:22:0247class COMPONENTS_PREFS_EXPORT JsonPrefStore
brettw58cd1f12016-01-30 05:56:0548 : public PersistentPrefStore,
49 public base::ImportantFileWriter::DataSerializer,
gab6e1fb5352017-05-31 18:27:1250 public base::SupportsWeakPtr<JsonPrefStore> {
brettw58cd1f12016-01-30 05:56:0551 public:
52 struct ReadResult;
53
probergec503d692016-09-28 19:51:0554 // A pair of callbacks to call before and after the preference file is written
55 // to disk.
56 using OnWriteCallbackPair =
57 std::pair<base::Closure, base::Callback<void(bool success)>>;
58
fdoray5f4a7a0b2017-05-15 16:15:5859 // |pref_filename| is the path to the file to read prefs from. It is incorrect
60 // to create multiple JsonPrefStore with the same |pref_filename|.
Francois Doray405dd2d2017-06-09 15:23:3361 // |file_task_runner| is used for asynchronous reads and writes. It must
fdoray5f4a7a0b2017-05-15 16:15:5862 // have the base::TaskShutdownBehavior::BLOCK_SHUTDOWN and base::MayBlock()
63 // traits. Unless external tasks need to run on the same sequence as
64 // JsonPrefStore tasks, keep the default value.
Gabriel Charette1f53ca32018-08-07 21:31:1765 // The initial read is done synchronously, the TaskPriority is thus only used
66 // for flushes to disks and BACKGROUND is therefore appropriate. Priority of
67 // remaining BACKGROUND+BLOCK_SHUTDOWN tasks is bumped by the TaskScheduler on
68 // shutdown. However, some shutdown use cases happen without
69 // TaskScheduler::Shutdown() (e.g. ChromeRestartRequest::Start() and
70 // BrowserProcessImpl::EndSession()) and we must thus unfortunately make this
71 // USER_VISIBLE until we solve https://crbug.com/747495 to allow bumping
72 // priority of a sequence on demand.
fdoray5f4a7a0b2017-05-15 16:15:5873 JsonPrefStore(const base::FilePath& pref_filename,
Gabriel Charette1f53ca32018-08-07 21:31:1774 std::unique_ptr<PrefFilter> pref_filter = nullptr,
Francois Doray405dd2d2017-06-09 15:23:3375 scoped_refptr<base::SequencedTaskRunner> file_task_runner =
fdoray5f4a7a0b2017-05-15 16:15:5876 base::CreateSequencedTaskRunnerWithTraits(
Gabriel Charette1f53ca32018-08-07 21:31:1777 {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
78 base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));
brettw58cd1f12016-01-30 05:56:0579
80 // PrefStore overrides:
81 bool GetValue(const std::string& key,
82 const base::Value** result) const override;
tibelle23659b42017-02-23 01:44:1383 std::unique_ptr<base::DictionaryValue> GetValues() const override;
brettw58cd1f12016-01-30 05:56:0584 void AddObserver(PrefStore::Observer* observer) override;
85 void RemoveObserver(PrefStore::Observer* observer) override;
86 bool HasObservers() const override;
87 bool IsInitializationComplete() const override;
88
89 // PersistentPrefStore overrides:
90 bool GetMutableValue(const std::string& key, base::Value** result) override;
91 void SetValue(const std::string& key,
dcheng5f043bc2016-04-22 19:09:0692 std::unique_ptr<base::Value> value,
brettw58cd1f12016-01-30 05:56:0593 uint32_t flags) override;
94 void SetValueSilently(const std::string& key,
dcheng5f043bc2016-04-22 19:09:0695 std::unique_ptr<base::Value> value,
brettw58cd1f12016-01-30 05:56:0596 uint32_t flags) override;
97 void RemoveValue(const std::string& key, uint32_t flags) override;
98 bool ReadOnly() const override;
99 PrefReadError GetReadError() const override;
100 // Note this method may be asynchronous if this instance has a |pref_filter_|
101 // in which case it will return PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE.
102 // See details in pref_filter.h.
103 PrefReadError ReadPrefs() override;
104 void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override;
Gabriel Charette788eaf62018-08-07 20:11:46105 void CommitPendingWrite(
106 base::OnceClosure reply_callback = base::OnceClosure(),
107 base::OnceClosure synchronous_done_callback =
108 base::OnceClosure()) override;
brettw58cd1f12016-01-30 05:56:05109 void SchedulePendingLossyWrites() override;
110 void ReportValueChanged(const std::string& key, uint32_t flags) override;
111
112 // Just like RemoveValue(), but doesn't notify observers. Used when doing some
113 // cleanup that shouldn't otherwise alert observers.
114 void RemoveValueSilently(const std::string& key, uint32_t flags);
115
probergefc46ac12016-09-21 18:03:00116 // Registers |on_next_successful_write_reply| to be called once, on the next
brettw58cd1f12016-01-30 05:56:05117 // successful write event of |writer_|.
probergefc46ac12016-09-21 18:03:00118 // |on_next_successful_write_reply| will be called on the thread from which
119 // this method is called and does not need to be thread safe.
120 void RegisterOnNextSuccessfulWriteReply(
121 const base::Closure& on_next_successful_write_reply);
122
dvadym53fc0d42016-02-05 13:34:57123 void ClearMutableValues() override;
124
proberge45e347282017-08-16 21:24:05125 void OnStoreDeletionFromDisk() override;
126
brettw58cd1f12016-01-30 05:56:05127 private:
128 // Represents a histogram for recording the number of writes to the pref file
129 // that occur every kHistogramWriteReportIntervalInMins minutes.
brettw066508682016-02-03 08:22:02130 class COMPONENTS_PREFS_EXPORT WriteCountHistogram {
brettw58cd1f12016-01-30 05:56:05131 public:
132 static const int32_t kHistogramWriteReportIntervalMins;
133
134 WriteCountHistogram(const base::TimeDelta& commit_interval,
135 const base::FilePath& path);
136 // Constructor for testing. |clock| is a test Clock that is used to retrieve
137 // the time.
138 WriteCountHistogram(const base::TimeDelta& commit_interval,
139 const base::FilePath& path,
dcheng5f043bc2016-04-22 19:09:06140 std::unique_ptr<base::Clock> clock);
brettw58cd1f12016-01-30 05:56:05141 ~WriteCountHistogram();
142
143 // Record that a write has occured.
144 void RecordWriteOccured();
145
146 // Reports writes (that have not yet been reported) in all of the recorded
147 // intervals that have elapsed up until current time.
148 void ReportOutstandingWrites();
149
150 base::HistogramBase* GetHistogram();
151
152 private:
153 // The minimum interval at which writes can occur.
154 const base::TimeDelta commit_interval_;
155
156 // The path to the file.
157 const base::FilePath path_;
158
159 // Clock which is used to retrieve the current time.
dcheng5f043bc2016-04-22 19:09:06160 std::unique_ptr<base::Clock> clock_;
brettw58cd1f12016-01-30 05:56:05161
162 // The interval at which to report write counts.
163 const base::TimeDelta report_interval_;
164
165 // The time at which the last histogram value was reported for the number
166 // of write counts.
167 base::Time last_report_time_;
168
169 // The number of writes that have occured since the last write count was
170 // reported.
171 uint32_t writes_since_last_report_;
172
173 DISALLOW_COPY_AND_ASSIGN(WriteCountHistogram);
174 };
175
176 FRIEND_TEST_ALL_PREFIXES(base::JsonPrefStoreTest,
177 WriteCountHistogramTestBasic);
178 FRIEND_TEST_ALL_PREFIXES(base::JsonPrefStoreTest,
179 WriteCountHistogramTestSinglePeriod);
180 FRIEND_TEST_ALL_PREFIXES(base::JsonPrefStoreTest,
181 WriteCountHistogramTestMultiplePeriods);
182 FRIEND_TEST_ALL_PREFIXES(base::JsonPrefStoreTest,
183 WriteCountHistogramTestPeriodWithGaps);
probergefc46ac12016-09-21 18:03:00184 friend class base::JsonPrefStoreCallbackTest;
brettw58cd1f12016-01-30 05:56:05185 friend class base::JsonPrefStoreLossyWriteTest;
probergec503d692016-09-28 19:51:05186 friend class base::WriteCallbacksObserver;
brettw58cd1f12016-01-30 05:56:05187
188 ~JsonPrefStore() override;
189
probergefc46ac12016-09-21 18:03:00190 // If |write_success| is true, runs |on_next_successful_write_|.
191 // Otherwise, re-registers |on_next_successful_write_|.
192 void RunOrScheduleNextSuccessfulWriteCallback(bool write_success);
193
194 // Handles the result of a write with result |write_success|. Runs
proberge269fd092016-10-04 22:13:41195 // |on_next_write_callback| on the current thread and posts
196 // |on_next_write_reply| on |reply_task_runner|.
probergefc46ac12016-09-21 18:03:00197 static void PostWriteCallback(
probergefc46ac12016-09-21 18:03:00198 const base::Callback<void(bool success)>& on_next_write_callback,
proberge269fd092016-10-04 22:13:41199 const base::Callback<void(bool success)>& on_next_write_reply,
probergefc46ac12016-09-21 18:03:00200 scoped_refptr<base::SequencedTaskRunner> reply_task_runner,
201 bool write_success);
202
probergec503d692016-09-28 19:51:05203 // Registers the |callbacks| pair to be called once synchronously before and
204 // after, respectively, the next write event of |writer_|.
205 // Both callbacks must be thread-safe.
206 void RegisterOnNextWriteSynchronousCallbacks(OnWriteCallbackPair callbacks);
207
brettw58cd1f12016-01-30 05:56:05208 // This method is called after the JSON file has been read. It then hands
209 // |value| (or an empty dictionary in some read error cases) to the
210 // |pref_filter| if one is set. It also gives a callback pointing at
211 // FinalizeFileRead() to that |pref_filter_| which is then responsible for
212 // invoking it when done. If there is no |pref_filter_|, FinalizeFileRead()
213 // is invoked directly.
dcheng5f043bc2016-04-22 19:09:06214 void OnFileRead(std::unique_ptr<ReadResult> read_result);
brettw58cd1f12016-01-30 05:56:05215
216 // ImportantFileWriter::DataSerializer overrides:
217 bool SerializeData(std::string* output) override;
218
219 // This method is called after the JSON file has been read and the result has
220 // potentially been intercepted and modified by |pref_filter_|.
221 // |initialization_successful| is pre-determined by OnFileRead() and should
222 // be used when reporting OnInitializationCompleted().
223 // |schedule_write| indicates whether a write should be immediately scheduled
224 // (typically because the |pref_filter_| has already altered the |prefs|) --
225 // this will be ignored if this store is read-only.
226 void FinalizeFileRead(bool initialization_successful,
dcheng5f043bc2016-04-22 19:09:06227 std::unique_ptr<base::DictionaryValue> prefs,
brettw58cd1f12016-01-30 05:56:05228 bool schedule_write);
229
230 // Schedule a write with the file writer as long as |flags| doesn't contain
231 // WriteablePrefStore::LOSSY_PREF_WRITE_FLAG.
232 void ScheduleWrite(uint32_t flags);
233
234 const base::FilePath path_;
Francois Doray405dd2d2017-06-09 15:23:33235 const scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
brettw58cd1f12016-01-30 05:56:05236
dcheng5f043bc2016-04-22 19:09:06237 std::unique_ptr<base::DictionaryValue> prefs_;
brettw58cd1f12016-01-30 05:56:05238
239 bool read_only_;
240
241 // Helper for safely writing pref data.
242 base::ImportantFileWriter writer_;
243
dcheng5f043bc2016-04-22 19:09:06244 std::unique_ptr<PrefFilter> pref_filter_;
Trent Apteda250ec3ab2018-08-19 08:52:19245 base::ObserverList<PrefStore::Observer, true>::Unchecked observers_;
brettw58cd1f12016-01-30 05:56:05246
dcheng5f043bc2016-04-22 19:09:06247 std::unique_ptr<ReadErrorDelegate> error_delegate_;
brettw58cd1f12016-01-30 05:56:05248
249 bool initialized_;
250 bool filtering_in_progress_;
251 bool pending_lossy_write_;
252 PrefReadError read_error_;
253
254 std::set<std::string> keys_need_empty_value_;
255
proberge269fd092016-10-04 22:13:41256 bool has_pending_write_reply_ = true;
probergefc46ac12016-09-21 18:03:00257 base::Closure on_next_successful_write_reply_;
258
brettw58cd1f12016-01-30 05:56:05259 WriteCountHistogram write_count_histogram_;
260
gab6e1fb5352017-05-31 18:27:12261 SEQUENCE_CHECKER(sequence_checker_);
262
brettw58cd1f12016-01-30 05:56:05263 DISALLOW_COPY_AND_ASSIGN(JsonPrefStore);
264};
265
brettw066508682016-02-03 08:22:02266#endif // COMPONENTS_PREFS_JSON_PREF_STORE_H_