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