summaryrefslogtreecommitdiff
path: root/chromium/components/prefs/json_pref_store.h
blob: 089ce0b685362119b7d0010f5177be95a7335edd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_PREFS_JSON_PREF_STORE_H_
#define COMPONENTS_PREFS_JSON_PREF_STORE_H_

#include <stdint.h>

#include <memory>
#include <set>
#include <string>

#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/files/important_file_writer.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "base/task/post_task.h"
#include "components/prefs/persistent_pref_store.h"
#include "components/prefs/pref_filter.h"
#include "components/prefs/prefs_export.h"

class PrefFilter;

namespace base {
class DictionaryValue;
class FilePath;
class JsonPrefStoreCallbackTest;
class JsonPrefStoreLossyWriteTest;
class SequencedTaskRunner;
class WriteCallbacksObserver;
class Value;
}

// A writable PrefStore implementation that is used for user preferences.
class COMPONENTS_PREFS_EXPORT JsonPrefStore
    : public PersistentPrefStore,
      public base::ImportantFileWriter::DataSerializer,
      public base::SupportsWeakPtr<JsonPrefStore> {
 public:
  struct ReadResult;

  // A pair of callbacks to call before and after the preference file is written
  // to disk.
  using OnWriteCallbackPair =
      std::pair<base::Closure, base::Callback<void(bool success)>>;

  // |pref_filename| is the path to the file to read prefs from. It is incorrect
  // to create multiple JsonPrefStore with the same |pref_filename|.
  // |file_task_runner| is used for asynchronous reads and writes. It must
  // have the base::TaskShutdownBehavior::BLOCK_SHUTDOWN and base::MayBlock()
  // traits. Unless external tasks need to run on the same sequence as
  // JsonPrefStore tasks, keep the default value.
  // The initial read is done synchronously, the TaskPriority is thus only used
  // for flushes to disks and BEST_EFFORT is therefore appropriate. Priority of
  // remaining BEST_EFFORT+BLOCK_SHUTDOWN tasks is bumped by the ThreadPool on
  // shutdown. However, some shutdown use cases happen without
  // ThreadPoolInstance::Shutdown() (e.g. ChromeRestartRequest::Start() and
  // BrowserProcessImpl::EndSession()) and we must thus unfortunately make this
  // USER_VISIBLE until we solve https://crbug.com/747495 to allow bumping
  // priority of a sequence on demand.
  JsonPrefStore(const base::FilePath& pref_filename,
                std::unique_ptr<PrefFilter> pref_filter = nullptr,
                scoped_refptr<base::SequencedTaskRunner> file_task_runner =
                    base::CreateSequencedTaskRunner(
                        {base::ThreadPool(), base::MayBlock(),
                         base::TaskPriority::USER_VISIBLE,
                         base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));

  // PrefStore overrides:
  bool GetValue(const std::string& key,
                const base::Value** result) const override;
  std::unique_ptr<base::DictionaryValue> GetValues() const override;
  void AddObserver(PrefStore::Observer* observer) override;
  void RemoveObserver(PrefStore::Observer* observer) override;
  bool HasObservers() const override;
  bool IsInitializationComplete() const override;

  // PersistentPrefStore overrides:
  bool GetMutableValue(const std::string& key, base::Value** result) override;
  void SetValue(const std::string& key,
                std::unique_ptr<base::Value> value,
                uint32_t flags) override;
  void SetValueSilently(const std::string& key,
                        std::unique_ptr<base::Value> value,
                        uint32_t flags) override;
  void RemoveValue(const std::string& key, uint32_t flags) override;
  bool ReadOnly() const override;
  PrefReadError GetReadError() const override;
  // Note this method may be asynchronous if this instance has a |pref_filter_|
  // in which case it will return PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE.
  // See details in pref_filter.h.
  PrefReadError ReadPrefs() override;
  void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override;
  void CommitPendingWrite(
      base::OnceClosure reply_callback = base::OnceClosure(),
      base::OnceClosure synchronous_done_callback =
          base::OnceClosure()) override;
  void SchedulePendingLossyWrites() override;
  void ReportValueChanged(const std::string& key, uint32_t flags) override;

  // Just like RemoveValue(), but doesn't notify observers. Used when doing some
  // cleanup that shouldn't otherwise alert observers.
  void RemoveValueSilently(const std::string& key, uint32_t flags);

  // Registers |on_next_successful_write_reply| to be called once, on the next
  // successful write event of |writer_|.
  // |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);

  void ClearMutableValues() override;

  void OnStoreDeletionFromDisk() override;

 private:
  friend class base::JsonPrefStoreCallbackTest;
  friend class base::JsonPrefStoreLossyWriteTest;
  friend class base::WriteCallbacksObserver;

  ~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
  // |on_next_write_reply| on |reply_task_runner|.
  static void PostWriteCallback(
      const base::Callback<void(bool success)>& on_next_write_callback,
      const base::Callback<void(bool success)>& on_next_write_reply,
      scoped_refptr<base::SequencedTaskRunner> reply_task_runner,
      bool write_success);

  // Registers the |callbacks| pair to be called once synchronously before and
  // after, respectively, the next write event of |writer_|.
  // Both callbacks must be thread-safe.
  void RegisterOnNextWriteSynchronousCallbacks(OnWriteCallbackPair callbacks);

  // 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
  // FinalizeFileRead() to that |pref_filter_| which is then responsible for
  // invoking it when done. If there is no |pref_filter_|, FinalizeFileRead()
  // is invoked directly.
  void OnFileRead(std::unique_ptr<ReadResult> read_result);

  // ImportantFileWriter::DataSerializer overrides:
  bool SerializeData(std::string* output) override;

  // This method is called after the JSON file has been read and the result has
  // potentially been intercepted and modified by |pref_filter_|.
  // |initialization_successful| is pre-determined by OnFileRead() and should
  // be used when reporting OnInitializationCompleted().
  // |schedule_write| indicates whether a write should be immediately scheduled
  // (typically because the |pref_filter_| has already altered the |prefs|) --
  // this will be ignored if this store is read-only.
  void FinalizeFileRead(bool initialization_successful,
                        std::unique_ptr<base::DictionaryValue> prefs,
                        bool schedule_write);

  // Schedule a write with the file writer as long as |flags| doesn't contain
  // WriteablePrefStore::LOSSY_PREF_WRITE_FLAG.
  void ScheduleWrite(uint32_t flags);

  const base::FilePath path_;
  const scoped_refptr<base::SequencedTaskRunner> file_task_runner_;

  std::unique_ptr<base::DictionaryValue> prefs_;

  bool read_only_;

  // Helper for safely writing pref data.
  base::ImportantFileWriter writer_;

  std::unique_ptr<PrefFilter> pref_filter_;
  base::ObserverList<PrefStore::Observer, true>::Unchecked observers_;

  std::unique_ptr<ReadErrorDelegate> error_delegate_;

  bool initialized_;
  bool filtering_in_progress_;
  bool pending_lossy_write_;
  PrefReadError read_error_;

  std::set<std::string> keys_need_empty_value_;

  bool has_pending_write_reply_ = true;
  base::Closure on_next_successful_write_reply_;

  SEQUENCE_CHECKER(sequence_checker_);

  DISALLOW_COPY_AND_ASSIGN(JsonPrefStore);
};

#endif  // COMPONENTS_PREFS_JSON_PREF_STORE_H_