diff options
author | msramek <msramek@chromium.org> | 2015-03-24 06:27:07 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-24 13:27:45 +0000 |
commit | 4e9ea92c1cdcb084be89748a08f5b2e05b37c950 (patch) | |
tree | 96182f8cfcbaebf3c62597b10304ed8b9574f5cb /components/content_settings | |
parent | d5d61bfbe952814e030869af35ef338eb2ee9930 (diff) | |
download | chromium_src-4e9ea92c1cdcb084be89748a08f5b2e05b37c950.zip chromium_src-4e9ea92c1cdcb084be89748a08f5b2e05b37c950.tar.gz chromium_src-4e9ea92c1cdcb084be89748a08f5b2e05b37c950.tar.bz2 |
Split the default content settings into syncable and nonsyncable.
Parallel to the default content setting dictionary pref, I added N individual integer prefs. Syncable preferences are kept in sync with the matching dictionary entries, so that they can be synced to/from old versions of Chrome.
Default provider used the following, somewhat complicated, logic:
- when we read from a dictionary and there is no value for a particular content type, we reset the value to default, except if default=CONTENT_SETTING_DEFAULT, then we reset it to NULL
- when someone calls SetWebsiteSetting() with value NULL, we reset the value to default, except if default=CONTENT_SETTING_DEFAULT, then we keep NULL
I kept this logic when working with the individual preferences, which explains why there are a lot of "if NULL" and "if default==..." checks.
To make sure that we don't forget these checks on any read/write, I added two pairs of methods for reading to/writing from individual prefs/dictionary pref:
(Read|Write)(Individual|Dictionary)Pref\(\)
and a wrapper for writing to the cache
ChangeSetting().
BUG=452388
TESTED=Between trunk and old M40 stable. Syncable settings are synced both ways. Nonsyncable settings are not synced either way.
Review URL: https://codereview.chromium.org/1004733003
Cr-Commit-Position: refs/heads/master@{#321988}
Diffstat (limited to 'components/content_settings')
4 files changed, 398 insertions, 111 deletions
diff --git a/components/content_settings/core/browser/content_settings_default_provider.cc b/components/content_settings/core/browser/content_settings_default_provider.cc index bd0f474..a0a3e33 100644 --- a/components/content_settings/core/browser/content_settings_default_provider.cc +++ b/components/content_settings/core/browser/content_settings_default_provider.cc @@ -24,34 +24,49 @@ namespace { -// The default setting for each content type. -const ContentSetting kDefaultSettings[] = { - CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_COOKIES - CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_IMAGES - CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_JAVASCRIPT - CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_PLUGINS - CONTENT_SETTING_BLOCK, // CONTENT_SETTINGS_TYPE_POPUPS - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_GEOLOCATION - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_NOTIFICATIONS - CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_FULLSCREEN - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MOUSELOCK - CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_MIXEDSCRIPT - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MEDIASTREAM - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA - CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PPAPI_BROKER - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MIDI_SYSEX - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PUSH_MESSAGING - CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS +struct DefaultContentSettingInfo { + // The profile preference associated with this default setting. + const char* pref_name; + + // The default value of this default setting. + const ContentSetting default_value; + + // Whether this preference should be synced. + const bool syncable; +}; + +// The corresponding preference, default value and syncability for each +// default content setting. This array must be kept in sync with the enum +// |ContentSettingsType|. +const DefaultContentSettingInfo kDefaultSettings[] = { + {prefs::kDefaultCookiesSetting, CONTENT_SETTING_ALLOW, true}, + {prefs::kDefaultImagesSetting, CONTENT_SETTING_ALLOW, true}, + {prefs::kDefaultJavaScriptSetting, CONTENT_SETTING_ALLOW, true}, + {prefs::kDefaultPluginsSetting, CONTENT_SETTING_ALLOW, true}, + {prefs::kDefaultPopupsSetting, CONTENT_SETTING_BLOCK, true}, + {prefs::kDefaultGeolocationSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultNotificationsSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultAutoSelectCertificateSetting, CONTENT_SETTING_DEFAULT, + false}, + {prefs::kDefaultFullScreenSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultMouseLockSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultMixedScriptSetting, CONTENT_SETTING_DEFAULT, true}, + {prefs::kDefaultMediaStreamSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultMediaStreamMicSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultMediaStreamCameraSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultProtocolHandlersSetting, CONTENT_SETTING_DEFAULT, true}, + {prefs::kDefaultPpapiBrokerSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultAutomaticDownloadsSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultMidiSysexSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultPushMessagingSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultSSLCertDecisionsSetting, CONTENT_SETTING_ALLOW, false}, #if defined(OS_WIN) - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP + {prefs::kDefaultMetroSwitchToDesktopSetting, CONTENT_SETTING_ASK, true}, #elif defined(OS_ANDROID) || defined(OS_CHROMEOS) - CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER + {prefs::kDefaultProtectedMediaIdentifierSetting, CONTENT_SETTING_ASK, + false}, #endif - CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_APP_BANNER + {prefs::kDefaultAppBannerSetting, CONTENT_SETTING_DEFAULT, false} }; static_assert(arraysize(kDefaultSettings) == CONTENT_SETTINGS_NUM_TYPES, "kDefaultSettings should have CONTENT_SETTINGS_NUM_TYPES " @@ -99,6 +114,25 @@ void DefaultProvider::RegisterProfilePrefs( prefs::kDefaultContentSettings, default_content_settings, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + + // Register individual default setting preferences. + // TODO(msramek): The aggregate preference above is deprecated. Remove it + // after two stable releases. + for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { + registry->RegisterIntegerPref( + kDefaultSettings[i].pref_name, + kDefaultSettings[i].default_value, + kDefaultSettings[i].syncable + ? user_prefs::PrefRegistrySyncable::SYNCABLE_PREF + : user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + } + + // Whether the deprecated dictionary preference has already been migrated + // into the individual preferences in this profile. + registry->RegisterBooleanPref( + prefs::kMigratedDefaultContentSettings, + false, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); } DefaultProvider::DefaultProvider(PrefService* prefs, bool incognito) @@ -107,69 +141,76 @@ DefaultProvider::DefaultProvider(PrefService* prefs, bool incognito) updating_preferences_(false) { DCHECK(prefs_); + // Migrate the dictionary of default content settings to the new individual + // preferences. + MigrateDefaultSettings(); + // Read global defaults. - ReadDefaultSettings(true); + ReadDefaultSettings(); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultCookiesSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_COOKIES].pref_name)), CONTENT_SETTING_NUM_SETTINGS); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultImagesSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_IMAGES].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_IMAGES].pref_name)), CONTENT_SETTING_NUM_SETTINGS); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultJavaScriptSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_JAVASCRIPT].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_JAVASCRIPT].pref_name)), CONTENT_SETTING_NUM_SETTINGS); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultPluginsSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_PLUGINS].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_PLUGINS].pref_name)), CONTENT_SETTING_NUM_SETTINGS); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultPopupsSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_POPUPS].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_POPUPS].pref_name)), CONTENT_SETTING_NUM_SETTINGS); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultLocationSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_GEOLOCATION].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_GEOLOCATION].pref_name)), CONTENT_SETTING_NUM_SETTINGS); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultNotificationsSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_NOTIFICATIONS].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_NOTIFICATIONS].pref_name)), CONTENT_SETTING_NUM_SETTINGS); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultMouseCursorSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_MOUSELOCK].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_MOUSELOCK].pref_name)), CONTENT_SETTING_NUM_SETTINGS); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultMediaStreamSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_MEDIASTREAM].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_MEDIASTREAM].pref_name)), CONTENT_SETTING_NUM_SETTINGS); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultMIDISysExSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_MIDI_SYSEX].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_MIDI_SYSEX].pref_name)), CONTENT_SETTING_NUM_SETTINGS); UMA_HISTOGRAM_ENUMERATION( "ContentSettings.DefaultPushMessagingSetting", - ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_PUSH_MESSAGING].get()), + IntToContentSetting(prefs_->GetInteger( + kDefaultSettings[CONTENT_SETTINGS_TYPE_PUSH_MESSAGING].pref_name)), CONTENT_SETTING_NUM_SETTINGS); pref_change_registrar_.Init(prefs_); PrefChangeRegistrar::NamedChangeCallback callback = base::Bind( &DefaultProvider::OnPreferenceChanged, base::Unretained(this)); pref_change_registrar_.Add(prefs::kDefaultContentSettings, callback); + + for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) + pref_change_registrar_.Add(kDefaultSettings[i].pref_name, callback); } DefaultProvider::~DefaultProvider() { @@ -200,32 +241,16 @@ bool DefaultProvider::SetWebsiteSetting( scoped_ptr<base::Value> value(in_value); { base::AutoReset<bool> auto_reset(&updating_preferences_, true); - - // |DefaultProvider| should not send any notifications when holding - // |lock_|. |DictionaryPrefUpdate| destructor and - // |PrefService::SetInteger()| send out notifications. As a response, the - // upper layers may call |GetAllContentSettingRules| which acquires |lock_| - // again. - DictionaryPrefUpdate update(prefs_, prefs::kDefaultContentSettings); - base::DictionaryValue* default_settings_dictionary = update.Get(); base::AutoLock lock(lock_); - if (value.get() == NULL || - ValueToContentSetting(value.get()) == kDefaultSettings[content_type]) { - // If |value| is NULL we need to reset the default setting the the - // hardcoded default. - default_settings_[content_type].reset( - new base::FundamentalValue(kDefaultSettings[content_type])); - - // Remove the corresponding pref entry since the hardcoded default value - // is used. - default_settings_dictionary->RemoveWithoutPathExpansion( - GetTypeName(content_type), NULL); - } else { - default_settings_[content_type].reset(value->DeepCopy()); - // Transfer ownership of |value| to the |default_settings_dictionary|. - default_settings_dictionary->SetWithoutPathExpansion( - GetTypeName(content_type), value.release()); - } + + ChangeSetting(content_type, value.get()); + WriteIndividualPref(content_type, value.get()); + + // If the changed setting is syncable, write it to the old dictionary + // preference as well, so it can be synced to older versions of Chrome. + // TODO(msramek): Remove this after two stable releases. + if (kDefaultSettings[content_type].syncable) + WriteDictionaryPref(content_type, value.get()); } NotifyObservers(ContentSettingsPattern(), @@ -267,52 +292,173 @@ void DefaultProvider::ShutdownOnUIThread() { prefs_ = NULL; } +void DefaultProvider::ReadDefaultSettings() { + base::AutoLock lock(lock_); + for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { + ContentSettingsType content_type = ContentSettingsType(i); + ChangeSetting(content_type, ReadIndividualPref(content_type).get()); + } +} + +bool DefaultProvider::IsValueEmptyOrDefault(ContentSettingsType content_type, + base::Value* value) { + return (value == NULL || + ValueToContentSetting(value) + == kDefaultSettings[content_type].default_value); +} + +void DefaultProvider::ChangeSetting(ContentSettingsType content_type, + base::Value* value) { + if (!value) { + default_settings_[content_type].reset( + kDefaultSettings[content_type].default_value != CONTENT_SETTING_DEFAULT + ? new base::FundamentalValue( + kDefaultSettings[content_type].default_value) + : NULL); + } else { + default_settings_[content_type].reset(value->DeepCopy()); + } +} + +void DefaultProvider::WriteIndividualPref(ContentSettingsType content_type, + base::Value* value) { + if (IsValueEmptyOrDefault(content_type, value)) { + prefs_->ClearPref(kDefaultSettings[content_type].pref_name); + return; + } + + int int_value = kDefaultSettings[content_type].default_value; + bool is_integer = value->GetAsInteger(&int_value); + DCHECK(is_integer); + prefs_->SetInteger(kDefaultSettings[content_type].pref_name, int_value); +} + +void DefaultProvider::WriteDictionaryPref(ContentSettingsType content_type, + base::Value* value) { + // |DefaultProvider| should not send any notifications when holding + // |lock_|. |DictionaryPrefUpdate| destructor and + // |PrefService::SetInteger()| send out notifications. As a response, the + // upper layers may call |GetAllContentSettingRules| which acquires |lock_| + // again. + DictionaryPrefUpdate update(prefs_, prefs::kDefaultContentSettings); + base::DictionaryValue* default_settings_dictionary = update.Get(); + + if (IsValueEmptyOrDefault(content_type, value)) { + default_settings_dictionary->RemoveWithoutPathExpansion( + GetTypeName(content_type), NULL); + return; + } + + default_settings_dictionary->SetWithoutPathExpansion( + GetTypeName(content_type), value->DeepCopy()); +} + void DefaultProvider::OnPreferenceChanged(const std::string& name) { DCHECK(CalledOnValidThread()); if (updating_preferences_) return; + // Write the changed setting from individual preferences to dictionary, + // or vice versa - depending on which of them changed. + // TODO(msramek): This is only necessary in the phase of migration between + // the old dictionary preference and the new individual preferences. Remove + // this after two stable releases. + std::vector<ContentSettingsType> to_notify; + if (name == prefs::kDefaultContentSettings) { - ReadDefaultSettings(true); + // If the dictionary preference gets synced from an old version + // of Chrome, we should update all individual preferences that + // are marked as syncable. + base::AutoLock lock(lock_); + base::AutoReset<bool> auto_reset(&updating_preferences_, true); + + scoped_ptr<ValueMap> dictionary = ReadDictionaryPref(); + + for (ValueMap::iterator it = dictionary->begin(); + it != dictionary->end(); ++it) { + if (!kDefaultSettings[it->first].syncable) + continue; + + DCHECK(default_settings_.find(it->first) != default_settings_.end()); + ChangeSetting(it->first, it->second.get()); + WriteIndividualPref(it->first, it->second.get()); + to_notify.push_back(it->first); + } } else { - NOTREACHED() << "Unexpected preference observed"; - return; + // Find out which content setting the preference corresponds to. + ContentSettingsType content_type = CONTENT_SETTINGS_TYPE_DEFAULT; + + for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { + if (kDefaultSettings[i].pref_name == name) { + content_type = ContentSettingsType(i); + break; + } + } + + if (content_type == CONTENT_SETTINGS_TYPE_DEFAULT) { + NOTREACHED() << "Unexpected preference observed"; + return; + } + + // A new individual preference is changed. If it is syncable, we should + // change its entry in the dictionary preference as well, so that it + // can be synced to older versions of Chrome. + base::AutoLock lock(lock_); + base::AutoReset<bool> auto_reset(&updating_preferences_, true); + + ChangeSetting(content_type, ReadIndividualPref(content_type).get()); + if (kDefaultSettings[content_type].syncable) + WriteDictionaryPref(content_type, default_settings_[content_type].get()); + to_notify.push_back(content_type); } - NotifyObservers(ContentSettingsPattern(), - ContentSettingsPattern(), - CONTENT_SETTINGS_TYPE_DEFAULT, - std::string()); + for (size_t i = 0; i < to_notify.size(); ++i) { + NotifyObservers(ContentSettingsPattern(), + ContentSettingsPattern(), + to_notify[i], + std::string()); + } } -void DefaultProvider::ReadDefaultSettings(bool overwrite) { - base::AutoLock lock(lock_); +scoped_ptr<base::Value> DefaultProvider::ReadIndividualPref( + ContentSettingsType content_type) { + int int_value = prefs_->GetInteger(kDefaultSettings[content_type].pref_name); + + if (int_value == CONTENT_SETTING_DEFAULT) + return make_scoped_ptr((base::Value*)NULL); + else + return make_scoped_ptr(new base::FundamentalValue(int_value)); +} + +scoped_ptr<DefaultProvider::ValueMap> DefaultProvider::ReadDictionaryPref() { const base::DictionaryValue* default_settings_dictionary = prefs_->GetDictionary(prefs::kDefaultContentSettings); - if (overwrite) - default_settings_.clear(); - - // Careful: The returned value could be NULL if the pref has never been set. - if (default_settings_dictionary) - GetSettingsFromDictionary(default_settings_dictionary); + scoped_ptr<ValueMap> value_map = + GetSettingsFromDictionary(default_settings_dictionary); - ForceDefaultsToBeExplicit(); + ForceDefaultsToBeExplicit(value_map.get()); + return value_map.Pass(); } -void DefaultProvider::ForceDefaultsToBeExplicit() { +void DefaultProvider::ForceDefaultsToBeExplicit(ValueMap* value_map) { for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { ContentSettingsType type = ContentSettingsType(i); - if (!default_settings_[type].get() && - kDefaultSettings[i] != CONTENT_SETTING_DEFAULT) { - default_settings_[type].reset( - new base::FundamentalValue(kDefaultSettings[i])); + if (!(*value_map)[type].get() && + kDefaultSettings[i].default_value != CONTENT_SETTING_DEFAULT) { + (*value_map)[type].reset( + new base::FundamentalValue(kDefaultSettings[i].default_value)); } } } -void DefaultProvider::GetSettingsFromDictionary( - const base::DictionaryValue* dictionary) { +scoped_ptr<DefaultProvider::ValueMap> + DefaultProvider::GetSettingsFromDictionary( + const base::DictionaryValue* dictionary) { + if (!dictionary) + return make_scoped_ptr(new ValueMap()); + ValueMap* value_map = new ValueMap(); + for (base::DictionaryValue::Iterator i(*dictionary); !i.IsAtEnd(); i.Advance()) { const std::string& content_type(i.key()); @@ -321,7 +467,7 @@ void DefaultProvider::GetSettingsFromDictionary( int int_value = CONTENT_SETTING_DEFAULT; bool is_integer = i.value().GetAsInteger(&int_value); DCHECK(is_integer); - default_settings_[ContentSettingsType(type)].reset( + (*value_map)[ContentSettingsType(type)].reset( new base::FundamentalValue(int_value)); break; } @@ -329,11 +475,34 @@ void DefaultProvider::GetSettingsFromDictionary( } // Migrate obsolete cookie prompt mode. if (ValueToContentSetting( - default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].get()) == - CONTENT_SETTING_ASK) { - default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].reset( + (*value_map)[CONTENT_SETTINGS_TYPE_COOKIES].get()) + == CONTENT_SETTING_ASK) { + (*value_map)[CONTENT_SETTINGS_TYPE_COOKIES].reset( new base::FundamentalValue(CONTENT_SETTING_BLOCK)); } + + return make_scoped_ptr(value_map); +} + +void DefaultProvider::MigrateDefaultSettings() { + // Only do the migration once. + if (prefs_->GetBoolean(prefs::kMigratedDefaultContentSettings)) + return; + + scoped_ptr<DefaultProvider::ValueMap> value_map = ReadDictionaryPref(); + + for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { + ContentSettingsType content_type = ContentSettingsType(i); + WriteIndividualPref(content_type, (*value_map)[content_type].get()); + } + +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) + // For protected media identifier, it is desirable to just reset the setting + // instead of migrating it from the old preference. + WriteIndividualPref(CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, NULL); +#endif + + prefs_->SetBoolean(prefs::kMigratedDefaultContentSettings, true); } } // namespace content_settings diff --git a/components/content_settings/core/browser/content_settings_default_provider.h b/components/content_settings/core/browser/content_settings_default_provider.h index 6679bdc..2a58fa8 100644 --- a/components/content_settings/core/browser/content_settings_default_provider.h +++ b/components/content_settings/core/browser/content_settings_default_provider.h @@ -50,22 +50,53 @@ class DefaultProvider : public ObservableProvider { void ShutdownOnUIThread() override; private: - // Sets the fields of |settings| based on the values in |dictionary|. - void GetSettingsFromDictionary(const base::DictionaryValue* dictionary); + typedef linked_ptr<base::Value> ValuePtr; + typedef std::map<ContentSettingsType, ValuePtr> ValueMap; + + // Reads all individual settings from the pref service. + void ReadDefaultSettings(); + + // Change the remembered setting in the memory. + void ChangeSetting(ContentSettingsType content_type, base::Value* value); + + // True if |value| is NULL or it is the default value for |content_type|. + bool IsValueEmptyOrDefault(ContentSettingsType content_type, + base::Value* value); + + // Parses a |DictionaryValue| into a |ValueMap|. + scoped_ptr<ValueMap> GetSettingsFromDictionary( + const base::DictionaryValue* dictionary); - // Forces the default settings to be explicitly set instead of themselves - // being CONTENT_SETTING_DEFAULT. - void ForceDefaultsToBeExplicit(); + // Forces the default settings in |value_map| to be explicitly set instead + // of themselves being CONTENT_SETTING_DEFAULT. + void ForceDefaultsToBeExplicit(ValueMap* value_map); - // Reads the default settings from the preferences service. If |overwrite| is - // true and the preference is missing, the local copy will be cleared as well. - void ReadDefaultSettings(bool overwrite); + // Reads the dictionary prefrence and returns the dictionary parsed as + // a |ValueMap|. + scoped_ptr<ValueMap> ReadDictionaryPref(); + + // Reads an individual preference. + scoped_ptr<base::Value> ReadIndividualPref(ContentSettingsType content_type); + + // Writes the value |value| to the individual preference corresponding + // to |content_type|. It's the responsibility of caller to obtain a lock + // and notify observers. + void WriteIndividualPref(ContentSettingsType content_type, + base::Value* value); + + // Writes the value |value| to the dictionary preference entry corresponding + // to |content_type|. It's the responsibility of caller to obtain a lock + // and notify observers. + void WriteDictionaryPref(ContentSettingsType content_type, + base::Value* value); // Called on prefs change. void OnPreferenceChanged(const std::string& pref_name); - typedef linked_ptr<base::Value> ValuePtr; - typedef std::map<ContentSettingsType, ValuePtr> ValueMap; + // Migrates the dictionary settings to the individual settings. Only called + // once during the first run. + void MigrateDefaultSettings(); + // Copies of the pref data, so that we can read it on the IO thread. ValueMap default_settings_; @@ -74,7 +105,7 @@ class DefaultProvider : public ObservableProvider { // Whether this settings map is for an Incognito session. bool is_incognito_; - // Used around accesses to the |default_content_settings_| object to guarantee + // Used around accesses to the |default_settings_| object to guarantee // thread safety. mutable base::Lock lock_; diff --git a/components/content_settings/core/common/pref_names.cc b/components/content_settings/core/common/pref_names.cc index ef9b66c..10353a5 100644 --- a/components/content_settings/core/common/pref_names.cc +++ b/components/content_settings/core/common/pref_names.cc @@ -21,8 +21,65 @@ const char kContentSettingsWindowLastTabIndex[] = "content_settings_window.last_tab_index"; // Dictionary of content settings applied to all hosts by default. +// TODO(msramek): Deprecated. Use the individual preferences below. const char kDefaultContentSettings[] = "profile.default_content_settings"; +// Whether |kDefaultContentSettings| has already been migrated to +// |kDefault<type>Setting| prefs. +const char kMigratedDefaultContentSettings[] = + "profile.migrated_default_content_settings"; + +// Preferences storing the default values for individual content settings. +const char kDefaultCookiesSetting[] = + "profile.default_content_setting_values.cookies"; +const char kDefaultImagesSetting[] = + "profile.default_content_setting_values.images"; +const char kDefaultJavaScriptSetting[] = + "profile.default_content_setting_values.javascript"; +const char kDefaultPluginsSetting[] = + "profile.default_content_setting_values.plugins"; +const char kDefaultPopupsSetting[] = + "profile.default_content_setting_values.popups"; +const char kDefaultGeolocationSetting[] = + "profile.default_content_setting_values.geolocation"; +const char kDefaultNotificationsSetting[] = + "profile.default_content_setting_values.notifications"; +const char kDefaultAutoSelectCertificateSetting[] = + "profile.default_content_setting_values.auto_select_certificate"; +const char kDefaultFullScreenSetting[] = + "profile.default_content_setting_values.fullscreen"; +const char kDefaultMouseLockSetting[] = + "profile.default_content_setting_values.mouselock"; +const char kDefaultMixedScriptSetting[] = + "profile.default_content_setting_values.mixed_script"; +const char kDefaultMediaStreamSetting[] = + "profile.default_content_setting_values.media_stream"; +const char kDefaultMediaStreamMicSetting[] = + "profile.default_content_setting_values.media_stream_mic"; +const char kDefaultMediaStreamCameraSetting[] = + "profile.default_content_setting_values.media_stream_camera"; +const char kDefaultProtocolHandlersSetting[] = + "profile.default_content_setting_values.protocol_handlers"; +const char kDefaultPpapiBrokerSetting[] = + "profile.default_content_setting_values.ppapi_broker"; +const char kDefaultAutomaticDownloadsSetting[] = + "profile.default_content_setting_values.automatic_downloads"; +const char kDefaultMidiSysexSetting[] = + "profile.default_content_setting_values.midi_sysex"; +const char kDefaultPushMessagingSetting[] = + "profile.default_content_setting_values.push_messaging"; +const char kDefaultSSLCertDecisionsSetting[] = + "profile.default_content_setting_values.ssl_cert_decisions"; +#if defined(OS_WIN) +const char kDefaultMetroSwitchToDesktopSetting[] = + "profile.default_content_setting_values.metro_switch_to_desktop"; +#elif defined(OS_ANDROID) || defined(OS_CHROMEOS) +const char kDefaultProtectedMediaIdentifierSetting[] = + "profile.default_content_setting_values.protected_media_identifier"; +#endif +const char kDefaultAppBannerSetting[] = + "profile.default_content_setting_values.app_banner"; + // Dictionary of content settings that can globally disallow all hosts by // default. If a value is set, it means the setting is globally disallowed. // If a value is not set, it means the setting is allowed. diff --git a/components/content_settings/core/common/pref_names.h b/components/content_settings/core/common/pref_names.h index 6bc4f45..77c6f53 100644 --- a/components/content_settings/core/common/pref_names.h +++ b/components/content_settings/core/common/pref_names.h @@ -5,6 +5,8 @@ #ifndef COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_PREF_NAMES_H_ #define COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_PREF_NAMES_H_ +#include "base/logging.h" + namespace prefs { extern const char kContentSettingsVersion[]; @@ -12,6 +14,34 @@ extern const char kContentSettingsPatternPairs[]; extern const char kContentSettingsWindowLastTabIndex[]; extern const char kDefaultContentSettings[]; extern const char kOverrideContentSettings[]; +extern const char kMigratedDefaultContentSettings[]; + +extern const char kDefaultCookiesSetting[]; +extern const char kDefaultImagesSetting[]; +extern const char kDefaultJavaScriptSetting[]; +extern const char kDefaultPluginsSetting[]; +extern const char kDefaultPopupsSetting[]; +extern const char kDefaultGeolocationSetting[]; +extern const char kDefaultNotificationsSetting[]; +extern const char kDefaultAutoSelectCertificateSetting[]; +extern const char kDefaultFullScreenSetting[]; +extern const char kDefaultMouseLockSetting[]; +extern const char kDefaultMixedScriptSetting[]; +extern const char kDefaultMediaStreamSetting[]; +extern const char kDefaultMediaStreamMicSetting[]; +extern const char kDefaultMediaStreamCameraSetting[]; +extern const char kDefaultProtocolHandlersSetting[]; +extern const char kDefaultPpapiBrokerSetting[]; +extern const char kDefaultAutomaticDownloadsSetting[]; +extern const char kDefaultMidiSysexSetting[]; +extern const char kDefaultPushMessagingSetting[]; +extern const char kDefaultSSLCertDecisionsSetting[]; +#if defined(OS_WIN) +extern const char kDefaultMetroSwitchToDesktopSetting[]; +#elif defined(OS_ANDROID) || defined(OS_CHROMEOS) +extern const char kDefaultProtectedMediaIdentifierSetting[]; +#endif +extern const char kDefaultAppBannerSetting[]; extern const char kManagedDefaultCookiesSetting[]; extern const char kManagedDefaultImagesSetting[]; |