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