Home | History | Annotate | Download | only in prefs
      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