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