blob: 1b0299bf51c7f41a5cfd50934e0512544aeffb60 [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>
Peter Kastingb2777ce2021-07-20 18:28:548#include <ostream>
danakj0c8d4aa2015-11-25 05:29:589#include <utility>
10
dcheng5f043bc2016-04-22 19:09:0611#include "base/memory/ptr_util.h"
Keishi Hattori0e45c022021-11-27 09:25:5212#include "base/memory/raw_ptr.h"
David Sanders88b24432022-02-28 01:10:0213#include "base/observer_list.h"
[email protected]39565dd2011-11-14 12:09:2714#include "base/values.h"
Johan Tibell0595f762017-05-25 23:54:5015#include "components/prefs/in_memory_pref_store.h"
[email protected]39565dd2011-11-14 12:09:2716
Johan Tibell0595f762017-05-25 23:54:5017// Allows us to monitor two pref stores and tell updates from them apart. It
18// essentially mimics a Callback for the Observer interface (e.g. it allows
19// binding additional arguments).
20class OverlayUserPrefStore::ObserverAdapter : public PrefStore::Observer {
21 public:
Ramin Halavatif623bafe92018-07-17 12:12:5822 ObserverAdapter(bool ephemeral, OverlayUserPrefStore* parent)
23 : ephemeral_user_pref_store_(ephemeral), parent_(parent) {}
Johan Tibell0595f762017-05-25 23:54:5024
25 // Methods of PrefStore::Observer.
26 void OnPrefValueChanged(const std::string& key) override {
Ramin Halavatif623bafe92018-07-17 12:12:5827 parent_->OnPrefValueChanged(ephemeral_user_pref_store_, key);
Johan Tibell0595f762017-05-25 23:54:5028 }
29 void OnInitializationCompleted(bool succeeded) override {
Ramin Halavatif623bafe92018-07-17 12:12:5830 parent_->OnInitializationCompleted(ephemeral_user_pref_store_, succeeded);
Johan Tibell0595f762017-05-25 23:54:5031 }
32
33 private:
Ramin Halavatif623bafe92018-07-17 12:12:5834 // Is the update for the ephemeral?
35 const bool ephemeral_user_pref_store_;
Keishi Hattori0e45c022021-11-27 09:25:5236 const raw_ptr<OverlayUserPrefStore> parent_;
Johan Tibell0595f762017-05-25 23:54:5037};
38
Ramin Halavatif623bafe92018-07-17 12:12:5839OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* persistent)
40 : OverlayUserPrefStore(new InMemoryPrefStore(), persistent) {}
Johan Tibell0595f762017-05-25 23:54:5041
Ramin Halavatif623bafe92018-07-17 12:12:5842OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* ephemeral,
43 PersistentPrefStore* persistent)
44 : ephemeral_pref_store_observer_(
Jinho Bang84b58bd2018-01-01 21:44:4845 std::make_unique<OverlayUserPrefStore::ObserverAdapter>(true, this)),
Ramin Halavatif623bafe92018-07-17 12:12:5846 persistent_pref_store_observer_(
Jinho Bang84b58bd2018-01-01 21:44:4847 std::make_unique<OverlayUserPrefStore::ObserverAdapter>(false, this)),
Ramin Halavatif623bafe92018-07-17 12:12:5848 ephemeral_user_pref_store_(ephemeral),
49 persistent_user_pref_store_(persistent) {
50 DCHECK(ephemeral->IsInitializationComplete());
51 ephemeral_user_pref_store_->AddObserver(ephemeral_pref_store_observer_.get());
52 persistent_user_pref_store_->AddObserver(
53 persistent_pref_store_observer_.get());
[email protected]39565dd2011-11-14 12:09:2754}
55
[email protected]39565dd2011-11-14 12:09:2756bool OverlayUserPrefStore::IsSetInOverlay(const std::string& key) const {
Ramin Halavatif623bafe92018-07-17 12:12:5857 return ephemeral_user_pref_store_->GetValue(key, nullptr);
[email protected]39565dd2011-11-14 12:09:2758}
59
60void OverlayUserPrefStore::AddObserver(PrefStore::Observer* observer) {
61 observers_.AddObserver(observer);
62}
63
64void OverlayUserPrefStore::RemoveObserver(PrefStore::Observer* observer) {
65 observers_.RemoveObserver(observer);
66}
67
[email protected]14e0ec62013-08-26 22:01:3968bool OverlayUserPrefStore::HasObservers() const {
Mitsuru Oshima28f9b6812021-01-20 19:33:0769 return !observers_.empty();
[email protected]d3b05ea2012-01-24 22:57:0570}
71
[email protected]39565dd2011-11-14 12:09:2772bool OverlayUserPrefStore::IsInitializationComplete() const {
Ramin Halavatif623bafe92018-07-17 12:12:5873 return persistent_user_pref_store_->IsInitializationComplete() &&
74 ephemeral_user_pref_store_->IsInitializationComplete();
[email protected]39565dd2011-11-14 12:09:2775}
76
[email protected]892f1d62012-11-08 18:24:3477bool OverlayUserPrefStore::GetValue(const std::string& key,
[email protected]a43a667b2013-06-14 17:56:0878 const base::Value** result) const {
Ramin Halavatif623bafe92018-07-17 12:12:5879 // If the |key| shall NOT be stored in the ephemeral store, there must not
[email protected]39565dd2011-11-14 12:09:2780 // be an entry.
Ramin Halavatif623bafe92018-07-17 12:12:5881 DCHECK(!ShallBeStoredInPersistent(key) ||
82 !ephemeral_user_pref_store_->GetValue(key, nullptr));
[email protected]39565dd2011-11-14 12:09:2783
Ramin Halavatif623bafe92018-07-17 12:12:5884 if (ephemeral_user_pref_store_->GetValue(key, result))
[email protected]892f1d62012-11-08 18:24:3485 return true;
Ramin Halavatif623bafe92018-07-17 12:12:5886 return persistent_user_pref_store_->GetValue(key, result);
[email protected]39565dd2011-11-14 12:09:2787}
88
tibelle23659b42017-02-23 01:44:1389std::unique_ptr<base::DictionaryValue> OverlayUserPrefStore::GetValues() const {
Ramin Halavatif623bafe92018-07-17 12:12:5890 auto values = ephemeral_user_pref_store_->GetValues();
91 auto persistent_values = persistent_user_pref_store_->GetValues();
92
93 // Output |values| are read from |ephemeral_user_pref_store_| (in-memory
94 // store). Then the values of preferences in |persistent_names_set_| are
95 // overwritten by the content of |persistent_user_pref_store_| (the persistent
96 // store).
97 for (const auto& key : persistent_names_set_) {
Song Fangzhen61767882021-07-16 04:59:4098 absl::optional<base::Value> out_value = persistent_values->ExtractPath(key);
99 if (out_value.has_value()) {
Song Fangzhenf4033a82021-06-22 09:12:42100 values->SetPath(key, std::move(*out_value));
tibelle23659b42017-02-23 01:44:13101 }
102 }
103 return values;
104}
105
[email protected]892f1d62012-11-08 18:24:34106bool OverlayUserPrefStore::GetMutableValue(const std::string& key,
[email protected]a43a667b2013-06-14 17:56:08107 base::Value** result) {
Ramin Halavatif623bafe92018-07-17 12:12:58108 if (ShallBeStoredInPersistent(key))
109 return persistent_user_pref_store_->GetMutableValue(key, result);
[email protected]39565dd2011-11-14 12:09:27110
Ramin Halavatif623bafe92018-07-17 12:12:58111 written_ephemeral_names_.insert(key);
112 if (ephemeral_user_pref_store_->GetMutableValue(key, result))
[email protected]892f1d62012-11-08 18:24:34113 return true;
[email protected]39565dd2011-11-14 12:09:27114
Ramin Halavatif623bafe92018-07-17 12:12:58115 // Try to create copy of persistent if the ephemeral does not contain a value.
116 base::Value* persistent_value = nullptr;
117 if (!persistent_user_pref_store_->GetMutableValue(key, &persistent_value))
[email protected]892f1d62012-11-08 18:24:34118 return false;
[email protected]39565dd2011-11-14 12:09:27119
Ramin Halavatif623bafe92018-07-17 12:12:58120 ephemeral_user_pref_store_->SetValue(
Austin Sullivan523eec12021-05-11 22:48:40121 key, base::Value::ToUniquePtrValue(persistent_value->Clone()),
Ramin Halavatif623bafe92018-07-17 12:12:58122 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
Vladislav Kuzkokov8ee75fbc2019-01-14 14:14:04123 ephemeral_user_pref_store_->GetMutableValue(key, result);
[email protected]892f1d62012-11-08 18:24:34124 return true;
[email protected]39565dd2011-11-14 12:09:27125}
126
127void OverlayUserPrefStore::SetValue(const std::string& key,
dcheng5f043bc2016-04-22 19:09:06128 std::unique_ptr<base::Value> value,
avi9ef8bb02015-12-24 05:29:36129 uint32_t flags) {
Ramin Halavatif623bafe92018-07-17 12:12:58130 if (ShallBeStoredInPersistent(key)) {
131 persistent_user_pref_store_->SetValue(key, std::move(value), flags);
[email protected]39565dd2011-11-14 12:09:27132 return;
133 }
134
Ramin Halavatif623bafe92018-07-17 12:12:58135 // TODO(https://crbug.com/861722): If we always store in in-memory storage
136 // and conditionally also stored in persistent one, we wouldn't have to do a
137 // complex merge in GetValues().
138 written_ephemeral_names_.insert(key);
139 ephemeral_user_pref_store_->SetValue(key, std::move(value), flags);
[email protected]39565dd2011-11-14 12:09:27140}
141
142void OverlayUserPrefStore::SetValueSilently(const std::string& key,
dcheng5f043bc2016-04-22 19:09:06143 std::unique_ptr<base::Value> value,
avi9ef8bb02015-12-24 05:29:36144 uint32_t flags) {
Ramin Halavatif623bafe92018-07-17 12:12:58145 if (ShallBeStoredInPersistent(key)) {
146 persistent_user_pref_store_->SetValueSilently(key, std::move(value), flags);
[email protected]39565dd2011-11-14 12:09:27147 return;
148 }
149
Ramin Halavatif623bafe92018-07-17 12:12:58150 written_ephemeral_names_.insert(key);
151 ephemeral_user_pref_store_->SetValueSilently(key, std::move(value), flags);
[email protected]39565dd2011-11-14 12:09:27152}
153
avi9ef8bb02015-12-24 05:29:36154void OverlayUserPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
Ramin Halavatif623bafe92018-07-17 12:12:58155 if (ShallBeStoredInPersistent(key)) {
156 persistent_user_pref_store_->RemoveValue(key, flags);
[email protected]39565dd2011-11-14 12:09:27157 return;
158 }
159
Ramin Halavatif623bafe92018-07-17 12:12:58160 written_ephemeral_names_.insert(key);
161 ephemeral_user_pref_store_->RemoveValue(key, flags);
[email protected]39565dd2011-11-14 12:09:27162}
163
Anatoliy Potapchuk5d9d8de2020-04-21 02:09:26164void OverlayUserPrefStore::RemoveValuesByPrefixSilently(
165 const std::string& prefix) {
166 NOTIMPLEMENTED();
167}
168
[email protected]39565dd2011-11-14 12:09:27169bool OverlayUserPrefStore::ReadOnly() const {
170 return false;
171}
172
[email protected]59c10712012-03-13 02:10:34173PersistentPrefStore::PrefReadError OverlayUserPrefStore::GetReadError() const {
174 return PersistentPrefStore::PREF_READ_ERROR_NONE;
175}
176
[email protected]39565dd2011-11-14 12:09:27177PersistentPrefStore::PrefReadError OverlayUserPrefStore::ReadPrefs() {
178 // We do not read intentionally.
Ramin Halavatif623bafe92018-07-17 12:12:58179 OnInitializationCompleted(/* ephemeral */ false, true);
[email protected]39565dd2011-11-14 12:09:27180 return PersistentPrefStore::PREF_READ_ERROR_NONE;
181}
182
183void OverlayUserPrefStore::ReadPrefsAsync(
184 ReadErrorDelegate* error_delegate_raw) {
dcheng5f043bc2016-04-22 19:09:06185 std::unique_ptr<ReadErrorDelegate> error_delegate(error_delegate_raw);
[email protected]39565dd2011-11-14 12:09:27186 // We do not read intentionally.
Ramin Halavatif623bafe92018-07-17 12:12:58187 OnInitializationCompleted(/* ephemeral */ false, true);
[email protected]39565dd2011-11-14 12:09:27188}
189
Gabriel Charette788eaf62018-08-07 20:11:46190void OverlayUserPrefStore::CommitPendingWrite(
191 base::OnceClosure reply_callback,
192 base::OnceClosure synchronous_done_callback) {
193 persistent_user_pref_store_->CommitPendingWrite(
194 std::move(reply_callback), std::move(synchronous_done_callback));
[email protected]39565dd2011-11-14 12:09:27195 // We do not write our content intentionally.
196}
197
benwells26730592015-05-28 13:08:08198void OverlayUserPrefStore::SchedulePendingLossyWrites() {
Ramin Halavatif623bafe92018-07-17 12:12:58199 persistent_user_pref_store_->SchedulePendingLossyWrites();
benwells26730592015-05-28 13:08:08200}
201
raymes76de1af2015-05-06 03:22:21202void OverlayUserPrefStore::ReportValueChanged(const std::string& key,
avi9ef8bb02015-12-24 05:29:36203 uint32_t flags) {
ericwilligers42b92c12016-10-24 20:21:13204 for (PrefStore::Observer& observer : observers_)
205 observer.OnPrefValueChanged(key);
[email protected]39565dd2011-11-14 12:09:27206}
207
Ramin Halavatif623bafe92018-07-17 12:12:58208void OverlayUserPrefStore::RegisterPersistentPref(const std::string& key) {
Johan Tibell6566c8ac2017-05-11 03:22:17209 DCHECK(!key.empty()) << "Key is empty";
Ramin Halavatif623bafe92018-07-17 12:12:58210 DCHECK(persistent_names_set_.find(key) == persistent_names_set_.end())
211 << "Key already registered: " << key;
212 persistent_names_set_.insert(key);
[email protected]39565dd2011-11-14 12:09:27213}
214
dvadym53fc0d42016-02-05 13:34:57215void OverlayUserPrefStore::ClearMutableValues() {
Ramin Halavatif623bafe92018-07-17 12:12:58216 for (const auto& key : written_ephemeral_names_) {
217 ephemeral_user_pref_store_->RemoveValue(
218 key, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
Johan Tibell0595f762017-05-25 23:54:50219 }
dvadym53fc0d42016-02-05 13:34:57220}
221
proberge45e347282017-08-16 21:24:05222void OverlayUserPrefStore::OnStoreDeletionFromDisk() {
Ramin Halavatif623bafe92018-07-17 12:12:58223 persistent_user_pref_store_->OnStoreDeletionFromDisk();
proberge45e347282017-08-16 21:24:05224}
225
[email protected]2dea5c02012-04-25 07:01:07226OverlayUserPrefStore::~OverlayUserPrefStore() {
Ramin Halavatif623bafe92018-07-17 12:12:58227 ephemeral_user_pref_store_->RemoveObserver(
228 ephemeral_pref_store_observer_.get());
229 persistent_user_pref_store_->RemoveObserver(
230 persistent_pref_store_observer_.get());
Johan Tibell0595f762017-05-25 23:54:50231}
232
Ramin Halavatif623bafe92018-07-17 12:12:58233void OverlayUserPrefStore::OnPrefValueChanged(bool ephemeral,
Johan Tibell0595f762017-05-25 23:54:50234 const std::string& key) {
Ramin Halavatif623bafe92018-07-17 12:12:58235 if (ephemeral) {
Johan Tibell0595f762017-05-25 23:54:50236 ReportValueChanged(key, DEFAULT_PREF_WRITE_FLAGS);
237 } else {
Ramin Halavatif623bafe92018-07-17 12:12:58238 if (!ephemeral_user_pref_store_->GetValue(key, nullptr))
Johan Tibell0595f762017-05-25 23:54:50239 ReportValueChanged(key, DEFAULT_PREF_WRITE_FLAGS);
240 }
241}
242
Ramin Halavatif623bafe92018-07-17 12:12:58243void OverlayUserPrefStore::OnInitializationCompleted(bool ephemeral,
Johan Tibell0595f762017-05-25 23:54:50244 bool succeeded) {
245 if (!IsInitializationComplete())
246 return;
247 for (PrefStore::Observer& observer : observers_)
248 observer.OnInitializationCompleted(succeeded);
[email protected]39565dd2011-11-14 12:09:27249}
250
Ramin Halavatif623bafe92018-07-17 12:12:58251bool OverlayUserPrefStore::ShallBeStoredInPersistent(
[email protected]39565dd2011-11-14 12:09:27252 const std::string& key) const {
Ramin Halavatif623bafe92018-07-17 12:12:58253 return persistent_names_set_.find(key) != persistent_names_set_.end();
[email protected]39565dd2011-11-14 12:09:27254}