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