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 11 PrefValueStore::PrefStoreKeeper::PrefStoreKeeper() 12 : pref_value_store_(NULL), 13 type_(PrefValueStore::INVALID_STORE) { 14 } 15 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 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 39 void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged( 40 const std::string& key) { 41 pref_value_store_->OnPrefValueChanged(type_, key); 42 } 43 44 void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted( 45 bool succeeded) { 46 pref_value_store_->OnInitializationCompleted(type_, succeeded); 47 } 48 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 70 PrefValueStore::~PrefValueStore() {} 71 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 102 void PrefValueStore::set_callback(const PrefChangedCallback& callback) { 103 pref_changed_callback_ = callback; 104 } 105 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.c_str(), type, 113 static_cast<PrefStoreType>(i), out_value)) 114 return true; 115 } 116 return false; 117 } 118 119 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 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 138 bool PrefValueStore::PrefValueInManagedStore(const char* name) const { 139 return PrefValueInStore(name, MANAGED_STORE); 140 } 141 142 bool PrefValueStore::PrefValueInExtensionStore(const char* name) const { 143 return PrefValueInStore(name, EXTENSION_STORE); 144 } 145 146 bool PrefValueStore::PrefValueInUserStore(const char* name) const { 147 return PrefValueInStore(name, USER_STORE); 148 } 149 150 bool PrefValueStore::PrefValueFromExtensionStore(const char* name) const { 151 return ControllingPrefStoreForPref(name) == EXTENSION_STORE; 152 } 153 154 bool PrefValueStore::PrefValueFromUserStore(const char* name) const { 155 return ControllingPrefStoreForPref(name) == USER_STORE; 156 } 157 158 bool PrefValueStore::PrefValueFromRecommendedStore(const char* name) const { 159 return ControllingPrefStoreForPref(name) == RECOMMENDED_STORE; 160 } 161 162 bool PrefValueStore::PrefValueFromDefaultStore(const char* name) const { 163 return ControllingPrefStoreForPref(name) == DEFAULT_STORE; 164 } 165 166 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 172 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 178 void PrefValueStore::UpdateCommandLinePrefStore(PrefStore* command_line_prefs) { 179 InitPrefStore(COMMAND_LINE_STORE, command_line_prefs); 180 } 181 182 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 191 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 208 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 217 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 232 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 250 void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type, 251 const std::string& key) { 252 NotifyPrefChanged(key.c_str(), type); 253 } 254 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 267 void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type, 268 PrefStore* pref_store) { 269 pref_stores_[type].Initialize(this, pref_store, type); 270 } 271 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