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