Home | History | Annotate | Download | only in extensions
      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 "chrome/browser/extensions/extension_pref_value_map.h"
      6 
      7 #include "base/prefs/pref_value_map.h"
      8 #include "base/stl_util.h"
      9 #include "base/values.h"
     10 
     11 using extensions::ExtensionPrefsScope;
     12 
     13 struct ExtensionPrefValueMap::ExtensionEntry {
     14   // Installation time of the extension.
     15   base::Time install_time;
     16   // Whether extension is enabled in the profile.
     17   bool enabled;
     18   // Extension controlled preferences for the regular profile.
     19   PrefValueMap regular_profile_preferences;
     20   // Extension controlled preferences that should *only* apply to the regular
     21   // profile.
     22   PrefValueMap regular_only_profile_preferences;
     23   // Persistent extension controlled preferences for the incognito profile,
     24   // empty for regular profile ExtensionPrefStore.
     25   PrefValueMap incognito_profile_preferences_persistent;
     26   // Session only extension controlled preferences for the incognito profile.
     27   // These preferences are deleted when the incognito profile is destroyed.
     28   PrefValueMap incognito_profile_preferences_session_only;
     29 };
     30 
     31 ExtensionPrefValueMap::ExtensionPrefValueMap() : destroyed_(false) {
     32 }
     33 
     34 ExtensionPrefValueMap::~ExtensionPrefValueMap() {
     35   if (!destroyed_) {
     36     NotifyOfDestruction();
     37     destroyed_ = true;
     38   }
     39   STLDeleteValues(&entries_);
     40   entries_.clear();
     41 }
     42 
     43 void ExtensionPrefValueMap::Shutdown() {
     44   NotifyOfDestruction();
     45   destroyed_ = true;
     46 }
     47 
     48 void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
     49                                              const std::string& key,
     50                                              ExtensionPrefsScope scope,
     51                                              Value* value) {
     52   PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
     53 
     54   if (prefs->SetValue(key, value))
     55     NotifyPrefValueChanged(key);
     56 }
     57 
     58 void ExtensionPrefValueMap::RemoveExtensionPref(
     59     const std::string& ext_id,
     60     const std::string& key,
     61     ExtensionPrefsScope scope) {
     62   PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
     63   if (prefs->RemoveValue(key))
     64     NotifyPrefValueChanged(key);
     65 }
     66 
     67 bool ExtensionPrefValueMap::CanExtensionControlPref(
     68     const std::string& extension_id,
     69     const std::string& pref_key,
     70     bool incognito) const {
     71   ExtensionEntryMap::const_iterator ext = entries_.find(extension_id);
     72   if (ext == entries_.end()) {
     73     NOTREACHED();
     74     return false;
     75   }
     76 
     77   ExtensionEntryMap::const_iterator winner =
     78       GetEffectivePrefValueController(pref_key, incognito, NULL);
     79   if (winner == entries_.end())
     80     return true;
     81 
     82   return winner->second->install_time <= ext->second->install_time;
     83 }
     84 
     85 void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
     86   typedef std::set<std::string> KeySet;
     87   KeySet deleted_keys;
     88 
     89   ExtensionEntryMap::iterator i;
     90   for (i = entries_.begin(); i != entries_.end(); ++i) {
     91     PrefValueMap& inc_prefs =
     92         i->second->incognito_profile_preferences_session_only;
     93     PrefValueMap::iterator j;
     94     for (j = inc_prefs.begin(); j != inc_prefs.end(); ++j)
     95       deleted_keys.insert(j->first);
     96     inc_prefs.Clear();
     97   }
     98 
     99   KeySet::iterator k;
    100   for (k = deleted_keys.begin(); k != deleted_keys.end(); ++k)
    101     NotifyPrefValueChanged(*k);
    102 }
    103 
    104 bool ExtensionPrefValueMap::DoesExtensionControlPref(
    105     const std::string& extension_id,
    106     const std::string& pref_key,
    107     bool* from_incognito) const {
    108   bool incognito = (from_incognito != NULL);
    109   ExtensionEntryMap::const_iterator winner =
    110       GetEffectivePrefValueController(pref_key, incognito, from_incognito);
    111   if (winner == entries_.end())
    112     return false;
    113   return winner->first == extension_id;
    114 }
    115 
    116 void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
    117                                               const base::Time& install_time,
    118                                               bool is_enabled) {
    119   if (entries_.find(ext_id) != entries_.end())
    120     UnregisterExtension(ext_id);
    121   entries_[ext_id] = new ExtensionEntry;
    122   entries_[ext_id]->install_time = install_time;
    123   entries_[ext_id]->enabled = is_enabled;
    124 }
    125 
    126 void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
    127   ExtensionEntryMap::iterator i = entries_.find(ext_id);
    128   if (i == entries_.end())
    129     return;
    130   std::set<std::string> keys;  // keys set by this extension
    131   GetExtensionControlledKeys(*(i->second), &keys);
    132 
    133   delete i->second;
    134   entries_.erase(i);
    135 
    136   NotifyPrefValueChanged(keys);
    137 }
    138 
    139 void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
    140                                               bool is_enabled) {
    141   ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
    142   // This may happen when sync sets the extension state for an
    143   // extension that is not installed.
    144   if (i == entries_.end())
    145     return;
    146   if (i->second->enabled == is_enabled)
    147     return;
    148   std::set<std::string> keys;  // keys set by this extension
    149   GetExtensionControlledKeys(*(i->second), &keys);
    150   i->second->enabled = is_enabled;
    151   NotifyPrefValueChanged(keys);
    152 }
    153 
    154 PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
    155     const std::string& ext_id,
    156     ExtensionPrefsScope scope) {
    157   ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
    158   CHECK(i != entries_.end());
    159   switch (scope) {
    160     case extensions::kExtensionPrefsScopeRegular:
    161       return &(i->second->regular_profile_preferences);
    162     case extensions::kExtensionPrefsScopeRegularOnly:
    163       return &(i->second->regular_only_profile_preferences);
    164     case extensions::kExtensionPrefsScopeIncognitoPersistent:
    165       return &(i->second->incognito_profile_preferences_persistent);
    166     case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
    167       return &(i->second->incognito_profile_preferences_session_only);
    168   }
    169   NOTREACHED();
    170   return NULL;
    171 }
    172 
    173 const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
    174     const std::string& ext_id,
    175     ExtensionPrefsScope scope) const {
    176   ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
    177   CHECK(i != entries_.end());
    178   switch (scope) {
    179     case extensions::kExtensionPrefsScopeRegular:
    180       return &(i->second->regular_profile_preferences);
    181     case extensions::kExtensionPrefsScopeRegularOnly:
    182       return &(i->second->regular_only_profile_preferences);
    183     case extensions::kExtensionPrefsScopeIncognitoPersistent:
    184       return &(i->second->incognito_profile_preferences_persistent);
    185     case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
    186       return &(i->second->incognito_profile_preferences_session_only);
    187   }
    188   NOTREACHED();
    189   return NULL;
    190 }
    191 
    192 void ExtensionPrefValueMap::GetExtensionControlledKeys(
    193     const ExtensionEntry& entry,
    194     std::set<std::string>* out) const {
    195   PrefValueMap::const_iterator i;
    196 
    197   const PrefValueMap& regular_prefs = entry.regular_profile_preferences;
    198   for (i = regular_prefs.begin(); i != regular_prefs.end(); ++i)
    199     out->insert(i->first);
    200 
    201   const PrefValueMap& regular_only_prefs =
    202       entry.regular_only_profile_preferences;
    203   for (i = regular_only_prefs.begin(); i != regular_only_prefs.end(); ++i)
    204     out->insert(i->first);
    205 
    206   const PrefValueMap& inc_prefs_pers =
    207       entry.incognito_profile_preferences_persistent;
    208   for (i = inc_prefs_pers.begin(); i != inc_prefs_pers.end(); ++i)
    209     out->insert(i->first);
    210 
    211   const PrefValueMap& inc_prefs_session =
    212       entry.incognito_profile_preferences_session_only;
    213   for (i = inc_prefs_session.begin(); i != inc_prefs_session.end(); ++i)
    214     out->insert(i->first);
    215 }
    216 
    217 const Value* ExtensionPrefValueMap::GetEffectivePrefValue(
    218     const std::string& key,
    219     bool incognito,
    220     bool* from_incognito) const {
    221   ExtensionEntryMap::const_iterator winner =
    222       GetEffectivePrefValueController(key, incognito, from_incognito);
    223   if (winner == entries_.end())
    224     return NULL;
    225 
    226   const Value* value = NULL;
    227   const std::string& ext_id = winner->first;
    228 
    229   // First search for incognito session only preferences.
    230   if (incognito) {
    231     const PrefValueMap* prefs = GetExtensionPrefValueMap(
    232         ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
    233     prefs->GetValue(key, &value);
    234     if (value)
    235       return value;
    236 
    237     // If no incognito session only preference exists, fall back to persistent
    238     // incognito preference.
    239     prefs = GetExtensionPrefValueMap(
    240         ext_id,
    241         extensions::kExtensionPrefsScopeIncognitoPersistent);
    242     prefs->GetValue(key, &value);
    243     if (value)
    244       return value;
    245   } else {
    246     // Regular-only preference.
    247     const PrefValueMap* prefs = GetExtensionPrefValueMap(
    248         ext_id, extensions::kExtensionPrefsScopeRegularOnly);
    249     prefs->GetValue(key, &value);
    250     if (value)
    251       return value;
    252   }
    253 
    254   // Regular preference.
    255   const PrefValueMap* prefs = GetExtensionPrefValueMap(
    256       ext_id, extensions::kExtensionPrefsScopeRegular);
    257   prefs->GetValue(key, &value);
    258   return value;
    259 }
    260 
    261 ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
    262 ExtensionPrefValueMap::GetEffectivePrefValueController(
    263     const std::string& key,
    264     bool incognito,
    265     bool* from_incognito) const {
    266   ExtensionEntryMap::const_iterator winner = entries_.end();
    267   base::Time winners_install_time;
    268 
    269   ExtensionEntryMap::const_iterator i;
    270   for (i = entries_.begin(); i != entries_.end(); ++i) {
    271     const std::string& ext_id = i->first;
    272     const base::Time& install_time = i->second->install_time;
    273     const bool enabled = i->second->enabled;
    274 
    275     if (!enabled)
    276       continue;
    277     if (install_time < winners_install_time)
    278       continue;
    279 
    280     const Value* value = NULL;
    281     const PrefValueMap* prefs = GetExtensionPrefValueMap(
    282         ext_id, extensions::kExtensionPrefsScopeRegular);
    283     if (prefs->GetValue(key, &value)) {
    284       winner = i;
    285       winners_install_time = install_time;
    286       if (from_incognito)
    287         *from_incognito = false;
    288     }
    289 
    290     if (!incognito) {
    291       const PrefValueMap* prefs = GetExtensionPrefValueMap(
    292           ext_id, extensions::kExtensionPrefsScopeRegularOnly);
    293       if (prefs->GetValue(key, &value)) {
    294         winner = i;
    295         winners_install_time = install_time;
    296         if (from_incognito)
    297           *from_incognito = false;
    298       }
    299       // Ignore the following prefs, because they're incognito-only.
    300       continue;
    301     }
    302 
    303     prefs = GetExtensionPrefValueMap(
    304         ext_id, extensions::kExtensionPrefsScopeIncognitoPersistent);
    305     if (prefs->GetValue(key, &value)) {
    306       winner = i;
    307       winners_install_time = install_time;
    308       if (from_incognito)
    309         *from_incognito = true;
    310     }
    311 
    312     prefs = GetExtensionPrefValueMap(
    313         ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
    314     if (prefs->GetValue(key, &value)) {
    315       winner = i;
    316       winners_install_time = install_time;
    317       if (from_incognito)
    318         *from_incognito = true;
    319     }
    320   }
    321   return winner;
    322 }
    323 
    324 void ExtensionPrefValueMap::AddObserver(
    325     ExtensionPrefValueMap::Observer* observer) {
    326   observers_.AddObserver(observer);
    327 
    328   // Collect all currently used keys and notify the new observer.
    329   std::set<std::string> keys;
    330   ExtensionEntryMap::const_iterator i;
    331   for (i = entries_.begin(); i != entries_.end(); ++i)
    332     GetExtensionControlledKeys(*(i->second), &keys);
    333 
    334   std::set<std::string>::const_iterator j;
    335   for (j = keys.begin(); j != keys.end(); ++j)
    336     observer->OnPrefValueChanged(*j);
    337 }
    338 
    339 void ExtensionPrefValueMap::RemoveObserver(
    340     ExtensionPrefValueMap::Observer* observer) {
    341   observers_.RemoveObserver(observer);
    342 }
    343 
    344 void ExtensionPrefValueMap::NotifyInitializationCompleted() {
    345   FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
    346                     OnInitializationCompleted());
    347 }
    348 
    349 void ExtensionPrefValueMap::NotifyPrefValueChanged(
    350     const std::set<std::string>& keys) {
    351   std::set<std::string>::const_iterator i;
    352   for (i = keys.begin(); i != keys.end(); ++i)
    353     NotifyPrefValueChanged(*i);
    354 }
    355 
    356 void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
    357   FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
    358                     OnPrefValueChanged(key));
    359 }
    360 
    361 void ExtensionPrefValueMap::NotifyOfDestruction() {
    362   FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
    363                     OnExtensionPrefValueMapDestruction());
    364 }
    365