1 // Copyright 2012 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/pref_value_store.h"
6
7 #include <stddef.h>
8
9 #include <string>
10 #include <string_view>
11
12 #include "base/logging.h"
13 #include "components/prefs/pref_notifier.h"
14 #include "components/prefs/pref_observer.h"
15
PrefStoreKeeper()16 PrefValueStore::PrefStoreKeeper::PrefStoreKeeper()
17 : pref_value_store_(nullptr), type_(PrefValueStore::INVALID_STORE) {}
18
~PrefStoreKeeper()19 PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() {
20 if (pref_store_) {
21 pref_store_->RemoveObserver(this);
22 pref_store_ = nullptr;
23 }
24 pref_value_store_ = nullptr;
25 }
26
Initialize(PrefValueStore * store,PrefStore * pref_store,PrefValueStore::PrefStoreType type)27 void PrefValueStore::PrefStoreKeeper::Initialize(
28 PrefValueStore* store,
29 PrefStore* pref_store,
30 PrefValueStore::PrefStoreType type) {
31 if (pref_store_) {
32 pref_store_->RemoveObserver(this);
33 DCHECK(!pref_store_->HasObservers());
34 }
35 type_ = type;
36 pref_value_store_ = store;
37 pref_store_ = pref_store;
38 if (pref_store_)
39 pref_store_->AddObserver(this);
40 }
41
OnPrefValueChanged(std::string_view key)42 void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged(std::string_view key) {
43 pref_value_store_->OnPrefValueChanged(type_, key);
44 }
45
OnInitializationCompleted(bool succeeded)46 void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted(
47 bool succeeded) {
48 pref_value_store_->OnInitializationCompleted(type_, succeeded);
49 }
50
PrefValueStore(PrefStore * managed_prefs,PrefStore * supervised_user_prefs,PrefStore * extension_prefs,PrefStore * standalone_browser_prefs,PrefStore * command_line_prefs,PrefStore * user_prefs,PrefStore * recommended_prefs,PrefStore * default_prefs,PrefNotifier * pref_notifier)51 PrefValueStore::PrefValueStore(PrefStore* managed_prefs,
52 PrefStore* supervised_user_prefs,
53 PrefStore* extension_prefs,
54 PrefStore* standalone_browser_prefs,
55 PrefStore* command_line_prefs,
56 PrefStore* user_prefs,
57 PrefStore* recommended_prefs,
58 PrefStore* default_prefs,
59 PrefNotifier* pref_notifier)
60 : pref_notifier_(pref_notifier), initialization_failed_(false) {
61 InitPrefStore(MANAGED_STORE, managed_prefs);
62 InitPrefStore(SUPERVISED_USER_STORE, supervised_user_prefs);
63 InitPrefStore(EXTENSION_STORE, extension_prefs);
64 InitPrefStore(STANDALONE_BROWSER_STORE, standalone_browser_prefs);
65 InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
66 InitPrefStore(USER_STORE, user_prefs);
67 InitPrefStore(RECOMMENDED_STORE, recommended_prefs);
68 InitPrefStore(DEFAULT_STORE, default_prefs);
69
70 CheckInitializationCompleted();
71 }
72
73 PrefValueStore::~PrefValueStore() = default;
74
CloneAndSpecialize(PrefStore * managed_prefs,PrefStore * supervised_user_prefs,PrefStore * extension_prefs,PrefStore * standalone_browser_prefs,PrefStore * command_line_prefs,PrefStore * user_prefs,PrefStore * recommended_prefs,PrefStore * default_prefs,PrefNotifier * pref_notifier)75 std::unique_ptr<PrefValueStore> PrefValueStore::CloneAndSpecialize(
76 PrefStore* managed_prefs,
77 PrefStore* supervised_user_prefs,
78 PrefStore* extension_prefs,
79 PrefStore* standalone_browser_prefs,
80 PrefStore* command_line_prefs,
81 PrefStore* user_prefs,
82 PrefStore* recommended_prefs,
83 PrefStore* default_prefs,
84 PrefNotifier* pref_notifier) {
85 DCHECK(pref_notifier);
86 if (!managed_prefs)
87 managed_prefs = GetPrefStore(MANAGED_STORE);
88 if (!supervised_user_prefs)
89 supervised_user_prefs = GetPrefStore(SUPERVISED_USER_STORE);
90 if (!extension_prefs)
91 extension_prefs = GetPrefStore(EXTENSION_STORE);
92 if (!standalone_browser_prefs)
93 standalone_browser_prefs = GetPrefStore(STANDALONE_BROWSER_STORE);
94 if (!command_line_prefs)
95 command_line_prefs = GetPrefStore(COMMAND_LINE_STORE);
96 if (!user_prefs)
97 user_prefs = GetPrefStore(USER_STORE);
98 if (!recommended_prefs)
99 recommended_prefs = GetPrefStore(RECOMMENDED_STORE);
100 if (!default_prefs)
101 default_prefs = GetPrefStore(DEFAULT_STORE);
102
103 return std::make_unique<PrefValueStore>(
104 managed_prefs, supervised_user_prefs, extension_prefs,
105 standalone_browser_prefs, command_line_prefs, user_prefs,
106 recommended_prefs, default_prefs, pref_notifier);
107 }
108
ControllingPrefStoreForPref(const std::string & name) const109 PrefValueStore::PrefStoreType PrefValueStore::ControllingPrefStoreForPref(
110 const std::string& name) const {
111 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
112 if (PrefValueInStore(name, static_cast<PrefStoreType>(i))) {
113 return static_cast<PrefStoreType>(i);
114 }
115 }
116 return INVALID_STORE;
117 }
118
GetValue(std::string_view name,base::Value::Type type,const base::Value ** out_value) const119 bool PrefValueStore::GetValue(std::string_view name,
120 base::Value::Type type,
121 const base::Value** out_value) const {
122 // Check the |PrefStore|s in order of their priority from highest to lowest,
123 // looking for the first preference value with the given |name| and |type|.
124 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
125 if (GetValueFromStoreWithType(name, type, static_cast<PrefStoreType>(i),
126 out_value))
127 return true;
128 }
129 return false;
130 }
131
GetRecommendedValue(const std::string & name,base::Value::Type type,const base::Value ** out_value) const132 bool PrefValueStore::GetRecommendedValue(const std::string& name,
133 base::Value::Type type,
134 const base::Value** out_value) const {
135 return GetValueFromStoreWithType(name, type, RECOMMENDED_STORE, out_value);
136 }
137
NotifyPrefChanged(std::string_view path,PrefValueStore::PrefStoreType new_store)138 void PrefValueStore::NotifyPrefChanged(
139 std::string_view path,
140 PrefValueStore::PrefStoreType new_store) {
141 DCHECK(new_store != INVALID_STORE);
142 // A notification is sent when the pref value in any store changes. If this
143 // store is currently being overridden by a higher-priority store, the
144 // effective value of the pref will not have changed.
145 pref_notifier_->OnPreferenceChanged(path);
146 }
147
PrefValueInManagedStore(const std::string & name) const148 bool PrefValueStore::PrefValueInManagedStore(const std::string& name) const {
149 return PrefValueInStore(name, MANAGED_STORE);
150 }
151
PrefValueInSupervisedStore(const std::string & name) const152 bool PrefValueStore::PrefValueInSupervisedStore(const std::string& name) const {
153 return PrefValueInStore(name, SUPERVISED_USER_STORE);
154 }
155
PrefValueInExtensionStore(const std::string & name) const156 bool PrefValueStore::PrefValueInExtensionStore(const std::string& name) const {
157 return PrefValueInStore(name, EXTENSION_STORE);
158 }
159
PrefValueInUserStore(const std::string & name) const160 bool PrefValueStore::PrefValueInUserStore(const std::string& name) const {
161 return PrefValueInStore(name, USER_STORE);
162 }
163
PrefValueFromExtensionStore(const std::string & name) const164 bool PrefValueStore::PrefValueFromExtensionStore(
165 const std::string& name) const {
166 return ControllingPrefStoreForPref(name) == EXTENSION_STORE;
167 }
168
PrefValueFromUserStore(const std::string & name) const169 bool PrefValueStore::PrefValueFromUserStore(const std::string& name) const {
170 return ControllingPrefStoreForPref(name) == USER_STORE;
171 }
172
PrefValueFromRecommendedStore(const std::string & name) const173 bool PrefValueStore::PrefValueFromRecommendedStore(
174 const std::string& name) const {
175 return ControllingPrefStoreForPref(name) == RECOMMENDED_STORE;
176 }
177
PrefValueFromStandaloneBrowserStore(const std::string & name) const178 bool PrefValueStore::PrefValueFromStandaloneBrowserStore(
179 const std::string& name) const {
180 return ControllingPrefStoreForPref(name) == STANDALONE_BROWSER_STORE;
181 }
182
PrefValueFromDefaultStore(const std::string & name) const183 bool PrefValueStore::PrefValueFromDefaultStore(const std::string& name) const {
184 return ControllingPrefStoreForPref(name) == DEFAULT_STORE;
185 }
186
PrefValueUserModifiable(const std::string & name) const187 bool PrefValueStore::PrefValueUserModifiable(const std::string& name) const {
188 PrefStoreType effective_store = ControllingPrefStoreForPref(name);
189 return effective_store >= USER_STORE ||
190 effective_store == INVALID_STORE;
191 }
192
PrefValueExtensionModifiable(const std::string & name) const193 bool PrefValueStore::PrefValueExtensionModifiable(
194 const std::string& name) const {
195 PrefStoreType effective_store = ControllingPrefStoreForPref(name);
196 return effective_store >= EXTENSION_STORE ||
197 effective_store == INVALID_STORE;
198 }
199
PrefValueStandaloneBrowserModifiable(const std::string & name) const200 bool PrefValueStore::PrefValueStandaloneBrowserModifiable(
201 const std::string& name) const {
202 PrefStoreType effective_store = ControllingPrefStoreForPref(name);
203 return effective_store >= STANDALONE_BROWSER_STORE ||
204 effective_store == INVALID_STORE;
205 }
206
UpdateCommandLinePrefStore(PrefStore * command_line_prefs)207 void PrefValueStore::UpdateCommandLinePrefStore(PrefStore* command_line_prefs) {
208 InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
209 }
210
IsInitializationComplete() const211 bool PrefValueStore::IsInitializationComplete() const {
212 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
213 const PrefStore* pref_store = GetPrefStore(static_cast<PrefStoreType>(i));
214 if (pref_store && !pref_store->IsInitializationComplete()) {
215 return false;
216 }
217 }
218 return true;
219 }
220
PrefValueInStore(const std::string & name,PrefValueStore::PrefStoreType store) const221 bool PrefValueStore::PrefValueInStore(
222 const std::string& name,
223 PrefValueStore::PrefStoreType store) const {
224 // Declare a temp Value* and call GetValueFromStore,
225 // ignoring the output value.
226 const base::Value* tmp_value = nullptr;
227 return GetValueFromStore(name, store, &tmp_value);
228 }
229
PrefValueInStoreRange(const std::string & name,PrefValueStore::PrefStoreType first_checked_store,PrefValueStore::PrefStoreType last_checked_store) const230 bool PrefValueStore::PrefValueInStoreRange(
231 const std::string& name,
232 PrefValueStore::PrefStoreType first_checked_store,
233 PrefValueStore::PrefStoreType last_checked_store) const {
234 if (first_checked_store > last_checked_store) {
235 NOTREACHED();
236 }
237
238 for (size_t i = first_checked_store;
239 i <= static_cast<size_t>(last_checked_store); ++i) {
240 if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
241 return true;
242 }
243 return false;
244 }
245
GetValueFromStore(std::string_view name,PrefValueStore::PrefStoreType store_type,const base::Value ** out_value) const246 bool PrefValueStore::GetValueFromStore(std::string_view name,
247 PrefValueStore::PrefStoreType store_type,
248 const base::Value** out_value) const {
249 // Only return true if we find a value and it is the correct type, so stale
250 // values with the incorrect type will be ignored.
251 const PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(store_type));
252 if (store && store->GetValue(name, out_value))
253 return true;
254
255 // No valid value found for the given preference name: set the return value
256 // to false.
257 *out_value = nullptr;
258 return false;
259 }
260
GetValueFromStoreWithType(std::string_view name,base::Value::Type type,PrefStoreType store,const base::Value ** out_value) const261 bool PrefValueStore::GetValueFromStoreWithType(
262 std::string_view name,
263 base::Value::Type type,
264 PrefStoreType store,
265 const base::Value** out_value) const {
266 if (GetValueFromStore(name, store, out_value)) {
267 if ((*out_value)->type() == type)
268 return true;
269
270 LOG(WARNING) << "Expected type for " << name << " is " << type
271 << " but got " << (*out_value)->type() << " in store "
272 << store;
273 }
274
275 *out_value = nullptr;
276 return false;
277 }
278
OnPrefValueChanged(PrefValueStore::PrefStoreType type,std::string_view key)279 void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type,
280 std::string_view key) {
281 NotifyPrefChanged(key, type);
282 }
283
OnInitializationCompleted(PrefValueStore::PrefStoreType type,bool succeeded)284 void PrefValueStore::OnInitializationCompleted(
285 PrefValueStore::PrefStoreType type, bool succeeded) {
286 if (initialization_failed_)
287 return;
288 if (!succeeded) {
289 initialization_failed_ = true;
290 pref_notifier_->OnInitializationCompleted(false);
291 return;
292 }
293 CheckInitializationCompleted();
294 }
295
InitPrefStore(PrefValueStore::PrefStoreType type,PrefStore * pref_store)296 void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type,
297 PrefStore* pref_store) {
298 pref_stores_[type].Initialize(this, pref_store, type);
299 }
300
CheckInitializationCompleted()301 void PrefValueStore::CheckInitializationCompleted() {
302 if (initialization_failed_)
303 return;
304 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
305 scoped_refptr<PrefStore> store =
306 GetPrefStore(static_cast<PrefStoreType>(i));
307 if (store.get() && !store->IsInitializationComplete())
308 return;
309 }
310 pref_notifier_->OnInitializationCompleted(true);
311 }
312