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 #include "base/prefs/pref_value_store.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/prefs/pref_notifier.h"
      9 #include "base/prefs/pref_observer.h"
     10 
     11 PrefValueStore::PrefStoreKeeper::PrefStoreKeeper()
     12     : pref_value_store_(NULL),
     13       type_(PrefValueStore::INVALID_STORE) {
     14 }
     15 
     16 PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() {
     17   if (pref_store_.get()) {
     18     pref_store_->RemoveObserver(this);
     19     pref_store_ = NULL;
     20   }
     21   pref_value_store_ = NULL;
     22 }
     23 
     24 void PrefValueStore::PrefStoreKeeper::Initialize(
     25     PrefValueStore* store,
     26     PrefStore* pref_store,
     27     PrefValueStore::PrefStoreType type) {
     28   if (pref_store_.get()) {
     29     pref_store_->RemoveObserver(this);
     30     DCHECK(!pref_store_->HasObservers());
     31   }
     32   type_ = type;
     33   pref_value_store_ = store;
     34   pref_store_ = pref_store;
     35   if (pref_store_.get())
     36     pref_store_->AddObserver(this);
     37 }
     38 
     39 void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged(
     40     const std::string& key) {
     41   pref_value_store_->OnPrefValueChanged(type_, key);
     42 }
     43 
     44 void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted(
     45     bool succeeded) {
     46   pref_value_store_->OnInitializationCompleted(type_, succeeded);
     47 }
     48 
     49 PrefValueStore::PrefValueStore(PrefStore* managed_prefs,
     50                                PrefStore* supervised_user_prefs,
     51                                PrefStore* extension_prefs,
     52                                PrefStore* command_line_prefs,
     53                                PrefStore* user_prefs,
     54                                PrefStore* recommended_prefs,
     55                                PrefStore* default_prefs,
     56                                PrefNotifier* pref_notifier)
     57     : pref_notifier_(pref_notifier),
     58       initialization_failed_(false) {
     59   InitPrefStore(MANAGED_STORE, managed_prefs);
     60   InitPrefStore(SUPERVISED_USER_STORE, supervised_user_prefs);
     61   InitPrefStore(EXTENSION_STORE, extension_prefs);
     62   InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
     63   InitPrefStore(USER_STORE, user_prefs);
     64   InitPrefStore(RECOMMENDED_STORE, recommended_prefs);
     65   InitPrefStore(DEFAULT_STORE, default_prefs);
     66 
     67   CheckInitializationCompleted();
     68 }
     69 
     70 PrefValueStore::~PrefValueStore() {}
     71 
     72 PrefValueStore* PrefValueStore::CloneAndSpecialize(
     73     PrefStore* managed_prefs,
     74     PrefStore* supervised_user_prefs,
     75     PrefStore* extension_prefs,
     76     PrefStore* command_line_prefs,
     77     PrefStore* user_prefs,
     78     PrefStore* recommended_prefs,
     79     PrefStore* default_prefs,
     80     PrefNotifier* pref_notifier) {
     81   DCHECK(pref_notifier);
     82   if (!managed_prefs)
     83     managed_prefs = GetPrefStore(MANAGED_STORE);
     84   if (!supervised_user_prefs)
     85     supervised_user_prefs = GetPrefStore(SUPERVISED_USER_STORE);
     86   if (!extension_prefs)
     87     extension_prefs = GetPrefStore(EXTENSION_STORE);
     88   if (!command_line_prefs)
     89     command_line_prefs = GetPrefStore(COMMAND_LINE_STORE);
     90   if (!user_prefs)
     91     user_prefs = GetPrefStore(USER_STORE);
     92   if (!recommended_prefs)
     93     recommended_prefs = GetPrefStore(RECOMMENDED_STORE);
     94   if (!default_prefs)
     95     default_prefs = GetPrefStore(DEFAULT_STORE);
     96 
     97   return new PrefValueStore(
     98       managed_prefs, supervised_user_prefs, extension_prefs, command_line_prefs,
     99       user_prefs, recommended_prefs, default_prefs, pref_notifier);
    100 }
    101 
    102 void PrefValueStore::set_callback(const PrefChangedCallback& callback) {
    103   pref_changed_callback_ = callback;
    104 }
    105 
    106 bool PrefValueStore::GetValue(const std::string& name,
    107                               base::Value::Type type,
    108                               const base::Value** out_value) const {
    109   // Check the |PrefStore|s in order of their priority from highest to lowest,
    110   // looking for the first preference value with the given |name| and |type|.
    111   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
    112     if (GetValueFromStoreWithType(name.c_str(), type,
    113                                   static_cast<PrefStoreType>(i), out_value))
    114       return true;
    115   }
    116   return false;
    117 }
    118 
    119 bool PrefValueStore::GetRecommendedValue(const std::string& name,
    120                                          base::Value::Type type,
    121                                          const base::Value** out_value) const {
    122   return GetValueFromStoreWithType(name.c_str(), type, RECOMMENDED_STORE,
    123                                    out_value);
    124 }
    125 
    126 void PrefValueStore::NotifyPrefChanged(
    127     const char* path,
    128     PrefValueStore::PrefStoreType new_store) {
    129   DCHECK(new_store != INVALID_STORE);
    130   // A notification is sent when the pref value in any store changes. If this
    131   // store is currently being overridden by a higher-priority store, the
    132   // effective value of the pref will not have changed.
    133   pref_notifier_->OnPreferenceChanged(path);
    134   if (!pref_changed_callback_.is_null())
    135     pref_changed_callback_.Run(path);
    136 }
    137 
    138 bool PrefValueStore::PrefValueInManagedStore(const char* name) const {
    139   return PrefValueInStore(name, MANAGED_STORE);
    140 }
    141 
    142 bool PrefValueStore::PrefValueInExtensionStore(const char* name) const {
    143   return PrefValueInStore(name, EXTENSION_STORE);
    144 }
    145 
    146 bool PrefValueStore::PrefValueInUserStore(const char* name) const {
    147   return PrefValueInStore(name, USER_STORE);
    148 }
    149 
    150 bool PrefValueStore::PrefValueFromExtensionStore(const char* name) const {
    151   return ControllingPrefStoreForPref(name) == EXTENSION_STORE;
    152 }
    153 
    154 bool PrefValueStore::PrefValueFromUserStore(const char* name) const {
    155   return ControllingPrefStoreForPref(name) == USER_STORE;
    156 }
    157 
    158 bool PrefValueStore::PrefValueFromRecommendedStore(const char* name) const {
    159   return ControllingPrefStoreForPref(name) == RECOMMENDED_STORE;
    160 }
    161 
    162 bool PrefValueStore::PrefValueFromDefaultStore(const char* name) const {
    163   return ControllingPrefStoreForPref(name) == DEFAULT_STORE;
    164 }
    165 
    166 bool PrefValueStore::PrefValueUserModifiable(const char* name) const {
    167   PrefStoreType effective_store = ControllingPrefStoreForPref(name);
    168   return effective_store >= USER_STORE ||
    169          effective_store == INVALID_STORE;
    170 }
    171 
    172 bool PrefValueStore::PrefValueExtensionModifiable(const char* name) const {
    173   PrefStoreType effective_store = ControllingPrefStoreForPref(name);
    174   return effective_store >= EXTENSION_STORE ||
    175          effective_store == INVALID_STORE;
    176 }
    177 
    178 void PrefValueStore::UpdateCommandLinePrefStore(PrefStore* command_line_prefs) {
    179   InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
    180 }
    181 
    182 bool PrefValueStore::PrefValueInStore(
    183     const char* name,
    184     PrefValueStore::PrefStoreType store) const {
    185   // Declare a temp Value* and call GetValueFromStore,
    186   // ignoring the output value.
    187   const base::Value* tmp_value = NULL;
    188   return GetValueFromStore(name, store, &tmp_value);
    189 }
    190 
    191 bool PrefValueStore::PrefValueInStoreRange(
    192     const char* name,
    193     PrefValueStore::PrefStoreType first_checked_store,
    194     PrefValueStore::PrefStoreType last_checked_store) const {
    195   if (first_checked_store > last_checked_store) {
    196     NOTREACHED();
    197     return false;
    198   }
    199 
    200   for (size_t i = first_checked_store;
    201        i <= static_cast<size_t>(last_checked_store); ++i) {
    202     if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
    203       return true;
    204   }
    205   return false;
    206 }
    207 
    208 PrefValueStore::PrefStoreType PrefValueStore::ControllingPrefStoreForPref(
    209     const char* name) const {
    210   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
    211     if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
    212       return static_cast<PrefStoreType>(i);
    213   }
    214   return INVALID_STORE;
    215 }
    216 
    217 bool PrefValueStore::GetValueFromStore(const char* name,
    218                                        PrefValueStore::PrefStoreType store_type,
    219                                        const base::Value** out_value) const {
    220   // Only return true if we find a value and it is the correct type, so stale
    221   // values with the incorrect type will be ignored.
    222   const PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(store_type));
    223   if (store && store->GetValue(name, out_value))
    224     return true;
    225 
    226   // No valid value found for the given preference name: set the return value
    227   // to false.
    228   *out_value = NULL;
    229   return false;
    230 }
    231 
    232 bool PrefValueStore::GetValueFromStoreWithType(
    233     const char* name,
    234     base::Value::Type type,
    235     PrefStoreType store,
    236     const base::Value** out_value) const {
    237   if (GetValueFromStore(name, store, out_value)) {
    238     if ((*out_value)->IsType(type))
    239       return true;
    240 
    241     LOG(WARNING) << "Expected type for " << name << " is " << type
    242                  << " but got " << (*out_value)->GetType()
    243                  << " in store " << store;
    244   }
    245 
    246   *out_value = NULL;
    247   return false;
    248 }
    249 
    250 void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type,
    251                                         const std::string& key) {
    252   NotifyPrefChanged(key.c_str(), type);
    253 }
    254 
    255 void PrefValueStore::OnInitializationCompleted(
    256     PrefValueStore::PrefStoreType type, bool succeeded) {
    257   if (initialization_failed_)
    258     return;
    259   if (!succeeded) {
    260     initialization_failed_ = true;
    261     pref_notifier_->OnInitializationCompleted(false);
    262     return;
    263   }
    264   CheckInitializationCompleted();
    265 }
    266 
    267 void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type,
    268                                    PrefStore* pref_store) {
    269   pref_stores_[type].Initialize(this, pref_store, type);
    270 }
    271 
    272 void PrefValueStore::CheckInitializationCompleted() {
    273   if (initialization_failed_)
    274     return;
    275   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
    276     scoped_refptr<PrefStore> store =
    277         GetPrefStore(static_cast<PrefStoreType>(i));
    278     if (store.get() && !store->IsInitializationComplete())
    279       return;
    280   }
    281   pref_notifier_->OnInitializationCompleted(true);
    282 }
    283