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 // A helper class that stays in sync with a preference (bool, int, real,
6 // string or filepath). For example:
10 // MyClass(PrefService* prefs) {
11 // my_string_.Init(prefs::kHomePage, prefs);
14 // StringPrefMember my_string_;
17 // my_string_ should stay in sync with the prefs::kHomePage pref and will
18 // update if either the pref changes or if my_string_.SetValue is called.
20 // An optional observer can be passed into the Init method which can be used to
21 // notify MyClass of changes. Note that if you use SetValue(), the observer
22 // will not be notified.
24 #ifndef BASE_PREFS_PREF_MEMBER_H_
25 #define BASE_PREFS_PREF_MEMBER_H_
30 #include "base/basictypes.h"
31 #include "base/bind.h"
32 #include "base/callback_forward.h"
33 #include "base/files/file_path.h"
34 #include "base/logging.h"
35 #include "base/memory/ref_counted.h"
36 #include "base/prefs/base_prefs_export.h"
37 #include "base/prefs/pref_observer.h"
38 #include "base/single_thread_task_runner.h"
39 #include "base/values.h"
45 class BASE_PREFS_EXPORT PrefMemberBase
: public PrefObserver
{
47 // Type of callback you can register if you need to know the name of
48 // the pref that is changing.
49 typedef base::Callback
<void(const std::string
&)> NamedChangeCallback
;
51 PrefService
* prefs() { return prefs_
; }
52 const PrefService
* prefs() const { return prefs_
; }
55 class BASE_PREFS_EXPORT Internal
56 : public base::RefCountedThreadSafe
<Internal
> {
60 // Update the value, either by calling |UpdateValueInternal| directly
61 // or by dispatching to the right thread.
62 // Takes ownership of |value|.
63 void UpdateValue(base::Value
* value
,
65 bool is_user_modifiable
,
66 const base::Closure
& callback
) const;
69 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
);
71 // See PrefMember<> for description.
72 bool IsManaged() const {
76 bool IsUserModifiable() const {
77 return is_user_modifiable_
;
81 friend class base::RefCountedThreadSafe
<Internal
>;
84 void CheckOnCorrectThread() const {
85 DCHECK(IsOnCorrectThread());
89 // This method actually updates the value. It should only be called from
90 // the thread the PrefMember is on.
91 virtual bool UpdateValueInternal(const base::Value
& value
) const = 0;
93 bool IsOnCorrectThread() const;
95 scoped_refptr
<base::SingleThreadTaskRunner
> thread_loop_
;
96 mutable bool is_managed_
;
97 mutable bool is_user_modifiable_
;
99 DISALLOW_COPY_AND_ASSIGN(Internal
);
103 virtual ~PrefMemberBase();
105 // See PrefMember<> for description.
106 void Init(const std::string
& pref_name
,
108 const NamedChangeCallback
& observer
);
109 void Init(const std::string
& pref_name
, PrefService
* prefs
);
111 virtual void CreateInternal() const = 0;
113 // See PrefMember<> for description.
117 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
);
120 void OnPreferenceChanged(PrefService
* service
,
121 const std::string
& pref_name
) override
;
123 void VerifyValuePrefName() const {
124 DCHECK(!pref_name_
.empty());
127 // This method is used to do the actual sync with the preference.
128 // Note: it is logically const, because it doesn't modify the state
129 // seen by the outside world. It is just doing a lazy load behind the scenes.
130 void UpdateValueFromPref(const base::Closure
& callback
) const;
132 // Verifies the preference name, and lazily loads the preference value if
133 // it hasn't been loaded yet.
134 void VerifyPref() const;
136 const std::string
& pref_name() const { return pref_name_
; }
138 virtual Internal
* internal() const = 0;
140 // Used to allow registering plain base::Closure callbacks.
141 static void InvokeUnnamedCallback(const base::Closure
& callback
,
142 const std::string
& pref_name
);
145 // Ordered the members to compact the class instance.
146 std::string pref_name_
;
147 NamedChangeCallback observer_
;
154 // This function implements StringListPrefMember::UpdateValue().
155 // It is exposed here for testing purposes.
156 bool BASE_PREFS_EXPORT
PrefMemberVectorStringUpdate(
157 const base::Value
& value
,
158 std::vector
<std::string
>* string_vector
);
160 } // namespace subtle
162 template <typename ValueType
>
163 class PrefMember
: public subtle::PrefMemberBase
{
165 // Defer initialization to an Init method so it's easy to make this class be
166 // a member variable.
168 virtual ~PrefMember() {}
170 // Do the actual initialization of the class. Use the two-parameter
171 // version if you don't want any notifications of changes. This
172 // method should only be called on the UI thread.
173 void Init(const std::string
& pref_name
,
175 const NamedChangeCallback
& observer
) {
176 subtle::PrefMemberBase::Init(pref_name
, prefs
, observer
);
178 void Init(const std::string
& pref_name
,
180 const base::Closure
& observer
) {
181 subtle::PrefMemberBase::Init(
183 base::Bind(&PrefMemberBase::InvokeUnnamedCallback
, observer
));
185 void Init(const std::string
& pref_name
, PrefService
* prefs
) {
186 subtle::PrefMemberBase::Init(pref_name
, prefs
);
189 // Unsubscribes the PrefMember from the PrefService. After calling this
190 // function, the PrefMember may not be used any more on the UI thread.
191 // Assuming |MoveToThread| was previously called, |GetValue|, |IsManaged|,
192 // and |IsUserModifiable| can still be called from the other thread but
193 // the results will no longer update from the PrefService.
194 // This method should only be called on the UI thread.
196 subtle::PrefMemberBase::Destroy();
199 // Moves the PrefMember to another thread, allowing read accesses from there.
200 // Changes from the PrefService will be propagated asynchronously
202 // This method should only be used from the thread the PrefMember is currently
203 // on, which is the UI thread by default.
205 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
) {
206 subtle::PrefMemberBase::MoveToThread(task_runner
);
209 // Check whether the pref is managed, i.e. controlled externally through
210 // enterprise configuration management (e.g. windows group policy). Returns
211 // false for unknown prefs.
212 // This method should only be used from the thread the PrefMember is currently
213 // on, which is the UI thread unless changed by |MoveToThread|.
214 bool IsManaged() const {
216 return internal_
->IsManaged();
219 // Checks whether the pref can be modified by the user. This returns false
220 // when the pref is managed by a policy or an extension, and when a command
221 // line flag overrides the pref.
222 // This method should only be used from the thread the PrefMember is currently
223 // on, which is the UI thread unless changed by |MoveToThread|.
224 bool IsUserModifiable() const {
226 return internal_
->IsUserModifiable();
229 // Retrieve the value of the member variable.
230 // This method should only be used from the thread the PrefMember is currently
231 // on, which is the UI thread unless changed by |MoveToThread|.
232 ValueType
GetValue() const {
234 return internal_
->value();
237 // Provided as a convenience.
238 ValueType
operator*() const {
242 // Set the value of the member variable.
243 // This method should only be called on the UI thread.
244 void SetValue(const ValueType
& value
) {
245 VerifyValuePrefName();
246 setting_value_
= true;
248 setting_value_
= false;
251 // Returns the pref name.
252 const std::string
& GetPrefName() const {
257 class Internal
: public subtle::PrefMemberBase::Internal
{
259 Internal() : value_(ValueType()) {}
262 CheckOnCorrectThread();
267 virtual ~Internal() {}
269 virtual BASE_PREFS_EXPORT
bool UpdateValueInternal(
270 const base::Value
& value
) const override
;
272 // We cache the value of the pref so we don't have to keep walking the pref
274 mutable ValueType value_
;
277 DISALLOW_COPY_AND_ASSIGN(Internal
);
280 virtual Internal
* internal() const override
{ return internal_
.get(); }
281 virtual void CreateInternal() const override
{ internal_
= new Internal(); }
283 // This method is used to do the actual sync with pref of the specified type.
284 void BASE_PREFS_EXPORT
UpdatePref(const ValueType
& value
);
286 mutable scoped_refptr
<Internal
> internal_
;
288 DISALLOW_COPY_AND_ASSIGN(PrefMember
);
291 // Declaration of template specialization need to be repeated here
292 // specifically for each specialization (rather than just once above)
293 // or at least one of our compilers won't be happy in all cases.
294 // Specifically, it was failing on ChromeOS with a complaint about
295 // PrefMember<FilePath>::UpdateValueInternal not being defined when
296 // built in a chroot with the following parameters:
298 // FEATURES="noclean nostrip" USE="-chrome_debug -chrome_remoting
299 // -chrome_internal -chrome_pdf component_build"
300 // ~/trunk/goma/goma-wrapper cros_chrome_make --board=${BOARD}
301 // --install --runhooks
304 BASE_PREFS_EXPORT
void PrefMember
<bool>::UpdatePref(const bool& value
);
307 BASE_PREFS_EXPORT
bool PrefMember
<bool>::Internal::UpdateValueInternal(
308 const base::Value
& value
) const;
311 BASE_PREFS_EXPORT
void PrefMember
<int>::UpdatePref(const int& value
);
314 BASE_PREFS_EXPORT
bool PrefMember
<int>::Internal::UpdateValueInternal(
315 const base::Value
& value
) const;
318 BASE_PREFS_EXPORT
void PrefMember
<double>::UpdatePref(const double& value
);
321 BASE_PREFS_EXPORT
bool PrefMember
<double>::Internal::UpdateValueInternal(
322 const base::Value
& value
) const;
325 BASE_PREFS_EXPORT
void PrefMember
<std::string
>::UpdatePref(
326 const std::string
& value
);
329 BASE_PREFS_EXPORT
bool PrefMember
<std::string
>::Internal::UpdateValueInternal(
330 const base::Value
& value
) const;
333 BASE_PREFS_EXPORT
void PrefMember
<base::FilePath
>::UpdatePref(
334 const base::FilePath
& value
);
337 BASE_PREFS_EXPORT
bool
338 PrefMember
<base::FilePath
>::Internal::UpdateValueInternal(
339 const base::Value
& value
) const;
342 BASE_PREFS_EXPORT
void PrefMember
<std::vector
<std::string
> >::UpdatePref(
343 const std::vector
<std::string
>& value
);
346 BASE_PREFS_EXPORT
bool
347 PrefMember
<std::vector
<std::string
> >::Internal::UpdateValueInternal(
348 const base::Value
& value
) const;
350 typedef PrefMember
<bool> BooleanPrefMember
;
351 typedef PrefMember
<int> IntegerPrefMember
;
352 typedef PrefMember
<double> DoublePrefMember
;
353 typedef PrefMember
<std::string
> StringPrefMember
;
354 typedef PrefMember
<base::FilePath
> FilePathPrefMember
;
355 // This preference member is expensive for large string arrays.
356 typedef PrefMember
<std::vector
<std::string
> > StringListPrefMember
;
358 #endif // BASE_PREFS_PREF_MEMBER_H_