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