blob: d3f285ba9f53b719d62057bc269b3298034bfedb [file] [log] [blame]
[email protected]32c3c752012-01-05 17:33:471// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]39565dd2011-11-14 12:09:272// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
brettwf00b9b42016-02-01 22:11:385#include "components/prefs/overlay_user_pref_store.h"
[email protected]39565dd2011-11-14 12:09:276
dcheng5f043bc2016-04-22 19:09:067#include <memory>
danakj0c8d4aa2015-11-25 05:29:588#include <utility>
9
dcheng5f043bc2016-04-22 19:09:0610#include "base/memory/ptr_util.h"
Caitlin Fischerce1e29492021-06-12 16:37:0111#include "base/notreached.h"
[email protected]39565dd2011-11-14 12:09:2712#include "base/values.h"
Johan Tibell0595f762017-05-25 23:54:5013#include "components/prefs/in_memory_pref_store.h"
[email protected]39565dd2011-11-14 12:09:2714
Johan Tibell0595f762017-05-25 23:54:5015// Allows us to monitor two pref stores and tell updates from them apart. It
16// essentially mimics a Callback for the Observer interface (e.g. it allows
17// binding additional arguments).
18class OverlayUserPrefStore::ObserverAdapter : public PrefStore::Observer {
19 public:
Ramin Halavatif623bafe92018-07-17 12:12:5820 ObserverAdapter(bool ephemeral, OverlayUserPrefStore* parent)
21 : ephemeral_user_pref_store_(ephemeral), parent_(parent) {}
Johan Tibell0595f762017-05-25 23:54:5022
23 // Methods of PrefStore::Observer.
24 void OnPrefValueChanged(const std::string& key) override {
Ramin Halavatif623bafe92018-07-17 12:12:5825 parent_->OnPrefValueChanged(ephemeral_user_pref_store_, key);
Johan Tibell0595f762017-05-25 23:54:5026 }
27 void OnInitializationCompleted(bool succeeded) override {
Ramin Halavatif623bafe92018-07-17 12:12:5828 parent_->OnInitializationCompleted(ephemeral_user_pref_store_, succeeded);
Johan Tibell0595f762017-05-25 23:54:5029 }
30
31 private:
Ramin Halavatif623bafe92018-07-17 12:12:5832 // Is the update for the ephemeral?
33 const bool ephemeral_user_pref_store_;
Johan Tibell0595f762017-05-25 23:54:5034 OverlayUserPrefStore* const parent_;
35};
36
Ramin Halavatif623bafe92018-07-17 12:12:5837OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* persistent)
38 : OverlayUserPrefStore(new InMemoryPrefStore(), persistent) {}
Johan Tibell0595f762017-05-25 23:54:5039
Ramin Halavatif623bafe92018-07-17 12:12:5840OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* ephemeral,
41 PersistentPrefStore* persistent)
42 : ephemeral_pref_store_observer_(
Jinho Bang84b58bd2018-01-01 21:44:4843 std::make_unique<OverlayUserPrefStore::ObserverAdapter>(true, this)),
Ramin Halavatif623bafe92018-07-17 12:12:5844 persistent_pref_store_observer_(
Jinho Bang84b58bd2018-01-01 21:44:4845 std::make_unique<OverlayUserPrefStore::ObserverAdapter>(false, this)),
Ramin Halavatif623bafe92018-07-17 12:12:5846 ephemeral_user_pref_store_(ephemeral),
47 persistent_user_pref_store_(persistent) {
48 DCHECK(ephemeral->IsInitializationComplete());
49 ephemeral_user_pref_store_->AddObserver(ephemeral_pref_store_observer_.get());
50 persistent_user_pref_store_->AddObserver(
51 persistent_pref_store_observer_.get());
[email protected]39565dd2011-11-14 12:09:2752}
53
[email protected]39565dd2011-11-14 12:09:2754bool OverlayUserPrefStore::IsSetInOverlay(const std::string& key) const {
Ramin Halavatif623bafe92018-07-17 12:12:5855 return ephemeral_user_pref_store_->GetValue(key, nullptr);
[email protected]39565dd2011-11-14 12:09:2756}
57
58void OverlayUserPrefStore::AddObserver(PrefStore::Observer* observer) {
59 observers_.AddObserver(observer);
60}
61
62void OverlayUserPrefStore::RemoveObserver(PrefStore::Observer* observer) {
63 observers_.RemoveObserver(observer);
64}
65
[email protected]14e0ec62013-08-26 22:01:3966bool OverlayUserPrefStore::HasObservers() const {
Mitsuru Oshima28f9b6812021-01-20 19:33:0767 return !observers_.empty();
[email protected]d3b05ea2012-01-24 22:57:0568}
69
[email protected]39565dd2011-11-14 12:09:2770bool OverlayUserPrefStore::IsInitializationComplete() const {
Ramin Halavatif623bafe92018-07-17 12:12:5871 return persistent_user_pref_store_->IsInitializationComplete() &&
72 ephemeral_user_pref_store_->IsInitializationComplete();
[email protected]39565dd2011-11-14 12:09:2773}
74
[email protected]892f1d62012-11-08 18:24:3475bool OverlayUserPrefStore::GetValue(const std::string& key,
[email protected]a43a667b2013-06-14 17:56:0876 const base::Value** result) const {
Ramin Halavatif623bafe92018-07-17 12:12:5877 // If the |key| shall NOT be stored in the ephemeral store, there must not
[email protected]39565dd2011-11-14 12:09:2778 // be an entry.
Ramin Halavatif623bafe92018-07-17 12:12:5879 DCHECK(!ShallBeStoredInPersistent(key) ||
80 !ephemeral_user_pref_store_->GetValue(key, nullptr));
[email protected]39565dd2011-11-14 12:09:2781
Ramin Halavatif623bafe92018-07-17 12:12:5882 if (ephemeral_user_pref_store_->GetValue(key, result))
[email protected]892f1d62012-11-08 18:24:3483 return true;
Ramin Halavatif623bafe92018-07-17 12:12:5884 return persistent_user_pref_store_->GetValue(key, result);
[email protected]39565dd2011-11-14 12:09:2785}
86
tibelle23659b42017-02-23 01:44:1387std::unique_ptr<base::DictionaryValue> OverlayUserPrefStore::GetValues() const {
Ramin Halavatif623bafe92018-07-17 12:12:5888 auto values = ephemeral_user_pref_store_->GetValues();
89 auto persistent_values = persistent_user_pref_store_->GetValues();
90
91 // Output |values| are read from |ephemeral_user_pref_store_| (in-memory
92 // store). Then the values of preferences in |persistent_names_set_| are
93 // overwritten by the content of |persistent_user_pref_store_| (the persistent
94 // store).
95 for (const auto& key : persistent_names_set_) {
tibelle23659b42017-02-23 01:44:1396 std::unique_ptr<base::Value> out_value;
Ramin Halavatif623bafe92018-07-17 12:12:5897 persistent_values->Remove(key, &out_value);
tibelle23659b42017-02-23 01:44:1398 if (out_value) {
Song Fangzhenf4033a82021-06-22 09:12:4299 values->SetPath(key, std::move(*out_value));
tibelle23659b42017-02-23 01:44:13100 }
101 }
102 return values;
103}
104
[email protected]892f1d62012-11-08 18:24:34105bool OverlayUserPrefStore::GetMutableValue(const std::string& key,
[email protected]a43a667b2013-06-14 17:56:08106 base::Value** result) {
Ramin Halavatif623bafe92018-07-17 12:12:58107 if (ShallBeStoredInPersistent(key))
108 return persistent_user_pref_store_->GetMutableValue(key, result);
[email protected]39565dd2011-11-14 12:09:27109
Ramin Halavatif623bafe92018-07-17 12:12:58110 written_ephemeral_names_.insert(key);
111 if (ephemeral_user_pref_store_->GetMutableValue(key, result))
[email protected]892f1d62012-11-08 18:24:34112 return true;
[email protected]39565dd2011-11-14 12:09:27113
Ramin Halavatif623bafe92018-07-17 12:12:58114 // Try to create copy of persistent if the ephemeral does not contain a value.
115 base::Value* persistent_value = nullptr;
116 if (!persistent_user_pref_store_->GetMutableValue(key, &persistent_value))
[email protected]892f1d62012-11-08 18:24:34117 return false;
[email protected]39565dd2011-11-14 12:09:27118
Ramin Halavatif623bafe92018-07-17 12:12:58119 ephemeral_user_pref_store_->SetValue(
Austin Sullivan523eec12021-05-11 22:48:40120 key, base::Value::ToUniquePtrValue(persistent_value->Clone()),
Ramin Halavatif623bafe92018-07-17 12:12:58121 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
Vladislav Kuzkokov8ee75fbc2019-01-14 14:14:04122 ephemeral_user_pref_store_->GetMutableValue(key, result);
[email protected]892f1d62012-11-08 18:24:34123 return true;
[email protected]39565dd2011-11-14 12:09:27124}
125
126void OverlayUserPrefStore::SetValue(const std::string& key,
dcheng5f043bc2016-04-22 19:09:06127 std::unique_ptr<base::Value> value,
avi9ef8bb02015-12-24 05:29:36128 uint32_t flags) {
Ramin Halavatif623bafe92018-07-17 12:12:58129 if (ShallBeStoredInPersistent(key)) {
130 persistent_user_pref_store_->SetValue(key, std::move(value), flags);
[email protected]39565dd2011-11-14 12:09:27131 return;
132 }
133
Ramin Halavatif623bafe92018-07-17 12:12:58134 // TODO(https://crbug.com/861722): If we always store in in-memory storage
135 // and conditionally also stored in persistent one, we wouldn't have to do a
136 // complex merge in GetValues().
137 written_ephemeral_names_.insert(key);
138 ephemeral_user_pref_store_->SetValue(key, std::move(value), flags);
[email protected]39565dd2011-11-14 12:09:27139}
140
141void OverlayUserPrefStore::SetValueSilently(const std::string& key,
dcheng5f043bc2016-04-22 19:09:06142 std::unique_ptr<base::Value> value,
avi9ef8bb02015-12-24 05:29:36143 uint32_t flags) {
Ramin Halavatif623bafe92018-07-17 12:12:58144 if (ShallBeStoredInPersistent(key)) {
145 persistent_user_pref_store_->SetValueSilently(key, std::move(value), flags);
[email protected]39565dd2011-11-14 12:09:27146 return;
147 }
148
Ramin Halavatif623bafe92018-07-17 12:12:58149 written_ephemeral_names_.insert(key);
150 ephemeral_user_pref_store_->SetValueSilently(key, std::move(value), flags);
[email protected]39565dd2011-11-14 12:09:27151}
152
avi9ef8bb02015-12-24 05:29:36153void OverlayUserPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
Ramin Halavatif623bafe92018-07-17 12:12:58154 if (ShallBeStoredInPersistent(key)) {
155 persistent_user_pref_store_->RemoveValue(key, flags);
[email protected]39565dd2011-11-14 12:09:27156 return;
157 }
158
Ramin Halavatif623bafe92018-07-17 12:12:58159 written_ephemeral_names_.insert(key);
160 ephemeral_user_pref_store_->RemoveValue(key, flags);
[email protected]39565dd2011-11-14 12:09:27161}
162
Anatoliy Potapchuk5d9d8de2020-04-21 02:09:26163void OverlayUserPrefStore::RemoveValuesByPrefixSilently(
164 const std::string& prefix) {
165 NOTIMPLEMENTED();
166}
167
[email protected]39565dd2011-11-14 12:09:27168bool OverlayUserPrefStore::ReadOnly() const {
169 return false;
170}
171
[email protected]59c10712012-03-13 02:10:34172PersistentPrefStore::PrefReadError OverlayUserPrefStore::GetReadError() const {
173 return PersistentPrefStore::PREF_READ_ERROR_NONE;
174}
175
[email protected]39565dd2011-11-14 12:09:27176PersistentPrefStore::PrefReadError OverlayUserPrefStore::ReadPrefs() {
177 // We do not read intentionally.
Ramin Halavatif623bafe92018-07-17 12:12:58178 OnInitializationCompleted(/* ephemeral */ false, true);
[email protected]39565dd2011-11-14 12:09:27179 return PersistentPrefStore::PREF_READ_ERROR_NONE;
180}
181
182void OverlayUserPrefStore::ReadPrefsAsync(
183 ReadErrorDelegate* error_delegate_raw) {
dcheng5f043bc2016-04-22 19:09:06184 std::unique_ptr<ReadErrorDelegate> error_delegate(error_delegate_raw);
[email protected]39565dd2011-11-14 12:09:27185 // We do not read intentionally.
Ramin Halavatif623bafe92018-07-17 12:12:58186 OnInitializationCompleted(/* ephemeral */ false, true);
[email protected]39565dd2011-11-14 12:09:27187}
188
Gabriel Charette788eaf62018-08-07 20:11:46189void OverlayUserPrefStore::CommitPendingWrite(
190 base::OnceClosure reply_callback,
191 base::OnceClosure synchronous_done_callback) {
192 persistent_user_pref_store_->CommitPendingWrite(
193 std::move(reply_callback), std::move(synchronous_done_callback));
[email protected]39565dd2011-11-14 12:09:27194 // We do not write our content intentionally.
195}
196
Caitlin Fischerce1e29492021-06-12 16:37:01197void OverlayUserPrefStore::CommitPendingWriteSynchronously() {
198 // This function was added for one very specific use case and is intentionally
199 // not implemented for other pref stores.
200 NOTREACHED();
201}
202
benwells26730592015-05-28 13:08:08203void OverlayUserPrefStore::SchedulePendingLossyWrites() {
Ramin Halavatif623bafe92018-07-17 12:12:58204 persistent_user_pref_store_->SchedulePendingLossyWrites();
benwells26730592015-05-28 13:08:08205}
206
raymes76de1af2015-05-06 03:22:21207void OverlayUserPrefStore::ReportValueChanged(const std::string& key,
avi9ef8bb02015-12-24 05:29:36208 uint32_t flags) {
ericwilligers42b92c12016-10-24 20:21:13209 for (PrefStore::Observer& observer : observers_)
210 observer.OnPrefValueChanged(key);
[email protected]39565dd2011-11-14 12:09:27211}
212
Ramin Halavatif623bafe92018-07-17 12:12:58213void OverlayUserPrefStore::RegisterPersistentPref(const std::string& key) {
Johan Tibell6566c8ac2017-05-11 03:22:17214 DCHECK(!key.empty()) << "Key is empty";
Ramin Halavatif623bafe92018-07-17 12:12:58215 DCHECK(persistent_names_set_.find(key) == persistent_names_set_.end())
216 << "Key already registered: " << key;
217 persistent_names_set_.insert(key);
[email protected]39565dd2011-11-14 12:09:27218}
219
dvadym53fc0d42016-02-05 13:34:57220void OverlayUserPrefStore::ClearMutableValues() {
Ramin Halavatif623bafe92018-07-17 12:12:58221 for (const auto& key : written_ephemeral_names_) {
222 ephemeral_user_pref_store_->RemoveValue(
223 key, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
Johan Tibell0595f762017-05-25 23:54:50224 }
dvadym53fc0d42016-02-05 13:34:57225}
226
proberge45e347282017-08-16 21:24:05227void OverlayUserPrefStore::OnStoreDeletionFromDisk() {
Ramin Halavatif623bafe92018-07-17 12:12:58228 persistent_user_pref_store_->OnStoreDeletionFromDisk();
proberge45e347282017-08-16 21:24:05229}
230
[email protected]2dea5c02012-04-25 07:01:07231OverlayUserPrefStore::~OverlayUserPrefStore() {
Ramin Halavatif623bafe92018-07-17 12:12:58232 ephemeral_user_pref_store_->RemoveObserver(
233 ephemeral_pref_store_observer_.get());
234 persistent_user_pref_store_->RemoveObserver(
235 persistent_pref_store_observer_.get());
Johan Tibell0595f762017-05-25 23:54:50236}
237
Ramin Halavatif623bafe92018-07-17 12:12:58238void OverlayUserPrefStore::OnPrefValueChanged(bool ephemeral,
Johan Tibell0595f762017-05-25 23:54:50239 const std::string& key) {
Ramin Halavatif623bafe92018-07-17 12:12:58240 if (ephemeral) {
Johan Tibell0595f762017-05-25 23:54:50241 ReportValueChanged(key, DEFAULT_PREF_WRITE_FLAGS);
242 } else {
Ramin Halavatif623bafe92018-07-17 12:12:58243 if (!ephemeral_user_pref_store_->GetValue(key, nullptr))
Johan Tibell0595f762017-05-25 23:54:50244 ReportValueChanged(key, DEFAULT_PREF_WRITE_FLAGS);
245 }
246}
247
Ramin Halavatif623bafe92018-07-17 12:12:58248void OverlayUserPrefStore::OnInitializationCompleted(bool ephemeral,
Johan Tibell0595f762017-05-25 23:54:50249 bool succeeded) {
250 if (!IsInitializationComplete())
251 return;
252 for (PrefStore::Observer& observer : observers_)
253 observer.OnInitializationCompleted(succeeded);
[email protected]39565dd2011-11-14 12:09:27254}
255
Ramin Halavatif623bafe92018-07-17 12:12:58256bool OverlayUserPrefStore::ShallBeStoredInPersistent(
[email protected]39565dd2011-11-14 12:09:27257 const std::string& key) const {
Ramin Halavatif623bafe92018-07-17 12:12:58258 return persistent_names_set_.find(key) != persistent_names_set_.end();
[email protected]39565dd2011-11-14 12:09:27259}