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.
5 #include "components/prefs/segregated_pref_store.h"
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"
19 SegregatedPrefStore::UnderlyingPrefStoreObserver::UnderlyingPrefStoreObserver(
20 SegregatedPrefStore* outer)
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())
32 for (auto& observer : outer_->observers_)
33 observer.OnPrefValueChanged(key);
36 void SegregatedPrefStore::UnderlyingPrefStoreObserver::
37 OnInitializationCompleted(bool succeeded) {
38 initialization_succeeded_ = succeeded;
40 // Notify Observers only after all underlying PrefStores of the outer
41 // SegregatedPrefStore are initialized.
42 if (!outer_->IsInitializationComplete())
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);
51 for (auto& observer : outer_->observers_)
52 observer.OnInitializationCompleted(outer_->IsInitializationSuccessful());
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_);
68 void SegregatedPrefStore::AddObserver(Observer* observer) {
69 observers_.AddObserver(observer);
72 void SegregatedPrefStore::RemoveObserver(Observer* observer) {
73 observers_.RemoveObserver(observer);
76 bool SegregatedPrefStore::HasObservers() const {
77 return !observers_.empty();
80 bool SegregatedPrefStore::IsInitializationComplete() const {
81 return default_pref_store_->IsInitializationComplete() &&
82 selected_pref_store_->IsInitializationComplete();
85 bool SegregatedPrefStore::IsInitializationSuccessful() const {
86 return default_observer_.initialization_succeeded() &&
87 selected_observer_.initialization_succeeded();
90 bool SegregatedPrefStore::GetValue(base::StringPiece key,
91 const base::Value** result) const {
92 return StoreForKey(key)->GetValue(key, result);
95 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));
109 void SegregatedPrefStore::SetValue(const std::string& key,
112 StoreForKey(key)->SetValue(key, std::move(value), flags);
115 void SegregatedPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
116 StoreForKey(key)->RemoveValue(key, flags);
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);
127 bool SegregatedPrefStore::GetMutableValue(const std::string& key,
128 base::Value** result) {
129 return StoreForKey(key)->GetMutableValue(key, result);
132 void SegregatedPrefStore::ReportValueChanged(const std::string& key,
134 StoreForKey(key)->ReportValueChanged(key, flags);
137 void SegregatedPrefStore::SetValueSilently(const std::string& key,
140 StoreForKey(key)->SetValueSilently(key, std::move(value), flags);
143 bool SegregatedPrefStore::ReadOnly() const {
144 return selected_pref_store_->ReadOnly() || default_pref_store_->ReadOnly();
147 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;
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);
170 return GetReadError();
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);
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.
187 base::RepeatingClosure reply_callback_wrapper =
188 reply_callback ? base::BarrierClosure(2, std::move(reply_callback))
189 : base::RepeatingClosure();
191 base::RepeatingClosure synchronous_callback_wrapper =
192 synchronous_done_callback
193 ? base::BarrierClosure(2, std::move(synchronous_done_callback))
194 : base::RepeatingClosure();
196 default_pref_store_->CommitPendingWrite(reply_callback_wrapper,
197 synchronous_callback_wrapper);
198 selected_pref_store_->CommitPendingWrite(reply_callback_wrapper,
199 synchronous_callback_wrapper);
202 void SegregatedPrefStore::SchedulePendingLossyWrites() {
203 default_pref_store_->SchedulePendingLossyWrites();
204 selected_pref_store_->SchedulePendingLossyWrites();
207 void SegregatedPrefStore::OnStoreDeletionFromDisk() {
208 default_pref_store_->OnStoreDeletionFromDisk();
209 selected_pref_store_->OnStoreDeletionFromDisk();
212 SegregatedPrefStore::~SegregatedPrefStore() {
213 default_pref_store_->RemoveObserver(&default_observer_);
214 selected_pref_store_->RemoveObserver(&selected_observer_);
217 PersistentPrefStore* SegregatedPrefStore::StoreForKey(base::StringPiece key) {
218 return (base::Contains(selected_preference_names_, key) ? selected_pref_store_
219 : default_pref_store_)
223 const PersistentPrefStore* SegregatedPrefStore::StoreForKey(
224 base::StringPiece key) const {
225 return (base::Contains(selected_preference_names_, key) ? selected_pref_store_
226 : default_pref_store_)