1 // Copyright (c) 2012 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.
5 #include "components/prefs/pref_service.h"
11 #include "base/bind.h"
12 #include "base/files/file_path.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/metrics/histogram.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/stl_util.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h"
21 #include "base/threading/thread_task_runner_handle.h"
22 #include "base/value_conversions.h"
23 #include "build/build_config.h"
24 #include "components/prefs/default_pref_store.h"
25 #include "components/prefs/pref_notifier_impl.h"
26 #include "components/prefs/pref_registry.h"
30 class ReadErrorHandler : public PersistentPrefStore::ReadErrorDelegate {
33 base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>;
34 explicit ReadErrorHandler(ErrorCallback cb) : callback_(cb) {}
36 void OnError(PersistentPrefStore::PrefReadError error) override {
41 ErrorCallback callback_;
43 DISALLOW_COPY_AND_ASSIGN(ReadErrorHandler);
46 // Returns the WriteablePrefStore::PrefWriteFlags for the pref with the given
48 uint32_t GetWriteFlags(const PrefService::Preference* pref) {
49 uint32_t write_flags = WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS;
54 if (pref->registration_flags() & PrefRegistry::LOSSY_PREF)
55 write_flags |= WriteablePrefStore::LOSSY_PREF_WRITE_FLAG;
59 // For prefs names in |pref_store| that are not presented in |pref_changed_map|,
60 // check if their values differ from those in pref_service->FindPreference() and
61 // add the result into |pref_changed_map|.
62 void CheckForNewPrefChangesInPrefStore(
63 std::map<std::string, bool>* pref_changed_map,
64 PrefStore* pref_store,
65 PrefService* pref_service) {
68 auto values = pref_store->GetValues();
69 for (const auto& item : values->DictItems()) {
70 // If the key already presents, skip it as a store with higher precedence
71 // already sets the entry.
72 if (pref_changed_map->find(item.first) != pref_changed_map->end())
74 const PrefService::Preference* pref =
75 pref_service->FindPreference(item.first);
78 pref_changed_map->emplace(item.first, *(pref->GetValue()) != item.second);
84 PrefService::PrefService(
85 std::unique_ptr<PrefNotifierImpl> pref_notifier,
86 std::unique_ptr<PrefValueStore> pref_value_store,
87 scoped_refptr<PersistentPrefStore> user_prefs,
88 scoped_refptr<PrefRegistry> pref_registry,
89 base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
92 : pref_notifier_(std::move(pref_notifier)),
93 pref_value_store_(std::move(pref_value_store)),
94 user_pref_store_(std::move(user_prefs)),
95 read_error_callback_(std::move(read_error_callback)),
96 pref_registry_(std::move(pref_registry)) {
97 pref_notifier_->SetPrefService(this);
99 DCHECK(pref_registry_);
100 DCHECK(pref_value_store_);
102 InitFromStorage(async);
105 PrefService::~PrefService() {
106 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
109 void PrefService::InitFromStorage(bool async) {
110 if (user_pref_store_->IsInitializationComplete()) {
111 read_error_callback_.Run(user_pref_store_->GetReadError());
113 read_error_callback_.Run(user_pref_store_->ReadPrefs());
115 // Guarantee that initialization happens after this function returned.
116 base::ThreadTaskRunnerHandle::Get()->PostTask(
118 base::BindOnce(&PersistentPrefStore::ReadPrefsAsync, user_pref_store_,
119 new ReadErrorHandler(read_error_callback_)));
123 void PrefService::CommitPendingWrite(
124 base::OnceClosure reply_callback,
125 base::OnceClosure synchronous_done_callback) {
126 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
127 user_pref_store_->CommitPendingWrite(std::move(reply_callback),
128 std::move(synchronous_done_callback));
131 void PrefService::SchedulePendingLossyWrites() {
132 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
133 user_pref_store_->SchedulePendingLossyWrites();
136 bool PrefService::GetBoolean(const std::string& path) const {
137 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
141 const base::Value* value = GetPreferenceValue(path);
143 NOTREACHED() << "Trying to read an unregistered pref: " << path;
146 bool rv = value->GetAsBoolean(&result);
151 int PrefService::GetInteger(const std::string& path) const {
152 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
156 const base::Value* value = GetPreferenceValue(path);
158 NOTREACHED() << "Trying to read an unregistered pref: " << path;
161 bool rv = value->GetAsInteger(&result);
166 double PrefService::GetDouble(const std::string& path) const {
167 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
171 const base::Value* value = GetPreferenceValue(path);
173 NOTREACHED() << "Trying to read an unregistered pref: " << path;
176 bool rv = value->GetAsDouble(&result);
181 std::string PrefService::GetString(const std::string& path) const {
182 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
186 const base::Value* value = GetPreferenceValue(path);
188 NOTREACHED() << "Trying to read an unregistered pref: " << path;
191 bool rv = value->GetAsString(&result);
196 base::FilePath PrefService::GetFilePath(const std::string& path) const {
197 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
199 base::FilePath result;
201 const base::Value* value = GetPreferenceValue(path);
203 NOTREACHED() << "Trying to read an unregistered pref: " << path;
204 return base::FilePath(result);
206 bool rv = base::GetValueAsFilePath(*value, &result);
211 bool PrefService::HasPrefPath(const std::string& path) const {
212 const Preference* pref = FindPreference(path);
213 return pref && !pref->IsDefaultValue();
216 void PrefService::IteratePreferenceValues(
217 base::RepeatingCallback<void(const std::string& key,
218 const base::Value& value)> callback) const {
219 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
220 for (const auto& it : *pref_registry_)
221 callback.Run(it.first, *GetPreferenceValue(it.first));
224 std::unique_ptr<base::DictionaryValue> PrefService::GetPreferenceValues(
225 IncludeDefaults include_defaults) const {
226 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
227 std::unique_ptr<base::DictionaryValue> out(new base::DictionaryValue);
228 for (const auto& it : *pref_registry_) {
229 if (include_defaults == INCLUDE_DEFAULTS) {
230 out->Set(it.first, GetPreferenceValue(it.first)->CreateDeepCopy());
232 const Preference* pref = FindPreference(it.first);
233 if (pref->IsDefaultValue())
235 out->Set(it.first, pref->GetValue()->CreateDeepCopy());
241 const PrefService::Preference* PrefService::FindPreference(
242 const std::string& pref_name) const {
243 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
244 auto it = prefs_map_.find(pref_name);
245 if (it != prefs_map_.end())
246 return &(it->second);
247 const base::Value* default_value = nullptr;
248 if (!pref_registry_->defaults()->GetValue(pref_name, &default_value))
251 .insert(std::make_pair(
252 pref_name, Preference(this, pref_name, default_value->type())))
254 return &(it->second);
257 bool PrefService::ReadOnly() const {
258 return user_pref_store_->ReadOnly();
261 PrefService::PrefInitializationStatus PrefService::GetInitializationStatus()
263 if (!user_pref_store_->IsInitializationComplete())
264 return INITIALIZATION_STATUS_WAITING;
266 switch (user_pref_store_->GetReadError()) {
267 case PersistentPrefStore::PREF_READ_ERROR_NONE:
268 return INITIALIZATION_STATUS_SUCCESS;
269 case PersistentPrefStore::PREF_READ_ERROR_NO_FILE:
270 return INITIALIZATION_STATUS_CREATED_NEW_PREF_STORE;
272 return INITIALIZATION_STATUS_ERROR;
276 PrefService::PrefInitializationStatus
277 PrefService::GetAllPrefStoresInitializationStatus() const {
278 if (!pref_value_store_->IsInitializationComplete())
279 return INITIALIZATION_STATUS_WAITING;
281 return GetInitializationStatus();
284 bool PrefService::IsManagedPreference(const std::string& pref_name) const {
285 const Preference* pref = FindPreference(pref_name);
286 return pref && pref->IsManaged();
289 bool PrefService::IsPreferenceManagedByCustodian(
290 const std::string& pref_name) const {
291 const Preference* pref = FindPreference(pref_name);
292 return pref && pref->IsManagedByCustodian();
295 bool PrefService::IsUserModifiablePreference(
296 const std::string& pref_name) const {
297 const Preference* pref = FindPreference(pref_name);
298 return pref && pref->IsUserModifiable();
301 const base::Value* PrefService::Get(const std::string& path) const {
302 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
304 const base::Value* value = GetPreferenceValue(path);
306 NOTREACHED() << "Trying to read an unregistered pref: " << path;
312 const base::DictionaryValue* PrefService::GetDictionary(
313 const std::string& path) const {
314 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
316 const base::Value* value = GetPreferenceValue(path);
318 NOTREACHED() << "Trying to read an unregistered pref: " << path;
321 if (value->type() != base::Value::Type::DICTIONARY) {
325 return static_cast<const base::DictionaryValue*>(value);
328 const base::Value* PrefService::GetUserPrefValue(
329 const std::string& path) const {
330 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
332 const Preference* pref = FindPreference(path);
334 NOTREACHED() << "Trying to get an unregistered pref: " << path;
338 // Look for an existing preference in the user store. If it doesn't
339 // exist, return NULL.
340 base::Value* value = nullptr;
341 if (!user_pref_store_->GetMutableValue(path, &value))
344 if (value->type() != pref->GetType()) {
345 NOTREACHED() << "Pref value type doesn't match registered type.";
352 void PrefService::SetDefaultPrefValue(const std::string& path,
354 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
355 pref_registry_->SetDefaultPrefValue(path, std::move(value));
358 const base::Value* PrefService::GetDefaultPrefValue(
359 const std::string& path) const {
360 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
361 // Lookup the preference in the default store.
362 const base::Value* value = nullptr;
363 bool has_value = pref_registry_->defaults()->GetValue(path, &value);
364 DCHECK(has_value) << "Default value missing for pref: " << path;
368 const base::ListValue* PrefService::GetList(const std::string& path) const {
369 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
371 const base::Value* value = GetPreferenceValue(path);
373 NOTREACHED() << "Trying to read an unregistered pref: " << path;
376 if (value->type() != base::Value::Type::LIST) {
380 return static_cast<const base::ListValue*>(value);
383 void PrefService::AddPrefObserver(const std::string& path, PrefObserver* obs) {
384 pref_notifier_->AddPrefObserver(path, obs);
387 void PrefService::RemovePrefObserver(const std::string& path,
389 pref_notifier_->RemovePrefObserver(path, obs);
392 void PrefService::AddPrefInitObserver(base::OnceCallback<void(bool)> obs) {
393 pref_notifier_->AddInitObserver(std::move(obs));
396 PrefRegistry* PrefService::DeprecatedGetPrefRegistry() {
397 return pref_registry_.get();
400 void PrefService::ClearPref(const std::string& path) {
401 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
403 const Preference* pref = FindPreference(path);
405 NOTREACHED() << "Trying to clear an unregistered pref: " << path;
408 user_pref_store_->RemoveValue(path, GetWriteFlags(pref));
411 void PrefService::ClearMutableValues() {
412 user_pref_store_->ClearMutableValues();
415 void PrefService::OnStoreDeletionFromDisk() {
416 user_pref_store_->OnStoreDeletionFromDisk();
419 void PrefService::ChangePrefValueStore(
420 PrefStore* managed_prefs,
421 PrefStore* supervised_user_prefs,
422 PrefStore* extension_prefs,
423 PrefStore* recommended_prefs,
424 std::unique_ptr<PrefValueStore::Delegate> delegate) {
425 // Only adding new pref stores are supported.
426 DCHECK(!pref_value_store_->HasPrefStore(PrefValueStore::MANAGED_STORE) ||
429 !pref_value_store_->HasPrefStore(PrefValueStore::SUPERVISED_USER_STORE) ||
430 !supervised_user_prefs);
431 DCHECK(!pref_value_store_->HasPrefStore(PrefValueStore::EXTENSION_STORE) ||
433 DCHECK(!pref_value_store_->HasPrefStore(PrefValueStore::RECOMMENDED_STORE) ||
436 // If some of the stores are already initialized, check for pref value changes
437 // according to store precedence.
438 std::map<std::string, bool> pref_changed_map;
439 CheckForNewPrefChangesInPrefStore(&pref_changed_map, managed_prefs, this);
440 CheckForNewPrefChangesInPrefStore(&pref_changed_map, supervised_user_prefs,
442 CheckForNewPrefChangesInPrefStore(&pref_changed_map, extension_prefs, this);
443 CheckForNewPrefChangesInPrefStore(&pref_changed_map, recommended_prefs, this);
445 pref_value_store_ = pref_value_store_->CloneAndSpecialize(
446 managed_prefs, supervised_user_prefs, extension_prefs,
447 nullptr /* command_line_prefs */, nullptr /* user_prefs */,
448 recommended_prefs, nullptr /* default_prefs */, pref_notifier_.get(),
449 std::move(delegate));
451 // Notify |pref_notifier_| on all changed values.
452 for (const auto& kv : pref_changed_map) {
454 pref_notifier_.get()->OnPreferenceChanged(kv.first);
458 void PrefService::AddPrefObserverAllPrefs(PrefObserver* obs) {
459 pref_notifier_->AddPrefObserverAllPrefs(obs);
462 void PrefService::RemovePrefObserverAllPrefs(PrefObserver* obs) {
463 pref_notifier_->RemovePrefObserverAllPrefs(obs);
466 void PrefService::Set(const std::string& path, const base::Value& value) {
467 SetUserPrefValue(path, value.CreateDeepCopy());
470 void PrefService::SetBoolean(const std::string& path, bool value) {
471 SetUserPrefValue(path, std::make_unique<base::Value>(value));
474 void PrefService::SetInteger(const std::string& path, int value) {
475 SetUserPrefValue(path, std::make_unique<base::Value>(value));
478 void PrefService::SetDouble(const std::string& path, double value) {
479 SetUserPrefValue(path, std::make_unique<base::Value>(value));
482 void PrefService::SetString(const std::string& path, const std::string& value) {
483 SetUserPrefValue(path, std::make_unique<base::Value>(value));
486 void PrefService::SetFilePath(const std::string& path,
487 const base::FilePath& value) {
489 path, base::Value::ToUniquePtrValue(base::CreateFilePathValue(value)));
492 void PrefService::SetInt64(const std::string& path, int64_t value) {
493 SetUserPrefValue(path,
494 std::make_unique<base::Value>(base::Int64ToString(value)));
497 int64_t PrefService::GetInt64(const std::string& path) const {
498 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
500 const base::Value* value = GetPreferenceValue(path);
502 NOTREACHED() << "Trying to read an unregistered pref: " << path;
505 std::string result("0");
506 bool rv = value->GetAsString(&result);
510 base::StringToInt64(result, &val);
514 void PrefService::SetUint64(const std::string& path, uint64_t value) {
515 SetUserPrefValue(path,
516 std::make_unique<base::Value>(base::NumberToString(value)));
519 uint64_t PrefService::GetUint64(const std::string& path) const {
520 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
522 const base::Value* value = GetPreferenceValue(path);
524 NOTREACHED() << "Trying to read an unregistered pref: " << path;
527 std::string result("0");
528 bool rv = value->GetAsString(&result);
532 base::StringToUint64(result, &val);
536 void PrefService::SetTime(const std::string& path, base::Time value) {
537 SetInt64(path, value.ToDeltaSinceWindowsEpoch().InMicroseconds());
540 base::Time PrefService::GetTime(const std::string& path) const {
541 return base::Time::FromDeltaSinceWindowsEpoch(
542 base::TimeDelta::FromMicroseconds(GetInt64(path)));
545 void PrefService::SetTimeDelta(const std::string& path, base::TimeDelta value) {
546 SetInt64(path, value.InMicroseconds());
549 base::TimeDelta PrefService::GetTimeDelta(const std::string& path) const {
550 return base::TimeDelta::FromMicroseconds(GetInt64(path));
553 base::Value* PrefService::GetMutableUserPref(const std::string& path,
554 base::Value::Type type) {
555 CHECK(type == base::Value::Type::DICTIONARY ||
556 type == base::Value::Type::LIST);
557 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
559 const Preference* pref = FindPreference(path);
561 NOTREACHED() << "Trying to get an unregistered pref: " << path;
564 if (pref->GetType() != type) {
565 NOTREACHED() << "Wrong type for GetMutableValue: " << path;
569 // Look for an existing preference in the user store. If it doesn't
570 // exist, create a new user preference.
571 base::Value* value = nullptr;
572 if (user_pref_store_->GetMutableValue(path, &value))
575 // If no user preference exists, clone default value.
576 const base::Value* default_value = nullptr;
577 pref_registry_->defaults()->GetValue(path, &default_value);
578 DCHECK_EQ(default_value->type(), type);
579 user_pref_store_->SetValueSilently(path, default_value->CreateDeepCopy(),
580 GetWriteFlags(pref));
581 user_pref_store_->GetMutableValue(path, &value);
585 void PrefService::ReportUserPrefChanged(const std::string& key) {
586 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
587 user_pref_store_->ReportValueChanged(key, GetWriteFlags(FindPreference(key)));
590 void PrefService::ReportUserPrefChanged(
591 const std::string& key,
592 std::set<std::vector<std::string>> path_components) {
593 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
594 user_pref_store_->ReportSubValuesChanged(key, std::move(path_components),
595 GetWriteFlags(FindPreference(key)));
598 void PrefService::SetUserPrefValue(const std::string& path,
599 std::unique_ptr<base::Value> new_value) {
600 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
602 const Preference* pref = FindPreference(path);
604 NOTREACHED() << "Trying to write an unregistered pref: " << path;
607 if (pref->GetType() != new_value->type()) {
608 NOTREACHED() << "Trying to set pref " << path << " of type "
609 << pref->GetType() << " to value of type "
610 << new_value->type();
614 user_pref_store_->SetValue(path, std::move(new_value), GetWriteFlags(pref));
617 void PrefService::UpdateCommandLinePrefStore(PrefStore* command_line_store) {
618 pref_value_store_->UpdateCommandLinePrefStore(command_line_store);
621 ///////////////////////////////////////////////////////////////////////////////
622 // PrefService::Preference
624 PrefService::Preference::Preference(const PrefService* service,
626 base::Value::Type type)
627 : name_(std::move(name)),
629 // Cache the registration flags at creation time to avoid multiple map
631 registration_flags_(service->pref_registry_->GetRegistrationFlags(name_)),
632 pref_service_(service) {}
634 const base::Value* PrefService::Preference::GetValue() const {
635 const base::Value* result = pref_service_->GetPreferenceValue(name_);
636 DCHECK(result) << "Must register pref before getting its value";
640 const base::Value* PrefService::Preference::GetRecommendedValue() const {
641 DCHECK(pref_service_->FindPreference(name_))
642 << "Must register pref before getting its value";
644 const base::Value* found_value = nullptr;
645 if (pref_value_store()->GetRecommendedValue(name_, type_, &found_value)) {
646 DCHECK(found_value->type() == type_);
650 // The pref has no recommended value.
654 bool PrefService::Preference::IsManaged() const {
655 return pref_value_store()->PrefValueInManagedStore(name_);
658 bool PrefService::Preference::IsManagedByCustodian() const {
659 return pref_value_store()->PrefValueInSupervisedStore(name_);
662 bool PrefService::Preference::IsRecommended() const {
663 return pref_value_store()->PrefValueFromRecommendedStore(name_);
666 bool PrefService::Preference::HasExtensionSetting() const {
667 return pref_value_store()->PrefValueInExtensionStore(name_);
670 bool PrefService::Preference::HasUserSetting() const {
671 return pref_value_store()->PrefValueInUserStore(name_);
674 bool PrefService::Preference::IsExtensionControlled() const {
675 return pref_value_store()->PrefValueFromExtensionStore(name_);
678 bool PrefService::Preference::IsUserControlled() const {
679 return pref_value_store()->PrefValueFromUserStore(name_);
682 bool PrefService::Preference::IsDefaultValue() const {
683 return pref_value_store()->PrefValueFromDefaultStore(name_);
686 bool PrefService::Preference::IsUserModifiable() const {
687 return pref_value_store()->PrefValueUserModifiable(name_);
690 bool PrefService::Preference::IsExtensionModifiable() const {
691 return pref_value_store()->PrefValueExtensionModifiable(name_);
694 const base::Value* PrefService::GetPreferenceValue(
695 const std::string& path) const {
696 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
698 // TODO(battre): This is a check for crbug.com/435208. After analyzing some
699 // crash dumps it looks like the PrefService is accessed even though it has
700 // been cleared already.
701 CHECK(pref_registry_);
702 CHECK(pref_registry_->defaults());
703 CHECK(pref_value_store_);
705 const base::Value* default_value = nullptr;
706 if (pref_registry_->defaults()->GetValue(path, &default_value)) {
707 const base::Value* found_value = nullptr;
708 base::Value::Type default_type = default_value->type();
709 if (pref_value_store_->GetValue(path, default_type, &found_value)) {
710 DCHECK(found_value->type() == default_type);
713 // Every registered preference has at least a default value.
714 NOTREACHED() << "no valid value found for registered pref " << path;