pref_service.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1c55a96383497a772a307b346368133960b02ad03Eric Laurent// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2c55a96383497a772a307b346368133960b02ad03Eric Laurent// Use of this source code is governed by a BSD-style license that can be 3c55a96383497a772a307b346368133960b02ad03Eric Laurent// found in the LICENSE file. 4c55a96383497a772a307b346368133960b02ad03Eric Laurent 5c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/prefs/pref_service.h" 6c55a96383497a772a307b346368133960b02ad03Eric Laurent 7c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <algorithm> 8c55a96383497a772a307b346368133960b02ad03Eric Laurent 9c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/bind.h" 10c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/files/file_path.h" 11c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/logging.h" 12c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/message_loop/message_loop.h" 13c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/metrics/histogram.h" 14c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/prefs/default_pref_store.h" 15c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/prefs/pref_notifier_impl.h" 16c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/prefs/pref_registry.h" 17c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/prefs/pref_value_store.h" 18c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/stl_util.h" 19c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/strings/string_number_conversions.h" 20c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/strings/string_util.h" 21c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "base/value_conversions.h" 22c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "build/build_config.h" 23c55a96383497a772a307b346368133960b02ad03Eric Laurent 24c55a96383497a772a307b346368133960b02ad03Eric Laurentnamespace { 25c55a96383497a772a307b346368133960b02ad03Eric Laurent 26c55a96383497a772a307b346368133960b02ad03Eric Laurentclass ReadErrorHandler : public PersistentPrefStore::ReadErrorDelegate { 27c55a96383497a772a307b346368133960b02ad03Eric Laurent public: 28c55a96383497a772a307b346368133960b02ad03Eric Laurent ReadErrorHandler(base::Callback<void(PersistentPrefStore::PrefReadError)> cb) 29c55a96383497a772a307b346368133960b02ad03Eric Laurent : callback_(cb) {} 30c55a96383497a772a307b346368133960b02ad03Eric Laurent 31c55a96383497a772a307b346368133960b02ad03Eric Laurent virtual void OnError(PersistentPrefStore::PrefReadError error) OVERRIDE { 32c55a96383497a772a307b346368133960b02ad03Eric Laurent callback_.Run(error); 33c55a96383497a772a307b346368133960b02ad03Eric Laurent } 34c55a96383497a772a307b346368133960b02ad03Eric Laurent 35c55a96383497a772a307b346368133960b02ad03Eric Laurent private: 36c55a96383497a772a307b346368133960b02ad03Eric Laurent base::Callback<void(PersistentPrefStore::PrefReadError)> callback_; 37c55a96383497a772a307b346368133960b02ad03Eric Laurent}; 38c55a96383497a772a307b346368133960b02ad03Eric Laurent 39c55a96383497a772a307b346368133960b02ad03Eric Laurent} // namespace 40c55a96383497a772a307b346368133960b02ad03Eric Laurent 41c55a96383497a772a307b346368133960b02ad03Eric LaurentPrefService::PrefService( 42c55a96383497a772a307b346368133960b02ad03Eric Laurent PrefNotifierImpl* pref_notifier, 43c55a96383497a772a307b346368133960b02ad03Eric Laurent PrefValueStore* pref_value_store, 44c55a96383497a772a307b346368133960b02ad03Eric Laurent PersistentPrefStore* user_prefs, 45c55a96383497a772a307b346368133960b02ad03Eric Laurent PrefRegistry* pref_registry, 46c55a96383497a772a307b346368133960b02ad03Eric Laurent base::Callback<void(PersistentPrefStore::PrefReadError)> 47c55a96383497a772a307b346368133960b02ad03Eric Laurent read_error_callback, 48c55a96383497a772a307b346368133960b02ad03Eric Laurent bool async) 49c55a96383497a772a307b346368133960b02ad03Eric Laurent : pref_notifier_(pref_notifier), 50c55a96383497a772a307b346368133960b02ad03Eric Laurent pref_value_store_(pref_value_store), 51c55a96383497a772a307b346368133960b02ad03Eric Laurent pref_registry_(pref_registry), 52c55a96383497a772a307b346368133960b02ad03Eric Laurent user_pref_store_(user_prefs), 53c55a96383497a772a307b346368133960b02ad03Eric Laurent read_error_callback_(read_error_callback) { 54c55a96383497a772a307b346368133960b02ad03Eric Laurent pref_notifier_->SetPrefService(this); 55c55a96383497a772a307b346368133960b02ad03Eric Laurent 56c55a96383497a772a307b346368133960b02ad03Eric Laurent InitFromStorage(async); 57c55a96383497a772a307b346368133960b02ad03Eric Laurent} 58c55a96383497a772a307b346368133960b02ad03Eric Laurent 59c55a96383497a772a307b346368133960b02ad03Eric LaurentPrefService::~PrefService() { 60c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(CalledOnValidThread()); 61c55a96383497a772a307b346368133960b02ad03Eric Laurent 62c55a96383497a772a307b346368133960b02ad03Eric Laurent // Reset pointers so accesses after destruction reliably crash. 63c55a96383497a772a307b346368133960b02ad03Eric Laurent pref_value_store_.reset(); 64c55a96383497a772a307b346368133960b02ad03Eric Laurent pref_registry_ = NULL; 65c55a96383497a772a307b346368133960b02ad03Eric Laurent user_pref_store_ = NULL; 66c55a96383497a772a307b346368133960b02ad03Eric Laurent pref_notifier_.reset(); 67c55a96383497a772a307b346368133960b02ad03Eric Laurent} 68c55a96383497a772a307b346368133960b02ad03Eric Laurent 69c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid PrefService::InitFromStorage(bool async) { 70c55a96383497a772a307b346368133960b02ad03Eric Laurent if (user_pref_store_->IsInitializationComplete()) { 71c55a96383497a772a307b346368133960b02ad03Eric Laurent read_error_callback_.Run(user_pref_store_->GetReadError()); 72c55a96383497a772a307b346368133960b02ad03Eric Laurent } else if (!async) { 73c55a96383497a772a307b346368133960b02ad03Eric Laurent read_error_callback_.Run(user_pref_store_->ReadPrefs()); 74c55a96383497a772a307b346368133960b02ad03Eric Laurent } else { 75c55a96383497a772a307b346368133960b02ad03Eric Laurent // Guarantee that initialization happens after this function returned. 76c55a96383497a772a307b346368133960b02ad03Eric Laurent base::MessageLoop::current()->PostTask( 77c55a96383497a772a307b346368133960b02ad03Eric Laurent FROM_HERE, 78c55a96383497a772a307b346368133960b02ad03Eric Laurent base::Bind(&PersistentPrefStore::ReadPrefsAsync, 79c55a96383497a772a307b346368133960b02ad03Eric Laurent user_pref_store_.get(), 80c55a96383497a772a307b346368133960b02ad03Eric Laurent new ReadErrorHandler(read_error_callback_))); 81c55a96383497a772a307b346368133960b02ad03Eric Laurent } 82c55a96383497a772a307b346368133960b02ad03Eric Laurent} 83c55a96383497a772a307b346368133960b02ad03Eric Laurent 84c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid PrefService::CommitPendingWrite() { 85c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(CalledOnValidThread()); 86c55a96383497a772a307b346368133960b02ad03Eric Laurent user_pref_store_->CommitPendingWrite(); 87c55a96383497a772a307b346368133960b02ad03Eric Laurent} 88c55a96383497a772a307b346368133960b02ad03Eric Laurent 89c55a96383497a772a307b346368133960b02ad03Eric Laurentbool PrefService::GetBoolean(const char* path) const { 90c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(CalledOnValidThread()); 91c55a96383497a772a307b346368133960b02ad03Eric Laurent 92c55a96383497a772a307b346368133960b02ad03Eric Laurent bool result = false; 93c55a96383497a772a307b346368133960b02ad03Eric Laurent 94c55a96383497a772a307b346368133960b02ad03Eric Laurent const base::Value* value = GetPreferenceValue(path); 95c55a96383497a772a307b346368133960b02ad03Eric Laurent if (!value) { 96c55a96383497a772a307b346368133960b02ad03Eric Laurent NOTREACHED() << "Trying to read an unregistered pref: " << path; 97c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 98c55a96383497a772a307b346368133960b02ad03Eric Laurent } 99c55a96383497a772a307b346368133960b02ad03Eric Laurent bool rv = value->GetAsBoolean(&result); 100c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(rv); 101c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 102c55a96383497a772a307b346368133960b02ad03Eric Laurent} 103c55a96383497a772a307b346368133960b02ad03Eric Laurent 104c55a96383497a772a307b346368133960b02ad03Eric Laurentint PrefService::GetInteger(const char* path) const { 105c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(CalledOnValidThread()); 106c55a96383497a772a307b346368133960b02ad03Eric Laurent 107c55a96383497a772a307b346368133960b02ad03Eric Laurent int result = 0; 108c55a96383497a772a307b346368133960b02ad03Eric Laurent 109c55a96383497a772a307b346368133960b02ad03Eric Laurent const base::Value* value = GetPreferenceValue(path); 110c55a96383497a772a307b346368133960b02ad03Eric Laurent if (!value) { 111c55a96383497a772a307b346368133960b02ad03Eric Laurent NOTREACHED() << "Trying to read an unregistered pref: " << path; 112c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 113c55a96383497a772a307b346368133960b02ad03Eric Laurent } 114c55a96383497a772a307b346368133960b02ad03Eric Laurent bool rv = value->GetAsInteger(&result); 115c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(rv); 116c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 117c55a96383497a772a307b346368133960b02ad03Eric Laurent} 118c55a96383497a772a307b346368133960b02ad03Eric Laurent 119c55a96383497a772a307b346368133960b02ad03Eric Laurentdouble PrefService::GetDouble(const char* path) const { 120c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(CalledOnValidThread()); 121c55a96383497a772a307b346368133960b02ad03Eric Laurent 122c55a96383497a772a307b346368133960b02ad03Eric Laurent double result = 0.0; 123c55a96383497a772a307b346368133960b02ad03Eric Laurent 124c55a96383497a772a307b346368133960b02ad03Eric Laurent const base::Value* value = GetPreferenceValue(path); 125c55a96383497a772a307b346368133960b02ad03Eric Laurent if (!value) { 126c55a96383497a772a307b346368133960b02ad03Eric Laurent NOTREACHED() << "Trying to read an unregistered pref: " << path; 127c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 128c55a96383497a772a307b346368133960b02ad03Eric Laurent } 129c55a96383497a772a307b346368133960b02ad03Eric Laurent bool rv = value->GetAsDouble(&result); 130c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(rv); 131c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 132c55a96383497a772a307b346368133960b02ad03Eric Laurent} 133c55a96383497a772a307b346368133960b02ad03Eric Laurent 134c55a96383497a772a307b346368133960b02ad03Eric Laurentstd::string PrefService::GetString(const char* path) const { 135c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(CalledOnValidThread()); 136c55a96383497a772a307b346368133960b02ad03Eric Laurent 137c55a96383497a772a307b346368133960b02ad03Eric Laurent std::string result; 138c55a96383497a772a307b346368133960b02ad03Eric Laurent 139c55a96383497a772a307b346368133960b02ad03Eric Laurent const base::Value* value = GetPreferenceValue(path); 140c55a96383497a772a307b346368133960b02ad03Eric Laurent if (!value) { 141c55a96383497a772a307b346368133960b02ad03Eric Laurent NOTREACHED() << "Trying to read an unregistered pref: " << path; 142c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 143c55a96383497a772a307b346368133960b02ad03Eric Laurent } 144c55a96383497a772a307b346368133960b02ad03Eric Laurent bool rv = value->GetAsString(&result); 145c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(rv); 146c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 147c55a96383497a772a307b346368133960b02ad03Eric Laurent} 148c55a96383497a772a307b346368133960b02ad03Eric Laurent 149c55a96383497a772a307b346368133960b02ad03Eric Laurentbase::FilePath PrefService::GetFilePath(const char* path) const { 150c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(CalledOnValidThread()); 151c55a96383497a772a307b346368133960b02ad03Eric Laurent 152c55a96383497a772a307b346368133960b02ad03Eric Laurent base::FilePath result; 153c55a96383497a772a307b346368133960b02ad03Eric Laurent 154c55a96383497a772a307b346368133960b02ad03Eric Laurent const base::Value* value = GetPreferenceValue(path); 155c55a96383497a772a307b346368133960b02ad03Eric Laurent if (!value) { 156c55a96383497a772a307b346368133960b02ad03Eric Laurent NOTREACHED() << "Trying to read an unregistered pref: " << path; 157c55a96383497a772a307b346368133960b02ad03Eric Laurent return base::FilePath(result); 158c55a96383497a772a307b346368133960b02ad03Eric Laurent } 159c55a96383497a772a307b346368133960b02ad03Eric Laurent bool rv = base::GetValueAsFilePath(*value, &result); 160c55a96383497a772a307b346368133960b02ad03Eric Laurent DCHECK(rv); 161c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 162c55a96383497a772a307b346368133960b02ad03Eric Laurent} 163c55a96383497a772a307b346368133960b02ad03Eric Laurent 164c55a96383497a772a307b346368133960b02ad03Eric Laurentbool PrefService::HasPrefPath(const char* path) const { 165c55a96383497a772a307b346368133960b02ad03Eric Laurent const Preference* pref = FindPreference(path); 166c55a96383497a772a307b346368133960b02ad03Eric Laurent return pref && !pref->IsDefaultValue(); 167c55a96383497a772a307b346368133960b02ad03Eric Laurent} 168 169scoped_ptr<base::DictionaryValue> PrefService::GetPreferenceValues() const { 170 DCHECK(CalledOnValidThread()); 171 scoped_ptr<base::DictionaryValue> out(new base::DictionaryValue); 172 PrefRegistry::const_iterator i = pref_registry_->begin(); 173 for (; i != pref_registry_->end(); ++i) { 174 const base::Value* value = GetPreferenceValue(i->first); 175 DCHECK(value); 176 out->Set(i->first, value->DeepCopy()); 177 } 178 return out.Pass(); 179} 180 181scoped_ptr<base::DictionaryValue> 182PrefService::GetPreferenceValuesWithoutPathExpansion() const { 183 DCHECK(CalledOnValidThread()); 184 scoped_ptr<base::DictionaryValue> out(new base::DictionaryValue); 185 PrefRegistry::const_iterator i = pref_registry_->begin(); 186 for (; i != pref_registry_->end(); ++i) { 187 const base::Value* value = GetPreferenceValue(i->first); 188 DCHECK(value); 189 out->SetWithoutPathExpansion(i->first, value->DeepCopy()); 190 } 191 return out.Pass(); 192} 193 194const PrefService::Preference* PrefService::FindPreference( 195 const char* pref_name) const { 196 DCHECK(CalledOnValidThread()); 197 PreferenceMap::iterator it = prefs_map_.find(pref_name); 198 if (it != prefs_map_.end()) 199 return &(it->second); 200 const base::Value* default_value = NULL; 201 if (!pref_registry_->defaults()->GetValue(pref_name, &default_value)) 202 return NULL; 203 it = prefs_map_.insert( 204 std::make_pair(pref_name, Preference( 205 this, pref_name, default_value->GetType()))).first; 206 return &(it->second); 207} 208 209bool PrefService::ReadOnly() const { 210 return user_pref_store_->ReadOnly(); 211} 212 213PrefService::PrefInitializationStatus PrefService::GetInitializationStatus() 214 const { 215 if (!user_pref_store_->IsInitializationComplete()) 216 return INITIALIZATION_STATUS_WAITING; 217 218 switch (user_pref_store_->GetReadError()) { 219 case PersistentPrefStore::PREF_READ_ERROR_NONE: 220 return INITIALIZATION_STATUS_SUCCESS; 221 case PersistentPrefStore::PREF_READ_ERROR_NO_FILE: 222 return INITIALIZATION_STATUS_CREATED_NEW_PREF_STORE; 223 default: 224 return INITIALIZATION_STATUS_ERROR; 225 } 226} 227 228bool PrefService::IsManagedPreference(const char* pref_name) const { 229 const Preference* pref = FindPreference(pref_name); 230 return pref && pref->IsManaged(); 231} 232 233bool PrefService::IsUserModifiablePreference(const char* pref_name) const { 234 const Preference* pref = FindPreference(pref_name); 235 return pref && pref->IsUserModifiable(); 236} 237 238const base::DictionaryValue* PrefService::GetDictionary( 239 const char* path) const { 240 DCHECK(CalledOnValidThread()); 241 242 const base::Value* value = GetPreferenceValue(path); 243 if (!value) { 244 NOTREACHED() << "Trying to read an unregistered pref: " << path; 245 return NULL; 246 } 247 if (value->GetType() != base::Value::TYPE_DICTIONARY) { 248 NOTREACHED(); 249 return NULL; 250 } 251 return static_cast<const base::DictionaryValue*>(value); 252} 253 254const base::Value* PrefService::GetUserPrefValue(const char* path) const { 255 DCHECK(CalledOnValidThread()); 256 257 const Preference* pref = FindPreference(path); 258 if (!pref) { 259 NOTREACHED() << "Trying to get an unregistered pref: " << path; 260 return NULL; 261 } 262 263 // Look for an existing preference in the user store. If it doesn't 264 // exist, return NULL. 265 base::Value* value = NULL; 266 if (!user_pref_store_->GetMutableValue(path, &value)) 267 return NULL; 268 269 if (!value->IsType(pref->GetType())) { 270 NOTREACHED() << "Pref value type doesn't match registered type."; 271 return NULL; 272 } 273 274 return value; 275} 276 277void PrefService::SetDefaultPrefValue(const char* path, 278 base::Value* value) { 279 DCHECK(CalledOnValidThread()); 280 pref_registry_->SetDefaultPrefValue(path, value); 281} 282 283const base::Value* PrefService::GetDefaultPrefValue(const char* path) const { 284 DCHECK(CalledOnValidThread()); 285 // Lookup the preference in the default store. 286 const base::Value* value = NULL; 287 if (!pref_registry_->defaults()->GetValue(path, &value)) { 288 NOTREACHED() << "Default value missing for pref: " << path; 289 return NULL; 290 } 291 return value; 292} 293 294const base::ListValue* PrefService::GetList(const char* path) const { 295 DCHECK(CalledOnValidThread()); 296 297 const base::Value* value = GetPreferenceValue(path); 298 if (!value) { 299 NOTREACHED() << "Trying to read an unregistered pref: " << path; 300 return NULL; 301 } 302 if (value->GetType() != base::Value::TYPE_LIST) { 303 NOTREACHED(); 304 return NULL; 305 } 306 return static_cast<const base::ListValue*>(value); 307} 308 309void PrefService::AddPrefObserver(const char* path, PrefObserver* obs) { 310 pref_notifier_->AddPrefObserver(path, obs); 311} 312 313void PrefService::RemovePrefObserver(const char* path, PrefObserver* obs) { 314 pref_notifier_->RemovePrefObserver(path, obs); 315} 316 317void PrefService::AddPrefInitObserver(base::Callback<void(bool)> obs) { 318 pref_notifier_->AddInitObserver(obs); 319} 320 321PrefRegistry* PrefService::DeprecatedGetPrefRegistry() { 322 return pref_registry_.get(); 323} 324 325void PrefService::ClearPref(const char* path) { 326 DCHECK(CalledOnValidThread()); 327 328 const Preference* pref = FindPreference(path); 329 if (!pref) { 330 NOTREACHED() << "Trying to clear an unregistered pref: " << path; 331 return; 332 } 333 user_pref_store_->RemoveValue(path); 334} 335 336void PrefService::Set(const char* path, const base::Value& value) { 337 SetUserPrefValue(path, value.DeepCopy()); 338} 339 340void PrefService::SetBoolean(const char* path, bool value) { 341 SetUserPrefValue(path, new base::FundamentalValue(value)); 342} 343 344void PrefService::SetInteger(const char* path, int value) { 345 SetUserPrefValue(path, new base::FundamentalValue(value)); 346} 347 348void PrefService::SetDouble(const char* path, double value) { 349 SetUserPrefValue(path, new base::FundamentalValue(value)); 350} 351 352void PrefService::SetString(const char* path, const std::string& value) { 353 SetUserPrefValue(path, new base::StringValue(value)); 354} 355 356void PrefService::SetFilePath(const char* path, const base::FilePath& value) { 357 SetUserPrefValue(path, base::CreateFilePathValue(value)); 358} 359 360void PrefService::SetInt64(const char* path, int64 value) { 361 SetUserPrefValue(path, new base::StringValue(base::Int64ToString(value))); 362} 363 364int64 PrefService::GetInt64(const char* path) const { 365 DCHECK(CalledOnValidThread()); 366 367 const base::Value* value = GetPreferenceValue(path); 368 if (!value) { 369 NOTREACHED() << "Trying to read an unregistered pref: " << path; 370 return 0; 371 } 372 std::string result("0"); 373 bool rv = value->GetAsString(&result); 374 DCHECK(rv); 375 376 int64 val; 377 base::StringToInt64(result, &val); 378 return val; 379} 380 381void PrefService::SetUint64(const char* path, uint64 value) { 382 SetUserPrefValue(path, new base::StringValue(base::Uint64ToString(value))); 383} 384 385uint64 PrefService::GetUint64(const char* path) const { 386 DCHECK(CalledOnValidThread()); 387 388 const base::Value* value = GetPreferenceValue(path); 389 if (!value) { 390 NOTREACHED() << "Trying to read an unregistered pref: " << path; 391 return 0; 392 } 393 std::string result("0"); 394 bool rv = value->GetAsString(&result); 395 DCHECK(rv); 396 397 uint64 val; 398 base::StringToUint64(result, &val); 399 return val; 400} 401 402base::Value* PrefService::GetMutableUserPref(const char* path, 403 base::Value::Type type) { 404 CHECK(type == base::Value::TYPE_DICTIONARY || type == base::Value::TYPE_LIST); 405 DCHECK(CalledOnValidThread()); 406 407 const Preference* pref = FindPreference(path); 408 if (!pref) { 409 NOTREACHED() << "Trying to get an unregistered pref: " << path; 410 return NULL; 411 } 412 if (pref->GetType() != type) { 413 NOTREACHED() << "Wrong type for GetMutableValue: " << path; 414 return NULL; 415 } 416 417 // Look for an existing preference in the user store. If it doesn't 418 // exist or isn't the correct type, create a new user preference. 419 base::Value* value = NULL; 420 if (!user_pref_store_->GetMutableValue(path, &value) || 421 !value->IsType(type)) { 422 if (type == base::Value::TYPE_DICTIONARY) { 423 value = new base::DictionaryValue; 424 } else if (type == base::Value::TYPE_LIST) { 425 value = new base::ListValue; 426 } else { 427 NOTREACHED(); 428 } 429 user_pref_store_->SetValueSilently(path, value); 430 } 431 return value; 432} 433 434void PrefService::ReportUserPrefChanged(const std::string& key) { 435 DCHECK(CalledOnValidThread()); 436 user_pref_store_->ReportValueChanged(key); 437} 438 439void PrefService::SetUserPrefValue(const char* path, base::Value* new_value) { 440 scoped_ptr<base::Value> owned_value(new_value); 441 DCHECK(CalledOnValidThread()); 442 443 const Preference* pref = FindPreference(path); 444 if (!pref) { 445 NOTREACHED() << "Trying to write an unregistered pref: " << path; 446 return; 447 } 448 if (pref->GetType() != new_value->GetType()) { 449 NOTREACHED() << "Trying to set pref " << path 450 << " of type " << pref->GetType() 451 << " to value of type " << new_value->GetType(); 452 return; 453 } 454 455 user_pref_store_->SetValue(path, owned_value.release()); 456} 457 458void PrefService::UpdateCommandLinePrefStore(PrefStore* command_line_store) { 459 pref_value_store_->UpdateCommandLinePrefStore(command_line_store); 460} 461 462/////////////////////////////////////////////////////////////////////////////// 463// PrefService::Preference 464 465PrefService::Preference::Preference(const PrefService* service, 466 const char* name, 467 base::Value::Type type) 468 : name_(name), 469 type_(type), 470 pref_service_(service) { 471 DCHECK(name); 472 DCHECK(service); 473} 474 475const std::string PrefService::Preference::name() const { 476 return name_; 477} 478 479base::Value::Type PrefService::Preference::GetType() const { 480 return type_; 481} 482 483const base::Value* PrefService::Preference::GetValue() const { 484 const base::Value* result= pref_service_->GetPreferenceValue(name_); 485 DCHECK(result) << "Must register pref before getting its value"; 486 return result; 487} 488 489const base::Value* PrefService::Preference::GetRecommendedValue() const { 490 DCHECK(pref_service_->FindPreference(name_.c_str())) << 491 "Must register pref before getting its value"; 492 493 const base::Value* found_value = NULL; 494 if (pref_value_store()->GetRecommendedValue(name_, type_, &found_value)) { 495 DCHECK(found_value->IsType(type_)); 496 return found_value; 497 } 498 499 // The pref has no recommended value. 500 return NULL; 501} 502 503bool PrefService::Preference::IsManaged() const { 504 return pref_value_store()->PrefValueInManagedStore(name_.c_str()); 505} 506 507bool PrefService::Preference::IsRecommended() const { 508 return pref_value_store()->PrefValueFromRecommendedStore(name_.c_str()); 509} 510 511bool PrefService::Preference::HasExtensionSetting() const { 512 return pref_value_store()->PrefValueInExtensionStore(name_.c_str()); 513} 514 515bool PrefService::Preference::HasUserSetting() const { 516 return pref_value_store()->PrefValueInUserStore(name_.c_str()); 517} 518 519bool PrefService::Preference::IsExtensionControlled() const { 520 return pref_value_store()->PrefValueFromExtensionStore(name_.c_str()); 521} 522 523bool PrefService::Preference::IsUserControlled() const { 524 return pref_value_store()->PrefValueFromUserStore(name_.c_str()); 525} 526 527bool PrefService::Preference::IsDefaultValue() const { 528 return pref_value_store()->PrefValueFromDefaultStore(name_.c_str()); 529} 530 531bool PrefService::Preference::IsUserModifiable() const { 532 return pref_value_store()->PrefValueUserModifiable(name_.c_str()); 533} 534 535bool PrefService::Preference::IsExtensionModifiable() const { 536 return pref_value_store()->PrefValueExtensionModifiable(name_.c_str()); 537} 538 539const base::Value* PrefService::GetPreferenceValue( 540 const std::string& path) const { 541 DCHECK(CalledOnValidThread()); 542 const base::Value* default_value = NULL; 543 if (pref_registry_->defaults()->GetValue(path, &default_value)) { 544 const base::Value* found_value = NULL; 545 base::Value::Type default_type = default_value->GetType(); 546 if (pref_value_store_->GetValue(path, default_type, &found_value)) { 547 DCHECK(found_value->IsType(default_type)); 548 return found_value; 549 } else { 550 // Every registered preference has at least a default value. 551 NOTREACHED() << "no valid value found for registered pref " << path; 552 } 553 } 554 555 return NULL; 556} 557