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.
5 #include "components/prefs/pref_value_store.h"
10 #include "base/logging.h"
11 #include "base/strings/string_piece.h"
12 #include "components/prefs/pref_notifier.h"
13 #include "components/prefs/pref_observer.h"
15 PrefValueStore::PrefStoreKeeper::PrefStoreKeeper()
16 : pref_value_store_(nullptr), type_(PrefValueStore::INVALID_STORE) {}
18 PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() {
20 pref_store_->RemoveObserver(this);
21 pref_store_ = nullptr;
23 pref_value_store_ = nullptr;
26 void PrefValueStore::PrefStoreKeeper::Initialize(
27 PrefValueStore* store,
28 PrefStore* pref_store,
29 PrefValueStore::PrefStoreType type) {
31 pref_store_->RemoveObserver(this);
32 DCHECK(!pref_store_->HasObservers());
35 pref_value_store_ = store;
36 pref_store_ = pref_store;
38 pref_store_->AddObserver(this);
41 void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged(
42 const std::string& key) {
43 pref_value_store_->OnPrefValueChanged(type_, key);
46 void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted(
48 pref_value_store_->OnInitializationCompleted(type_, succeeded);
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);
70 CheckInitializationCompleted();
73 PrefValueStore::~PrefValueStore() {}
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);
87 managed_prefs = GetPrefStore(MANAGED_STORE);
88 if (!supervised_user_prefs)
89 supervised_user_prefs = GetPrefStore(SUPERVISED_USER_STORE);
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);
97 user_prefs = GetPrefStore(USER_STORE);
98 if (!recommended_prefs)
99 recommended_prefs = GetPrefStore(RECOMMENDED_STORE);
101 default_prefs = GetPrefStore(DEFAULT_STORE);
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);
109 bool PrefValueStore::GetValue(base::StringPiece name,
110 base::Value::Type type,
111 const base::Value** out_value) const {
112 // Check the |PrefStore|s in order of their priority from highest to lowest,
113 // looking for the first preference value with the given |name| and |type|.
114 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
115 if (GetValueFromStoreWithType(name, type, static_cast<PrefStoreType>(i),
122 bool PrefValueStore::GetRecommendedValue(const std::string& name,
123 base::Value::Type type,
124 const base::Value** out_value) const {
125 return GetValueFromStoreWithType(name, type, RECOMMENDED_STORE, out_value);
128 void PrefValueStore::NotifyPrefChanged(
129 const std::string& path,
130 PrefValueStore::PrefStoreType new_store) {
131 DCHECK(new_store != INVALID_STORE);
132 // A notification is sent when the pref value in any store changes. If this
133 // store is currently being overridden by a higher-priority store, the
134 // effective value of the pref will not have changed.
135 pref_notifier_->OnPreferenceChanged(path);
136 if (!pref_changed_callback_.is_null())
137 pref_changed_callback_.Run(path);
140 bool PrefValueStore::PrefValueInManagedStore(const std::string& name) const {
141 return PrefValueInStore(name, MANAGED_STORE);
144 bool PrefValueStore::PrefValueInSupervisedStore(const std::string& name) const {
145 return PrefValueInStore(name, SUPERVISED_USER_STORE);
148 bool PrefValueStore::PrefValueInExtensionStore(const std::string& name) const {
149 return PrefValueInStore(name, EXTENSION_STORE);
152 bool PrefValueStore::PrefValueInUserStore(const std::string& name) const {
153 return PrefValueInStore(name, USER_STORE);
156 bool PrefValueStore::PrefValueFromExtensionStore(
157 const std::string& name) const {
158 return ControllingPrefStoreForPref(name) == EXTENSION_STORE;
161 bool PrefValueStore::PrefValueFromUserStore(const std::string& name) const {
162 return ControllingPrefStoreForPref(name) == USER_STORE;
165 bool PrefValueStore::PrefValueFromRecommendedStore(
166 const std::string& name) const {
167 return ControllingPrefStoreForPref(name) == RECOMMENDED_STORE;
170 bool PrefValueStore::PrefValueFromStandaloneBrowserStore(
171 const std::string& name) const {
172 return ControllingPrefStoreForPref(name) == STANDALONE_BROWSER_STORE;
175 bool PrefValueStore::PrefValueFromDefaultStore(const std::string& name) const {
176 return ControllingPrefStoreForPref(name) == DEFAULT_STORE;
179 bool PrefValueStore::PrefValueUserModifiable(const std::string& name) const {
180 PrefStoreType effective_store = ControllingPrefStoreForPref(name);
181 return effective_store >= USER_STORE ||
182 effective_store == INVALID_STORE;
185 bool PrefValueStore::PrefValueExtensionModifiable(
186 const std::string& name) const {
187 PrefStoreType effective_store = ControllingPrefStoreForPref(name);
188 return effective_store >= EXTENSION_STORE ||
189 effective_store == INVALID_STORE;
192 bool PrefValueStore::PrefValueStandaloneBrowserModifiable(
193 const std::string& name) const {
194 PrefStoreType effective_store = ControllingPrefStoreForPref(name);
195 return effective_store >= STANDALONE_BROWSER_STORE ||
196 effective_store == INVALID_STORE;
199 void PrefValueStore::UpdateCommandLinePrefStore(PrefStore* command_line_prefs) {
200 InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
203 bool PrefValueStore::IsInitializationComplete() const {
204 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
205 const PrefStore* pref_store = GetPrefStore(static_cast<PrefStoreType>(i));
206 if (pref_store && !pref_store->IsInitializationComplete())
212 bool PrefValueStore::PrefValueInStore(
213 const std::string& name,
214 PrefValueStore::PrefStoreType store) const {
215 // Declare a temp Value* and call GetValueFromStore,
216 // ignoring the output value.
217 const base::Value* tmp_value = nullptr;
218 return GetValueFromStore(name, store, &tmp_value);
221 bool PrefValueStore::PrefValueInStoreRange(
222 const std::string& name,
223 PrefValueStore::PrefStoreType first_checked_store,
224 PrefValueStore::PrefStoreType last_checked_store) const {
225 if (first_checked_store > last_checked_store) {
230 for (size_t i = first_checked_store;
231 i <= static_cast<size_t>(last_checked_store); ++i) {
232 if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
238 PrefValueStore::PrefStoreType PrefValueStore::ControllingPrefStoreForPref(
239 const std::string& name) const {
240 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
241 if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
242 return static_cast<PrefStoreType>(i);
244 return INVALID_STORE;
247 bool PrefValueStore::GetValueFromStore(base::StringPiece name,
248 PrefValueStore::PrefStoreType store_type,
249 const base::Value** out_value) const {
250 // Only return true if we find a value and it is the correct type, so stale
251 // values with the incorrect type will be ignored.
252 const PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(store_type));
253 if (store && store->GetValue(name, out_value))
256 // No valid value found for the given preference name: set the return value
258 *out_value = nullptr;
262 bool PrefValueStore::GetValueFromStoreWithType(
263 base::StringPiece name,
264 base::Value::Type type,
266 const base::Value** out_value) const {
267 if (GetValueFromStore(name, store, out_value)) {
268 if ((*out_value)->type() == type)
271 LOG(WARNING) << "Expected type for " << name << " is " << type
272 << " but got " << (*out_value)->type() << " in store "
276 *out_value = nullptr;
280 void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type,
281 const std::string& key) {
282 NotifyPrefChanged(key, type);
285 void PrefValueStore::OnInitializationCompleted(
286 PrefValueStore::PrefStoreType type, bool succeeded) {
287 if (initialization_failed_)
290 initialization_failed_ = true;
291 pref_notifier_->OnInitializationCompleted(false);
294 CheckInitializationCompleted();
297 void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type,
298 PrefStore* pref_store) {
299 pref_stores_[type].Initialize(this, pref_store, type);
302 void PrefValueStore::CheckInitializationCompleted() {
303 if (initialization_failed_)
305 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
306 scoped_refptr<PrefStore> store =
307 GetPrefStore(static_cast<PrefStoreType>(i));
308 if (store.get() && !store->IsInitializationComplete())
311 pref_notifier_->OnInitializationCompleted(true);