summaryrefslogtreecommitdiffstats
path: root/extensions/browser/extension_pref_value_map.cc
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/browser/extension_pref_value_map.cc')
-rw-r--r--extensions/browser/extension_pref_value_map.cc376
1 files changed, 376 insertions, 0 deletions
diff --git a/extensions/browser/extension_pref_value_map.cc b/extensions/browser/extension_pref_value_map.cc
new file mode 100644
index 0000000..5cba7e5
--- /dev/null
+++ b/extensions/browser/extension_pref_value_map.cc
@@ -0,0 +1,376 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/extension_pref_value_map.h"
+
+#include "base/prefs/pref_value_map.h"
+#include "base/stl_util.h"
+#include "base/values.h"
+
+using extensions::ExtensionPrefsScope;
+
+struct ExtensionPrefValueMap::ExtensionEntry {
+ // Installation time of the extension.
+ base::Time install_time;
+ // Whether extension is enabled in the profile.
+ bool enabled;
+ // Extension controlled preferences for the regular profile.
+ PrefValueMap regular_profile_preferences;
+ // Extension controlled preferences that should *only* apply to the regular
+ // profile.
+ PrefValueMap regular_only_profile_preferences;
+ // Persistent extension controlled preferences for the incognito profile,
+ // empty for regular profile ExtensionPrefStore.
+ PrefValueMap incognito_profile_preferences_persistent;
+ // Session only extension controlled preferences for the incognito profile.
+ // These preferences are deleted when the incognito profile is destroyed.
+ PrefValueMap incognito_profile_preferences_session_only;
+};
+
+ExtensionPrefValueMap::ExtensionPrefValueMap() : destroyed_(false) {
+}
+
+ExtensionPrefValueMap::~ExtensionPrefValueMap() {
+ if (!destroyed_) {
+ NotifyOfDestruction();
+ destroyed_ = true;
+ }
+ STLDeleteValues(&entries_);
+ entries_.clear();
+}
+
+void ExtensionPrefValueMap::Shutdown() {
+ NotifyOfDestruction();
+ destroyed_ = true;
+}
+
+void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
+ const std::string& key,
+ ExtensionPrefsScope scope,
+ base::Value* value) {
+ PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
+
+ if (prefs->SetValue(key, value))
+ NotifyPrefValueChanged(key);
+}
+
+void ExtensionPrefValueMap::RemoveExtensionPref(
+ const std::string& ext_id,
+ const std::string& key,
+ ExtensionPrefsScope scope) {
+ PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
+ if (prefs->RemoveValue(key))
+ NotifyPrefValueChanged(key);
+}
+
+bool ExtensionPrefValueMap::CanExtensionControlPref(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ bool incognito) const {
+ ExtensionEntryMap::const_iterator ext = entries_.find(extension_id);
+ if (ext == entries_.end()) {
+ NOTREACHED();
+ return false;
+ }
+
+ ExtensionEntryMap::const_iterator winner =
+ GetEffectivePrefValueController(pref_key, incognito, NULL);
+ if (winner == entries_.end())
+ return true;
+
+ return winner->second->install_time <= ext->second->install_time;
+}
+
+void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
+ typedef std::set<std::string> KeySet;
+ KeySet deleted_keys;
+
+ ExtensionEntryMap::iterator i;
+ for (i = entries_.begin(); i != entries_.end(); ++i) {
+ PrefValueMap& inc_prefs =
+ i->second->incognito_profile_preferences_session_only;
+ PrefValueMap::iterator j;
+ for (j = inc_prefs.begin(); j != inc_prefs.end(); ++j)
+ deleted_keys.insert(j->first);
+ inc_prefs.Clear();
+ }
+
+ KeySet::iterator k;
+ for (k = deleted_keys.begin(); k != deleted_keys.end(); ++k)
+ NotifyPrefValueChanged(*k);
+}
+
+bool ExtensionPrefValueMap::DoesExtensionControlPref(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ bool* from_incognito) const {
+ bool incognito = (from_incognito != NULL);
+ ExtensionEntryMap::const_iterator winner =
+ GetEffectivePrefValueController(pref_key, incognito, from_incognito);
+ if (winner == entries_.end())
+ return false;
+ return winner->first == extension_id;
+}
+
+void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
+ const base::Time& install_time,
+ bool is_enabled) {
+ if (entries_.find(ext_id) == entries_.end()) {
+ entries_[ext_id] = new ExtensionEntry;
+
+ // Only update the install time if the extension is newly installed.
+ entries_[ext_id]->install_time = install_time;
+ }
+
+ entries_[ext_id]->enabled = is_enabled;
+}
+
+void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
+ ExtensionEntryMap::iterator i = entries_.find(ext_id);
+ if (i == entries_.end())
+ return;
+ std::set<std::string> keys; // keys set by this extension
+ GetExtensionControlledKeys(*(i->second), &keys);
+
+ delete i->second;
+ entries_.erase(i);
+
+ NotifyPrefValueChanged(keys);
+}
+
+void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
+ bool is_enabled) {
+ ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+ // This may happen when sync sets the extension state for an
+ // extension that is not installed.
+ if (i == entries_.end())
+ return;
+ if (i->second->enabled == is_enabled)
+ return;
+ std::set<std::string> keys; // keys set by this extension
+ GetExtensionControlledKeys(*(i->second), &keys);
+ i->second->enabled = is_enabled;
+ NotifyPrefValueChanged(keys);
+}
+
+PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
+ const std::string& ext_id,
+ ExtensionPrefsScope scope) {
+ ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+ CHECK(i != entries_.end());
+ switch (scope) {
+ case extensions::kExtensionPrefsScopeRegular:
+ return &(i->second->regular_profile_preferences);
+ case extensions::kExtensionPrefsScopeRegularOnly:
+ return &(i->second->regular_only_profile_preferences);
+ case extensions::kExtensionPrefsScopeIncognitoPersistent:
+ return &(i->second->incognito_profile_preferences_persistent);
+ case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
+ return &(i->second->incognito_profile_preferences_session_only);
+ }
+ NOTREACHED();
+ return NULL;
+}
+
+const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
+ const std::string& ext_id,
+ ExtensionPrefsScope scope) const {
+ ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+ CHECK(i != entries_.end());
+ switch (scope) {
+ case extensions::kExtensionPrefsScopeRegular:
+ return &(i->second->regular_profile_preferences);
+ case extensions::kExtensionPrefsScopeRegularOnly:
+ return &(i->second->regular_only_profile_preferences);
+ case extensions::kExtensionPrefsScopeIncognitoPersistent:
+ return &(i->second->incognito_profile_preferences_persistent);
+ case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
+ return &(i->second->incognito_profile_preferences_session_only);
+ }
+ NOTREACHED();
+ return NULL;
+}
+
+void ExtensionPrefValueMap::GetExtensionControlledKeys(
+ const ExtensionEntry& entry,
+ std::set<std::string>* out) const {
+ PrefValueMap::const_iterator i;
+
+ const PrefValueMap& regular_prefs = entry.regular_profile_preferences;
+ for (i = regular_prefs.begin(); i != regular_prefs.end(); ++i)
+ out->insert(i->first);
+
+ const PrefValueMap& regular_only_prefs =
+ entry.regular_only_profile_preferences;
+ for (i = regular_only_prefs.begin(); i != regular_only_prefs.end(); ++i)
+ out->insert(i->first);
+
+ const PrefValueMap& inc_prefs_pers =
+ entry.incognito_profile_preferences_persistent;
+ for (i = inc_prefs_pers.begin(); i != inc_prefs_pers.end(); ++i)
+ out->insert(i->first);
+
+ const PrefValueMap& inc_prefs_session =
+ entry.incognito_profile_preferences_session_only;
+ for (i = inc_prefs_session.begin(); i != inc_prefs_session.end(); ++i)
+ out->insert(i->first);
+}
+
+const base::Value* ExtensionPrefValueMap::GetEffectivePrefValue(
+ const std::string& key,
+ bool incognito,
+ bool* from_incognito) const {
+ ExtensionEntryMap::const_iterator winner =
+ GetEffectivePrefValueController(key, incognito, from_incognito);
+ if (winner == entries_.end())
+ return NULL;
+
+ const base::Value* value = NULL;
+ const std::string& ext_id = winner->first;
+
+ // First search for incognito session only preferences.
+ if (incognito) {
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
+ prefs->GetValue(key, &value);
+ if (value)
+ return value;
+
+ // If no incognito session only preference exists, fall back to persistent
+ // incognito preference.
+ prefs = GetExtensionPrefValueMap(
+ ext_id,
+ extensions::kExtensionPrefsScopeIncognitoPersistent);
+ prefs->GetValue(key, &value);
+ if (value)
+ return value;
+ } else {
+ // Regular-only preference.
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeRegularOnly);
+ prefs->GetValue(key, &value);
+ if (value)
+ return value;
+ }
+
+ // Regular preference.
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeRegular);
+ prefs->GetValue(key, &value);
+ return value;
+}
+
+ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
+ExtensionPrefValueMap::GetEffectivePrefValueController(
+ const std::string& key,
+ bool incognito,
+ bool* from_incognito) const {
+ ExtensionEntryMap::const_iterator winner = entries_.end();
+ base::Time winners_install_time;
+
+ ExtensionEntryMap::const_iterator i;
+ for (i = entries_.begin(); i != entries_.end(); ++i) {
+ const std::string& ext_id = i->first;
+ const base::Time& install_time = i->second->install_time;
+ const bool enabled = i->second->enabled;
+
+ if (!enabled)
+ continue;
+ if (install_time < winners_install_time)
+ continue;
+
+ const base::Value* value = NULL;
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeRegular);
+ if (prefs->GetValue(key, &value)) {
+ winner = i;
+ winners_install_time = install_time;
+ if (from_incognito)
+ *from_incognito = false;
+ }
+
+ if (!incognito) {
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeRegularOnly);
+ if (prefs->GetValue(key, &value)) {
+ winner = i;
+ winners_install_time = install_time;
+ if (from_incognito)
+ *from_incognito = false;
+ }
+ // Ignore the following prefs, because they're incognito-only.
+ continue;
+ }
+
+ prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeIncognitoPersistent);
+ if (prefs->GetValue(key, &value)) {
+ winner = i;
+ winners_install_time = install_time;
+ if (from_incognito)
+ *from_incognito = true;
+ }
+
+ prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
+ if (prefs->GetValue(key, &value)) {
+ winner = i;
+ winners_install_time = install_time;
+ if (from_incognito)
+ *from_incognito = true;
+ }
+ }
+ return winner;
+}
+
+void ExtensionPrefValueMap::AddObserver(
+ ExtensionPrefValueMap::Observer* observer) {
+ observers_.AddObserver(observer);
+
+ // Collect all currently used keys and notify the new observer.
+ std::set<std::string> keys;
+ ExtensionEntryMap::const_iterator i;
+ for (i = entries_.begin(); i != entries_.end(); ++i)
+ GetExtensionControlledKeys(*(i->second), &keys);
+
+ std::set<std::string>::const_iterator j;
+ for (j = keys.begin(); j != keys.end(); ++j)
+ observer->OnPrefValueChanged(*j);
+}
+
+void ExtensionPrefValueMap::RemoveObserver(
+ ExtensionPrefValueMap::Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+std::string ExtensionPrefValueMap::GetExtensionControllingPref(
+ const std::string& pref_key) const {
+ ExtensionEntryMap::const_iterator winner =
+ GetEffectivePrefValueController(pref_key, false, NULL);
+ if (winner == entries_.end())
+ return std::string();
+ return winner->first;
+}
+
+void ExtensionPrefValueMap::NotifyInitializationCompleted() {
+ FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+ OnInitializationCompleted());
+}
+
+void ExtensionPrefValueMap::NotifyPrefValueChanged(
+ const std::set<std::string>& keys) {
+ std::set<std::string>::const_iterator i;
+ for (i = keys.begin(); i != keys.end(); ++i)
+ NotifyPrefValueChanged(*i);
+}
+
+void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
+ FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+ OnPrefValueChanged(key));
+}
+
+void ExtensionPrefValueMap::NotifyOfDestruction() {
+ FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+ OnExtensionPrefValueMapDestruction());
+}