Home | History | Annotate | Download | only in prefs
      1 // Copyright 2013 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 assists preferences in firing notifications when lists
      6 // or dictionaries are changed.
      7 
      8 #ifndef BASE_PREFS_SCOPED_USER_PREF_UPDATE_H_
      9 #define BASE_PREFS_SCOPED_USER_PREF_UPDATE_H_
     10 
     11 #include <string>
     12 
     13 #include "base/basictypes.h"
     14 #include "base/prefs/base_prefs_export.h"
     15 #include "base/prefs/pref_service.h"
     16 #include "base/threading/non_thread_safe.h"
     17 #include "base/values.h"
     18 
     19 class PrefService;
     20 
     21 namespace base {
     22 class DictionaryValue;
     23 class ListValue;
     24 }
     25 
     26 namespace subtle {
     27 
     28 // Base class for ScopedUserPrefUpdateTemplate that contains the parts
     29 // that do not depend on ScopedUserPrefUpdateTemplate's template parameter.
     30 //
     31 // We need this base class mostly for making it a friend of PrefService
     32 // and getting access to PrefService::GetMutableUserPref and
     33 // PrefService::ReportUserPrefChanged.
     34 class BASE_PREFS_EXPORT ScopedUserPrefUpdateBase : public base::NonThreadSafe {
     35  protected:
     36   ScopedUserPrefUpdateBase(PrefService* service, const char* path);
     37 
     38   // Calls Notify().
     39   ~ScopedUserPrefUpdateBase();
     40 
     41   // Sets |value_| to |service_|->GetMutableUserPref and returns it.
     42   base::Value* GetValueOfType(base::Value::Type type);
     43 
     44  private:
     45   // If |value_| is not null, triggers a notification of PrefObservers and
     46   // resets |value_|.
     47   void Notify();
     48 
     49   // Weak pointer.
     50   PrefService* service_;
     51   // Path of the preference being updated.
     52   std::string path_;
     53   // Cache of value from user pref store (set between Get() and Notify() calls).
     54   base::Value* value_;
     55 
     56   DISALLOW_COPY_AND_ASSIGN(ScopedUserPrefUpdateBase);
     57 };
     58 
     59 }  // namespace subtle
     60 
     61 // Class to support modifications to DictionaryValues and ListValues while
     62 // guaranteeing that PrefObservers are notified of changed values.
     63 //
     64 // This class may only be used on the UI thread as it requires access to the
     65 // PrefService.
     66 template <typename T, base::Value::Type type_enum_value>
     67 class ScopedUserPrefUpdate : public subtle::ScopedUserPrefUpdateBase {
     68  public:
     69   ScopedUserPrefUpdate(PrefService* service, const char* path)
     70       : ScopedUserPrefUpdateBase(service, path) {}
     71 
     72   // Triggers an update notification if Get() was called.
     73   virtual ~ScopedUserPrefUpdate() {}
     74 
     75   // Returns a mutable |T| instance that
     76   // - is already in the user pref store, or
     77   // - is (silently) created and written to the user pref store if none existed
     78   //   before.
     79   //
     80   // Calling Get() implies that an update notification is necessary at
     81   // destruction time.
     82   //
     83   // The ownership of the return value remains with the user pref store.
     84   // Virtual so it can be overriden in subclasses that transform the value
     85   // before returning it (for example to return a subelement of a dictionary).
     86   virtual T* Get() {
     87     return static_cast<T*>(GetValueOfType(type_enum_value));
     88   }
     89 
     90   T& operator*() {
     91     return *Get();
     92   }
     93 
     94   T* operator->() {
     95     return Get();
     96   }
     97 
     98  private:
     99   DISALLOW_COPY_AND_ASSIGN(ScopedUserPrefUpdate);
    100 };
    101 
    102 typedef ScopedUserPrefUpdate<base::DictionaryValue,
    103                              base::Value::TYPE_DICTIONARY>
    104     DictionaryPrefUpdate;
    105 typedef ScopedUserPrefUpdate<base::ListValue, base::Value::TYPE_LIST>
    106     ListPrefUpdate;
    107 
    108 #endif  // BASE_PREFS_SCOPED_USER_PREF_UPDATE_H_
    109