pref_value_store.cc revision 5af4e3efaa07e1369024c188538dcf582ed5a21e
1// Copyright (c) 2010 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 "chrome/browser/prefs/pref_value_store.h" 6 7#ifdef ANDROID 8#include "base/logging.h" 9#endif 10#include "chrome/browser/prefs/pref_notifier.h" 11 12PrefValueStore::PrefStoreKeeper::PrefStoreKeeper() 13 : pref_value_store_(NULL), 14 type_(PrefValueStore::INVALID_STORE) { 15} 16 17PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() { 18 if (pref_store_.get()) 19 pref_store_->RemoveObserver(this); 20} 21 22void PrefValueStore::PrefStoreKeeper::Initialize( 23 PrefValueStore* store, 24 PrefStore* pref_store, 25 PrefValueStore::PrefStoreType type) { 26 if (pref_store_.get()) 27 pref_store_->RemoveObserver(this); 28 type_ = type; 29 pref_value_store_ = store; 30 pref_store_.reset(pref_store); 31 if (pref_store_.get()) 32 pref_store_->AddObserver(this); 33} 34 35void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged( 36 const std::string& key) { 37 pref_value_store_->OnPrefValueChanged(type_, key); 38} 39 40void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted() { 41 pref_value_store_->OnInitializationCompleted(type_); 42} 43 44PrefValueStore::PrefValueStore(PrefStore* managed_platform_prefs, 45 PrefStore* device_management_prefs, 46 PrefStore* extension_prefs, 47 PrefStore* command_line_prefs, 48 PrefStore* user_prefs, 49 PrefStore* recommended_prefs, 50 PrefStore* default_prefs, 51 PrefNotifier* pref_notifier) 52 : pref_notifier_(pref_notifier) { 53 InitPrefStore(MANAGED_PLATFORM_STORE, managed_platform_prefs); 54 InitPrefStore(DEVICE_MANAGEMENT_STORE, device_management_prefs); 55 InitPrefStore(EXTENSION_STORE, extension_prefs); 56 InitPrefStore(COMMAND_LINE_STORE, command_line_prefs); 57 InitPrefStore(USER_STORE, user_prefs); 58 InitPrefStore(RECOMMENDED_STORE, recommended_prefs); 59 InitPrefStore(DEFAULT_STORE, default_prefs); 60 61 CheckInitializationCompleted(); 62} 63 64PrefValueStore::~PrefValueStore() {} 65 66bool PrefValueStore::GetValue(const std::string& name, 67 Value** out_value) const { 68 // Check the |PrefStore|s in order of their priority from highest to lowest 69 // to find the value of the preference described by the given preference name. 70 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) { 71 if (GetValueFromStore(name.c_str(), static_cast<PrefStoreType>(i), 72 out_value)) 73 return true; 74 } 75 return false; 76} 77 78void PrefValueStore::RegisterPreferenceType(const std::string& name, 79 Value::ValueType type) { 80 pref_types_[name] = type; 81} 82 83Value::ValueType PrefValueStore::GetRegisteredType( 84 const std::string& name) const { 85 PrefTypeMap::const_iterator found = pref_types_.find(name); 86 if (found == pref_types_.end()) 87 return Value::TYPE_NULL; 88 return found->second; 89} 90 91bool PrefValueStore::HasPrefPath(const char* path) const { 92 Value* tmp_value = NULL; 93 const std::string name(path); 94 bool rv = GetValue(name, &tmp_value); 95 // Merely registering a pref doesn't count as "having" it: we require a 96 // non-default value set. 97 return rv && !PrefValueFromDefaultStore(path); 98} 99 100void PrefValueStore::NotifyPrefChanged( 101 const char* path, 102 PrefValueStore::PrefStoreType new_store) { 103 DCHECK(new_store != INVALID_STORE); 104 105 // If this pref is not registered, just discard the notification. 106 if (!pref_types_.count(path)) 107 return; 108 109 bool changed = true; 110 // Replying that the pref has changed in case the new store is invalid may 111 // cause problems, but it's the safer choice. 112 if (new_store != INVALID_STORE) { 113 PrefStoreType controller = ControllingPrefStoreForPref(path); 114 DCHECK(controller != INVALID_STORE); 115 // If the pref is controlled by a higher-priority store, its effective value 116 // cannot have changed. 117 if (controller != INVALID_STORE && 118 controller < new_store) { 119 changed = false; 120 } 121 } 122 123 if (changed) 124 pref_notifier_->OnPreferenceChanged(path); 125} 126 127bool PrefValueStore::PrefValueInManagedPlatformStore(const char* name) const { 128 return PrefValueInStore(name, MANAGED_PLATFORM_STORE); 129} 130 131bool PrefValueStore::PrefValueInDeviceManagementStore(const char* name) const { 132 return PrefValueInStore(name, DEVICE_MANAGEMENT_STORE); 133} 134 135bool PrefValueStore::PrefValueInExtensionStore(const char* name) const { 136 return PrefValueInStore(name, EXTENSION_STORE); 137} 138 139bool PrefValueStore::PrefValueInUserStore(const char* name) const { 140 return PrefValueInStore(name, USER_STORE); 141} 142 143bool PrefValueStore::PrefValueFromExtensionStore(const char* name) const { 144 return ControllingPrefStoreForPref(name) == EXTENSION_STORE; 145} 146 147bool PrefValueStore::PrefValueFromUserStore(const char* name) const { 148 return ControllingPrefStoreForPref(name) == USER_STORE; 149} 150 151bool PrefValueStore::PrefValueFromDefaultStore(const char* name) const { 152 return ControllingPrefStoreForPref(name) == DEFAULT_STORE; 153} 154 155bool PrefValueStore::PrefValueUserModifiable(const char* name) const { 156 PrefStoreType effective_store = ControllingPrefStoreForPref(name); 157 return effective_store >= USER_STORE || 158 effective_store == INVALID_STORE; 159} 160 161// Returns true if the actual value is a valid type for the expected type when 162// found in the given store. 163bool PrefValueStore::IsValidType(Value::ValueType expected, 164 Value::ValueType actual, 165 PrefValueStore::PrefStoreType store) { 166 if (expected == actual) 167 return true; 168 169 // Dictionaries and lists are allowed to hold TYPE_NULL values too, but only 170 // in the default pref store. 171 if (store == DEFAULT_STORE && 172 actual == Value::TYPE_NULL && 173 (expected == Value::TYPE_DICTIONARY || expected == Value::TYPE_LIST)) { 174 return true; 175 } 176 return false; 177} 178 179bool PrefValueStore::PrefValueInStore( 180 const char* name, 181 PrefValueStore::PrefStoreType store) const { 182 // Declare a temp Value* and call GetValueFromStore, 183 // ignoring the output value. 184 Value* tmp_value = NULL; 185 return GetValueFromStore(name, store, &tmp_value); 186} 187 188bool PrefValueStore::PrefValueInStoreRange( 189 const char* name, 190 PrefValueStore::PrefStoreType first_checked_store, 191 PrefValueStore::PrefStoreType last_checked_store) const { 192 if (first_checked_store > last_checked_store) { 193 NOTREACHED(); 194 return false; 195 } 196 197 for (size_t i = first_checked_store; 198 i <= static_cast<size_t>(last_checked_store); ++i) { 199 if (PrefValueInStore(name, static_cast<PrefStoreType>(i))) 200 return true; 201 } 202 return false; 203} 204 205PrefValueStore::PrefStoreType PrefValueStore::ControllingPrefStoreForPref( 206 const char* name) const { 207 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) { 208 if (PrefValueInStore(name, static_cast<PrefStoreType>(i))) 209 return static_cast<PrefStoreType>(i); 210 } 211 return INVALID_STORE; 212} 213 214bool PrefValueStore::GetValueFromStore(const char* name, 215 PrefValueStore::PrefStoreType store_type, 216 Value** out_value) const { 217 // Only return true if we find a value and it is the correct type, so stale 218 // values with the incorrect type will be ignored. 219 const PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(store_type)); 220 if (store) { 221 switch (store->GetValue(name, out_value)) { 222 case PrefStore::READ_USE_DEFAULT: 223 store = GetPrefStore(DEFAULT_STORE); 224 if (!store || store->GetValue(name, out_value) != PrefStore::READ_OK) { 225 *out_value = NULL; 226 return false; 227 } 228 // Fall through... 229 case PrefStore::READ_OK: 230 if (IsValidType(GetRegisteredType(name), 231 (*out_value)->GetType(), 232 store_type)) { 233 return true; 234 } 235 break; 236 case PrefStore::READ_NO_VALUE: 237 break; 238 } 239 } 240 241 // No valid value found for the given preference name: set the return false. 242 *out_value = NULL; 243 return false; 244} 245 246void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type, 247 const std::string& key) { 248 NotifyPrefChanged(key.c_str(), type); 249} 250 251void PrefValueStore::OnInitializationCompleted( 252 PrefValueStore::PrefStoreType type) { 253 CheckInitializationCompleted(); 254} 255 256void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type, 257 PrefStore* pref_store) { 258 pref_stores_[type].Initialize(this, pref_store, type); 259} 260 261void PrefValueStore::CheckInitializationCompleted() { 262 for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) { 263 PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(i)); 264 if (store && !store->IsInitializationComplete()) 265 return; 266 } 267 pref_notifier_->OnInitializationCompleted(); 268} 269