1 // Copyright 2014 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 #include "components/prefs/segregated_pref_store.h"
6
7 #include <string_view>
8 #include <utility>
9
10 #include "base/barrier_closure.h"
11 #include "base/check_op.h"
12 #include "base/containers/contains.h"
13 #include "base/notreached.h"
14 #include "base/observer_list.h"
15 #include "base/values.h"
16 #include "components/prefs/pref_name_set.h"
17
UnderlyingPrefStoreObserver(SegregatedPrefStore * outer)18 SegregatedPrefStore::UnderlyingPrefStoreObserver::UnderlyingPrefStoreObserver(
19 SegregatedPrefStore* outer)
20 : outer_(outer) {
21 DCHECK(outer_);
22 }
23
OnPrefValueChanged(std::string_view key)24 void SegregatedPrefStore::UnderlyingPrefStoreObserver::OnPrefValueChanged(
25 std::string_view key) {
26 // Notify Observers only after all underlying PrefStores of the outer
27 // SegregatedPrefStore are initialized.
28 if (!outer_->IsInitializationComplete())
29 return;
30
31 for (auto& observer : outer_->observers_)
32 observer.OnPrefValueChanged(key);
33 }
34
35 void SegregatedPrefStore::UnderlyingPrefStoreObserver::
OnInitializationCompleted(bool succeeded)36 OnInitializationCompleted(bool succeeded) {
37 initialization_succeeded_ = succeeded;
38
39 // Notify Observers only after all underlying PrefStores of the outer
40 // SegregatedPrefStore are initialized.
41 if (!outer_->IsInitializationComplete())
42 return;
43
44 if (outer_->read_error_delegate_.has_value() &&
45 outer_->read_error_delegate_.value()) {
46 PersistentPrefStore::PrefReadError read_error = outer_->GetReadError();
47 if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE)
48 outer_->read_error_delegate_.value()->OnError(read_error);
49 }
50
51 for (auto& observer : outer_->observers_)
52 observer.OnInitializationCompleted(outer_->IsInitializationSuccessful());
53 }
54
SegregatedPrefStore(scoped_refptr<PersistentPrefStore> default_pref_store,scoped_refptr<PersistentPrefStore> selected_pref_store,PrefNameSet selected_pref_names)55 SegregatedPrefStore::SegregatedPrefStore(
56 scoped_refptr<PersistentPrefStore> default_pref_store,
57 scoped_refptr<PersistentPrefStore> selected_pref_store,
58 PrefNameSet selected_pref_names)
59 : default_pref_store_(std::move(default_pref_store)),
60 selected_pref_store_(std::move(selected_pref_store)),
61 selected_preference_names_(std::move(selected_pref_names)),
62 default_observer_(this),
63 selected_observer_(this) {
64 default_pref_store_->AddObserver(&default_observer_);
65 selected_pref_store_->AddObserver(&selected_observer_);
66 }
67
AddObserver(Observer * observer)68 void SegregatedPrefStore::AddObserver(Observer* observer) {
69 observers_.AddObserver(observer);
70 }
71
RemoveObserver(Observer * observer)72 void SegregatedPrefStore::RemoveObserver(Observer* observer) {
73 observers_.RemoveObserver(observer);
74 }
75
HasObservers() const76 bool SegregatedPrefStore::HasObservers() const {
77 return !observers_.empty();
78 }
79
IsInitializationComplete() const80 bool SegregatedPrefStore::IsInitializationComplete() const {
81 return default_pref_store_->IsInitializationComplete() &&
82 selected_pref_store_->IsInitializationComplete();
83 }
84
IsInitializationSuccessful() const85 bool SegregatedPrefStore::IsInitializationSuccessful() const {
86 return default_observer_.initialization_succeeded() &&
87 selected_observer_.initialization_succeeded();
88 }
89
GetValue(std::string_view key,const base::Value ** result) const90 bool SegregatedPrefStore::GetValue(std::string_view key,
91 const base::Value** result) const {
92 return StoreForKey(key)->GetValue(key, result);
93 }
94
GetValues() const95 base::Value::Dict SegregatedPrefStore::GetValues() const {
96 base::Value::Dict values = default_pref_store_->GetValues();
97 base::Value::Dict selected_pref_store_values =
98 selected_pref_store_->GetValues();
99 for (const auto& key : selected_preference_names_) {
100 if (base::Value* value = selected_pref_store_values.FindByDottedPath(key)) {
101 values.SetByDottedPath(key, std::move(*value));
102 } else {
103 values.Remove(key);
104 }
105 }
106 return values;
107 }
108
SetValue(std::string_view key,base::Value value,uint32_t flags)109 void SegregatedPrefStore::SetValue(std::string_view key,
110 base::Value value,
111 uint32_t flags) {
112 StoreForKey(key)->SetValue(key, std::move(value), flags);
113 }
114
RemoveValue(std::string_view key,uint32_t flags)115 void SegregatedPrefStore::RemoveValue(std::string_view key, uint32_t flags) {
116 StoreForKey(key)->RemoveValue(key, flags);
117 }
118
RemoveValuesByPrefixSilently(std::string_view prefix)119 void SegregatedPrefStore::RemoveValuesByPrefixSilently(
120 std::string_view prefix) {
121 // Since we can't guarantee to have all the prefs in one the pref stores, we
122 // have to push the removal command down to both of them.
123 default_pref_store_->RemoveValuesByPrefixSilently(prefix);
124 selected_pref_store_->RemoveValuesByPrefixSilently(prefix);
125 }
126
GetMutableValue(std::string_view key,base::Value ** result)127 bool SegregatedPrefStore::GetMutableValue(std::string_view key,
128 base::Value** result) {
129 return StoreForKey(key)->GetMutableValue(key, result);
130 }
131
ReportValueChanged(std::string_view key,uint32_t flags)132 void SegregatedPrefStore::ReportValueChanged(std::string_view key,
133 uint32_t flags) {
134 StoreForKey(key)->ReportValueChanged(key, flags);
135 }
136
SetValueSilently(std::string_view key,base::Value value,uint32_t flags)137 void SegregatedPrefStore::SetValueSilently(std::string_view key,
138 base::Value value,
139 uint32_t flags) {
140 StoreForKey(key)->SetValueSilently(key, std::move(value), flags);
141 }
142
ReadOnly() const143 bool SegregatedPrefStore::ReadOnly() const {
144 return selected_pref_store_->ReadOnly() || default_pref_store_->ReadOnly();
145 }
146
GetReadError() const147 PersistentPrefStore::PrefReadError SegregatedPrefStore::GetReadError() const {
148 PersistentPrefStore::PrefReadError read_error =
149 default_pref_store_->GetReadError();
150 if (read_error == PersistentPrefStore::PREF_READ_ERROR_NONE) {
151 read_error = selected_pref_store_->GetReadError();
152 // Ignore NO_FILE from selected_pref_store_.
153 if (read_error == PersistentPrefStore::PREF_READ_ERROR_NO_FILE)
154 read_error = PersistentPrefStore::PREF_READ_ERROR_NONE;
155 }
156 return read_error;
157 }
158
ReadPrefs()159 PersistentPrefStore::PrefReadError SegregatedPrefStore::ReadPrefs() {
160 // Note: Both of these stores own PrefFilters which makes ReadPrefs
161 // asynchronous. This is okay in this case as only the first call will be
162 // truly asynchronous, the second call will then unblock the migration in
163 // TrackedPreferencesMigrator and complete synchronously.
164 default_pref_store_->ReadPrefs();
165 PersistentPrefStore::PrefReadError selected_store_read_error =
166 selected_pref_store_->ReadPrefs();
167 DCHECK_NE(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE,
168 selected_store_read_error);
169
170 return GetReadError();
171 }
172
ReadPrefsAsync(ReadErrorDelegate * error_delegate)173 void SegregatedPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
174 read_error_delegate_.emplace(error_delegate);
175 default_pref_store_->ReadPrefsAsync(nullptr);
176 selected_pref_store_->ReadPrefsAsync(nullptr);
177 }
178
CommitPendingWrite(base::OnceClosure reply_callback,base::OnceClosure synchronous_done_callback)179 void SegregatedPrefStore::CommitPendingWrite(
180 base::OnceClosure reply_callback,
181 base::OnceClosure synchronous_done_callback) {
182 // A BarrierClosure will run its callback wherever the last instance of the
183 // returned wrapper is invoked. As such it is guaranteed to respect the reply
184 // vs synchronous semantics assuming |default_pref_store_| and
185 // |selected_pref_store_| honor it.
186
187 base::RepeatingClosure reply_callback_wrapper =
188 reply_callback ? base::BarrierClosure(2, std::move(reply_callback))
189 : base::RepeatingClosure();
190
191 base::RepeatingClosure synchronous_callback_wrapper =
192 synchronous_done_callback
193 ? base::BarrierClosure(2, std::move(synchronous_done_callback))
194 : base::RepeatingClosure();
195
196 default_pref_store_->CommitPendingWrite(reply_callback_wrapper,
197 synchronous_callback_wrapper);
198 selected_pref_store_->CommitPendingWrite(reply_callback_wrapper,
199 synchronous_callback_wrapper);
200 }
201
SchedulePendingLossyWrites()202 void SegregatedPrefStore::SchedulePendingLossyWrites() {
203 default_pref_store_->SchedulePendingLossyWrites();
204 selected_pref_store_->SchedulePendingLossyWrites();
205 }
206
OnStoreDeletionFromDisk()207 void SegregatedPrefStore::OnStoreDeletionFromDisk() {
208 default_pref_store_->OnStoreDeletionFromDisk();
209 selected_pref_store_->OnStoreDeletionFromDisk();
210 }
211
~SegregatedPrefStore()212 SegregatedPrefStore::~SegregatedPrefStore() {
213 default_pref_store_->RemoveObserver(&default_observer_);
214 selected_pref_store_->RemoveObserver(&selected_observer_);
215 }
216
StoreForKey(std::string_view key)217 PersistentPrefStore* SegregatedPrefStore::StoreForKey(std::string_view key) {
218 return (base::Contains(selected_preference_names_, key) ? selected_pref_store_
219 : default_pref_store_)
220 .get();
221 }
222
StoreForKey(std::string_view key) const223 const PersistentPrefStore* SegregatedPrefStore::StoreForKey(
224 std::string_view key) const {
225 return (base::Contains(selected_preference_names_, key) ? selected_pref_store_
226 : default_pref_store_)
227 .get();
228 }
229
HasReadErrorDelegate() const230 bool SegregatedPrefStore::HasReadErrorDelegate() const {
231 return read_error_delegate_.has_value();
232 }
233