• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
CreateLocaleDefaultValue(Value::ValueType type,int message_id)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.
NotifyReadError(PrefService * pref,int message_id)80 void NotifyReadError(PrefService* pref, int message_id) {
81   ShowProfileErrorDialog(message_id);
82 }
83 
84 }  // namespace
85 
86 // static
CreatePrefService(const FilePath & pref_filename,PrefStore * extension_prefs,Profile * profile)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
CreatePrefServiceAsync(const FilePath & pref_filename,PrefStore * extension_prefs,Profile * profile,PrefService::Delegate * delegate)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 
CreateIncognitoPrefService(PrefStore * incognito_extension_prefs)135 PrefService* PrefService::CreateIncognitoPrefService(
136     PrefStore* incognito_extension_prefs) {
137   return new PrefService(*this, incognito_extension_prefs);
138 }
139 
PrefService(PrefStore * managed_platform_prefs,PrefStore * managed_cloud_prefs,PrefStore * extension_prefs,PrefStore * command_line_prefs,PersistentPrefStore * user_prefs,PrefStore * recommended_platform_prefs,PrefStore * recommended_cloud_prefs,DefaultPrefStore * default_store,PrefService::Delegate * delegate)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 
PrefService(const PrefService & original,PrefStore * incognito_extension_prefs)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 
~PrefService()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 
OnPrefsRead(PersistentPrefStore::PrefReadError error,bool no_dir)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 
InitFromStorage()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 
ReloadPersistentPrefs()241 bool PrefService::ReloadPersistentPrefs() {
242   return user_pref_store_->ReadPrefs() ==
243              PersistentPrefStore::PREF_READ_ERROR_NONE;
244 }
245 
SavePersistentPrefs()246 bool PrefService::SavePersistentPrefs() {
247   DCHECK(CalledOnValidThread());
248   return user_pref_store_->WritePrefs();
249 }
250 
ScheduleSavePersistentPrefs()251 void PrefService::ScheduleSavePersistentPrefs() {
252   DCHECK(CalledOnValidThread());
253   user_pref_store_->ScheduleWritePrefs();
254 }
255 
CommitPendingWrite()256 void PrefService::CommitPendingWrite() {
257   DCHECK(CalledOnValidThread());
258   user_pref_store_->CommitPendingWrite();
259 }
260 
RegisterBooleanPref(const char * path,bool default_value)261 void PrefService::RegisterBooleanPref(const char* path,
262                                       bool default_value) {
263   RegisterPreference(path, Value::CreateBooleanValue(default_value));
264 }
265 
RegisterIntegerPref(const char * path,int default_value)266 void PrefService::RegisterIntegerPref(const char* path, int default_value) {
267   RegisterPreference(path, Value::CreateIntegerValue(default_value));
268 }
269 
RegisterDoublePref(const char * path,double default_value)270 void PrefService::RegisterDoublePref(const char* path, double default_value) {
271   RegisterPreference(path, Value::CreateDoubleValue(default_value));
272 }
273 
RegisterStringPref(const char * path,const std::string & default_value)274 void PrefService::RegisterStringPref(const char* path,
275                                      const std::string& default_value) {
276   RegisterPreference(path, Value::CreateStringValue(default_value));
277 }
278 
RegisterFilePathPref(const char * path,const FilePath & default_value)279 void PrefService::RegisterFilePathPref(const char* path,
280                                        const FilePath& default_value) {
281   RegisterPreference(path, Value::CreateStringValue(default_value.value()));
282 }
283 
RegisterListPref(const char * path)284 void PrefService::RegisterListPref(const char* path) {
285   RegisterPreference(path, new ListValue());
286 }
287 
RegisterListPref(const char * path,ListValue * default_value)288 void PrefService::RegisterListPref(const char* path, ListValue* default_value) {
289   RegisterPreference(path, default_value);
290 }
291 
RegisterDictionaryPref(const char * path)292 void PrefService::RegisterDictionaryPref(const char* path) {
293   RegisterPreference(path, new DictionaryValue());
294 }
295 
RegisterDictionaryPref(const char * path,DictionaryValue * default_value)296 void PrefService::RegisterDictionaryPref(const char* path,
297                                          DictionaryValue* default_value) {
298   RegisterPreference(path, default_value);
299 }
300 
RegisterLocalizedBooleanPref(const char * path,int locale_default_message_id)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 
RegisterLocalizedIntegerPref(const char * path,int locale_default_message_id)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 
RegisterLocalizedDoublePref(const char * path,int locale_default_message_id)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 
RegisterLocalizedStringPref(const char * path,int locale_default_message_id)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 
GetBoolean(const char * path) const329 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 
GetInteger(const char * path) const344 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 
GetDouble(const char * path) const359 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 
GetString(const char * path) const374 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 
GetFilePath(const char * path) const389 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 
HasPrefPath(const char * path) const404 bool PrefService::HasPrefPath(const char* path) const {
405   const Preference* pref = FindPreference(path);
406   return pref && !pref->IsDefaultValue();
407 }
408 
GetPreferenceValues() const409 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 
FindPreference(const char * pref_name) const423 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 
ReadOnly() const438 bool PrefService::ReadOnly() const {
439   return user_pref_store_->ReadOnly();
440 }
441 
IsManagedPreference(const char * pref_name) const442 bool PrefService::IsManagedPreference(const char* pref_name) const {
443   const Preference* pref = FindPreference(pref_name);
444   return pref && pref->IsManaged();
445 }
446 
GetDictionary(const char * path) const447 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 
GetList(const char * path) const463 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 
AddPrefObserver(const char * path,NotificationObserver * obs)479 void PrefService::AddPrefObserver(const char* path,
480                                   NotificationObserver* obs) {
481   pref_notifier_->AddPrefObserver(path, obs);
482 }
483 
RemovePrefObserver(const char * path,NotificationObserver * obs)484 void PrefService::RemovePrefObserver(const char* path,
485                                      NotificationObserver* obs) {
486   pref_notifier_->RemovePrefObserver(path, obs);
487 }
488 
RegisterPreference(const char * path,Value * default_value)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 
ClearPref(const char * path)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 
Set(const char * path,const Value & value)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 
SetBoolean(const char * path,bool value)537 void PrefService::SetBoolean(const char* path, bool value) {
538   SetUserPrefValue(path, Value::CreateBooleanValue(value));
539 }
540 
SetInteger(const char * path,int value)541 void PrefService::SetInteger(const char* path, int value) {
542   SetUserPrefValue(path, Value::CreateIntegerValue(value));
543 }
544 
SetDouble(const char * path,double value)545 void PrefService::SetDouble(const char* path, double value) {
546   SetUserPrefValue(path, Value::CreateDoubleValue(value));
547 }
548 
SetString(const char * path,const std::string & value)549 void PrefService::SetString(const char* path, const std::string& value) {
550   SetUserPrefValue(path, Value::CreateStringValue(value));
551 }
552 
SetFilePath(const char * path,const FilePath & value)553 void PrefService::SetFilePath(const char* path, const FilePath& value) {
554   SetUserPrefValue(path, base::CreateFilePathValue(value));
555 }
556 
SetList(const char * path,ListValue * value)557 void PrefService::SetList(const char* path, ListValue* value) {
558   SetUserPrefValue(path, value);
559 }
560 
SetInt64(const char * path,int64 value)561 void PrefService::SetInt64(const char* path, int64 value) {
562   SetUserPrefValue(path, Value::CreateStringValue(base::Int64ToString(value)));
563 }
564 
GetInt64(const char * path) const565 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 
RegisterInt64Pref(const char * path,int64 default_value)582 void PrefService::RegisterInt64Pref(const char* path, int64 default_value) {
583   RegisterPreference(
584       path, Value::CreateStringValue(base::Int64ToString(default_value)));
585 }
586 
GetMutableUserPref(const char * path,Value::ValueType type)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 
ReportUserPrefChanged(const std::string & key)622 void PrefService::ReportUserPrefChanged(const std::string& key) {
623   user_pref_store_->ReportValueChanged(key);
624 }
625 
SetUserPrefValue(const char * path,Value * new_value)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 
Preference(const PrefService * service,const char * name,Value::ValueType type)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 
GetType() const659 Value::ValueType PrefService::Preference::GetType() const {
660   return type_;
661 }
662 
GetValue() const663 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 
IsManaged() const678 bool PrefService::Preference::IsManaged() const {
679   return pref_value_store()->PrefValueInManagedStore(name_.c_str());
680 }
681 
HasExtensionSetting() const682 bool PrefService::Preference::HasExtensionSetting() const {
683   return pref_value_store()->PrefValueInExtensionStore(name_.c_str());
684 }
685 
HasUserSetting() const686 bool PrefService::Preference::HasUserSetting() const {
687   return pref_value_store()->PrefValueInUserStore(name_.c_str());
688 }
689 
IsExtensionControlled() const690 bool PrefService::Preference::IsExtensionControlled() const {
691   return pref_value_store()->PrefValueFromExtensionStore(name_.c_str());
692 }
693 
IsUserControlled() const694 bool PrefService::Preference::IsUserControlled() const {
695   return pref_value_store()->PrefValueFromUserStore(name_.c_str());
696 }
697 
IsDefaultValue() const698 bool PrefService::Preference::IsDefaultValue() const {
699   return pref_value_store()->PrefValueFromDefaultStore(name_.c_str());
700 }
701 
IsUserModifiable() const702 bool PrefService::Preference::IsUserModifiable() const {
703   return pref_value_store()->PrefValueUserModifiable(name_.c_str());
704 }
705 
IsExtensionModifiable() const706 bool PrefService::Preference::IsExtensionModifiable() const {
707   return pref_value_store()->PrefValueExtensionModifiable(name_.c_str());
708 }
709