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