Home | History | Annotate | Download | only in prefs
      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.
      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 
     24 #ifndef BASE_PREFS_PREF_MEMBER_H_
     25 #define BASE_PREFS_PREF_MEMBER_H_
     26 
     27 #include <string>
     28 #include <vector>
     29 
     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/message_loop/message_loop_proxy.h"
     37 #include "base/prefs/base_prefs_export.h"
     38 #include "base/prefs/pref_observer.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(
     69         const scoped_refptr<base::MessageLoopProxy>& message_loop);
     70 
     71     // See PrefMember<> for description.
     72     bool IsManaged() const {
     73       return is_managed_;
     74     }
     75 
     76     bool IsUserModifiable() const {
     77       return is_user_modifiable_;
     78     }
     79 
     80    protected:
     81     friend class base::RefCountedThreadSafe<Internal>;
     82     virtual ~Internal();
     83 
     84     void CheckOnCorrectThread() const {
     85       DCHECK(IsOnCorrectThread());
     86     }
     87 
     88    private:
     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;
     92 
     93     bool IsOnCorrectThread() const;
     94 
     95     scoped_refptr<base::MessageLoopProxy> thread_loop_;
     96     mutable bool is_managed_;
     97     mutable bool is_user_modifiable_;
     98 
     99     DISALLOW_COPY_AND_ASSIGN(Internal);
    100   };
    101 
    102   PrefMemberBase();
    103   virtual ~PrefMemberBase();
    104 
    105   // See PrefMember<> for description.
    106   void Init(const char* pref_name, PrefService* prefs,
    107             const NamedChangeCallback& observer);
    108   void Init(const char* pref_name, PrefService* prefs);
    109 
    110   virtual void CreateInternal() const = 0;
    111 
    112   // See PrefMember<> for description.
    113   void Destroy();
    114 
    115   void MoveToThread(const scoped_refptr<base::MessageLoopProxy>& message_loop);
    116 
    117   // PrefObserver
    118   virtual 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 char* pref_name, PrefService* prefs,
    172             const NamedChangeCallback& observer) {
    173     subtle::PrefMemberBase::Init(pref_name, prefs, observer);
    174   }
    175   void Init(const char* pref_name, PrefService* prefs,
    176             const base::Closure& observer) {
    177     subtle::PrefMemberBase::Init(
    178         pref_name, prefs,
    179         base::Bind(&PrefMemberBase::InvokeUnnamedCallback, observer));
    180   }
    181   void Init(const char* pref_name, PrefService* prefs) {
    182     subtle::PrefMemberBase::Init(pref_name, prefs);
    183   }
    184 
    185   // Unsubscribes the PrefMember from the PrefService. After calling this
    186   // function, the PrefMember may not be used any more on the UI thread.
    187   // Assuming |MoveToThread| was previously called, |GetValue|, |IsManaged|,
    188   // and |IsUserModifiable| can still be called from the other thread but
    189   // the results will no longer update from the PrefService.
    190   // This method should only be called on the UI thread.
    191   void Destroy() {
    192     subtle::PrefMemberBase::Destroy();
    193   }
    194 
    195   // Moves the PrefMember to another thread, allowing read accesses from there.
    196   // Changes from the PrefService will be propagated asynchronously
    197   // via PostTask.
    198   // This method should only be used from the thread the PrefMember is currently
    199   // on, which is the UI thread by default.
    200   void MoveToThread(const scoped_refptr<base::MessageLoopProxy>& message_loop) {
    201     subtle::PrefMemberBase::MoveToThread(message_loop);
    202   }
    203 
    204   // Check whether the pref is managed, i.e. controlled externally through
    205   // enterprise configuration management (e.g. windows group policy). Returns
    206   // false for unknown prefs.
    207   // This method should only be used from the thread the PrefMember is currently
    208   // on, which is the UI thread unless changed by |MoveToThread|.
    209   bool IsManaged() const {
    210     VerifyPref();
    211     return internal_->IsManaged();
    212   }
    213 
    214   // Checks whether the pref can be modified by the user. This returns false
    215   // when the pref is managed by a policy or an extension, and when a command
    216   // line flag overrides the pref.
    217   // This method should only be used from the thread the PrefMember is currently
    218   // on, which is the UI thread unless changed by |MoveToThread|.
    219   bool IsUserModifiable() const {
    220     VerifyPref();
    221     return internal_->IsUserModifiable();
    222   }
    223 
    224   // Retrieve the value of the member variable.
    225   // This method should only be used from the thread the PrefMember is currently
    226   // on, which is the UI thread unless changed by |MoveToThread|.
    227   ValueType GetValue() const {
    228     VerifyPref();
    229     return internal_->value();
    230   }
    231 
    232   // Provided as a convenience.
    233   ValueType operator*() const {
    234     return GetValue();
    235   }
    236 
    237   // Set the value of the member variable.
    238   // This method should only be called on the UI thread.
    239   void SetValue(const ValueType& value) {
    240     VerifyValuePrefName();
    241     setting_value_ = true;
    242     UpdatePref(value);
    243     setting_value_ = false;
    244   }
    245 
    246   // Returns the pref name.
    247   const std::string& GetPrefName() const {
    248     return pref_name();
    249   }
    250 
    251  private:
    252   class Internal : public subtle::PrefMemberBase::Internal {
    253    public:
    254     Internal() : value_(ValueType()) {}
    255 
    256     ValueType value() {
    257       CheckOnCorrectThread();
    258       return value_;
    259     }
    260 
    261    protected:
    262     virtual ~Internal() {}
    263 
    264     virtual BASE_PREFS_EXPORT bool UpdateValueInternal(
    265         const base::Value& value) const OVERRIDE;
    266 
    267     // We cache the value of the pref so we don't have to keep walking the pref
    268     // tree.
    269     mutable ValueType value_;
    270 
    271     DISALLOW_COPY_AND_ASSIGN(Internal);
    272   };
    273 
    274   virtual Internal* internal() const OVERRIDE { return internal_.get(); }
    275   virtual void CreateInternal() const OVERRIDE { internal_ = new Internal(); }
    276 
    277   // This method is used to do the actual sync with pref of the specified type.
    278   void BASE_PREFS_EXPORT UpdatePref(const ValueType& value);
    279 
    280   mutable scoped_refptr<Internal> internal_;
    281 
    282   DISALLOW_COPY_AND_ASSIGN(PrefMember);
    283 };
    284 
    285 // Declaration of template specialization need to be repeated here
    286 // specifically for each specialization (rather than just once above)
    287 // or at least one of our compilers won't be happy in all cases.
    288 // Specifically, it was failing on ChromeOS with a complaint about
    289 // PrefMember<FilePath>::UpdateValueInternal not being defined when
    290 // built in a chroot with the following parameters:
    291 //
    292 // FEATURES="noclean nostrip" USE="-chrome_debug -chrome_remoting
    293 // -chrome_internal -chrome_pdf component_build"
    294 // ~/trunk/goma/goma-wrapper cros_chrome_make --board=${BOARD}
    295 // --install --runhooks
    296 
    297 template <>
    298 BASE_PREFS_EXPORT void PrefMember<bool>::UpdatePref(const bool& value);
    299 
    300 template <>
    301 BASE_PREFS_EXPORT bool PrefMember<bool>::Internal::UpdateValueInternal(
    302     const base::Value& value) const;
    303 
    304 template <>
    305 BASE_PREFS_EXPORT void PrefMember<int>::UpdatePref(const int& value);
    306 
    307 template <>
    308 BASE_PREFS_EXPORT bool PrefMember<int>::Internal::UpdateValueInternal(
    309     const base::Value& value) const;
    310 
    311 template <>
    312 BASE_PREFS_EXPORT void PrefMember<double>::UpdatePref(const double& value);
    313 
    314 template <>
    315 BASE_PREFS_EXPORT bool PrefMember<double>::Internal::UpdateValueInternal(
    316     const base::Value& value) const;
    317 
    318 template <>
    319 BASE_PREFS_EXPORT void PrefMember<std::string>::UpdatePref(
    320     const std::string& value);
    321 
    322 template <>
    323 BASE_PREFS_EXPORT bool PrefMember<std::string>::Internal::UpdateValueInternal(
    324     const base::Value& value) const;
    325 
    326 template <>
    327 BASE_PREFS_EXPORT void PrefMember<base::FilePath>::UpdatePref(
    328     const base::FilePath& value);
    329 
    330 template <>
    331 BASE_PREFS_EXPORT bool
    332 PrefMember<base::FilePath>::Internal::UpdateValueInternal(
    333     const base::Value& value) const;
    334 
    335 template <>
    336 BASE_PREFS_EXPORT void PrefMember<std::vector<std::string> >::UpdatePref(
    337     const std::vector<std::string>& value);
    338 
    339 template <>
    340 BASE_PREFS_EXPORT bool
    341 PrefMember<std::vector<std::string> >::Internal::UpdateValueInternal(
    342     const base::Value& value) const;
    343 
    344 typedef PrefMember<bool> BooleanPrefMember;
    345 typedef PrefMember<int> IntegerPrefMember;
    346 typedef PrefMember<double> DoublePrefMember;
    347 typedef PrefMember<std::string> StringPrefMember;
    348 typedef PrefMember<base::FilePath> FilePathPrefMember;
    349 // This preference member is expensive for large string arrays.
    350 typedef PrefMember<std::vector<std::string> > StringListPrefMember;
    351 
    352 #endif  // BASE_PREFS_PREF_MEMBER_H_
    353