• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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.
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, NULL /* no observer */);
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 
24 #ifndef CHROME_BROWSER_PREFS_PREF_MEMBER_H_
25 #define CHROME_BROWSER_PREFS_PREF_MEMBER_H_
26 #pragma once
27 
28 #include <string>
29 
30 #include "base/basictypes.h"
31 #include "base/file_path.h"
32 #include "base/memory/ref_counted.h"
33 #include "base/values.h"
34 #include "content/browser/browser_thread.h"
35 #include "content/common/notification_observer.h"
36 
37 class PrefService;
38 
39 namespace subtle {
40 
41 class PrefMemberBase : public NotificationObserver {
42  protected:
43   class Internal : public base::RefCountedThreadSafe<Internal> {
44    public:
45     Internal();
46 
47     // Update the value, either by calling |UpdateValueInternal| directly
48     // or by dispatching to the right thread.
49     // Takes ownership of |value|.
50     virtual void UpdateValue(Value* value, bool is_managed) const;
51 
52     void MoveToThread(BrowserThread::ID thread_id);
53 
54     // See PrefMember<> for description.
IsManaged()55     bool IsManaged() const {
56       return is_managed_;
57     }
58 
59    protected:
60     friend class base::RefCountedThreadSafe<Internal>;
61     virtual ~Internal();
62 
CheckOnCorrectThread()63     void CheckOnCorrectThread() const {
64       DCHECK(IsOnCorrectThread());
65     }
66 
67    private:
68     // This method actually updates the value. It should only be called from
69     // the thread the PrefMember is on.
70     virtual bool UpdateValueInternal(const Value& value) const = 0;
71 
72     bool IsOnCorrectThread() const;
73 
74     BrowserThread::ID thread_id_;
75     mutable bool is_managed_;
76 
77     DISALLOW_COPY_AND_ASSIGN(Internal);
78   };
79 
80   PrefMemberBase();
81   virtual ~PrefMemberBase();
82 
83   // See PrefMember<> for description.
84   void Init(const char* pref_name, PrefService* prefs,
85             NotificationObserver* observer);
86 
87   virtual void CreateInternal() const = 0;
88 
89   // See PrefMember<> for description.
90   void Destroy();
91 
92   void MoveToThread(BrowserThread::ID thread_id);
93 
94   // NotificationObserver
95   virtual void Observe(NotificationType type,
96                        const NotificationSource& source,
97                        const NotificationDetails& details);
98 
VerifyValuePrefName()99   void VerifyValuePrefName() const {
100     DCHECK(!pref_name_.empty());
101   }
102 
103   // This method is used to do the actual sync with the preference.
104   // Note: it is logically const, because it doesn't modify the state
105   // seen by the outside world. It is just doing a lazy load behind the scenes.
106   virtual void UpdateValueFromPref() const;
107 
108   // Verifies the preference name, and lazily loads the preference value if
109   // it hasn't been loaded yet.
110   void VerifyPref() const;
111 
pref_name()112   const std::string& pref_name() const { return pref_name_; }
prefs()113   PrefService* prefs() { return prefs_; }
prefs()114   const PrefService* prefs() const { return prefs_; }
115 
116   virtual Internal* internal() const = 0;
117 
118  // Ordered the members to compact the class instance.
119  private:
120   std::string pref_name_;
121   NotificationObserver* observer_;
122   PrefService* prefs_;
123 
124  protected:
125   bool setting_value_;
126 };
127 
128 }  // namespace subtle
129 
130 template <typename ValueType>
131 class PrefMember : public subtle::PrefMemberBase {
132  public:
133   // Defer initialization to an Init method so it's easy to make this class be
134   // a member variable.
PrefMember()135   PrefMember() {}
~PrefMember()136   virtual ~PrefMember() {}
137 
138   // Do the actual initialization of the class.  |observer| may be null if you
139   // don't want any notifications of changes.
140   // This method should only be called on the UI thread.
Init(const char * pref_name,PrefService * prefs,NotificationObserver * observer)141   void Init(const char* pref_name, PrefService* prefs,
142             NotificationObserver* observer) {
143     subtle::PrefMemberBase::Init(pref_name, prefs, observer);
144   }
145 
146   // Unsubscribes the PrefMember from the PrefService. After calling this
147   // function, the PrefMember may not be used any more.
148   // This method should only be called on the UI thread.
Destroy()149   void Destroy() {
150     subtle::PrefMemberBase::Destroy();
151   }
152 
153   // Moves the PrefMember to another thread, allowing read accesses from there.
154   // Changes from the PrefService will be propagated asynchronously
155   // via PostTask.
156   // This method should only be used from the thread the PrefMember is currently
157   // on, which is the UI thread by default.
MoveToThread(BrowserThread::ID thread_id)158   void MoveToThread(BrowserThread::ID thread_id) {
159     subtle::PrefMemberBase::MoveToThread(thread_id);
160   }
161 
162   // Check whether the pref is managed, i.e. controlled externally through
163   // enterprise configuration management (e.g. windows group policy). Returns
164   // false for unknown prefs.
165   // This method should only be used from the thread the PrefMember is currently
166   // on, which is the UI thread unless changed by |MoveToThread|.
IsManaged()167   bool IsManaged() const {
168     VerifyPref();
169     return internal_->IsManaged();
170   }
171 
172   // Retrieve the value of the member variable.
173   // This method should only be used from the thread the PrefMember is currently
174   // on, which is the UI thread unless changed by |MoveToThread|.
GetValue()175   ValueType GetValue() const {
176     VerifyPref();
177     return internal_->value();
178   }
179 
180   // Provided as a convenience.
181   ValueType operator*() const {
182     return GetValue();
183   }
184 
185   // Set the value of the member variable.
186   // This method should only be called on the UI thread.
SetValue(const ValueType & value)187   void SetValue(const ValueType& value) {
188     VerifyValuePrefName();
189     setting_value_ = true;
190     UpdatePref(value);
191     setting_value_ = false;
192   }
193 
194   // Set the value of the member variable if it is not managed.
195   // This method should only be called on the UI thread.
SetValueIfNotManaged(const ValueType & value)196   void SetValueIfNotManaged(const ValueType& value) {
197     if (!IsManaged()) {
198       SetValue(value);
199     }
200   }
201 
202   // Returns the pref name.
GetPrefName()203   const std::string& GetPrefName() const {
204     return pref_name();
205   }
206 
207  private:
208   class Internal : public subtle::PrefMemberBase::Internal {
209    public:
Internal()210     Internal() : value_(ValueType()) {}
211 
value()212     ValueType value() {
213       CheckOnCorrectThread();
214       return value_;
215     }
216 
217    protected:
~Internal()218     virtual ~Internal() {}
219 
220     virtual bool UpdateValueInternal(const Value& value) const;
221 
222     // We cache the value of the pref so we don't have to keep walking the pref
223     // tree.
224     mutable ValueType value_;
225 
226     DISALLOW_COPY_AND_ASSIGN(Internal);
227   };
228 
internal()229   virtual Internal* internal() const { return internal_; }
CreateInternal()230   virtual void CreateInternal() const {
231     internal_ = new Internal();
232   }
233 
234   // This method is used to do the actual sync with pref of the specified type.
235   virtual void UpdatePref(const ValueType& value);
236 
237   mutable scoped_refptr<Internal> internal_;
238 
239   DISALLOW_COPY_AND_ASSIGN(PrefMember);
240 };
241 
242 typedef PrefMember<bool> BooleanPrefMember;
243 typedef PrefMember<int> IntegerPrefMember;
244 typedef PrefMember<double> DoublePrefMember;
245 typedef PrefMember<std::string> StringPrefMember;
246 typedef PrefMember<FilePath> FilePathPrefMember;
247 typedef PrefMember<ListValue*> ListPrefMember;
248 
249 #endif  // CHROME_BROWSER_PREFS_PREF_MEMBER_H_
250