Home | History | Annotate | Download | only in prefs
      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 #include "chrome/browser/prefs/pref_value_store.h"
      6 
      7 #include "chrome/browser/prefs/pref_notifier.h"
      8 
      9 PrefValueStore::PrefStoreKeeper::PrefStoreKeeper()
     10     : pref_value_store_(NULL),
     11       type_(PrefValueStore::INVALID_STORE) {
     12 }
     13 
     14 PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() {
     15   if (pref_store_.get()) {
     16     pref_store_->RemoveObserver(this);
     17     pref_store_ = NULL;
     18   }
     19   pref_value_store_ = NULL;
     20 }
     21 
     22 void PrefValueStore::PrefStoreKeeper::Initialize(
     23     PrefValueStore* store,
     24     PrefStore* pref_store,
     25     PrefValueStore::PrefStoreType type) {
     26   if (pref_store_.get())
     27     pref_store_->RemoveObserver(this);
     28   type_ = type;
     29   pref_value_store_ = store;
     30   pref_store_ = pref_store;
     31   if (pref_store_.get())
     32     pref_store_->AddObserver(this);
     33 }
     34 
     35 void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged(
     36     const std::string& key) {
     37   pref_value_store_->OnPrefValueChanged(type_, key);
     38 }
     39 
     40 void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted() {
     41   pref_value_store_->OnInitializationCompleted(type_);
     42 }
     43 
     44 PrefValueStore::PrefValueStore(PrefStore* managed_platform_prefs,
     45                                PrefStore* managed_cloud_prefs,
     46                                PrefStore* extension_prefs,
     47                                PrefStore* command_line_prefs,
     48                                PrefStore* user_prefs,
     49                                PrefStore* recommended_platform_prefs,
     50                                PrefStore* recommended_cloud_prefs,
     51                                PrefStore* default_prefs,
     52                                PrefNotifier* pref_notifier)
     53     : pref_notifier_(pref_notifier) {
     54   InitPrefStore(MANAGED_PLATFORM_STORE, managed_platform_prefs);
     55   InitPrefStore(MANAGED_CLOUD_STORE, managed_cloud_prefs);
     56   InitPrefStore(EXTENSION_STORE, extension_prefs);
     57   InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
     58   InitPrefStore(USER_STORE, user_prefs);
     59   InitPrefStore(RECOMMENDED_PLATFORM_STORE, recommended_platform_prefs);
     60   InitPrefStore(RECOMMENDED_CLOUD_STORE, recommended_cloud_prefs);
     61   InitPrefStore(DEFAULT_STORE, default_prefs);
     62 
     63   CheckInitializationCompleted();
     64 }
     65 
     66 PrefValueStore::~PrefValueStore() {}
     67 
     68 PrefValueStore* PrefValueStore::CloneAndSpecialize(
     69     PrefStore* managed_platform_prefs,
     70     PrefStore* managed_cloud_prefs,
     71     PrefStore* extension_prefs,
     72     PrefStore* command_line_prefs,
     73     PrefStore* user_prefs,
     74     PrefStore* recommended_platform_prefs,
     75     PrefStore* recommended_cloud_prefs,
     76     PrefStore* default_prefs,
     77     PrefNotifier* pref_notifier) {
     78   DCHECK(pref_notifier);
     79   if (!managed_platform_prefs)
     80     managed_platform_prefs = GetPrefStore(MANAGED_PLATFORM_STORE);
     81   if (!managed_cloud_prefs)
     82     managed_cloud_prefs = GetPrefStore(MANAGED_CLOUD_STORE);
     83   if (!extension_prefs)
     84     extension_prefs = GetPrefStore(EXTENSION_STORE);
     85   if (!command_line_prefs)
     86     command_line_prefs = GetPrefStore(COMMAND_LINE_STORE);
     87   if (!user_prefs)
     88     user_prefs = GetPrefStore(USER_STORE);
     89   if (!recommended_platform_prefs)
     90     recommended_platform_prefs = GetPrefStore(RECOMMENDED_PLATFORM_STORE);
     91   if (!recommended_cloud_prefs)
     92     recommended_cloud_prefs = GetPrefStore(RECOMMENDED_CLOUD_STORE);
     93   if (!default_prefs)
     94     default_prefs = GetPrefStore(DEFAULT_STORE);
     95 
     96   return new PrefValueStore(
     97       managed_platform_prefs, managed_cloud_prefs, extension_prefs,
     98       command_line_prefs, user_prefs, recommended_platform_prefs,
     99       recommended_cloud_prefs, default_prefs,
    100       pref_notifier);
    101 }
    102 
    103 bool PrefValueStore::GetValue(const std::string& name,
    104                               Value::ValueType type,
    105                               const Value** out_value) const {
    106   *out_value = NULL;
    107   // Check the |PrefStore|s in order of their priority from highest to lowest
    108   // to find the value of the preference described by the given preference name.
    109   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
    110     if (GetValueFromStore(name.c_str(), static_cast<PrefStoreType>(i),
    111                           out_value)) {
    112       if (!(*out_value)->IsType(type)) {
    113         LOG(WARNING) << "Expected type for " << name << " is " << type
    114                      << " but got " << (*out_value)->GetType()
    115                      << " in store " << i;
    116         continue;
    117       }
    118       return true;
    119     }
    120   }
    121   return false;
    122 }
    123 
    124 void PrefValueStore::NotifyPrefChanged(
    125     const char* path,
    126     PrefValueStore::PrefStoreType new_store) {
    127   DCHECK(new_store != INVALID_STORE);
    128 
    129   // If the pref is controlled by a higher-priority store, its effective value
    130   // cannot have changed.
    131   PrefStoreType controller = ControllingPrefStoreForPref(path);
    132   if (controller == INVALID_STORE || controller >= new_store)
    133     pref_notifier_->OnPreferenceChanged(path);
    134 }
    135 
    136 bool PrefValueStore::PrefValueInManagedStore(const char* name) const {
    137   return PrefValueInStore(name, MANAGED_PLATFORM_STORE) ||
    138          PrefValueInStore(name, MANAGED_CLOUD_STORE);
    139 }
    140 
    141 bool PrefValueStore::PrefValueInExtensionStore(const char* name) const {
    142   return PrefValueInStore(name, EXTENSION_STORE);
    143 }
    144 
    145 bool PrefValueStore::PrefValueInUserStore(const char* name) const {
    146   return PrefValueInStore(name, USER_STORE);
    147 }
    148 
    149 bool PrefValueStore::PrefValueFromExtensionStore(const char* name) const {
    150   return ControllingPrefStoreForPref(name) == EXTENSION_STORE;
    151 }
    152 
    153 bool PrefValueStore::PrefValueFromUserStore(const char* name) const {
    154   return ControllingPrefStoreForPref(name) == USER_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 bool PrefValueStore::PrefValueInStore(
    174     const char* name,
    175     PrefValueStore::PrefStoreType store) const {
    176   // Declare a temp Value* and call GetValueFromStore,
    177   // ignoring the output value.
    178   const Value* tmp_value = NULL;
    179   return GetValueFromStore(name, store, &tmp_value);
    180 }
    181 
    182 bool PrefValueStore::PrefValueInStoreRange(
    183     const char* name,
    184     PrefValueStore::PrefStoreType first_checked_store,
    185     PrefValueStore::PrefStoreType last_checked_store) const {
    186   if (first_checked_store > last_checked_store) {
    187     NOTREACHED();
    188     return false;
    189   }
    190 
    191   for (size_t i = first_checked_store;
    192        i <= static_cast<size_t>(last_checked_store); ++i) {
    193     if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
    194       return true;
    195   }
    196   return false;
    197 }
    198 
    199 PrefValueStore::PrefStoreType PrefValueStore::ControllingPrefStoreForPref(
    200     const char* name) const {
    201   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
    202     if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
    203       return static_cast<PrefStoreType>(i);
    204   }
    205   return INVALID_STORE;
    206 }
    207 
    208 bool PrefValueStore::GetValueFromStore(const char* name,
    209                                        PrefValueStore::PrefStoreType store_type,
    210                                        const Value** out_value) const {
    211   // Only return true if we find a value and it is the correct type, so stale
    212   // values with the incorrect type will be ignored.
    213   const PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(store_type));
    214   if (store) {
    215     switch (store->GetValue(name, out_value)) {
    216       case PrefStore::READ_USE_DEFAULT:
    217         store = GetPrefStore(DEFAULT_STORE);
    218         if (!store || store->GetValue(name, out_value) != PrefStore::READ_OK) {
    219           *out_value = NULL;
    220           return false;
    221         }
    222         // Fall through...
    223       case PrefStore::READ_OK:
    224         return true;
    225       case PrefStore::READ_NO_VALUE:
    226         break;
    227     }
    228   }
    229 
    230   // No valid value found for the given preference name: set the return false.
    231   *out_value = NULL;
    232   return false;
    233 }
    234 
    235 void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type,
    236                                         const std::string& key) {
    237   NotifyPrefChanged(key.c_str(), type);
    238 }
    239 
    240 void PrefValueStore::OnInitializationCompleted(
    241     PrefValueStore::PrefStoreType type) {
    242   CheckInitializationCompleted();
    243 }
    244 
    245 void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type,
    246                                    PrefStore* pref_store) {
    247   pref_stores_[type].Initialize(this, pref_store, type);
    248 }
    249 
    250 void PrefValueStore::CheckInitializationCompleted() {
    251   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
    252     scoped_refptr<PrefStore> store =
    253         GetPrefStore(static_cast<PrefStoreType>(i));
    254     if (store && !store->IsInitializationComplete())
    255       return;
    256   }
    257   pref_notifier_->OnInitializationCompleted();
    258 }
    259