1 // Copyright 2012 The Chromium Authors
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_member.h"
9 #include "base/functional/callback.h"
10 #include "base/functional/callback_helpers.h"
11 #include "base/json/values_util.h"
12 #include "base/location.h"
13 #include "base/task/sequenced_task_runner.h"
14 #include "base/values.h"
15 #include "components/prefs/pref_service.h"
17 using base::SequencedTaskRunner;
21 PrefMemberBase::PrefMemberBase() : prefs_(nullptr), setting_value_(false) {}
23 PrefMemberBase::~PrefMemberBase() {
27 void PrefMemberBase::Init(const std::string& pref_name,
29 const NamedChangeCallback& observer) {
31 Init(pref_name, prefs);
34 void PrefMemberBase::Init(const std::string& pref_name, PrefService* prefs) {
36 DCHECK(pref_name_.empty()); // Check that Init is only called once.
38 pref_name_ = pref_name;
39 // Check that the preference is registered.
40 DCHECK(prefs_->FindPreference(pref_name_)) << pref_name << " not registered.";
42 // Add ourselves as a pref observer so we can keep our local value in sync.
43 prefs_->AddPrefObserver(pref_name, this);
46 void PrefMemberBase::Destroy() {
47 if (prefs_ && !pref_name_.empty()) {
48 prefs_->RemovePrefObserver(pref_name_, this);
53 void PrefMemberBase::MoveToSequence(
54 scoped_refptr<SequencedTaskRunner> task_runner) {
55 VerifyValuePrefName();
56 // Load the value from preferences if it hasn't been loaded so far.
58 UpdateValueFromPref(base::OnceClosure());
59 internal()->MoveToSequence(std::move(task_runner));
62 void PrefMemberBase::OnPreferenceChanged(PrefService* service,
63 const std::string& pref_name) {
64 VerifyValuePrefName();
65 UpdateValueFromPref((!setting_value_ && !observer_.is_null())
66 ? base::BindOnce(observer_, pref_name)
67 : base::OnceClosure());
70 void PrefMemberBase::UpdateValueFromPref(base::OnceClosure callback) const {
71 VerifyValuePrefName();
72 const PrefService::Preference* pref = prefs_->FindPreference(pref_name_);
76 internal()->UpdateValue(
77 base::Value::ToUniquePtrValue(pref->GetValue()->Clone()).release(),
78 pref->IsManaged(), pref->IsUserModifiable(), pref->IsDefaultValue(),
82 void PrefMemberBase::VerifyPref() const {
83 VerifyValuePrefName();
85 UpdateValueFromPref(base::OnceClosure());
88 void PrefMemberBase::InvokeUnnamedCallback(
89 const base::RepeatingClosure& callback,
90 const std::string& pref_name) {
94 PrefMemberBase::Internal::Internal()
95 : owning_task_runner_(base::SequencedTaskRunner::GetCurrentDefault()) {}
96 PrefMemberBase::Internal::~Internal() = default;
98 bool PrefMemberBase::Internal::IsOnCorrectSequence() const {
99 return owning_task_runner_->RunsTasksInCurrentSequence();
102 void PrefMemberBase::Internal::UpdateValue(base::Value* v,
104 bool is_user_modifiable,
105 bool is_default_value,
106 base::OnceClosure callback) const {
107 std::unique_ptr<base::Value> value(v);
108 base::ScopedClosureRunner closure_runner(std::move(callback));
109 if (IsOnCorrectSequence()) {
110 bool rv = UpdateValueInternal(*value);
112 is_managed_ = is_managed;
113 is_user_modifiable_ = is_user_modifiable;
114 is_default_value_ = is_default_value;
116 bool may_run = owning_task_runner_->PostTask(
118 base::BindOnce(&PrefMemberBase::Internal::UpdateValue, this,
119 value.release(), is_managed, is_user_modifiable,
120 is_default_value, closure_runner.Release()));
125 void PrefMemberBase::Internal::MoveToSequence(
126 scoped_refptr<SequencedTaskRunner> task_runner) {
127 CheckOnCorrectSequence();
128 owning_task_runner_ = std::move(task_runner);
131 bool PrefMemberVectorStringUpdate(const base::Value& value,
132 std::vector<std::string>* string_vector) {
133 if (!value.is_list())
136 std::vector<std::string> local_vector;
137 for (const auto& item : value.GetList()) {
138 if (!item.is_string())
140 local_vector.push_back(item.GetString());
143 string_vector->swap(local_vector);
147 } // namespace subtle
150 void PrefMember<bool>::UpdatePref(const bool& value) {
151 prefs()->SetBoolean(pref_name(), value);
155 bool PrefMember<bool>::Internal::UpdateValueInternal(
156 const base::Value& value) const {
158 value_ = value.GetBool();
159 return value.is_bool();
163 void PrefMember<int>::UpdatePref(const int& value) {
164 prefs()->SetInteger(pref_name(), value);
168 bool PrefMember<int>::Internal::UpdateValueInternal(
169 const base::Value& value) const {
171 value_ = value.GetInt();
172 return value.is_int();
176 void PrefMember<double>::UpdatePref(const double& value) {
177 prefs()->SetDouble(pref_name(), value);
181 bool PrefMember<double>::Internal::UpdateValueInternal(const base::Value& value)
183 if (value.is_double() || value.is_int())
184 value_ = value.GetDouble();
185 return value.is_double() || value.is_int();
189 void PrefMember<std::string>::UpdatePref(const std::string& value) {
190 prefs()->SetString(pref_name(), value);
194 bool PrefMember<std::string>::Internal::UpdateValueInternal(
195 const base::Value& value)
197 if (value.is_string())
198 value_ = value.GetString();
199 return value.is_string();
203 void PrefMember<base::FilePath>::UpdatePref(const base::FilePath& value) {
204 prefs()->SetFilePath(pref_name(), value);
208 bool PrefMember<base::FilePath>::Internal::UpdateValueInternal(
209 const base::Value& value)
211 absl::optional<base::FilePath> path = base::ValueToFilePath(value);
219 void PrefMember<std::vector<std::string> >::UpdatePref(
220 const std::vector<std::string>& value) {
221 base::Value::List list_value;
222 for (const std::string& val : value)
223 list_value.Append(val);
225 prefs()->SetList(pref_name(), std::move(list_value));
229 bool PrefMember<std::vector<std::string> >::Internal::UpdateValueInternal(
230 const base::Value& value) const {
231 return subtle::PrefMemberVectorStringUpdate(value, &value_);