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>
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/strings/string_piece.h"
16 #include "base/values.h"
17 #include "components/prefs/pref_name_set.h"
18
UnderlyingPrefStoreObserver(SegregatedPrefStore * outer)19 SegregatedPrefStore::UnderlyingPrefStoreObserver::UnderlyingPrefStoreObserver(
20 SegregatedPrefStore* outer)
21 : outer_(outer) {
22 DCHECK(outer_);
23 }
24
OnPrefValueChanged(const std::string & key)25 void SegregatedPrefStore::UnderlyingPrefStoreObserver::OnPrefValueChanged(
26 const std::string& key) {
27 // Notify Observers only after all underlying PrefStores of the outer
28 // SegregatedPrefStore are initialized.
29 if (!outer_->IsInitializationComplete())
30 return;
31
32 for (auto& observer : outer_->observers_)
33 observer.OnPrefValueChanged(key);
34 }
35
36 void SegregatedPrefStore::UnderlyingPrefStoreObserver::
OnInitializationCompleted(bool succeeded)37 OnInitializationCompleted(bool succeeded) {
38 initialization_succeeded_ = succeeded;
39
40 // Notify Observers only after all underlying PrefStores of the outer
41 // SegregatedPrefStore are initialized.
42 if (!outer_->IsInitializationComplete())
43 return;
44
45 if (outer_->read_error_delegate_) {
46 PersistentPrefStore::PrefReadError read_error = outer_->GetReadError();
47 if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE)
48 outer_->read_error_delegate_->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(base::StringPiece key,const base::Value ** result) const90 bool SegregatedPrefStore::GetValue(base::StringPiece 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(const std::string & key,base::Value value,uint32_t flags)109 void SegregatedPrefStore::SetValue(const std::string& key,
110 base::Value value,
111 uint32_t flags) {
112 StoreForKey(key)->SetValue(key, std::move(value), flags);
113 }
114
RemoveValue(const std::string & key,uint32_t flags)115 void SegregatedPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
116 StoreForKey(key)->RemoveValue(key, flags);
117 }
118
RemoveValuesByPrefixSilently(const std::string & prefix)119 void SegregatedPrefStore::RemoveValuesByPrefixSilently(
120 const std::string& 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(const std::string & key,base::Value ** result)127 bool SegregatedPrefStore::GetMutableValue(const std::string& key,
128 base::Value** result) {
129 return StoreForKey(key)->GetMutableValue(key, result);
130 }
131
ReportValueChanged(const std::string & key,uint32_t flags)132 void SegregatedPrefStore::ReportValueChanged(const std::string& key,
133 uint32_t flags) {
134 StoreForKey(key)->ReportValueChanged(key, flags);
135 }
136
SetValueSilently(const std::string & key,base::Value value,uint32_t flags)137 void SegregatedPrefStore::SetValueSilently(const std::string& 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_.reset(error_delegate);
175 default_pref_store_->ReadPrefsAsync(NULL);
176 selected_pref_store_->ReadPrefsAsync(NULL);
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(base::StringPiece key)217 PersistentPrefStore* SegregatedPrefStore::StoreForKey(base::StringPiece key) {
218 return (base::Contains(selected_preference_names_, key) ? selected_pref_store_
219 : default_pref_store_)
220 .get();
221 }
222
StoreForKey(base::StringPiece key) const223 const PersistentPrefStore* SegregatedPrefStore::StoreForKey(
224 base::StringPiece key) const {
225 return (base::Contains(selected_preference_names_, key) ? selected_pref_store_
226 : default_pref_store_)
227 .get();
228 }
229