xref: /aosp_15_r20/external/cronet/components/prefs/pref_member.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "components/prefs/pref_member.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <utility>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/json/values_util.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/task/sequenced_task_runner.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/values.h"
15*6777b538SAndroid Build Coastguard Worker #include "components/prefs/pref_service.h"
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker using base::SequencedTaskRunner;
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace subtle {
20*6777b538SAndroid Build Coastguard Worker 
PrefMemberBase()21*6777b538SAndroid Build Coastguard Worker PrefMemberBase::PrefMemberBase() : prefs_(nullptr), setting_value_(false) {}
22*6777b538SAndroid Build Coastguard Worker 
~PrefMemberBase()23*6777b538SAndroid Build Coastguard Worker PrefMemberBase::~PrefMemberBase() {
24*6777b538SAndroid Build Coastguard Worker   Destroy();
25*6777b538SAndroid Build Coastguard Worker }
26*6777b538SAndroid Build Coastguard Worker 
Init(const std::string & pref_name,PrefService * prefs,const NamedChangeCallback & observer)27*6777b538SAndroid Build Coastguard Worker void PrefMemberBase::Init(const std::string& pref_name,
28*6777b538SAndroid Build Coastguard Worker                           PrefService* prefs,
29*6777b538SAndroid Build Coastguard Worker                           const NamedChangeCallback& observer) {
30*6777b538SAndroid Build Coastguard Worker   observer_ = observer;
31*6777b538SAndroid Build Coastguard Worker   Init(pref_name, prefs);
32*6777b538SAndroid Build Coastguard Worker }
33*6777b538SAndroid Build Coastguard Worker 
Init(const std::string & pref_name,PrefService * prefs)34*6777b538SAndroid Build Coastguard Worker void PrefMemberBase::Init(const std::string& pref_name, PrefService* prefs) {
35*6777b538SAndroid Build Coastguard Worker   DCHECK(prefs);
36*6777b538SAndroid Build Coastguard Worker   DCHECK(pref_name_.empty());  // Check that Init is only called once.
37*6777b538SAndroid Build Coastguard Worker   prefs_ = prefs;
38*6777b538SAndroid Build Coastguard Worker   pref_name_ = pref_name;
39*6777b538SAndroid Build Coastguard Worker   // Check that the preference is registered.
40*6777b538SAndroid Build Coastguard Worker   DCHECK(prefs_->FindPreference(pref_name_)) << pref_name << " not registered.";
41*6777b538SAndroid Build Coastguard Worker 
42*6777b538SAndroid Build Coastguard Worker   // Add ourselves as a pref observer so we can keep our local value in sync.
43*6777b538SAndroid Build Coastguard Worker   prefs_->AddPrefObserver(pref_name, this);
44*6777b538SAndroid Build Coastguard Worker }
45*6777b538SAndroid Build Coastguard Worker 
Destroy()46*6777b538SAndroid Build Coastguard Worker void PrefMemberBase::Destroy() {
47*6777b538SAndroid Build Coastguard Worker   if (prefs_ && !pref_name_.empty()) {
48*6777b538SAndroid Build Coastguard Worker     prefs_->RemovePrefObserver(pref_name_, this);
49*6777b538SAndroid Build Coastguard Worker   }
50*6777b538SAndroid Build Coastguard Worker   prefs_ = nullptr;
51*6777b538SAndroid Build Coastguard Worker }
52*6777b538SAndroid Build Coastguard Worker 
MoveToSequence(scoped_refptr<SequencedTaskRunner> task_runner)53*6777b538SAndroid Build Coastguard Worker void PrefMemberBase::MoveToSequence(
54*6777b538SAndroid Build Coastguard Worker     scoped_refptr<SequencedTaskRunner> task_runner) {
55*6777b538SAndroid Build Coastguard Worker   VerifyValuePrefName();
56*6777b538SAndroid Build Coastguard Worker   // Load the value from preferences if it hasn't been loaded so far.
57*6777b538SAndroid Build Coastguard Worker   if (!internal())
58*6777b538SAndroid Build Coastguard Worker     UpdateValueFromPref(base::OnceClosure());
59*6777b538SAndroid Build Coastguard Worker   internal()->MoveToSequence(std::move(task_runner));
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker 
OnPreferenceChanged(PrefService * service,const std::string & pref_name)62*6777b538SAndroid Build Coastguard Worker void PrefMemberBase::OnPreferenceChanged(PrefService* service,
63*6777b538SAndroid Build Coastguard Worker                                          const std::string& pref_name) {
64*6777b538SAndroid Build Coastguard Worker   VerifyValuePrefName();
65*6777b538SAndroid Build Coastguard Worker   UpdateValueFromPref((!setting_value_ && !observer_.is_null())
66*6777b538SAndroid Build Coastguard Worker                           ? base::BindOnce(observer_, pref_name)
67*6777b538SAndroid Build Coastguard Worker                           : base::OnceClosure());
68*6777b538SAndroid Build Coastguard Worker }
69*6777b538SAndroid Build Coastguard Worker 
UpdateValueFromPref(base::OnceClosure callback) const70*6777b538SAndroid Build Coastguard Worker void PrefMemberBase::UpdateValueFromPref(base::OnceClosure callback) const {
71*6777b538SAndroid Build Coastguard Worker   VerifyValuePrefName();
72*6777b538SAndroid Build Coastguard Worker   const PrefService::Preference* pref = prefs_->FindPreference(pref_name_);
73*6777b538SAndroid Build Coastguard Worker   DCHECK(pref);
74*6777b538SAndroid Build Coastguard Worker   if (!internal())
75*6777b538SAndroid Build Coastguard Worker     CreateInternal();
76*6777b538SAndroid Build Coastguard Worker   internal()->UpdateValue(
77*6777b538SAndroid Build Coastguard Worker       base::Value::ToUniquePtrValue(pref->GetValue()->Clone()).release(),
78*6777b538SAndroid Build Coastguard Worker       pref->IsManaged(), pref->IsUserModifiable(), pref->IsDefaultValue(),
79*6777b538SAndroid Build Coastguard Worker       std::move(callback));
80*6777b538SAndroid Build Coastguard Worker }
81*6777b538SAndroid Build Coastguard Worker 
VerifyPref() const82*6777b538SAndroid Build Coastguard Worker void PrefMemberBase::VerifyPref() const {
83*6777b538SAndroid Build Coastguard Worker   VerifyValuePrefName();
84*6777b538SAndroid Build Coastguard Worker   if (!internal())
85*6777b538SAndroid Build Coastguard Worker     UpdateValueFromPref(base::OnceClosure());
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker 
InvokeUnnamedCallback(const base::RepeatingClosure & callback,const std::string & pref_name)88*6777b538SAndroid Build Coastguard Worker void PrefMemberBase::InvokeUnnamedCallback(
89*6777b538SAndroid Build Coastguard Worker     const base::RepeatingClosure& callback,
90*6777b538SAndroid Build Coastguard Worker     const std::string& pref_name) {
91*6777b538SAndroid Build Coastguard Worker   callback.Run();
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker 
Internal()94*6777b538SAndroid Build Coastguard Worker PrefMemberBase::Internal::Internal()
95*6777b538SAndroid Build Coastguard Worker     : owning_task_runner_(base::SequencedTaskRunner::GetCurrentDefault()) {}
96*6777b538SAndroid Build Coastguard Worker PrefMemberBase::Internal::~Internal() = default;
97*6777b538SAndroid Build Coastguard Worker 
IsOnCorrectSequence() const98*6777b538SAndroid Build Coastguard Worker bool PrefMemberBase::Internal::IsOnCorrectSequence() const {
99*6777b538SAndroid Build Coastguard Worker   return owning_task_runner_->RunsTasksInCurrentSequence();
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker 
UpdateValue(base::Value * v,bool is_managed,bool is_user_modifiable,bool is_default_value,base::OnceClosure callback) const102*6777b538SAndroid Build Coastguard Worker void PrefMemberBase::Internal::UpdateValue(base::Value* v,
103*6777b538SAndroid Build Coastguard Worker                                            bool is_managed,
104*6777b538SAndroid Build Coastguard Worker                                            bool is_user_modifiable,
105*6777b538SAndroid Build Coastguard Worker                                            bool is_default_value,
106*6777b538SAndroid Build Coastguard Worker                                            base::OnceClosure callback) const {
107*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<base::Value> value(v);
108*6777b538SAndroid Build Coastguard Worker   base::ScopedClosureRunner closure_runner(std::move(callback));
109*6777b538SAndroid Build Coastguard Worker   if (IsOnCorrectSequence()) {
110*6777b538SAndroid Build Coastguard Worker     bool rv = UpdateValueInternal(*value);
111*6777b538SAndroid Build Coastguard Worker     DCHECK(rv);
112*6777b538SAndroid Build Coastguard Worker     is_managed_ = is_managed;
113*6777b538SAndroid Build Coastguard Worker     is_user_modifiable_ = is_user_modifiable;
114*6777b538SAndroid Build Coastguard Worker     is_default_value_ = is_default_value;
115*6777b538SAndroid Build Coastguard Worker   } else {
116*6777b538SAndroid Build Coastguard Worker     bool may_run = owning_task_runner_->PostTask(
117*6777b538SAndroid Build Coastguard Worker         FROM_HERE,
118*6777b538SAndroid Build Coastguard Worker         base::BindOnce(&PrefMemberBase::Internal::UpdateValue, this,
119*6777b538SAndroid Build Coastguard Worker                        value.release(), is_managed, is_user_modifiable,
120*6777b538SAndroid Build Coastguard Worker                        is_default_value, closure_runner.Release()));
121*6777b538SAndroid Build Coastguard Worker     DCHECK(may_run);
122*6777b538SAndroid Build Coastguard Worker   }
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker 
MoveToSequence(scoped_refptr<SequencedTaskRunner> task_runner)125*6777b538SAndroid Build Coastguard Worker void PrefMemberBase::Internal::MoveToSequence(
126*6777b538SAndroid Build Coastguard Worker     scoped_refptr<SequencedTaskRunner> task_runner) {
127*6777b538SAndroid Build Coastguard Worker   CheckOnCorrectSequence();
128*6777b538SAndroid Build Coastguard Worker   owning_task_runner_ = std::move(task_runner);
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker 
PrefMemberVectorStringUpdate(const base::Value & value,std::vector<std::string> * string_vector)131*6777b538SAndroid Build Coastguard Worker bool PrefMemberVectorStringUpdate(const base::Value& value,
132*6777b538SAndroid Build Coastguard Worker                                   std::vector<std::string>* string_vector) {
133*6777b538SAndroid Build Coastguard Worker   if (!value.is_list())
134*6777b538SAndroid Build Coastguard Worker     return false;
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker   std::vector<std::string> local_vector;
137*6777b538SAndroid Build Coastguard Worker   for (const auto& item : value.GetList()) {
138*6777b538SAndroid Build Coastguard Worker     if (!item.is_string())
139*6777b538SAndroid Build Coastguard Worker       return false;
140*6777b538SAndroid Build Coastguard Worker     local_vector.push_back(item.GetString());
141*6777b538SAndroid Build Coastguard Worker   }
142*6777b538SAndroid Build Coastguard Worker 
143*6777b538SAndroid Build Coastguard Worker   string_vector->swap(local_vector);
144*6777b538SAndroid Build Coastguard Worker   return true;
145*6777b538SAndroid Build Coastguard Worker }
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker }  // namespace subtle
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker template <>
UpdatePref(const bool & value)150*6777b538SAndroid Build Coastguard Worker void PrefMember<bool>::UpdatePref(const bool& value) {
151*6777b538SAndroid Build Coastguard Worker   prefs()->SetBoolean(pref_name(), value);
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker 
154*6777b538SAndroid Build Coastguard Worker template <>
UpdateValueInternal(const base::Value & value) const155*6777b538SAndroid Build Coastguard Worker bool PrefMember<bool>::Internal::UpdateValueInternal(
156*6777b538SAndroid Build Coastguard Worker     const base::Value& value) const {
157*6777b538SAndroid Build Coastguard Worker   if (value.is_bool())
158*6777b538SAndroid Build Coastguard Worker     value_ = value.GetBool();
159*6777b538SAndroid Build Coastguard Worker   return value.is_bool();
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker template <>
UpdatePref(const int & value)163*6777b538SAndroid Build Coastguard Worker void PrefMember<int>::UpdatePref(const int& value) {
164*6777b538SAndroid Build Coastguard Worker   prefs()->SetInteger(pref_name(), value);
165*6777b538SAndroid Build Coastguard Worker }
166*6777b538SAndroid Build Coastguard Worker 
167*6777b538SAndroid Build Coastguard Worker template <>
UpdateValueInternal(const base::Value & value) const168*6777b538SAndroid Build Coastguard Worker bool PrefMember<int>::Internal::UpdateValueInternal(
169*6777b538SAndroid Build Coastguard Worker     const base::Value& value) const {
170*6777b538SAndroid Build Coastguard Worker   if (value.is_int())
171*6777b538SAndroid Build Coastguard Worker     value_ = value.GetInt();
172*6777b538SAndroid Build Coastguard Worker   return value.is_int();
173*6777b538SAndroid Build Coastguard Worker }
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker template <>
UpdatePref(const double & value)176*6777b538SAndroid Build Coastguard Worker void PrefMember<double>::UpdatePref(const double& value) {
177*6777b538SAndroid Build Coastguard Worker   prefs()->SetDouble(pref_name(), value);
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker template <>
UpdateValueInternal(const base::Value & value) const181*6777b538SAndroid Build Coastguard Worker bool PrefMember<double>::Internal::UpdateValueInternal(const base::Value& value)
182*6777b538SAndroid Build Coastguard Worker     const {
183*6777b538SAndroid Build Coastguard Worker   if (value.is_double() || value.is_int())
184*6777b538SAndroid Build Coastguard Worker     value_ = value.GetDouble();
185*6777b538SAndroid Build Coastguard Worker   return value.is_double() || value.is_int();
186*6777b538SAndroid Build Coastguard Worker }
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker template <>
UpdatePref(const std::string & value)189*6777b538SAndroid Build Coastguard Worker void PrefMember<std::string>::UpdatePref(const std::string& value) {
190*6777b538SAndroid Build Coastguard Worker   prefs()->SetString(pref_name(), value);
191*6777b538SAndroid Build Coastguard Worker }
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker template <>
UpdateValueInternal(const base::Value & value) const194*6777b538SAndroid Build Coastguard Worker bool PrefMember<std::string>::Internal::UpdateValueInternal(
195*6777b538SAndroid Build Coastguard Worker     const base::Value& value)
196*6777b538SAndroid Build Coastguard Worker     const {
197*6777b538SAndroid Build Coastguard Worker   if (value.is_string())
198*6777b538SAndroid Build Coastguard Worker     value_ = value.GetString();
199*6777b538SAndroid Build Coastguard Worker   return value.is_string();
200*6777b538SAndroid Build Coastguard Worker }
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker template <>
UpdatePref(const base::FilePath & value)203*6777b538SAndroid Build Coastguard Worker void PrefMember<base::FilePath>::UpdatePref(const base::FilePath& value) {
204*6777b538SAndroid Build Coastguard Worker   prefs()->SetFilePath(pref_name(), value);
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker template <>
UpdateValueInternal(const base::Value & value) const208*6777b538SAndroid Build Coastguard Worker bool PrefMember<base::FilePath>::Internal::UpdateValueInternal(
209*6777b538SAndroid Build Coastguard Worker     const base::Value& value)
210*6777b538SAndroid Build Coastguard Worker     const {
211*6777b538SAndroid Build Coastguard Worker   std::optional<base::FilePath> path = base::ValueToFilePath(value);
212*6777b538SAndroid Build Coastguard Worker   if (!path)
213*6777b538SAndroid Build Coastguard Worker     return false;
214*6777b538SAndroid Build Coastguard Worker   value_ = *path;
215*6777b538SAndroid Build Coastguard Worker   return true;
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker 
218*6777b538SAndroid Build Coastguard Worker template <>
UpdatePref(const std::vector<std::string> & value)219*6777b538SAndroid Build Coastguard Worker void PrefMember<std::vector<std::string> >::UpdatePref(
220*6777b538SAndroid Build Coastguard Worker     const std::vector<std::string>& value) {
221*6777b538SAndroid Build Coastguard Worker   base::Value::List list_value;
222*6777b538SAndroid Build Coastguard Worker   for (const std::string& val : value)
223*6777b538SAndroid Build Coastguard Worker     list_value.Append(val);
224*6777b538SAndroid Build Coastguard Worker 
225*6777b538SAndroid Build Coastguard Worker   prefs()->SetList(pref_name(), std::move(list_value));
226*6777b538SAndroid Build Coastguard Worker }
227*6777b538SAndroid Build Coastguard Worker 
228*6777b538SAndroid Build Coastguard Worker template <>
UpdateValueInternal(const base::Value & value) const229*6777b538SAndroid Build Coastguard Worker bool PrefMember<std::vector<std::string> >::Internal::UpdateValueInternal(
230*6777b538SAndroid Build Coastguard Worker     const base::Value& value) const {
231*6777b538SAndroid Build Coastguard Worker   return subtle::PrefMemberVectorStringUpdate(value, &value_);
232*6777b538SAndroid Build Coastguard Worker }
233