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