1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/prefs/pref_value_store.h"
7 #include "base/logging.h"
8 #include "base/prefs/pref_notifier.h"
9 #include "base/prefs/pref_observer.h"
11 PrefValueStore::PrefStoreKeeper::PrefStoreKeeper()
12 : pref_value_store_(NULL
),
13 type_(PrefValueStore::INVALID_STORE
) {
16 PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() {
17 if (pref_store_
.get()) {
18 pref_store_
->RemoveObserver(this);
21 pref_value_store_
= NULL
;
24 void PrefValueStore::PrefStoreKeeper::Initialize(
25 PrefValueStore
* store
,
26 PrefStore
* pref_store
,
27 PrefValueStore::PrefStoreType type
) {
28 if (pref_store_
.get()) {
29 pref_store_
->RemoveObserver(this);
30 DCHECK(!pref_store_
->HasObservers());
33 pref_value_store_
= store
;
34 pref_store_
= pref_store
;
35 if (pref_store_
.get())
36 pref_store_
->AddObserver(this);
39 void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged(
40 const std::string
& key
) {
41 pref_value_store_
->OnPrefValueChanged(type_
, key
);
44 void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted(
46 pref_value_store_
->OnInitializationCompleted(type_
, succeeded
);
49 PrefValueStore::PrefValueStore(PrefStore
* managed_prefs
,
50 PrefStore
* supervised_user_prefs
,
51 PrefStore
* extension_prefs
,
52 PrefStore
* command_line_prefs
,
53 PrefStore
* user_prefs
,
54 PrefStore
* recommended_prefs
,
55 PrefStore
* default_prefs
,
56 PrefNotifier
* pref_notifier
)
57 : pref_notifier_(pref_notifier
),
58 initialization_failed_(false) {
59 InitPrefStore(MANAGED_STORE
, managed_prefs
);
60 InitPrefStore(SUPERVISED_USER_STORE
, supervised_user_prefs
);
61 InitPrefStore(EXTENSION_STORE
, extension_prefs
);
62 InitPrefStore(COMMAND_LINE_STORE
, command_line_prefs
);
63 InitPrefStore(USER_STORE
, user_prefs
);
64 InitPrefStore(RECOMMENDED_STORE
, recommended_prefs
);
65 InitPrefStore(DEFAULT_STORE
, default_prefs
);
67 CheckInitializationCompleted();
70 PrefValueStore::~PrefValueStore() {}
72 PrefValueStore
* PrefValueStore::CloneAndSpecialize(
73 PrefStore
* managed_prefs
,
74 PrefStore
* supervised_user_prefs
,
75 PrefStore
* extension_prefs
,
76 PrefStore
* command_line_prefs
,
77 PrefStore
* user_prefs
,
78 PrefStore
* recommended_prefs
,
79 PrefStore
* default_prefs
,
80 PrefNotifier
* pref_notifier
) {
81 DCHECK(pref_notifier
);
83 managed_prefs
= GetPrefStore(MANAGED_STORE
);
84 if (!supervised_user_prefs
)
85 supervised_user_prefs
= GetPrefStore(SUPERVISED_USER_STORE
);
87 extension_prefs
= GetPrefStore(EXTENSION_STORE
);
88 if (!command_line_prefs
)
89 command_line_prefs
= GetPrefStore(COMMAND_LINE_STORE
);
91 user_prefs
= GetPrefStore(USER_STORE
);
92 if (!recommended_prefs
)
93 recommended_prefs
= GetPrefStore(RECOMMENDED_STORE
);
95 default_prefs
= GetPrefStore(DEFAULT_STORE
);
97 return new PrefValueStore(
98 managed_prefs
, supervised_user_prefs
, extension_prefs
, command_line_prefs
,
99 user_prefs
, recommended_prefs
, default_prefs
, pref_notifier
);
102 void PrefValueStore::set_callback(const PrefChangedCallback
& callback
) {
103 pref_changed_callback_
= callback
;
106 bool PrefValueStore::GetValue(const std::string
& name
,
107 base::Value::Type type
,
108 const base::Value
** out_value
) const {
109 // Check the |PrefStore|s in order of their priority from highest to lowest,
110 // looking for the first preference value with the given |name| and |type|.
111 for (size_t i
= 0; i
<= PREF_STORE_TYPE_MAX
; ++i
) {
112 if (GetValueFromStoreWithType(name
, type
, static_cast<PrefStoreType
>(i
),
119 bool PrefValueStore::GetRecommendedValue(const std::string
& name
,
120 base::Value::Type type
,
121 const base::Value
** out_value
) const {
122 return GetValueFromStoreWithType(name
, type
, RECOMMENDED_STORE
, out_value
);
125 void PrefValueStore::NotifyPrefChanged(
126 const std::string
& path
,
127 PrefValueStore::PrefStoreType new_store
) {
128 DCHECK(new_store
!= INVALID_STORE
);
129 // A notification is sent when the pref value in any store changes. If this
130 // store is currently being overridden by a higher-priority store, the
131 // effective value of the pref will not have changed.
132 pref_notifier_
->OnPreferenceChanged(path
);
133 if (!pref_changed_callback_
.is_null())
134 pref_changed_callback_
.Run(path
);
137 bool PrefValueStore::PrefValueInManagedStore(const std::string
& name
) const {
138 return PrefValueInStore(name
, MANAGED_STORE
);
141 bool PrefValueStore::PrefValueInSupervisedStore(const std::string
& name
) const {
142 return PrefValueInStore(name
, SUPERVISED_USER_STORE
);
145 bool PrefValueStore::PrefValueInExtensionStore(const std::string
& name
) const {
146 return PrefValueInStore(name
, EXTENSION_STORE
);
149 bool PrefValueStore::PrefValueInUserStore(const std::string
& name
) const {
150 return PrefValueInStore(name
, USER_STORE
);
153 bool PrefValueStore::PrefValueFromExtensionStore(
154 const std::string
& name
) const {
155 return ControllingPrefStoreForPref(name
) == EXTENSION_STORE
;
158 bool PrefValueStore::PrefValueFromUserStore(const std::string
& name
) const {
159 return ControllingPrefStoreForPref(name
) == USER_STORE
;
162 bool PrefValueStore::PrefValueFromRecommendedStore(
163 const std::string
& name
) const {
164 return ControllingPrefStoreForPref(name
) == RECOMMENDED_STORE
;
167 bool PrefValueStore::PrefValueFromDefaultStore(const std::string
& name
) const {
168 return ControllingPrefStoreForPref(name
) == DEFAULT_STORE
;
171 bool PrefValueStore::PrefValueUserModifiable(const std::string
& name
) const {
172 PrefStoreType effective_store
= ControllingPrefStoreForPref(name
);
173 return effective_store
>= USER_STORE
||
174 effective_store
== INVALID_STORE
;
177 bool PrefValueStore::PrefValueExtensionModifiable(
178 const std::string
& name
) const {
179 PrefStoreType effective_store
= ControllingPrefStoreForPref(name
);
180 return effective_store
>= EXTENSION_STORE
||
181 effective_store
== INVALID_STORE
;
184 void PrefValueStore::UpdateCommandLinePrefStore(PrefStore
* command_line_prefs
) {
185 InitPrefStore(COMMAND_LINE_STORE
, command_line_prefs
);
188 bool PrefValueStore::PrefValueInStore(
189 const std::string
& name
,
190 PrefValueStore::PrefStoreType store
) const {
191 // Declare a temp Value* and call GetValueFromStore,
192 // ignoring the output value.
193 const base::Value
* tmp_value
= NULL
;
194 return GetValueFromStore(name
, store
, &tmp_value
);
197 bool PrefValueStore::PrefValueInStoreRange(
198 const std::string
& name
,
199 PrefValueStore::PrefStoreType first_checked_store
,
200 PrefValueStore::PrefStoreType last_checked_store
) const {
201 if (first_checked_store
> last_checked_store
) {
206 for (size_t i
= first_checked_store
;
207 i
<= static_cast<size_t>(last_checked_store
); ++i
) {
208 if (PrefValueInStore(name
, static_cast<PrefStoreType
>(i
)))
214 PrefValueStore::PrefStoreType
PrefValueStore::ControllingPrefStoreForPref(
215 const std::string
& name
) const {
216 for (size_t i
= 0; i
<= PREF_STORE_TYPE_MAX
; ++i
) {
217 if (PrefValueInStore(name
, static_cast<PrefStoreType
>(i
)))
218 return static_cast<PrefStoreType
>(i
);
220 return INVALID_STORE
;
223 bool PrefValueStore::GetValueFromStore(const std::string
& name
,
224 PrefValueStore::PrefStoreType store_type
,
225 const base::Value
** out_value
) const {
226 // Only return true if we find a value and it is the correct type, so stale
227 // values with the incorrect type will be ignored.
228 const PrefStore
* store
= GetPrefStore(static_cast<PrefStoreType
>(store_type
));
229 if (store
&& store
->GetValue(name
, out_value
))
232 // No valid value found for the given preference name: set the return value
238 bool PrefValueStore::GetValueFromStoreWithType(
239 const std::string
& name
,
240 base::Value::Type type
,
242 const base::Value
** out_value
) const {
243 if (GetValueFromStore(name
, store
, out_value
)) {
244 if ((*out_value
)->IsType(type
))
247 LOG(WARNING
) << "Expected type for " << name
<< " is " << type
248 << " but got " << (*out_value
)->GetType()
249 << " in store " << store
;
256 void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type
,
257 const std::string
& key
) {
258 NotifyPrefChanged(key
, type
);
261 void PrefValueStore::OnInitializationCompleted(
262 PrefValueStore::PrefStoreType type
, bool succeeded
) {
263 if (initialization_failed_
)
266 initialization_failed_
= true;
267 pref_notifier_
->OnInitializationCompleted(false);
270 CheckInitializationCompleted();
273 void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type
,
274 PrefStore
* pref_store
) {
275 pref_stores_
[type
].Initialize(this, pref_store
, type
);
278 void PrefValueStore::CheckInitializationCompleted() {
279 if (initialization_failed_
)
281 for (size_t i
= 0; i
<= PREF_STORE_TYPE_MAX
; ++i
) {
282 scoped_refptr
<PrefStore
> store
=
283 GetPrefStore(static_cast<PrefStoreType
>(i
));
284 if (store
.get() && !store
->IsInitializationComplete())
287 pref_notifier_
->OnInitializationCompleted(true);