pref_service.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
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_service.h" 6 7#include <algorithm> 8#include <string> 9 10#include "app/l10n_util.h" 11#ifndef ANDROID 12#include "base/command_line.h" 13#endif 14#include "base/file_path.h" 15#include "base/file_util.h" 16#include "base/logging.h" 17#include "base/message_loop.h" 18#include "base/metrics/histogram.h" 19#include "base/stl_util-inl.h" 20#include "base/string_number_conversions.h" 21#include "base/string_util.h" 22#include "base/sys_string_conversions.h" 23#include "base/utf_string_conversions.h" 24#include "build/build_config.h" 25#include "chrome/browser/browser_thread.h" 26<<<<<<< HEAD 27#include "chrome/browser/profile.h" 28#ifndef ANDROID 29// Notifications do not compile on Android and are the cause 30// of most of the ANDROID guards in this file. 31======= 32#include "chrome/browser/policy/configuration_policy_pref_store.h" 33#include "chrome/browser/prefs/command_line_pref_store.h" 34#include "chrome/browser/prefs/default_pref_store.h" 35#include "chrome/browser/prefs/pref_notifier_impl.h" 36#include "chrome/browser/prefs/pref_value_store.h" 37#include "chrome/common/json_pref_store.h" 38>>>>>>> chromium.org at r10.0.621.0 39#include "chrome/common/notification_service.h" 40#include "grit/chromium_strings.h" 41#include "grit/generated_resources.h" 42#endif 43 44namespace { 45 46// A helper function for RegisterLocalized*Pref that creates a Value* based on 47// the string value in the locale dll. Because we control the values in a 48// locale dll, this should always return a Value of the appropriate type. 49Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) { 50#ifndef ANDROID 51 std::string resource_string = l10n_util::GetStringUTF8(message_id); 52 DCHECK(!resource_string.empty()); 53 switch (type) { 54 case Value::TYPE_BOOLEAN: { 55 if ("true" == resource_string) 56 return Value::CreateBooleanValue(true); 57 if ("false" == resource_string) 58 return Value::CreateBooleanValue(false); 59 break; 60 } 61 62 case Value::TYPE_INTEGER: { 63 int val; 64 base::StringToInt(resource_string, &val); 65 return Value::CreateIntegerValue(val); 66 } 67 68 case Value::TYPE_REAL: { 69 double val; 70 base::StringToDouble(resource_string, &val); 71 return Value::CreateRealValue(val); 72 } 73 74 case Value::TYPE_STRING: { 75 return Value::CreateStringValue(resource_string); 76 } 77 78 default: { 79 NOTREACHED() << 80 "list and dictionary types cannot have default locale values"; 81 } 82 } 83#endif 84 NOTREACHED(); 85 return Value::CreateNullValue(); 86} 87 88// Forwards a notification after a PostMessage so that we can wait for the 89// MessageLoop to run. 90void NotifyReadError(PrefService* pref, int message_id) { 91#ifndef ANDROID 92 Source<PrefService> source(pref); 93 NotificationService::current()->Notify(NotificationType::PROFILE_ERROR, 94 source, Details<int>(&message_id)); 95#endif 96} 97 98} // namespace 99 100// static 101PrefService* PrefService::CreatePrefService(const FilePath& pref_filename, 102 PrefStore* extension_prefs, 103 Profile* profile) { 104<<<<<<< HEAD 105#if defined(OS_LINUX) && !defined(ANDROID) 106======= 107 using policy::ConfigurationPolicyPrefStore; 108 109#if defined(OS_LINUX) 110>>>>>>> chromium.org at r10.0.621.0 111 // We'd like to see what fraction of our users have the preferences 112 // stored on a network file system, as we've had no end of troubles 113 // with NFS/AFS. 114 // TODO(evanm): remove this once we've collected state. 115 file_util::FileSystemType fstype; 116 if (file_util::GetFileSystemType(pref_filename.DirName(), &fstype)) { 117 UMA_HISTOGRAM_ENUMERATION("PrefService.FileSystemType", 118 static_cast<int>(fstype), 119 file_util::FILE_SYSTEM_TYPE_COUNT); 120 } 121#endif 122 123<<<<<<< HEAD 124 return new PrefService( 125 PrefValueStore::CreatePrefValueStore(pref_filename, profile, false)); 126} 127 128// static 129PrefService* PrefService::CreateUserPrefService(const FilePath& pref_filename) { 130 return new PrefService( 131 PrefValueStore::CreatePrefValueStore(pref_filename, NULL, true)); 132} 133 134PrefService::PrefService(PrefValueStore* pref_value_store) 135 : pref_value_store_(pref_value_store) { 136#ifndef ANDROID 137 pref_notifier_.reset(new PrefNotifier(this, pref_value_store)); 138#endif 139======= 140 ConfigurationPolicyPrefStore* managed = 141 ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore(); 142 ConfigurationPolicyPrefStore* device_management = 143 ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore( 144 profile); 145 CommandLinePrefStore* command_line = 146 new CommandLinePrefStore(CommandLine::ForCurrentProcess()); 147 JsonPrefStore* user = new JsonPrefStore( 148 pref_filename, 149 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); 150 ConfigurationPolicyPrefStore* recommended = 151 ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore(); 152 153 return new PrefService(managed, device_management, extension_prefs, 154 command_line, user, recommended); 155} 156 157PrefService::PrefService(PrefStore* managed_platform_prefs, 158 PrefStore* device_management_prefs, 159 PrefStore* extension_prefs, 160 PrefStore* command_line_prefs, 161 PersistentPrefStore* user_prefs, 162 PrefStore* recommended_prefs) 163 : user_pref_store_(user_prefs) { 164 pref_notifier_.reset(new PrefNotifierImpl(this)); 165 default_store_ = new DefaultPrefStore(); 166 pref_value_store_ = 167 new PrefValueStore(managed_platform_prefs, 168 device_management_prefs, 169 extension_prefs, 170 command_line_prefs, 171 user_pref_store_, 172 recommended_prefs, 173 default_store_, 174 pref_notifier_.get()); 175>>>>>>> chromium.org at r10.0.621.0 176 InitFromStorage(); 177} 178 179PrefService::~PrefService() { 180 DCHECK(CalledOnValidThread()); 181 STLDeleteContainerPointers(prefs_.begin(), prefs_.end()); 182 prefs_.clear(); 183} 184 185void PrefService::InitFromStorage() { 186<<<<<<< HEAD 187#ifndef ANDROID 188 PrefStore::PrefReadError error = LoadPersistentPrefs(); 189 if (error == PrefStore::PREF_READ_ERROR_NONE) 190======= 191 const PersistentPrefStore::PrefReadError error = 192 user_pref_store_->ReadPrefs(); 193 if (error == PersistentPrefStore::PREF_READ_ERROR_NONE) 194>>>>>>> chromium.org at r10.0.621.0 195 return; 196 197 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for 198 // an example problem that this can cause. 199 // Do some diagnosis and try to avoid losing data. 200 int message_id = 0; 201 if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) { 202 message_id = IDS_PREFERENCES_CORRUPT_ERROR; 203 } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) { 204 message_id = IDS_PREFERENCES_UNREADABLE_ERROR; 205 } 206 207 if (message_id) { 208 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 209 NewRunnableFunction(&NotifyReadError, this, message_id)); 210 } 211 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20); 212#endif 213} 214 215bool PrefService::ReloadPersistentPrefs() { 216 return user_pref_store_->ReadPrefs() == 217 PersistentPrefStore::PREF_READ_ERROR_NONE; 218} 219 220bool PrefService::SavePersistentPrefs() { 221 DCHECK(CalledOnValidThread()); 222 223 return user_pref_store_->WritePrefs(); 224} 225 226void PrefService::ScheduleSavePersistentPrefs() { 227 DCHECK(CalledOnValidThread()); 228 229 user_pref_store_->ScheduleWritePrefs(); 230} 231 232void PrefService::RegisterBooleanPref(const char* path, 233 bool default_value) { 234 RegisterPreference(path, Value::CreateBooleanValue(default_value)); 235} 236 237void PrefService::RegisterIntegerPref(const char* path, int default_value) { 238 RegisterPreference(path, Value::CreateIntegerValue(default_value)); 239} 240 241void PrefService::RegisterRealPref(const char* path, double default_value) { 242 RegisterPreference(path, Value::CreateRealValue(default_value)); 243} 244 245void PrefService::RegisterStringPref(const char* path, 246 const std::string& default_value) { 247 RegisterPreference(path, Value::CreateStringValue(default_value)); 248} 249 250void PrefService::RegisterFilePathPref(const char* path, 251 const FilePath& default_value) { 252 RegisterPreference(path, Value::CreateStringValue(default_value.value())); 253} 254 255void PrefService::RegisterListPref(const char* path) { 256 RegisterPreference(path, new ListValue()); 257} 258 259void PrefService::RegisterDictionaryPref(const char* path) { 260 RegisterPreference(path, new DictionaryValue()); 261} 262 263void PrefService::RegisterLocalizedBooleanPref(const char* path, 264 int locale_default_message_id) { 265 RegisterPreference( 266 path, 267 CreateLocaleDefaultValue(Value::TYPE_BOOLEAN, locale_default_message_id)); 268} 269 270void PrefService::RegisterLocalizedIntegerPref(const char* path, 271 int locale_default_message_id) { 272 RegisterPreference( 273 path, 274 CreateLocaleDefaultValue(Value::TYPE_INTEGER, locale_default_message_id)); 275} 276 277void PrefService::RegisterLocalizedRealPref(const char* path, 278 int locale_default_message_id) { 279 RegisterPreference( 280 path, 281 CreateLocaleDefaultValue(Value::TYPE_REAL, locale_default_message_id)); 282} 283 284void PrefService::RegisterLocalizedStringPref(const char* path, 285 int locale_default_message_id) { 286 RegisterPreference( 287 path, 288 CreateLocaleDefaultValue(Value::TYPE_STRING, locale_default_message_id)); 289} 290 291bool PrefService::GetBoolean(const char* path) const { 292 DCHECK(CalledOnValidThread()); 293 294 bool result = false; 295 296 const Preference* pref = FindPreference(path); 297 if (!pref) { 298 NOTREACHED() << "Trying to read an unregistered pref: " << path; 299 return result; 300 } 301 bool rv = pref->GetValue()->GetAsBoolean(&result); 302 DCHECK(rv); 303 return result; 304} 305 306int PrefService::GetInteger(const char* path) const { 307 DCHECK(CalledOnValidThread()); 308 309 int result = 0; 310 311 const Preference* pref = FindPreference(path); 312 if (!pref) { 313 NOTREACHED() << "Trying to read an unregistered pref: " << path; 314 return result; 315 } 316 bool rv = pref->GetValue()->GetAsInteger(&result); 317 DCHECK(rv); 318 return result; 319} 320 321double PrefService::GetReal(const char* path) const { 322 DCHECK(CalledOnValidThread()); 323 324 double result = 0.0; 325 326 const Preference* pref = FindPreference(path); 327 if (!pref) { 328 NOTREACHED() << "Trying to read an unregistered pref: " << path; 329 return result; 330 } 331 bool rv = pref->GetValue()->GetAsReal(&result); 332 DCHECK(rv); 333 return result; 334} 335 336std::string PrefService::GetString(const char* path) const { 337 DCHECK(CalledOnValidThread()); 338 339 std::string result; 340 341 const Preference* pref = FindPreference(path); 342 if (!pref) { 343 NOTREACHED() << "Trying to read an unregistered pref: " << path; 344 return result; 345 } 346 bool rv = pref->GetValue()->GetAsString(&result); 347 DCHECK(rv); 348 return result; 349} 350 351FilePath PrefService::GetFilePath(const char* path) const { 352 DCHECK(CalledOnValidThread()); 353 354 FilePath::StringType result; 355 356 const Preference* pref = FindPreference(path); 357 if (!pref) { 358 NOTREACHED() << "Trying to read an unregistered pref: " << path; 359 return FilePath(result); 360 } 361 bool rv = pref->GetValue()->GetAsString(&result); 362 DCHECK(rv); 363#if defined(OS_POSIX) 364 // We store filepaths as UTF8, so convert it back to the system type. 365 result = base::SysWideToNativeMB(UTF8ToWide(result)); 366#endif 367 return FilePath(result); 368} 369 370bool PrefService::HasPrefPath(const char* path) const { 371 return pref_value_store_->HasPrefPath(path); 372} 373 374const PrefService::Preference* PrefService::FindPreference( 375 const char* pref_name) const { 376 DCHECK(CalledOnValidThread()); 377 Preference p(this, pref_name); 378 PreferenceSet::const_iterator it = prefs_.find(&p); 379 return it == prefs_.end() ? NULL : *it; 380} 381 382bool PrefService::ReadOnly() const { 383 return user_pref_store_->ReadOnly(); 384} 385 386PrefNotifier* PrefService::pref_notifier() const { 387 return pref_notifier_.get(); 388} 389 390bool PrefService::IsManagedPreference(const char* pref_name) const { 391 const Preference* pref = FindPreference(pref_name); 392 if (pref && pref->IsManaged()) { 393 return true; 394 } 395 return false; 396} 397 398const DictionaryValue* PrefService::GetDictionary(const char* path) const { 399 DCHECK(CalledOnValidThread()); 400 401 const Preference* pref = FindPreference(path); 402 if (!pref) { 403 NOTREACHED() << "Trying to read an unregistered pref: " << path; 404 return NULL; 405 } 406 const Value* value = pref->GetValue(); 407 if (value->GetType() == Value::TYPE_NULL) 408 return NULL; 409 return static_cast<const DictionaryValue*>(value); 410} 411 412const ListValue* PrefService::GetList(const char* path) const { 413 DCHECK(CalledOnValidThread()); 414 415 const Preference* pref = FindPreference(path); 416 if (!pref) { 417 NOTREACHED() << "Trying to read an unregistered pref: " << path; 418 return NULL; 419 } 420 const Value* value = pref->GetValue(); 421 if (value->GetType() == Value::TYPE_NULL) 422 return NULL; 423 return static_cast<const ListValue*>(value); 424} 425 426#ifndef ANDROID 427void PrefService::AddPrefObserver(const char* path, 428 NotificationObserver* obs) { 429 pref_notifier_->AddPrefObserver(path, obs); 430} 431 432void PrefService::RemovePrefObserver(const char* path, 433 NotificationObserver* obs) { 434 pref_notifier_->RemovePrefObserver(path, obs); 435} 436#endif 437 438void PrefService::RegisterPreference(const char* path, Value* default_value) { 439 DCHECK(CalledOnValidThread()); 440 441 // The main code path takes ownership, but most don't. We'll be safe. 442 scoped_ptr<Value> scoped_value(default_value); 443 444 if (FindPreference(path)) { 445 NOTREACHED() << "Tried to register duplicate pref " << path; 446 return; 447 } 448 449 Value::ValueType orig_type = default_value->GetType(); 450 DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) << 451 "invalid preference type: " << orig_type; 452 453 // We set the default value of dictionaries and lists to be null so it's 454 // easier for callers to check for empty dict/list prefs. The PrefValueStore 455 // accepts ownership of the value (null or default_value). 456 if (Value::TYPE_LIST == orig_type || Value::TYPE_DICTIONARY == orig_type) { 457 default_store_->SetDefaultValue(path, Value::CreateNullValue()); 458 } else { 459 // Hand off ownership. 460 default_store_->SetDefaultValue(path, scoped_value.release()); 461 } 462 463 pref_value_store_->RegisterPreferenceType(path, orig_type); 464 prefs_.insert(new Preference(this, path)); 465} 466 467void PrefService::ClearPref(const char* path) { 468 DCHECK(CalledOnValidThread()); 469 470 const Preference* pref = FindPreference(path); 471 if (!pref) { 472 NOTREACHED() << "Trying to clear an unregistered pref: " << path; 473 return; 474 } 475<<<<<<< HEAD 476#ifndef ANDROID 477 if (pref_value_store_->RemoveUserPrefValue(path)) 478 pref_notifier_->OnUserPreferenceSet(path); 479#endif 480======= 481 user_pref_store_->RemoveValue(path); 482>>>>>>> chromium.org at r10.0.621.0 483} 484 485void PrefService::Set(const char* path, const Value& value) { 486 DCHECK(CalledOnValidThread()); 487 488 const Preference* pref = FindPreference(path); 489 if (!pref) { 490 NOTREACHED() << "Trying to write an unregistered pref: " << path; 491 return; 492 } 493 494 // Allow dictionary and list types to be set to null, which removes their 495 // user values. 496 if (value.GetType() == Value::TYPE_NULL && 497 (pref->GetType() == Value::TYPE_DICTIONARY || 498 pref->GetType() == Value::TYPE_LIST)) { 499 user_pref_store_->RemoveValue(path); 500 } else if (pref->GetType() != value.GetType()) { 501 NOTREACHED() << "Trying to set pref " << path 502 << " of type " << pref->GetType() 503 << " to value of type " << value.GetType(); 504 } else { 505 user_pref_store_->SetValue(path, value.DeepCopy()); 506 } 507<<<<<<< HEAD 508#ifndef ANDROID 509 if (value_changed) 510 pref_notifier_->OnUserPreferenceSet(path); 511#endif 512======= 513>>>>>>> chromium.org at r10.0.621.0 514} 515 516void PrefService::SetBoolean(const char* path, bool value) { 517 SetUserPrefValue(path, Value::CreateBooleanValue(value)); 518} 519 520void PrefService::SetInteger(const char* path, int value) { 521 SetUserPrefValue(path, Value::CreateIntegerValue(value)); 522} 523 524void PrefService::SetReal(const char* path, double value) { 525 SetUserPrefValue(path, Value::CreateRealValue(value)); 526} 527 528void PrefService::SetString(const char* path, const std::string& value) { 529 SetUserPrefValue(path, Value::CreateStringValue(value)); 530} 531 532void PrefService::SetFilePath(const char* path, const FilePath& value) { 533#if defined(OS_POSIX) 534 // Value::SetString only knows about UTF8 strings, so convert the path from 535 // the system native value to UTF8. 536 std::string path_utf8 = WideToUTF8(base::SysNativeMBToWide(value.value())); 537 Value* new_value = Value::CreateStringValue(path_utf8); 538#else 539 Value* new_value = Value::CreateStringValue(value.value()); 540#endif 541 542 SetUserPrefValue(path, new_value); 543} 544 545void PrefService::SetInt64(const char* path, int64 value) { 546 SetUserPrefValue(path, Value::CreateStringValue(base::Int64ToString(value))); 547} 548 549int64 PrefService::GetInt64(const char* path) const { 550 DCHECK(CalledOnValidThread()); 551 552 const Preference* pref = FindPreference(path); 553 if (!pref) { 554 NOTREACHED() << "Trying to read an unregistered pref: " << path; 555 return 0; 556 } 557 std::string result("0"); 558 bool rv = pref->GetValue()->GetAsString(&result); 559 DCHECK(rv); 560 561 int64 val; 562 base::StringToInt64(result, &val); 563 return val; 564} 565 566void PrefService::RegisterInt64Pref(const char* path, int64 default_value) { 567 RegisterPreference( 568 path, Value::CreateStringValue(base::Int64ToString(default_value))); 569} 570 571DictionaryValue* PrefService::GetMutableDictionary(const char* path) { 572 DCHECK(CalledOnValidThread()); 573 574 const Preference* pref = FindPreference(path); 575 if (!pref) { 576 NOTREACHED() << "Trying to get an unregistered pref: " << path; 577 return NULL; 578 } 579 if (pref->GetType() != Value::TYPE_DICTIONARY) { 580 NOTREACHED() << "Wrong type for GetMutableDictionary: " << path; 581 return NULL; 582 } 583 584 DictionaryValue* dict = NULL; 585 Value* tmp_value = NULL; 586 // Look for an existing preference in the user store. If it doesn't 587 // exist or isn't the correct type, create a new user preference. 588 if (user_pref_store_->GetValue(path, &tmp_value) 589 != PersistentPrefStore::READ_OK || 590 !tmp_value->IsType(Value::TYPE_DICTIONARY)) { 591 dict = new DictionaryValue; 592 user_pref_store_->SetValueSilently(path, dict); 593 } else { 594 dict = static_cast<DictionaryValue*>(tmp_value); 595 } 596 return dict; 597} 598 599ListValue* PrefService::GetMutableList(const char* path) { 600 DCHECK(CalledOnValidThread()); 601 602 const Preference* pref = FindPreference(path); 603 if (!pref) { 604 NOTREACHED() << "Trying to get an unregistered pref: " << path; 605 return NULL; 606 } 607 if (pref->GetType() != Value::TYPE_LIST) { 608 NOTREACHED() << "Wrong type for GetMutableList: " << path; 609 return NULL; 610 } 611 612 ListValue* list = NULL; 613 Value* tmp_value = NULL; 614 // Look for an existing preference in the user store. If it doesn't 615 // exist or isn't the correct type, create a new user preference. 616 if (user_pref_store_->GetValue(path, &tmp_value) 617 != PersistentPrefStore::READ_OK || 618 !tmp_value->IsType(Value::TYPE_LIST)) { 619 list = new ListValue; 620 user_pref_store_->SetValueSilently(path, list); 621 } else { 622 list = static_cast<ListValue*>(tmp_value); 623 } 624 return list; 625} 626 627void PrefService::SetUserPrefValue(const char* path, Value* new_value) { 628 DCHECK(CalledOnValidThread()); 629 630 const Preference* pref = FindPreference(path); 631 if (!pref) { 632 NOTREACHED() << "Trying to write an unregistered pref: " << path; 633 return; 634 } 635 if (pref->GetType() != new_value->GetType()) { 636 NOTREACHED() << "Trying to set pref " << path 637 << " of type " << pref->GetType() 638 << " to value of type " << new_value->GetType(); 639 return; 640 } 641 642<<<<<<< HEAD 643#ifndef ANDROID 644 if (pref_value_store_->SetUserPrefValue(path, new_value)) 645 pref_notifier_->OnUserPreferenceSet(path); 646#endif 647======= 648 user_pref_store_->SetValue(path, new_value); 649>>>>>>> chromium.org at r10.0.621.0 650} 651 652/////////////////////////////////////////////////////////////////////////////// 653// PrefService::Preference 654 655PrefService::Preference::Preference(const PrefService* service, 656 const char* name) 657 : name_(name), 658 pref_service_(service) { 659 DCHECK(name); 660 DCHECK(service); 661} 662 663Value::ValueType PrefService::Preference::GetType() const { 664 return pref_service_->pref_value_store_->GetRegisteredType(name_); 665} 666 667const Value* PrefService::Preference::GetValue() const { 668 DCHECK(pref_service_->FindPreference(name_.c_str())) << 669 "Must register pref before getting its value"; 670 671 Value* found_value = NULL; 672 if (pref_service_->pref_value_store_->GetValue(name_, &found_value)) 673 return found_value; 674 675 // Every registered preference has at least a default value. 676 NOTREACHED() << "no valid value found for registered pref " << name_; 677 return NULL; 678} 679 680bool PrefService::Preference::IsManaged() const { 681 PrefValueStore* pref_value_store = pref_service_->pref_value_store_; 682 return pref_value_store->PrefValueInManagedPlatformStore(name_.c_str()) || 683 pref_value_store->PrefValueInDeviceManagementStore(name_.c_str()); 684} 685 686bool PrefService::Preference::HasExtensionSetting() const { 687 return pref_service_->pref_value_store_-> 688 PrefValueInExtensionStore(name_.c_str()); 689} 690 691bool PrefService::Preference::HasUserSetting() const { 692 return pref_service_->pref_value_store_-> 693 PrefValueInUserStore(name_.c_str()); 694} 695 696bool PrefService::Preference::IsExtensionControlled() const { 697 return pref_service_->pref_value_store_-> 698 PrefValueFromExtensionStore(name_.c_str()); 699} 700 701bool PrefService::Preference::IsUserControlled() const { 702 return pref_service_->pref_value_store_-> 703 PrefValueFromUserStore(name_.c_str()); 704} 705 706bool PrefService::Preference::IsDefaultValue() const { 707 return pref_service_->pref_value_store_-> 708 PrefValueFromDefaultStore(name_.c_str()); 709} 710 711bool PrefService::Preference::IsUserModifiable() const { 712 return pref_service_->pref_value_store_-> 713 PrefValueUserModifiable(name_.c_str()); 714} 715