• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "base/prefs/pref_value_store.h"
6 
7 #include "base/logging.h"
8 #include "base/prefs/pref_notifier.h"
9 #include "base/prefs/pref_observer.h"
10 
PrefStoreKeeper()11 PrefValueStore::PrefStoreKeeper::PrefStoreKeeper()
12     : pref_value_store_(NULL),
13       type_(PrefValueStore::INVALID_STORE) {
14 }
15 
~PrefStoreKeeper()16 PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() {
17   if (pref_store_.get()) {
18     pref_store_->RemoveObserver(this);
19     pref_store_ = NULL;
20   }
21   pref_value_store_ = NULL;
22 }
23 
Initialize(PrefValueStore * store,PrefStore * pref_store,PrefValueStore::PrefStoreType type)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());
31   }
32   type_ = type;
33   pref_value_store_ = store;
34   pref_store_ = pref_store;
35   if (pref_store_.get())
36     pref_store_->AddObserver(this);
37 }
38 
OnPrefValueChanged(const std::string & key)39 void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged(
40     const std::string& key) {
41   pref_value_store_->OnPrefValueChanged(type_, key);
42 }
43 
OnInitializationCompleted(bool succeeded)44 void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted(
45     bool succeeded) {
46   pref_value_store_->OnInitializationCompleted(type_, succeeded);
47 }
48 
PrefValueStore(PrefStore * managed_prefs,PrefStore * supervised_user_prefs,PrefStore * extension_prefs,PrefStore * command_line_prefs,PrefStore * user_prefs,PrefStore * recommended_prefs,PrefStore * default_prefs,PrefNotifier * pref_notifier)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);
66 
67   CheckInitializationCompleted();
68 }
69 
~PrefValueStore()70 PrefValueStore::~PrefValueStore() {}
71 
CloneAndSpecialize(PrefStore * managed_prefs,PrefStore * supervised_user_prefs,PrefStore * extension_prefs,PrefStore * command_line_prefs,PrefStore * user_prefs,PrefStore * recommended_prefs,PrefStore * default_prefs,PrefNotifier * pref_notifier)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);
82   if (!managed_prefs)
83     managed_prefs = GetPrefStore(MANAGED_STORE);
84   if (!supervised_user_prefs)
85     supervised_user_prefs = GetPrefStore(SUPERVISED_USER_STORE);
86   if (!extension_prefs)
87     extension_prefs = GetPrefStore(EXTENSION_STORE);
88   if (!command_line_prefs)
89     command_line_prefs = GetPrefStore(COMMAND_LINE_STORE);
90   if (!user_prefs)
91     user_prefs = GetPrefStore(USER_STORE);
92   if (!recommended_prefs)
93     recommended_prefs = GetPrefStore(RECOMMENDED_STORE);
94   if (!default_prefs)
95     default_prefs = GetPrefStore(DEFAULT_STORE);
96 
97   return new PrefValueStore(
98       managed_prefs, supervised_user_prefs, extension_prefs, command_line_prefs,
99       user_prefs, recommended_prefs, default_prefs, pref_notifier);
100 }
101 
set_callback(const PrefChangedCallback & callback)102 void PrefValueStore::set_callback(const PrefChangedCallback& callback) {
103   pref_changed_callback_ = callback;
104 }
105 
GetValue(const std::string & name,base::Value::Type type,const base::Value ** out_value) const106 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.c_str(), type,
113                                   static_cast<PrefStoreType>(i), out_value))
114       return true;
115   }
116   return false;
117 }
118 
GetRecommendedValue(const std::string & name,base::Value::Type type,const base::Value ** out_value) const119 bool PrefValueStore::GetRecommendedValue(const std::string& name,
120                                          base::Value::Type type,
121                                          const base::Value** out_value) const {
122   return GetValueFromStoreWithType(name.c_str(), type, RECOMMENDED_STORE,
123                                    out_value);
124 }
125 
NotifyPrefChanged(const char * path,PrefValueStore::PrefStoreType new_store)126 void PrefValueStore::NotifyPrefChanged(
127     const char* path,
128     PrefValueStore::PrefStoreType new_store) {
129   DCHECK(new_store != INVALID_STORE);
130   // A notification is sent when the pref value in any store changes. If this
131   // store is currently being overridden by a higher-priority store, the
132   // effective value of the pref will not have changed.
133   pref_notifier_->OnPreferenceChanged(path);
134   if (!pref_changed_callback_.is_null())
135     pref_changed_callback_.Run(path);
136 }
137 
PrefValueInManagedStore(const char * name) const138 bool PrefValueStore::PrefValueInManagedStore(const char* name) const {
139   return PrefValueInStore(name, MANAGED_STORE);
140 }
141 
PrefValueInExtensionStore(const char * name) const142 bool PrefValueStore::PrefValueInExtensionStore(const char* name) const {
143   return PrefValueInStore(name, EXTENSION_STORE);
144 }
145 
PrefValueInUserStore(const char * name) const146 bool PrefValueStore::PrefValueInUserStore(const char* name) const {
147   return PrefValueInStore(name, USER_STORE);
148 }
149 
PrefValueFromExtensionStore(const char * name) const150 bool PrefValueStore::PrefValueFromExtensionStore(const char* name) const {
151   return ControllingPrefStoreForPref(name) == EXTENSION_STORE;
152 }
153 
PrefValueFromUserStore(const char * name) const154 bool PrefValueStore::PrefValueFromUserStore(const char* name) const {
155   return ControllingPrefStoreForPref(name) == USER_STORE;
156 }
157 
PrefValueFromRecommendedStore(const char * name) const158 bool PrefValueStore::PrefValueFromRecommendedStore(const char* name) const {
159   return ControllingPrefStoreForPref(name) == RECOMMENDED_STORE;
160 }
161 
PrefValueFromDefaultStore(const char * name) const162 bool PrefValueStore::PrefValueFromDefaultStore(const char* name) const {
163   return ControllingPrefStoreForPref(name) == DEFAULT_STORE;
164 }
165 
PrefValueUserModifiable(const char * name) const166 bool PrefValueStore::PrefValueUserModifiable(const char* name) const {
167   PrefStoreType effective_store = ControllingPrefStoreForPref(name);
168   return effective_store >= USER_STORE ||
169          effective_store == INVALID_STORE;
170 }
171 
PrefValueExtensionModifiable(const char * name) const172 bool PrefValueStore::PrefValueExtensionModifiable(const char* name) const {
173   PrefStoreType effective_store = ControllingPrefStoreForPref(name);
174   return effective_store >= EXTENSION_STORE ||
175          effective_store == INVALID_STORE;
176 }
177 
UpdateCommandLinePrefStore(PrefStore * command_line_prefs)178 void PrefValueStore::UpdateCommandLinePrefStore(PrefStore* command_line_prefs) {
179   InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
180 }
181 
PrefValueInStore(const char * name,PrefValueStore::PrefStoreType store) const182 bool PrefValueStore::PrefValueInStore(
183     const char* name,
184     PrefValueStore::PrefStoreType store) const {
185   // Declare a temp Value* and call GetValueFromStore,
186   // ignoring the output value.
187   const base::Value* tmp_value = NULL;
188   return GetValueFromStore(name, store, &tmp_value);
189 }
190 
PrefValueInStoreRange(const char * name,PrefValueStore::PrefStoreType first_checked_store,PrefValueStore::PrefStoreType last_checked_store) const191 bool PrefValueStore::PrefValueInStoreRange(
192     const char* name,
193     PrefValueStore::PrefStoreType first_checked_store,
194     PrefValueStore::PrefStoreType last_checked_store) const {
195   if (first_checked_store > last_checked_store) {
196     NOTREACHED();
197     return false;
198   }
199 
200   for (size_t i = first_checked_store;
201        i <= static_cast<size_t>(last_checked_store); ++i) {
202     if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
203       return true;
204   }
205   return false;
206 }
207 
ControllingPrefStoreForPref(const char * name) const208 PrefValueStore::PrefStoreType PrefValueStore::ControllingPrefStoreForPref(
209     const char* name) const {
210   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
211     if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
212       return static_cast<PrefStoreType>(i);
213   }
214   return INVALID_STORE;
215 }
216 
GetValueFromStore(const char * name,PrefValueStore::PrefStoreType store_type,const base::Value ** out_value) const217 bool PrefValueStore::GetValueFromStore(const char* name,
218                                        PrefValueStore::PrefStoreType store_type,
219                                        const base::Value** out_value) const {
220   // Only return true if we find a value and it is the correct type, so stale
221   // values with the incorrect type will be ignored.
222   const PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(store_type));
223   if (store && store->GetValue(name, out_value))
224     return true;
225 
226   // No valid value found for the given preference name: set the return value
227   // to false.
228   *out_value = NULL;
229   return false;
230 }
231 
GetValueFromStoreWithType(const char * name,base::Value::Type type,PrefStoreType store,const base::Value ** out_value) const232 bool PrefValueStore::GetValueFromStoreWithType(
233     const char* name,
234     base::Value::Type type,
235     PrefStoreType store,
236     const base::Value** out_value) const {
237   if (GetValueFromStore(name, store, out_value)) {
238     if ((*out_value)->IsType(type))
239       return true;
240 
241     LOG(WARNING) << "Expected type for " << name << " is " << type
242                  << " but got " << (*out_value)->GetType()
243                  << " in store " << store;
244   }
245 
246   *out_value = NULL;
247   return false;
248 }
249 
OnPrefValueChanged(PrefValueStore::PrefStoreType type,const std::string & key)250 void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type,
251                                         const std::string& key) {
252   NotifyPrefChanged(key.c_str(), type);
253 }
254 
OnInitializationCompleted(PrefValueStore::PrefStoreType type,bool succeeded)255 void PrefValueStore::OnInitializationCompleted(
256     PrefValueStore::PrefStoreType type, bool succeeded) {
257   if (initialization_failed_)
258     return;
259   if (!succeeded) {
260     initialization_failed_ = true;
261     pref_notifier_->OnInitializationCompleted(false);
262     return;
263   }
264   CheckInitializationCompleted();
265 }
266 
InitPrefStore(PrefValueStore::PrefStoreType type,PrefStore * pref_store)267 void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type,
268                                    PrefStore* pref_store) {
269   pref_stores_[type].Initialize(this, pref_store, type);
270 }
271 
CheckInitializationCompleted()272 void PrefValueStore::CheckInitializationCompleted() {
273   if (initialization_failed_)
274     return;
275   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
276     scoped_refptr<PrefStore> store =
277         GetPrefStore(static_cast<PrefStoreType>(i));
278     if (store.get() && !store->IsInitializationComplete())
279       return;
280   }
281   pref_notifier_->OnInitializationCompleted(true);
282 }
283