OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | |
5 // A helper class that stays in sync with a preference (bool, int, real, | |
6 // string or filepath). For example: | |
7 // | |
8 // class MyClass { | |
9 // public: | |
10 // MyClass(PrefService* prefs) { | |
11 // my_string_.Init(prefs::kHomePage, prefs); | |
12 // } | |
13 // private: | |
14 // StringPrefMember my_string_; | |
15 // }; | |
16 // | |
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. | |
19 // | |
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. | |
23 | 4 |
24 #ifndef BASE_PREFS_PREF_MEMBER_H_ | 5 // TODO(brettw) remove this forwarding header when prefs is completely moved to |
25 #define BASE_PREFS_PREF_MEMBER_H_ | 6 // components. |
26 | 7 #include "components/prefs/pref_member.h" |
27 #include <string> | |
28 #include <vector> | |
29 | |
30 #include "base/bind.h" | |
31 #include "base/callback_forward.h" | |
32 #include "base/files/file_path.h" | |
33 #include "base/logging.h" | |
34 #include "base/macros.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" | |
40 | |
41 class PrefService; | |
42 | |
43 namespace subtle { | |
44 | |
45 class BASE_PREFS_EXPORT PrefMemberBase : public PrefObserver { | |
46 public: | |
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; | |
50 | |
51 PrefService* prefs() { return prefs_; } | |
52 const PrefService* prefs() const { return prefs_; } | |
53 | |
54 protected: | |
55 class BASE_PREFS_EXPORT Internal | |
56 : public base::RefCountedThreadSafe<Internal> { | |
57 public: | |
58 Internal(); | |
59 | |
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, | |
64 bool is_managed, | |
65 bool is_user_modifiable, | |
66 const base::Closure& callback) const; | |
67 | |
68 void MoveToThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner); | |
69 | |
70 // See PrefMember<> for description. | |
71 bool IsManaged() const { | |
72 return is_managed_; | |
73 } | |
74 | |
75 bool IsUserModifiable() const { | |
76 return is_user_modifiable_; | |
77 } | |
78 | |
79 protected: | |
80 friend class base::RefCountedThreadSafe<Internal>; | |
81 virtual ~Internal(); | |
82 | |
83 void CheckOnCorrectThread() const { | |
84 DCHECK(IsOnCorrectThread()); | |
85 } | |
86 | |
87 private: | |
88 // This method actually updates the value. It should only be called from | |
89 // the thread the PrefMember is on. | |
90 virtual bool UpdateValueInternal(const base::Value& value) const = 0; | |
91 | |
92 bool IsOnCorrectThread() const; | |
93 | |
94 scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_; | |
95 mutable bool is_managed_; | |
96 mutable bool is_user_modifiable_; | |
97 | |
98 DISALLOW_COPY_AND_ASSIGN(Internal); | |
99 }; | |
100 | |
101 PrefMemberBase(); | |
102 virtual ~PrefMemberBase(); | |
103 | |
104 // See PrefMember<> for description. | |
105 void Init(const std::string& pref_name, | |
106 PrefService* prefs, | |
107 const NamedChangeCallback& observer); | |
108 void Init(const std::string& pref_name, PrefService* prefs); | |
109 | |
110 virtual void CreateInternal() const = 0; | |
111 | |
112 // See PrefMember<> for description. | |
113 void Destroy(); | |
114 | |
115 void MoveToThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner); | |
116 | |
117 // PrefObserver | |
118 void OnPreferenceChanged(PrefService* service, | |
119 const std::string& pref_name) override; | |
120 | |
121 void VerifyValuePrefName() const { | |
122 DCHECK(!pref_name_.empty()); | |
123 } | |
124 | |
125 // This method is used to do the actual sync with the preference. | |
126 // Note: it is logically const, because it doesn't modify the state | |
127 // seen by the outside world. It is just doing a lazy load behind the scenes. | |
128 void UpdateValueFromPref(const base::Closure& callback) const; | |
129 | |
130 // Verifies the preference name, and lazily loads the preference value if | |
131 // it hasn't been loaded yet. | |
132 void VerifyPref() const; | |
133 | |
134 const std::string& pref_name() const { return pref_name_; } | |
135 | |
136 virtual Internal* internal() const = 0; | |
137 | |
138 // Used to allow registering plain base::Closure callbacks. | |
139 static void InvokeUnnamedCallback(const base::Closure& callback, | |
140 const std::string& pref_name); | |
141 | |
142 private: | |
143 // Ordered the members to compact the class instance. | |
144 std::string pref_name_; | |
145 NamedChangeCallback observer_; | |
146 PrefService* prefs_; | |
147 | |
148 protected: | |
149 bool setting_value_; | |
150 }; | |
151 | |
152 // This function implements StringListPrefMember::UpdateValue(). | |
153 // It is exposed here for testing purposes. | |
154 bool BASE_PREFS_EXPORT PrefMemberVectorStringUpdate( | |
155 const base::Value& value, | |
156 std::vector<std::string>* string_vector); | |
157 | |
158 } // namespace subtle | |
159 | |
160 template <typename ValueType> | |
161 class PrefMember : public subtle::PrefMemberBase { | |
162 public: | |
163 // Defer initialization to an Init method so it's easy to make this class be | |
164 // a member variable. | |
165 PrefMember() {} | |
166 virtual ~PrefMember() {} | |
167 | |
168 // Do the actual initialization of the class. Use the two-parameter | |
169 // version if you don't want any notifications of changes. This | |
170 // method should only be called on the UI thread. | |
171 void Init(const std::string& pref_name, | |
172 PrefService* prefs, | |
173 const NamedChangeCallback& observer) { | |
174 subtle::PrefMemberBase::Init(pref_name, prefs, observer); | |
175 } | |
176 void Init(const std::string& pref_name, | |
177 PrefService* prefs, | |
178 const base::Closure& observer) { | |
179 subtle::PrefMemberBase::Init( | |
180 pref_name, prefs, | |
181 base::Bind(&PrefMemberBase::InvokeUnnamedCallback, observer)); | |
182 } | |
183 void Init(const std::string& pref_name, PrefService* prefs) { | |
184 subtle::PrefMemberBase::Init(pref_name, prefs); | |
185 } | |
186 | |
187 // Unsubscribes the PrefMember from the PrefService. After calling this | |
188 // function, the PrefMember may not be used any more on the UI thread. | |
189 // Assuming |MoveToThread| was previously called, |GetValue|, |IsManaged|, | |
190 // and |IsUserModifiable| can still be called from the other thread but | |
191 // the results will no longer update from the PrefService. | |
192 // This method should only be called on the UI thread. | |
193 void Destroy() { | |
194 subtle::PrefMemberBase::Destroy(); | |
195 } | |
196 | |
197 // Moves the PrefMember to another thread, allowing read accesses from there. | |
198 // Changes from the PrefService will be propagated asynchronously | |
199 // via PostTask. | |
200 // This method should only be used from the thread the PrefMember is currently | |
201 // on, which is the UI thread by default. | |
202 void MoveToThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner) { | |
203 subtle::PrefMemberBase::MoveToThread(task_runner); | |
204 } | |
205 | |
206 // Check whether the pref is managed, i.e. controlled externally through | |
207 // enterprise configuration management (e.g. windows group policy). Returns | |
208 // false for unknown prefs. | |
209 // This method should only be used from the thread the PrefMember is currently | |
210 // on, which is the UI thread unless changed by |MoveToThread|. | |
211 bool IsManaged() const { | |
212 VerifyPref(); | |
213 return internal_->IsManaged(); | |
214 } | |
215 | |
216 // Checks whether the pref can be modified by the user. This returns false | |
217 // when the pref is managed by a policy or an extension, and when a command | |
218 // line flag overrides the pref. | |
219 // This method should only be used from the thread the PrefMember is currently | |
220 // on, which is the UI thread unless changed by |MoveToThread|. | |
221 bool IsUserModifiable() const { | |
222 VerifyPref(); | |
223 return internal_->IsUserModifiable(); | |
224 } | |
225 | |
226 // Retrieve the value of the member variable. | |
227 // This method should only be used from the thread the PrefMember is currently | |
228 // on, which is the UI thread unless changed by |MoveToThread|. | |
229 ValueType GetValue() const { | |
230 VerifyPref(); | |
231 return internal_->value(); | |
232 } | |
233 | |
234 // Provided as a convenience. | |
235 ValueType operator*() const { | |
236 return GetValue(); | |
237 } | |
238 | |
239 // Set the value of the member variable. | |
240 // This method should only be called on the UI thread. | |
241 void SetValue(const ValueType& value) { | |
242 VerifyValuePrefName(); | |
243 setting_value_ = true; | |
244 UpdatePref(value); | |
245 setting_value_ = false; | |
246 } | |
247 | |
248 // Returns the pref name. | |
249 const std::string& GetPrefName() const { | |
250 return pref_name(); | |
251 } | |
252 | |
253 private: | |
254 class Internal : public subtle::PrefMemberBase::Internal { | |
255 public: | |
256 Internal() : value_(ValueType()) {} | |
257 | |
258 ValueType value() { | |
259 CheckOnCorrectThread(); | |
260 return value_; | |
261 } | |
262 | |
263 protected: | |
264 ~Internal() override {} | |
265 | |
266 BASE_PREFS_EXPORT bool UpdateValueInternal( | |
267 const base::Value& value) const override; | |
268 | |
269 // We cache the value of the pref so we don't have to keep walking the pref | |
270 // tree. | |
271 mutable ValueType value_; | |
272 | |
273 private: | |
274 DISALLOW_COPY_AND_ASSIGN(Internal); | |
275 }; | |
276 | |
277 Internal* internal() const override { return internal_.get(); } | |
278 void CreateInternal() const override { internal_ = new Internal(); } | |
279 | |
280 // This method is used to do the actual sync with pref of the specified type. | |
281 void BASE_PREFS_EXPORT UpdatePref(const ValueType& value); | |
282 | |
283 mutable scoped_refptr<Internal> internal_; | |
284 | |
285 DISALLOW_COPY_AND_ASSIGN(PrefMember); | |
286 }; | |
287 | |
288 // Declaration of template specialization need to be repeated here | |
289 // specifically for each specialization (rather than just once above) | |
290 // or at least one of our compilers won't be happy in all cases. | |
291 // Specifically, it was failing on ChromeOS with a complaint about | |
292 // PrefMember<FilePath>::UpdateValueInternal not being defined when | |
293 // built in a chroot with the following parameters: | |
294 // | |
295 // FEATURES="noclean nostrip" USE="-chrome_debug -chrome_remoting | |
296 // -chrome_internal -chrome_pdf component_build" | |
297 // ~/trunk/goma/goma-wrapper cros_chrome_make --board=${BOARD} | |
298 // --install --runhooks | |
299 | |
300 template <> | |
301 BASE_PREFS_EXPORT void PrefMember<bool>::UpdatePref(const bool& value); | |
302 | |
303 template <> | |
304 BASE_PREFS_EXPORT bool PrefMember<bool>::Internal::UpdateValueInternal( | |
305 const base::Value& value) const; | |
306 | |
307 template <> | |
308 BASE_PREFS_EXPORT void PrefMember<int>::UpdatePref(const int& value); | |
309 | |
310 template <> | |
311 BASE_PREFS_EXPORT bool PrefMember<int>::Internal::UpdateValueInternal( | |
312 const base::Value& value) const; | |
313 | |
314 template <> | |
315 BASE_PREFS_EXPORT void PrefMember<double>::UpdatePref(const double& value); | |
316 | |
317 template <> | |
318 BASE_PREFS_EXPORT bool PrefMember<double>::Internal::UpdateValueInternal( | |
319 const base::Value& value) const; | |
320 | |
321 template <> | |
322 BASE_PREFS_EXPORT void PrefMember<std::string>::UpdatePref( | |
323 const std::string& value); | |
324 | |
325 template <> | |
326 BASE_PREFS_EXPORT bool PrefMember<std::string>::Internal::UpdateValueInternal( | |
327 const base::Value& value) const; | |
328 | |
329 template <> | |
330 BASE_PREFS_EXPORT void PrefMember<base::FilePath>::UpdatePref( | |
331 const base::FilePath& value); | |
332 | |
333 template <> | |
334 BASE_PREFS_EXPORT bool | |
335 PrefMember<base::FilePath>::Internal::UpdateValueInternal( | |
336 const base::Value& value) const; | |
337 | |
338 template <> | |
339 BASE_PREFS_EXPORT void PrefMember<std::vector<std::string> >::UpdatePref( | |
340 const std::vector<std::string>& value); | |
341 | |
342 template <> | |
343 BASE_PREFS_EXPORT bool | |
344 PrefMember<std::vector<std::string> >::Internal::UpdateValueInternal( | |
345 const base::Value& value) const; | |
346 | |
347 typedef PrefMember<bool> BooleanPrefMember; | |
348 typedef PrefMember<int> IntegerPrefMember; | |
349 typedef PrefMember<double> DoublePrefMember; | |
350 typedef PrefMember<std::string> StringPrefMember; | |
351 typedef PrefMember<base::FilePath> FilePathPrefMember; | |
352 // This preference member is expensive for large string arrays. | |
353 typedef PrefMember<std::vector<std::string> > StringListPrefMember; | |
354 | |
355 #endif // BASE_PREFS_PREF_MEMBER_H_ | |
OLD | NEW |