diff options
author | mukai <mukai@chromium.org> | 2014-10-25 10:53:16 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-25 17:53:36 +0000 |
commit | 8eaec82caaae926faedbfd7df0beb4979c3f6792 (patch) | |
tree | 2b34a3065ebc7bfc8ec242139e20fea4184ccde7 /components/content_settings | |
parent | 0b7b27587319dbc86e363501eb83ea99f39f10df (diff) | |
download | chromium_src-8eaec82caaae926faedbfd7df0beb4979c3f6792.zip chromium_src-8eaec82caaae926faedbfd7df0beb4979c3f6792.tar.gz chromium_src-8eaec82caaae926faedbfd7df0beb4979c3f6792.tar.bz2 |
Componentize HostContentSettingsMap and content settings providers.
These files are mutually dependent via includes (default provider
includes content_settings_util.h but content_settings_util.cc
includes host_content_settings_map.h, for example).
BUG=384869, 384876
R=bauerb@chromium.org, vabr@chromium.org
TBR=sky@chromium.org, rch@chromium.org
TEST=no functional changes, build succeeds
Review URL: https://codereview.chromium.org/670953006
Cr-Commit-Position: refs/heads/master@{#301286}
Diffstat (limited to 'components/content_settings')
21 files changed, 3860 insertions, 2 deletions
diff --git a/components/content_settings/core/browser/BUILD.gn b/components/content_settings/core/browser/BUILD.gn index 4535a9a..6bbbe6e 100644 --- a/components/content_settings/core/browser/BUILD.gn +++ b/components/content_settings/core/browser/BUILD.gn @@ -5,17 +5,29 @@ static_library("browser") { sources = [ "content_settings_client.h", + "content_settings_default_provider.cc", + "content_settings_default_provider.h", "content_settings_details.cc", "content_settings_details.h", - "content_settings_observer.h", - "content_settings_provider.h", "content_settings_observable_provider.cc", "content_settings_observable_provider.h", + "content_settings_observer.h", + "content_settings_override_provider.cc", + "content_settings_override_provider.h", + "content_settings_policy_provider.cc", + "content_settings_policy_provider.h", + "content_settings_pref_provider.cc", + "content_settings_pref_provider.h", + "content_settings_provider.h", "content_settings_origin_identifier_value_map.cc", "content_settings_origin_identifier_value_map.h", "content_settings_rule.cc", "content_settings_rule.h", + "content_settings_utils.cc", + "content_settings_utils.h", "local_shared_objects_counter.h", + "host_content_settings_map.cc", + "host_content_settings_map.h", ] deps = [ @@ -27,7 +39,11 @@ static_library("browser") { source_set("unit_tests") { testonly = true sources = [ + "content_settings_mock_provider.cc", + "content_settings_mock_provider.h", + "content_settings_provider_unittest.cc", "content_settings_rule_unittest.cc", + "content_settings_utils_unittest.cc", ] deps = [ diff --git a/components/content_settings/core/browser/DEPS b/components/content_settings/core/browser/DEPS index 2a5227a..a69d8b3 100644 --- a/components/content_settings/core/browser/DEPS +++ b/components/content_settings/core/browser/DEPS @@ -1,3 +1,5 @@ include_rules = [ + "+components/pref_registry", + "+net/base", "+net/cookies", ] diff --git a/components/content_settings/core/browser/content_settings_default_provider.cc b/components/content_settings/core/browser/content_settings_default_provider.cc new file mode 100644 index 0000000..90b91a3 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_default_provider.cc @@ -0,0 +1,340 @@ +// Copyright (c) 2012 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 "components/content_settings/core/browser/content_settings_default_provider.h" + +#include <string> +#include <vector> + +#include "base/auto_reset.h" +#include "base/basictypes.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/metrics/histogram.h" +#include "base/prefs/pref_service.h" +#include "base/prefs/scoped_user_pref_update.h" +#include "components/content_settings/core/browser/content_settings_rule.h" +#include "components/content_settings/core/browser/content_settings_utils.h" +#include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/content_settings/core/common/pref_names.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "url/gurl.h" + +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 +#if defined(OS_WIN) + CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP +#elif defined(OS_ANDROID) || defined(OS_CHROMEOS) + CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER +#endif +#if defined(OS_ANDROID) + CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_APP_BANNER +#endif +}; +COMPILE_ASSERT(arraysize(kDefaultSettings) == CONTENT_SETTINGS_NUM_TYPES, + default_settings_incorrect_size); + +} // namespace + +namespace content_settings { + +namespace { + +class DefaultRuleIterator : public RuleIterator { + public: + explicit DefaultRuleIterator(const base::Value* value) { + if (value) + value_.reset(value->DeepCopy()); + } + + bool HasNext() const override { return value_.get() != NULL; } + + Rule Next() override { + DCHECK(value_.get()); + return Rule(ContentSettingsPattern::Wildcard(), + ContentSettingsPattern::Wildcard(), + value_.release()); + } + + private: + scoped_ptr<base::Value> value_; +}; + +} // namespace + +// static +void DefaultProvider::RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) { + // The registration of the preference prefs::kDefaultContentSettings should + // also include the default values for default content settings. This allows + // functional tests to get default content settings by reading the preference + // prefs::kDefaultContentSettings via pyauto. + // TODO(markusheintz): Write pyauto hooks for the content settings map as + // content settings should be read from the host content settings map. + base::DictionaryValue* default_content_settings = new base::DictionaryValue(); + registry->RegisterDictionaryPref( + prefs::kDefaultContentSettings, + default_content_settings, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); +} + +DefaultProvider::DefaultProvider(PrefService* prefs, bool incognito) + : prefs_(prefs), + is_incognito_(incognito), + updating_preferences_(false) { + DCHECK(prefs_); + + // Read global defaults. + ReadDefaultSettings(true); + + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultCookiesSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].get()), + CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultImagesSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_IMAGES].get()), + CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultJavaScriptSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_JAVASCRIPT].get()), + CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultPluginsSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_PLUGINS].get()), + CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultPopupsSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_POPUPS].get()), + CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultLocationSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_GEOLOCATION].get()), + CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultNotificationsSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_NOTIFICATIONS].get()), + CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultMouseCursorSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_MOUSELOCK].get()), + CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultMediaStreamSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_MEDIASTREAM].get()), + CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultMIDISysExSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_MIDI_SYSEX].get()), + CONTENT_SETTING_NUM_SETTINGS); + UMA_HISTOGRAM_ENUMERATION( + "ContentSettings.DefaultPushMessagingSetting", + ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_PUSH_MESSAGING].get()), + 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); +} + +DefaultProvider::~DefaultProvider() { +} + +bool DefaultProvider::SetWebsiteSetting( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Value* in_value) { + DCHECK(CalledOnValidThread()); + DCHECK(prefs_); + + // Ignore non default settings + if (primary_pattern != ContentSettingsPattern::Wildcard() || + secondary_pattern != ContentSettingsPattern::Wildcard()) { + return false; + } + + // The default settings may not be directly modified for OTR sessions. + // Instead, they are synced to the main profile's setting. + if (is_incognito_) + return false; + + // Put |in_value| in a scoped pointer to ensure that it gets cleaned up + // properly if we don't pass on the ownership. + 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()); + } + } + + NotifyObservers(ContentSettingsPattern(), + ContentSettingsPattern(), + content_type, + std::string()); + + return true; +} + +RuleIterator* DefaultProvider::GetRuleIterator( + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + bool incognito) const { + base::AutoLock lock(lock_); + if (resource_identifier.empty()) { + ValueMap::const_iterator it(default_settings_.find(content_type)); + if (it != default_settings_.end()) { + return new DefaultRuleIterator(it->second.get()); + } + NOTREACHED(); + } + return new EmptyRuleIterator(); +} + +void DefaultProvider::ClearAllContentSettingsRules( + ContentSettingsType content_type) { + // TODO(markusheintz): This method is only called when the + // |DesktopNotificationService| calls |ClearAllSettingsForType| method on the + // |HostContentSettingsMap|. Don't implement this method yet, otherwise the + // default notification settings will be cleared as well. +} + +void DefaultProvider::ShutdownOnUIThread() { + DCHECK(CalledOnValidThread()); + DCHECK(prefs_); + RemoveAllObservers(); + pref_change_registrar_.RemoveAll(); + prefs_ = NULL; +} + +void DefaultProvider::OnPreferenceChanged(const std::string& name) { + DCHECK(CalledOnValidThread()); + if (updating_preferences_) + return; + + if (name == prefs::kDefaultContentSettings) { + ReadDefaultSettings(true); + } else { + NOTREACHED() << "Unexpected preference observed"; + return; + } + + NotifyObservers(ContentSettingsPattern(), + ContentSettingsPattern(), + CONTENT_SETTINGS_TYPE_DEFAULT, + std::string()); +} + +void DefaultProvider::ReadDefaultSettings(bool overwrite) { + base::AutoLock lock(lock_); + 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); + + ForceDefaultsToBeExplicit(); +} + +void DefaultProvider::ForceDefaultsToBeExplicit() { + 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])); + } + } +} + +void DefaultProvider::GetSettingsFromDictionary( + const base::DictionaryValue* dictionary) { + for (base::DictionaryValue::Iterator i(*dictionary); + !i.IsAtEnd(); i.Advance()) { + const std::string& content_type(i.key()); + for (size_t type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) { + if (content_type == GetTypeName(ContentSettingsType(type))) { + int int_value = CONTENT_SETTING_DEFAULT; + bool is_integer = i.value().GetAsInteger(&int_value); + DCHECK(is_integer); + default_settings_[ContentSettingsType(type)].reset( + new base::FundamentalValue(int_value)); + break; + } + } + } + // Migrate obsolete cookie prompt mode. + if (ValueToContentSetting( + default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].get()) == + CONTENT_SETTING_ASK) { + default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].reset( + new base::FundamentalValue(CONTENT_SETTING_BLOCK)); + } +} + +} // 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 new file mode 100644 index 0000000..6679bdc --- /dev/null +++ b/components/content_settings/core/browser/content_settings_default_provider.h @@ -0,0 +1,92 @@ +// Copyright (c) 2011 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. + +#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_DEFAULT_PROVIDER_H_ +#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_DEFAULT_PROVIDER_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/linked_ptr.h" +#include "base/prefs/pref_change_registrar.h" +#include "base/synchronization/lock.h" +#include "components/content_settings/core/browser/content_settings_observable_provider.h" + +class PrefService; + +namespace user_prefs { +class PrefRegistrySyncable; +} + +namespace content_settings { + +// Provider that provides default content settings based on +// user prefs. If no default values are set by the user we use the hard coded +// default values. +class DefaultProvider : public ObservableProvider { + public: + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + + DefaultProvider(PrefService* prefs, + bool incognito); + ~DefaultProvider() override; + + // ProviderInterface implementations. + RuleIterator* GetRuleIterator(ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + bool incognito) const override; + + bool SetWebsiteSetting(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Value* value) override; + + void ClearAllContentSettingsRules(ContentSettingsType content_type) override; + + void ShutdownOnUIThread() override; + + private: + // Sets the fields of |settings| based on the values in |dictionary|. + void GetSettingsFromDictionary(const base::DictionaryValue* dictionary); + + // Forces the default settings to be explicitly set instead of themselves + // being CONTENT_SETTING_DEFAULT. + void ForceDefaultsToBeExplicit(); + + // 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); + + // Called on prefs change. + void OnPreferenceChanged(const std::string& pref_name); + + typedef linked_ptr<base::Value> ValuePtr; + typedef std::map<ContentSettingsType, ValuePtr> ValueMap; + // Copies of the pref data, so that we can read it on the IO thread. + ValueMap default_settings_; + + PrefService* prefs_; + + // Whether this settings map is for an Incognito session. + bool is_incognito_; + + // Used around accesses to the |default_content_settings_| object to guarantee + // thread safety. + mutable base::Lock lock_; + + PrefChangeRegistrar pref_change_registrar_; + + // Whether we are currently updating preferences, this is used to ignore + // notifications from the preferences service that we triggered ourself. + bool updating_preferences_; + + DISALLOW_COPY_AND_ASSIGN(DefaultProvider); +}; + +} // namespace content_settings + +#endif // COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_DEFAULT_PROVIDER_H_ diff --git a/components/content_settings/core/browser/content_settings_mock_provider.cc b/components/content_settings/core/browser/content_settings_mock_provider.cc new file mode 100644 index 0000000..fb79057 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_mock_provider.cc @@ -0,0 +1,46 @@ +// Copyright (c) 2011 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 "components/content_settings/core/browser/content_settings_mock_provider.h" + +namespace content_settings { + +MockProvider::MockProvider() + : read_only_(false) {} + +MockProvider::MockProvider(bool read_only) + : read_only_(read_only) { +} + +MockProvider::~MockProvider() {} + +RuleIterator* MockProvider::GetRuleIterator( + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + bool incognito) const { + return value_map_.GetRuleIterator(content_type, resource_identifier, NULL); +} + +bool MockProvider::SetWebsiteSetting( + const ContentSettingsPattern& requesting_url_pattern, + const ContentSettingsPattern& embedding_url_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Value* value) { + if (read_only_) + return false; + value_map_.clear(); + value_map_.SetValue(requesting_url_pattern, + embedding_url_pattern, + content_type, + resource_identifier, + value); + return true; +} + +void MockProvider::ShutdownOnUIThread() { + RemoveAllObservers(); +} + +} // namespace content_settings diff --git a/components/content_settings/core/browser/content_settings_mock_provider.h b/components/content_settings/core/browser/content_settings_mock_provider.h new file mode 100644 index 0000000..7d16b9b0 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_mock_provider.h @@ -0,0 +1,59 @@ +// Copyright (c) 2011 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. + +#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_MOCK_PROVIDER_H_ +#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_MOCK_PROVIDER_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "components/content_settings/core/browser/content_settings_observable_provider.h" +#include "components/content_settings/core/browser/content_settings_origin_identifier_value_map.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/content_settings/core/common/content_settings_types.h" + +namespace content_settings { + +// The class MockProvider is a mock for a non default content settings provider. +class MockProvider : public ObservableProvider { + public: + MockProvider(); + explicit MockProvider(bool read_only); + ~MockProvider() override; + + RuleIterator* GetRuleIterator(ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + bool incognito) const override; + + // The MockProvider is only able to store one content setting. So every time + // this method is called the previously set content settings is overwritten. + bool SetWebsiteSetting(const ContentSettingsPattern& requesting_url_pattern, + const ContentSettingsPattern& embedding_url_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Value* value) override; + + void ClearAllContentSettingsRules(ContentSettingsType content_type) override { + } + + void ShutdownOnUIThread() override; + + void set_read_only(bool read_only) { + read_only_ = read_only; + } + + bool read_only() const { + return read_only_; + } + + private: + OriginIdentifierValueMap value_map_; + bool read_only_; + + DISALLOW_COPY_AND_ASSIGN(MockProvider); +}; + +} // namespace content_settings + +#endif // COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_MOCK_PROVIDER_H_ diff --git a/components/content_settings/core/browser/content_settings_override_provider.cc b/components/content_settings/core/browser/content_settings_override_provider.cc new file mode 100644 index 0000000..edb36a5 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_override_provider.cc @@ -0,0 +1,130 @@ +// 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 "components/content_settings/core/browser/content_settings_override_provider.h" + +#include <string> + +#include "base/auto_reset.h" +#include "base/prefs/pref_service.h" +#include "base/prefs/scoped_user_pref_update.h" +#include "base/values.h" +#include "components/content_settings/core/browser/content_settings_rule.h" +#include "components/content_settings/core/browser/content_settings_utils.h" +#include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/content_settings/core/common/pref_names.h" +#include "components/pref_registry/pref_registry_syncable.h" + +namespace content_settings { + +namespace { + +class OverrideRuleIterator : public RuleIterator { + public: + explicit OverrideRuleIterator(bool is_allowed) : is_done_(is_allowed) {} + + bool HasNext() const override { return !is_done_; } + + Rule Next() override { + DCHECK(!is_done_); + is_done_ = true; + return Rule(ContentSettingsPattern::Wildcard(), + ContentSettingsPattern::Wildcard(), + new base::FundamentalValue(CONTENT_SETTING_BLOCK)); + } + + private: + bool is_done_; +}; + +} // namespace + +// static +void OverrideProvider::RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterDictionaryPref( + prefs::kOverrideContentSettings, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); +} + +OverrideProvider::OverrideProvider(PrefService* prefs, bool incognito) + : prefs_(prefs), is_incognito_(incognito) { + DCHECK(prefs_); + + // Read global overrides. + ReadOverrideSettings(); +} + +OverrideProvider::~OverrideProvider() { +} + +RuleIterator* OverrideProvider::GetRuleIterator( + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + bool incognito) const { + base::AutoLock lock(lock_); + if (resource_identifier.empty()) { + return new OverrideRuleIterator(allowed_settings_[content_type]); + } + return new EmptyRuleIterator(); +} + +void OverrideProvider::ClearAllContentSettingsRules( + ContentSettingsType content_type) { +} + +bool OverrideProvider::SetWebsiteSetting( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Value* in_value) { + return false; +} + +void OverrideProvider::ShutdownOnUIThread() { + DCHECK(prefs_); + prefs_ = NULL; +} + +void OverrideProvider::SetOverrideSetting(ContentSettingsType content_type, + bool enabled) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(prefs_); + + // Disallow incognito to change the state. + DCHECK(!is_incognito_); + + base::AutoLock lock(lock_); + DictionaryPrefUpdate update(prefs_, prefs::kOverrideContentSettings); + base::DictionaryValue* default_settings_dictionary = update.Get(); + if (enabled) { + allowed_settings_[content_type] = true; + default_settings_dictionary->RemoveWithoutPathExpansion( + GetTypeName(content_type), NULL); + } else { + allowed_settings_[content_type] = false; + default_settings_dictionary->SetWithoutPathExpansion( + GetTypeName(content_type), new base::FundamentalValue(true)); + } +} + +bool OverrideProvider::IsEnabled(ContentSettingsType content_type) const { + base::AutoLock lock(lock_); + return allowed_settings_[content_type]; +} + +void OverrideProvider::ReadOverrideSettings() { + const base::DictionaryValue* blocked_settings_dictionary = + prefs_->GetDictionary(prefs::kOverrideContentSettings); + + for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) { + ContentSettingsType content_setting = ContentSettingsType(type); + allowed_settings_[content_setting] = + !blocked_settings_dictionary->HasKey(GetTypeName(content_setting)); + } +} + +} // namespace content_settings diff --git a/components/content_settings/core/browser/content_settings_override_provider.h b/components/content_settings/core/browser/content_settings_override_provider.h new file mode 100644 index 0000000..08f3052 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_override_provider.h @@ -0,0 +1,79 @@ +// 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. + +#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_OVERRIDE_PROVIDER_H_ +#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_OVERRIDE_PROVIDER_H_ + +#include "base/macros.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" +#include "components/content_settings/core/browser/content_settings_provider.h" +#include "components/content_settings/core/common/content_settings_types.h" + +class ContentSettingsPattern; +class PrefService; + +namespace user_prefs { +class PrefRegistrySyncable; +} + +namespace content_settings { + +// OverrideProvider contains if certain content settings are enabled or +// globally disabled. It may only be written to using the UI thread, but may be +// read on any thread. +class OverrideProvider : public ProviderInterface { + public: + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + + OverrideProvider(PrefService* prefs, bool incognito); + ~OverrideProvider() override; + + // ProviderInterface implementations. + RuleIterator* GetRuleIterator(ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + bool incognito) const override; + + void ClearAllContentSettingsRules(ContentSettingsType content_type) override; + + bool SetWebsiteSetting(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Value* value) override; + + void ShutdownOnUIThread() override; + + // Sets if a given |content_type| is |enabled|. + void SetOverrideSetting(ContentSettingsType content_type, bool enabled); + + // Returns if |content_type| is enabled. If it is not enabled, the content + // setting type is considered globally disabled and acts as though it is + // blocked. If it is enabled, the content setting type's permission is granted + // by the other providers. + bool IsEnabled(ContentSettingsType content_type) const; + + private: + // Reads the override settings from the preferences service. + void ReadOverrideSettings(); + + // Copies of the pref data, so that we can read it on the IO thread. + bool allowed_settings_[CONTENT_SETTINGS_NUM_TYPES]; + + PrefService* prefs_; + + bool is_incognito_; + + // Used around accesses to the |override_content_settings_| object to + // guarantee thread safety. + mutable base::Lock lock_; + + base::ThreadChecker thread_checker_; + + DISALLOW_COPY_AND_ASSIGN(OverrideProvider); +}; + +} // namespace content_settings + +#endif // COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_OVERRIDE_PROVIDER_H_ diff --git a/components/content_settings/core/browser/content_settings_policy_provider.cc b/components/content_settings/core/browser/content_settings_policy_provider.cc new file mode 100644 index 0000000..e2976070 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_policy_provider.cc @@ -0,0 +1,495 @@ +// Copyright (c) 2012 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 "components/content_settings/core/browser/content_settings_policy_provider.h" + +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/json/json_reader.h" +#include "base/prefs/pref_service.h" +#include "base/values.h" +#include "components/content_settings/core/browser/content_settings_rule.h" +#include "components/content_settings/core/browser/content_settings_utils.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/content_settings/core/common/pref_names.h" +#include "components/pref_registry/pref_registry_syncable.h" + +namespace { + +// The preferences used to manage ContentSettingsTypes. +const char* kPrefToManageType[] = { + prefs::kManagedDefaultCookiesSetting, + prefs::kManagedDefaultImagesSetting, + prefs::kManagedDefaultJavaScriptSetting, + prefs::kManagedDefaultPluginsSetting, + prefs::kManagedDefaultPopupsSetting, + prefs::kManagedDefaultGeolocationSetting, + prefs::kManagedDefaultNotificationsSetting, + NULL, // No policy for default value of content type auto-select-certificate + NULL, // No policy for default value of fullscreen requests + NULL, // No policy for default value of mouse lock requests + NULL, // No policy for default value of mixed script blocking + prefs::kManagedDefaultMediaStreamSetting, + NULL, // No policy for default value of media stream mic + NULL, // No policy for default value of media stream camera + NULL, // No policy for default value of protocol handlers + NULL, // No policy for default value of PPAPI broker + NULL, // No policy for default value of multiple automatic downloads + NULL, // No policy for default value of MIDI system exclusive requests + NULL, // No policy for default value of push messaging requests + NULL, // No policy for default value of SSL certificate decisions +#if defined(OS_WIN) + NULL, // No policy for default value of "switch to desktop" +#elif defined(OS_ANDROID) || defined(OS_CHROMEOS) + NULL, // No policy for default value of protected media identifier +#endif +#if defined(OS_ANDROID) + NULL, // No policy for default value of app banners +#endif +}; +COMPILE_ASSERT(arraysize(kPrefToManageType) == CONTENT_SETTINGS_NUM_TYPES, + managed_content_settings_pref_names_array_size_incorrect); + +struct PrefsForManagedContentSettingsMapEntry { + const char* pref_name; + ContentSettingsType content_type; + ContentSetting setting; +}; + +const PrefsForManagedContentSettingsMapEntry + kPrefsForManagedContentSettingsMap[] = { + { + prefs::kManagedCookiesAllowedForUrls, + CONTENT_SETTINGS_TYPE_COOKIES, + CONTENT_SETTING_ALLOW + }, { + prefs::kManagedCookiesSessionOnlyForUrls, + CONTENT_SETTINGS_TYPE_COOKIES, + CONTENT_SETTING_SESSION_ONLY + }, { + prefs::kManagedCookiesBlockedForUrls, + CONTENT_SETTINGS_TYPE_COOKIES, + CONTENT_SETTING_BLOCK + }, { + prefs::kManagedImagesAllowedForUrls, + CONTENT_SETTINGS_TYPE_IMAGES, + CONTENT_SETTING_ALLOW + }, { + prefs::kManagedImagesBlockedForUrls, + CONTENT_SETTINGS_TYPE_IMAGES, + CONTENT_SETTING_BLOCK + }, { + prefs::kManagedJavaScriptAllowedForUrls, + CONTENT_SETTINGS_TYPE_JAVASCRIPT, + CONTENT_SETTING_ALLOW + }, { + prefs::kManagedJavaScriptBlockedForUrls, + CONTENT_SETTINGS_TYPE_JAVASCRIPT, + CONTENT_SETTING_BLOCK + }, { + prefs::kManagedPluginsAllowedForUrls, + CONTENT_SETTINGS_TYPE_PLUGINS, + CONTENT_SETTING_ALLOW + }, { + prefs::kManagedPluginsBlockedForUrls, + CONTENT_SETTINGS_TYPE_PLUGINS, + CONTENT_SETTING_BLOCK + }, { + prefs::kManagedPopupsAllowedForUrls, + CONTENT_SETTINGS_TYPE_POPUPS, + CONTENT_SETTING_ALLOW + }, { + prefs::kManagedPopupsBlockedForUrls, + CONTENT_SETTINGS_TYPE_POPUPS, + CONTENT_SETTING_BLOCK + }, { + prefs::kManagedNotificationsAllowedForUrls, + CONTENT_SETTINGS_TYPE_NOTIFICATIONS, + CONTENT_SETTING_ALLOW + }, { + prefs::kManagedNotificationsBlockedForUrls, + CONTENT_SETTINGS_TYPE_NOTIFICATIONS, + CONTENT_SETTING_BLOCK + } +}; + +} // namespace + +namespace content_settings { + +// static +void PolicyProvider::RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterListPref(prefs::kManagedAutoSelectCertificateForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedCookiesAllowedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedCookiesBlockedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedCookiesSessionOnlyForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedImagesAllowedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedImagesBlockedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedJavaScriptAllowedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedJavaScriptBlockedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedPluginsAllowedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedPluginsBlockedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedPopupsAllowedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedPopupsBlockedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedNotificationsAllowedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedNotificationsBlockedForUrls, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + // Preferences for default content setting policies. If a policy is not set of + // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT. + registry->RegisterIntegerPref( + prefs::kManagedDefaultCookiesSetting, + CONTENT_SETTING_DEFAULT, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref( + prefs::kManagedDefaultImagesSetting, + CONTENT_SETTING_DEFAULT, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref( + prefs::kManagedDefaultJavaScriptSetting, + CONTENT_SETTING_DEFAULT, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref( + prefs::kManagedDefaultPluginsSetting, + CONTENT_SETTING_DEFAULT, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref( + prefs::kManagedDefaultPopupsSetting, + CONTENT_SETTING_DEFAULT, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref( + prefs::kManagedDefaultGeolocationSetting, + CONTENT_SETTING_DEFAULT, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref( + prefs::kManagedDefaultNotificationsSetting, + CONTENT_SETTING_DEFAULT, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref( + prefs::kManagedDefaultMediaStreamSetting, + CONTENT_SETTING_DEFAULT, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); +} + +PolicyProvider::PolicyProvider(PrefService* prefs) : prefs_(prefs) { + ReadManagedDefaultSettings(); + ReadManagedContentSettings(false); + + pref_change_registrar_.Init(prefs_); + PrefChangeRegistrar::NamedChangeCallback callback = + base::Bind(&PolicyProvider::OnPreferenceChanged, base::Unretained(this)); + pref_change_registrar_.Add( + prefs::kManagedAutoSelectCertificateForUrls, callback); + pref_change_registrar_.Add(prefs::kManagedCookiesBlockedForUrls, callback); + pref_change_registrar_.Add(prefs::kManagedCookiesAllowedForUrls, callback); + pref_change_registrar_.Add( + prefs::kManagedCookiesSessionOnlyForUrls, callback); + pref_change_registrar_.Add(prefs::kManagedImagesBlockedForUrls, callback); + pref_change_registrar_.Add(prefs::kManagedImagesAllowedForUrls, callback); + pref_change_registrar_.Add(prefs::kManagedJavaScriptBlockedForUrls, callback); + pref_change_registrar_.Add(prefs::kManagedJavaScriptAllowedForUrls, callback); + pref_change_registrar_.Add(prefs::kManagedPluginsBlockedForUrls, callback); + pref_change_registrar_.Add(prefs::kManagedPluginsAllowedForUrls, callback); + pref_change_registrar_.Add(prefs::kManagedPopupsBlockedForUrls, callback); + pref_change_registrar_.Add(prefs::kManagedPopupsAllowedForUrls, callback); + pref_change_registrar_.Add( + prefs::kManagedNotificationsAllowedForUrls, callback); + pref_change_registrar_.Add( + prefs::kManagedNotificationsBlockedForUrls, callback); + // The following preferences are only used to indicate if a default content + // setting is managed and to hold the managed default setting value. If the + // value for any of the following preferences is set then the corresponding + // default content setting is managed. These preferences exist in parallel to + // the preference default content settings. If a default content settings type + // is managed any user defined exceptions (patterns) for this type are + // ignored. + pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, callback); + pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, callback); + pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, callback); + pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, callback); + pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, callback); + pref_change_registrar_.Add( + prefs::kManagedDefaultGeolocationSetting, callback); + pref_change_registrar_.Add( + prefs::kManagedDefaultNotificationsSetting, callback); + pref_change_registrar_.Add( + prefs::kManagedDefaultMediaStreamSetting, callback); +} + +PolicyProvider::~PolicyProvider() { + DCHECK(!prefs_); +} + +RuleIterator* PolicyProvider::GetRuleIterator( + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + bool incognito) const { + return value_map_.GetRuleIterator(content_type, resource_identifier, &lock_); +} + +void PolicyProvider::GetContentSettingsFromPreferences( + OriginIdentifierValueMap* value_map) { + for (size_t i = 0; i < arraysize(kPrefsForManagedContentSettingsMap); ++i) { + const char* pref_name = kPrefsForManagedContentSettingsMap[i].pref_name; + // Skip unset policies. + if (!prefs_->HasPrefPath(pref_name)) { + VLOG(2) << "Skipping unset preference: " << pref_name; + continue; + } + + const PrefService::Preference* pref = prefs_->FindPreference(pref_name); + DCHECK(pref); + DCHECK(pref->IsManaged()); + + const base::ListValue* pattern_str_list = NULL; + if (!pref->GetValue()->GetAsList(&pattern_str_list)) { + NOTREACHED(); + return; + } + + for (size_t j = 0; j < pattern_str_list->GetSize(); ++j) { + std::string original_pattern_str; + if (!pattern_str_list->GetString(j, &original_pattern_str)) { + NOTREACHED(); + continue; + } + + PatternPair pattern_pair = ParsePatternString(original_pattern_str); + // Ignore invalid patterns. + if (!pattern_pair.first.IsValid()) { + VLOG(1) << "Ignoring invalid content settings pattern: " << + original_pattern_str; + continue; + } + + ContentSettingsType content_type = + kPrefsForManagedContentSettingsMap[i].content_type; + DCHECK_NE(content_type, CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE); + // If only one pattern was defined auto expand it to a pattern pair. + ContentSettingsPattern secondary_pattern = + !pattern_pair.second.IsValid() ? ContentSettingsPattern::Wildcard() + : pattern_pair.second; + value_map->SetValue(pattern_pair.first, + secondary_pattern, + content_type, + NO_RESOURCE_IDENTIFIER, + new base::FundamentalValue( + kPrefsForManagedContentSettingsMap[i].setting)); + } + } +} + +void PolicyProvider::GetAutoSelectCertificateSettingsFromPreferences( + OriginIdentifierValueMap* value_map) { + const char* pref_name = prefs::kManagedAutoSelectCertificateForUrls; + + if (!prefs_->HasPrefPath(pref_name)) { + VLOG(2) << "Skipping unset preference: " << pref_name; + return; + } + + const PrefService::Preference* pref = prefs_->FindPreference(pref_name); + DCHECK(pref); + DCHECK(pref->IsManaged()); + + const base::ListValue* pattern_filter_str_list = NULL; + if (!pref->GetValue()->GetAsList(&pattern_filter_str_list)) { + NOTREACHED(); + return; + } + + // Parse the list of pattern filter strings. A pattern filter string has + // the following JSON format: + // + // { + // "pattern": <content settings pattern string>, + // "filter" : <certificate filter in JSON format> + // } + // + // e.g. + // { + // "pattern": "[*.]example.com", + // "filter": { + // "ISSUER": { + // "CN": "some name" + // } + // } + // } + for (size_t j = 0; j < pattern_filter_str_list->GetSize(); ++j) { + std::string pattern_filter_json; + if (!pattern_filter_str_list->GetString(j, &pattern_filter_json)) { + NOTREACHED(); + continue; + } + + scoped_ptr<base::Value> value(base::JSONReader::Read(pattern_filter_json, + base::JSON_ALLOW_TRAILING_COMMAS)); + if (!value || !value->IsType(base::Value::TYPE_DICTIONARY)) { + VLOG(1) << "Ignoring invalid certificate auto select setting. Reason:" + " Invalid JSON object: " << pattern_filter_json; + continue; + } + + scoped_ptr<base::DictionaryValue> pattern_filter_pair( + static_cast<base::DictionaryValue*>(value.release())); + std::string pattern_str; + bool pattern_read = pattern_filter_pair->GetStringWithoutPathExpansion( + "pattern", &pattern_str); + base::DictionaryValue* cert_filter = NULL; + pattern_filter_pair->GetDictionaryWithoutPathExpansion("filter", + &cert_filter); + if (!pattern_read || !cert_filter) { + VLOG(1) << "Ignoring invalid certificate auto select setting. Reason:" + " Missing pattern or filter."; + continue; + } + + ContentSettingsPattern pattern = + ContentSettingsPattern::FromString(pattern_str); + // Ignore invalid patterns. + if (!pattern.IsValid()) { + VLOG(1) << "Ignoring invalid certificate auto select setting:" + " Invalid content settings pattern: " << pattern.ToString(); + continue; + } + + // Don't pass removed values from |value|, because base::Values read with + // JSONReader use a shared string buffer. Instead, DeepCopy here. + value_map->SetValue(pattern, + ContentSettingsPattern::Wildcard(), + CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, + std::string(), + cert_filter->DeepCopy()); + } +} + +void PolicyProvider::ReadManagedDefaultSettings() { + for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) { + if (kPrefToManageType[type] == NULL) { + continue; + } + UpdateManagedDefaultSetting(ContentSettingsType(type)); + } +} + +void PolicyProvider::UpdateManagedDefaultSetting( + ContentSettingsType content_type) { + // If a pref to manage a default-content-setting was not set (NOTICE: + // "HasPrefPath" returns false if no value was set for a registered pref) then + // the default value of the preference is used. The default value of a + // preference to manage a default-content-settings is CONTENT_SETTING_DEFAULT. + // This indicates that no managed value is set. If a pref was set, than it + // MUST be managed. + DCHECK(!prefs_->HasPrefPath(kPrefToManageType[content_type]) || + prefs_->IsManagedPreference(kPrefToManageType[content_type])); + base::AutoLock auto_lock(lock_); + + int setting = prefs_->GetInteger(kPrefToManageType[content_type]); + if (setting == CONTENT_SETTING_DEFAULT) { + value_map_.DeleteValue( + ContentSettingsPattern::Wildcard(), + ContentSettingsPattern::Wildcard(), + content_type, + std::string()); + } else { + value_map_.SetValue(ContentSettingsPattern::Wildcard(), + ContentSettingsPattern::Wildcard(), + content_type, + std::string(), + new base::FundamentalValue(setting)); + } +} + + +void PolicyProvider::ReadManagedContentSettings(bool overwrite) { + base::AutoLock auto_lock(lock_); + if (overwrite) + value_map_.clear(); + GetContentSettingsFromPreferences(&value_map_); + GetAutoSelectCertificateSettingsFromPreferences(&value_map_); +} + +// Since the PolicyProvider is a read only content settings provider, all +// methodes of the ProviderInterface that set or delete any settings do nothing. +bool PolicyProvider::SetWebsiteSetting( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Value* value) { + return false; +} + +void PolicyProvider::ClearAllContentSettingsRules( + ContentSettingsType content_type) { +} + +void PolicyProvider::ShutdownOnUIThread() { + DCHECK(CalledOnValidThread()); + RemoveAllObservers(); + if (!prefs_) + return; + pref_change_registrar_.RemoveAll(); + prefs_ = NULL; +} + +void PolicyProvider::OnPreferenceChanged(const std::string& name) { + DCHECK(CalledOnValidThread()); + + if (name == prefs::kManagedDefaultCookiesSetting) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES); + } else if (name == prefs::kManagedDefaultImagesSetting) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_IMAGES); + } else if (name == prefs::kManagedDefaultJavaScriptSetting) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT); + } else if (name == prefs::kManagedDefaultPluginsSetting) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_PLUGINS); + } else if (name == prefs::kManagedDefaultPopupsSetting) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_POPUPS); + } else if (name == prefs::kManagedDefaultGeolocationSetting) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_GEOLOCATION); + } else if (name == prefs::kManagedDefaultNotificationsSetting) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS); + } else if (name == prefs::kManagedDefaultMediaStreamSetting) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM); + } else if (name == prefs::kManagedAutoSelectCertificateForUrls || + name == prefs::kManagedCookiesAllowedForUrls || + name == prefs::kManagedCookiesBlockedForUrls || + name == prefs::kManagedCookiesSessionOnlyForUrls || + name == prefs::kManagedImagesAllowedForUrls || + name == prefs::kManagedImagesBlockedForUrls || + name == prefs::kManagedJavaScriptAllowedForUrls || + name == prefs::kManagedJavaScriptBlockedForUrls || + name == prefs::kManagedPluginsAllowedForUrls || + name == prefs::kManagedPluginsBlockedForUrls || + name == prefs::kManagedPopupsAllowedForUrls || + name == prefs::kManagedPopupsBlockedForUrls || + name == prefs::kManagedNotificationsAllowedForUrls || + name == prefs::kManagedNotificationsBlockedForUrls) { + ReadManagedContentSettings(true); + ReadManagedDefaultSettings(); + } + + NotifyObservers(ContentSettingsPattern(), + ContentSettingsPattern(), + CONTENT_SETTINGS_TYPE_DEFAULT, + std::string()); +} + +} // namespace content_settings diff --git a/components/content_settings/core/browser/content_settings_policy_provider.h b/components/content_settings/core/browser/content_settings_policy_provider.h new file mode 100644 index 0000000..b0a80a1 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_policy_provider.h @@ -0,0 +1,82 @@ +// Copyright (c) 2011 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. + +#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_POLICY_PROVIDER_H_ +#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_POLICY_PROVIDER_H_ + +// A content settings provider that takes its settings out of policies. + +#include <vector> + +#include "base/basictypes.h" +#include "base/prefs/pref_change_registrar.h" +#include "base/synchronization/lock.h" +#include "components/content_settings/core/browser/content_settings_observable_provider.h" +#include "components/content_settings/core/browser/content_settings_origin_identifier_value_map.h" + +class PrefService; + +namespace user_prefs { +class PrefRegistrySyncable; +} + +namespace content_settings { + +// PolicyProvider that provides managed content-settings. +class PolicyProvider : public ObservableProvider { + public: + explicit PolicyProvider(PrefService* prefs); + ~PolicyProvider() override; + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + + // ProviderInterface implementations. + RuleIterator* GetRuleIterator(ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + bool incognito) const override; + + bool SetWebsiteSetting(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Value* value) override; + + void ClearAllContentSettingsRules(ContentSettingsType content_type) override; + + void ShutdownOnUIThread() override; + + private: + // Reads the policy managed default settings. + void ReadManagedDefaultSettings(); + + // Callback for preference changes. + void OnPreferenceChanged(const std::string& pref_name); + + // Reads the policy controlled default settings for a specific content type. + void UpdateManagedDefaultSetting(ContentSettingsType content_type); + + void ReadManagedContentSettings(bool overwrite); + + void GetContentSettingsFromPreferences(OriginIdentifierValueMap* rules); + + void GetAutoSelectCertificateSettingsFromPreferences( + OriginIdentifierValueMap* value_map); + + void ReadManagedContentSettingsTypes(ContentSettingsType content_type); + + OriginIdentifierValueMap value_map_; + + PrefService* prefs_; + + PrefChangeRegistrar pref_change_registrar_; + + // Used around accesses to the |value_map_| object to guarantee + // thread safety. + mutable base::Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(PolicyProvider); +}; + +} // namespace content_settings + +#endif // COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_POLICY_PROVIDER_H_ diff --git a/components/content_settings/core/browser/content_settings_pref_provider.cc b/components/content_settings/core/browser/content_settings_pref_provider.cc new file mode 100644 index 0000000..1c0dcc3 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_pref_provider.cc @@ -0,0 +1,657 @@ +// Copyright (c) 2012 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 "components/content_settings/core/browser/content_settings_pref_provider.h" + +#include <map> +#include <string> +#include <utility> + +#include "base/auto_reset.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/memory/scoped_ptr.h" +#include "base/metrics/histogram.h" +#include "base/prefs/pref_service.h" +#include "base/prefs/scoped_user_pref_update.h" +#include "base/strings/string_split.h" +#include "base/time/clock.h" +#include "base/time/default_clock.h" +#include "components/content_settings/core/browser/content_settings_rule.h" +#include "components/content_settings/core/browser/content_settings_utils.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/content_settings/core/common/pref_names.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "url/gurl.h" + +namespace { + +typedef std::pair<std::string, std::string> StringPair; +typedef std::map<std::string, std::string> StringMap; + +const char kPerPluginPrefName[] = "per_plugin"; +const char kAudioKey[] = "audio"; +const char kVideoKey[] = "video"; +const char kLastUsed[] = "last_used"; + +ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type, + ContentSetting setting) { + if (content_type == CONTENT_SETTINGS_TYPE_COOKIES && + setting == CONTENT_SETTING_ASK) { + return CONTENT_SETTING_BLOCK; + } + return setting; +} + +// If the given content type supports resource identifiers in user preferences, +// returns true and sets |pref_key| to the key in the content settings +// dictionary under which per-resource content settings are stored. +// Otherwise, returns false. +bool GetResourceTypeName(ContentSettingsType content_type, + std::string* pref_key) { + if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) { + *pref_key = kPerPluginPrefName; + return true; + } + return false; +} + +} // namespace + +namespace content_settings { + +// //////////////////////////////////////////////////////////////////////////// +// PrefProvider: +// + +// static +void PrefProvider::RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterIntegerPref( + prefs::kContentSettingsVersion, + ContentSettingsPattern::kContentSettingsPatternVersion, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref( + prefs::kContentSettingsPatternPairs, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); +} + +PrefProvider::PrefProvider(PrefService* prefs, bool incognito) + : prefs_(prefs), + clock_(new base::DefaultClock()), + is_incognito_(incognito), + updating_preferences_(false) { + DCHECK(prefs_); + // Verify preferences version. + if (!prefs_->HasPrefPath(prefs::kContentSettingsVersion)) { + prefs_->SetInteger(prefs::kContentSettingsVersion, + ContentSettingsPattern::kContentSettingsPatternVersion); + } + if (prefs_->GetInteger(prefs::kContentSettingsVersion) > + ContentSettingsPattern::kContentSettingsPatternVersion) { + return; + } + + // Read content settings exceptions. + ReadContentSettingsFromPref(false); + + if (!is_incognito_) { + UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfExceptions", + value_map_.size()); + } + + // Migrate the obsolete media content setting exceptions to the new settings. + // This needs to be done after ReadContentSettingsFromPref(). + if (!is_incognito_) + MigrateObsoleteMediaContentSetting(); + + pref_change_registrar_.Init(prefs_); + pref_change_registrar_.Add( + prefs::kContentSettingsPatternPairs, + base::Bind(&PrefProvider::OnContentSettingsPatternPairsChanged, + base::Unretained(this))); +} + +bool PrefProvider::SetWebsiteSetting( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Value* in_value) { + DCHECK(CalledOnValidThread()); + DCHECK(prefs_); + // Default settings are set using a wildcard pattern for both + // |primary_pattern| and |secondary_pattern|. Don't store default settings in + // the |PrefProvider|. The |PrefProvider| handles settings for specific + // sites/origins defined by the |primary_pattern| and the |secondary_pattern|. + // Default settings are handled by the |DefaultProvider|. + if (primary_pattern == ContentSettingsPattern::Wildcard() && + secondary_pattern == ContentSettingsPattern::Wildcard() && + resource_identifier.empty()) { + return false; + } + + // At this point take the ownership of the |in_value|. + scoped_ptr<base::Value> value(in_value); + // Update in memory value map. + OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; + if (!is_incognito_) + map_to_modify = &value_map_; + + { + base::AutoLock auto_lock(lock_); + if (value.get()) { + map_to_modify->SetValue( + primary_pattern, + secondary_pattern, + content_type, + resource_identifier, + value->DeepCopy()); + } else { + map_to_modify->DeleteValue( + primary_pattern, + secondary_pattern, + content_type, + resource_identifier); + } + } + // Update the content settings preference. + if (!is_incognito_) { + UpdatePref(primary_pattern, + secondary_pattern, + content_type, + resource_identifier, + value.get()); + } + + NotifyObservers( + primary_pattern, secondary_pattern, content_type, resource_identifier); + + return true; +} + +void PrefProvider::ClearAllContentSettingsRules( + ContentSettingsType content_type) { + DCHECK(CalledOnValidThread()); + DCHECK(prefs_); + + OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; + if (!is_incognito_) + map_to_modify = &value_map_; + + std::vector<Rule> rules_to_delete; + { + base::AutoLock auto_lock(lock_); + scoped_ptr<RuleIterator> rule_iterator( + map_to_modify->GetRuleIterator(content_type, std::string(), NULL)); + // Copy the rules; we cannot call |UpdatePref| while holding |lock_|. + while (rule_iterator->HasNext()) + rules_to_delete.push_back(rule_iterator->Next()); + + map_to_modify->DeleteValues(content_type, std::string()); + } + + for (std::vector<Rule>::const_iterator it = rules_to_delete.begin(); + it != rules_to_delete.end(); ++it) { + UpdatePref(it->primary_pattern, + it->secondary_pattern, + content_type, + std::string(), + NULL); + } + NotifyObservers(ContentSettingsPattern(), + ContentSettingsPattern(), + content_type, + std::string()); +} + +PrefProvider::~PrefProvider() { + DCHECK(!prefs_); +} + +RuleIterator* PrefProvider::GetRuleIterator( + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + bool incognito) const { + if (incognito) + return incognito_value_map_.GetRuleIterator(content_type, + resource_identifier, + &lock_); + return value_map_.GetRuleIterator(content_type, resource_identifier, &lock_); +} + +// //////////////////////////////////////////////////////////////////////////// +// Private + +void PrefProvider::UpdatePref( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + const base::Value* value) { + // Ensure that |lock_| is not held by this thread, since this function will + // send out notifications (by |~DictionaryPrefUpdate|). + AssertLockNotHeld(); + + base::AutoReset<bool> auto_reset(&updating_preferences_, true); + { + DictionaryPrefUpdate update(prefs_, + prefs::kContentSettingsPatternPairs); + base::DictionaryValue* pattern_pairs_settings = update.Get(); + + // Get settings dictionary for the given patterns. + std::string pattern_str(CreatePatternString(primary_pattern, + secondary_pattern)); + base::DictionaryValue* settings_dictionary = NULL; + bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( + pattern_str, &settings_dictionary); + + if (!found && value) { + settings_dictionary = new base::DictionaryValue; + pattern_pairs_settings->SetWithoutPathExpansion( + pattern_str, settings_dictionary); + } + + if (settings_dictionary) { + std::string res_dictionary_path; + if (GetResourceTypeName(content_type, &res_dictionary_path) && + !resource_identifier.empty()) { + base::DictionaryValue* resource_dictionary = NULL; + found = settings_dictionary->GetDictionary( + res_dictionary_path, &resource_dictionary); + if (!found) { + if (value == NULL) + return; // Nothing to remove. Exit early. + resource_dictionary = new base::DictionaryValue; + settings_dictionary->Set(res_dictionary_path, resource_dictionary); + } + // Update resource dictionary. + if (value == NULL) { + resource_dictionary->RemoveWithoutPathExpansion(resource_identifier, + NULL); + if (resource_dictionary->empty()) { + settings_dictionary->RemoveWithoutPathExpansion( + res_dictionary_path, NULL); + } + } else { + resource_dictionary->SetWithoutPathExpansion( + resource_identifier, value->DeepCopy()); + } + } else { + // Update settings dictionary. + std::string setting_path = GetTypeName(content_type); + if (value == NULL) { + settings_dictionary->RemoveWithoutPathExpansion(setting_path, + NULL); + settings_dictionary->RemoveWithoutPathExpansion(kLastUsed, NULL); + } else { + settings_dictionary->SetWithoutPathExpansion( + setting_path, value->DeepCopy()); + } + } + // Remove the settings dictionary if it is empty. + if (settings_dictionary->empty()) { + pattern_pairs_settings->RemoveWithoutPathExpansion( + pattern_str, NULL); + } + } + } +} + + +void PrefProvider::MigrateObsoleteMediaContentSetting() { + std::vector<Rule> rules_to_delete; + { + scoped_ptr<RuleIterator> rule_iterator(GetRuleIterator( + CONTENT_SETTINGS_TYPE_MEDIASTREAM, std::string(), false)); + while (rule_iterator->HasNext()) { + // Skip default setting and rules without a value. + const content_settings::Rule& rule = rule_iterator->Next(); + DCHECK(rule.primary_pattern != ContentSettingsPattern::Wildcard()); + if (!rule.value.get()) + continue; + rules_to_delete.push_back(rule); + } + } + + for (std::vector<Rule>::const_iterator it = rules_to_delete.begin(); + it != rules_to_delete.end(); ++it) { + const base::DictionaryValue* value_dict = NULL; + if (!it->value->GetAsDictionary(&value_dict) || value_dict->empty()) + return; + + std::string audio_device, video_device; + value_dict->GetString(kAudioKey, &audio_device); + value_dict->GetString(kVideoKey, &video_device); + // Add the exception to the new microphone content setting. + if (!audio_device.empty()) { + SetWebsiteSetting(it->primary_pattern, + it->secondary_pattern, + CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, + std::string(), + new base::FundamentalValue(CONTENT_SETTING_ALLOW)); + } + // Add the exception to the new camera content setting. + if (!video_device.empty()) { + SetWebsiteSetting(it->primary_pattern, + it->secondary_pattern, + CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, + std::string(), + new base::FundamentalValue(CONTENT_SETTING_ALLOW)); + } + + // Remove the old exception in CONTENT_SETTINGS_TYPE_MEDIASTREAM. + SetWebsiteSetting(it->primary_pattern, + it->secondary_pattern, + CONTENT_SETTINGS_TYPE_MEDIASTREAM, + std::string(), + NULL); + } +} + +void PrefProvider::ReadContentSettingsFromPref(bool overwrite) { + // |DictionaryPrefUpdate| sends out notifications when destructed. This + // construction order ensures |AutoLock| gets destroyed first and |lock_| is + // not held when the notifications are sent. Also, |auto_reset| must be still + // valid when the notifications are sent, so that |Observe| skips the + // notification. + base::AutoReset<bool> auto_reset(&updating_preferences_, true); + DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); + base::AutoLock auto_lock(lock_); + + const base::DictionaryValue* all_settings_dictionary = + prefs_->GetDictionary(prefs::kContentSettingsPatternPairs); + + if (overwrite) + value_map_.clear(); + + // Careful: The returned value could be NULL if the pref has never been set. + if (!all_settings_dictionary) + return; + + base::DictionaryValue* mutable_settings; + scoped_ptr<base::DictionaryValue> mutable_settings_scope; + + if (!is_incognito_) { + mutable_settings = update.Get(); + } else { + // Create copy as we do not want to persist anything in OTR prefs. + mutable_settings = all_settings_dictionary->DeepCopy(); + mutable_settings_scope.reset(mutable_settings); + } + // Convert all Unicode patterns into punycode form, then read. + CanonicalizeContentSettingsExceptions(mutable_settings); + + size_t cookies_block_exception_count = 0; + size_t cookies_allow_exception_count = 0; + size_t cookies_session_only_exception_count = 0; + for (base::DictionaryValue::Iterator i(*mutable_settings); !i.IsAtEnd(); + i.Advance()) { + const std::string& pattern_str(i.key()); + std::pair<ContentSettingsPattern, ContentSettingsPattern> pattern_pair = + ParsePatternString(pattern_str); + if (!pattern_pair.first.IsValid() || + !pattern_pair.second.IsValid()) { + // TODO: Change this to DFATAL when crbug.com/132659 is fixed. + LOG(ERROR) << "Invalid pattern strings: " << pattern_str; + continue; + } + + // Get settings dictionary for the current pattern string, and read + // settings from the dictionary. + const base::DictionaryValue* settings_dictionary = NULL; + bool is_dictionary = i.value().GetAsDictionary(&settings_dictionary); + DCHECK(is_dictionary); + + for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { + ContentSettingsType content_type = static_cast<ContentSettingsType>(i); + + std::string res_dictionary_path; + if (GetResourceTypeName(content_type, &res_dictionary_path)) { + const base::DictionaryValue* resource_dictionary = NULL; + if (settings_dictionary->GetDictionary( + res_dictionary_path, &resource_dictionary)) { + for (base::DictionaryValue::Iterator j(*resource_dictionary); + !j.IsAtEnd(); + j.Advance()) { + const std::string& resource_identifier(j.key()); + int setting = CONTENT_SETTING_DEFAULT; + bool is_integer = j.value().GetAsInteger(&setting); + DCHECK(is_integer); + DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); + value_map_.SetValue(pattern_pair.first, + pattern_pair.second, + content_type, + resource_identifier, + new base::FundamentalValue(setting)); + } + } + } + base::Value* value = NULL; + if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type)) { + const base::DictionaryValue* setting = NULL; + // TODO(xians): Handle the non-dictionary types. + if (settings_dictionary->GetDictionaryWithoutPathExpansion( + GetTypeName(ContentSettingsType(i)), &setting)) { + DCHECK(!setting->empty()); + value = setting->DeepCopy(); + } + } else { + int setting = CONTENT_SETTING_DEFAULT; + if (settings_dictionary->GetIntegerWithoutPathExpansion( + GetTypeName(ContentSettingsType(i)), &setting)) { + DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); + setting = FixObsoleteCookiePromptMode(content_type, + ContentSetting(setting)); + value = new base::FundamentalValue(setting); + } + } + + // |value_map_| will take the ownership of |value|. + if (value != NULL) { + value_map_.SetValue(pattern_pair.first, + pattern_pair.second, + content_type, + ResourceIdentifier(), + value); + if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) { + ContentSetting s = ValueToContentSetting(value); + switch (s) { + case CONTENT_SETTING_ALLOW : + ++cookies_allow_exception_count; + break; + case CONTENT_SETTING_BLOCK : + ++cookies_block_exception_count; + break; + case CONTENT_SETTING_SESSION_ONLY : + ++cookies_session_only_exception_count; + break; + default: + NOTREACHED(); + break; + } + } + } + } + } + UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfBlockCookiesExceptions", + cookies_block_exception_count); + UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfAllowCookiesExceptions", + cookies_allow_exception_count); + UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfSessionOnlyCookiesExceptions", + cookies_session_only_exception_count); +} + +void PrefProvider::OnContentSettingsPatternPairsChanged() { + DCHECK(CalledOnValidThread()); + + if (updating_preferences_) + return; + + ReadContentSettingsFromPref(true); + + NotifyObservers(ContentSettingsPattern(), + ContentSettingsPattern(), + CONTENT_SETTINGS_TYPE_DEFAULT, + std::string()); +} + +// static +void PrefProvider::CanonicalizeContentSettingsExceptions( + base::DictionaryValue* all_settings_dictionary) { + DCHECK(all_settings_dictionary); + + std::vector<std::string> remove_items; + base::StringPairs move_items; + for (base::DictionaryValue::Iterator i(*all_settings_dictionary); + !i.IsAtEnd(); + i.Advance()) { + const std::string& pattern_str(i.key()); + std::pair<ContentSettingsPattern, ContentSettingsPattern> pattern_pair = + ParsePatternString(pattern_str); + if (!pattern_pair.first.IsValid() || + !pattern_pair.second.IsValid()) { + LOG(ERROR) << "Invalid pattern strings: " << pattern_str; + continue; + } + + const std::string canonicalized_pattern_str = CreatePatternString( + pattern_pair.first, pattern_pair.second); + + if (canonicalized_pattern_str.empty() || + canonicalized_pattern_str == pattern_str) { + continue; + } + + // Clear old pattern if prefs already have canonicalized pattern. + const base::DictionaryValue* new_pattern_settings_dictionary = NULL; + if (all_settings_dictionary->GetDictionaryWithoutPathExpansion( + canonicalized_pattern_str, &new_pattern_settings_dictionary)) { + remove_items.push_back(pattern_str); + continue; + } + + // Move old pattern to canonicalized pattern. + const base::DictionaryValue* old_pattern_settings_dictionary = NULL; + if (i.value().GetAsDictionary(&old_pattern_settings_dictionary)) { + move_items.push_back( + std::make_pair(pattern_str, canonicalized_pattern_str)); + } + } + + for (size_t i = 0; i < remove_items.size(); ++i) { + all_settings_dictionary->RemoveWithoutPathExpansion(remove_items[i], NULL); + } + + for (size_t i = 0; i < move_items.size(); ++i) { + scoped_ptr<base::Value> pattern_settings_dictionary; + all_settings_dictionary->RemoveWithoutPathExpansion( + move_items[i].first, &pattern_settings_dictionary); + all_settings_dictionary->SetWithoutPathExpansion( + move_items[i].second, pattern_settings_dictionary.release()); + } +} + +void PrefProvider::ShutdownOnUIThread() { + DCHECK(CalledOnValidThread()); + DCHECK(prefs_); + RemoveAllObservers(); + pref_change_registrar_.RemoveAll(); + prefs_ = NULL; +} + +void PrefProvider::UpdateLastUsage( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type) { + // Don't write if in incognito. + if (is_incognito_) { + return; + } + + // Ensure that |lock_| is not held by this thread, since this function will + // send out notifications (by |~DictionaryPrefUpdate|). + AssertLockNotHeld(); + + base::AutoReset<bool> auto_reset(&updating_preferences_, true); + { + DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); + base::DictionaryValue* pattern_pairs_settings = update.Get(); + + std::string pattern_str( + CreatePatternString(primary_pattern, secondary_pattern)); + base::DictionaryValue* settings_dictionary = NULL; + bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( + pattern_str, &settings_dictionary); + + if (!found) { + settings_dictionary = new base::DictionaryValue; + pattern_pairs_settings->SetWithoutPathExpansion(pattern_str, + settings_dictionary); + } + + base::DictionaryValue* last_used_dictionary = NULL; + found = settings_dictionary->GetDictionaryWithoutPathExpansion( + kLastUsed, &last_used_dictionary); + + if (!found) { + last_used_dictionary = new base::DictionaryValue; + settings_dictionary->SetWithoutPathExpansion(kLastUsed, + last_used_dictionary); + } + + std::string settings_path = GetTypeName(content_type); + last_used_dictionary->Set( + settings_path, new base::FundamentalValue(clock_->Now().ToDoubleT())); + } +} + +base::Time PrefProvider::GetLastUsage( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type) { + const base::DictionaryValue* pattern_pairs_settings = + prefs_->GetDictionary(prefs::kContentSettingsPatternPairs); + std::string pattern_str( + CreatePatternString(primary_pattern, secondary_pattern)); + + const base::DictionaryValue* settings_dictionary = NULL; + bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( + pattern_str, &settings_dictionary); + + if (!found) + return base::Time(); + + const base::DictionaryValue* last_used_dictionary = NULL; + found = settings_dictionary->GetDictionaryWithoutPathExpansion( + kLastUsed, &last_used_dictionary); + + if (!found) + return base::Time(); + + double last_used_time; + found = last_used_dictionary->GetDoubleWithoutPathExpansion( + GetTypeName(content_type), &last_used_time); + + if (!found) + return base::Time(); + + return base::Time::FromDoubleT(last_used_time); +} + +void PrefProvider::AssertLockNotHeld() const { +#if !defined(NDEBUG) + // |Lock::Acquire()| will assert if the lock is held by this thread. + lock_.Acquire(); + lock_.Release(); +#endif +} + +void PrefProvider::SetClockForTesting(scoped_ptr<base::Clock> clock) { + clock_ = clock.Pass(); +} + +} // namespace content_settings diff --git a/components/content_settings/core/browser/content_settings_pref_provider.h b/components/content_settings/core/browser/content_settings_pref_provider.h new file mode 100644 index 0000000..9d71589 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_pref_provider.h @@ -0,0 +1,126 @@ +// Copyright (c) 2012 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. + +#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_PREF_PROVIDER_H_ +#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_PREF_PROVIDER_H_ + +// A content settings provider that takes its settings out of the pref service. + +#include <vector> + +#include "base/basictypes.h" +#include "base/prefs/pref_change_registrar.h" +#include "base/synchronization/lock.h" +#include "components/content_settings/core/browser/content_settings_observable_provider.h" +#include "components/content_settings/core/browser/content_settings_origin_identifier_value_map.h" +#include "components/content_settings/core/browser/content_settings_utils.h" + +class PrefService; + +namespace base { +class Clock; +class DictionaryValue; +} + +namespace user_prefs { +class PrefRegistrySyncable; +} + +namespace content_settings { + +// Content settings provider that provides content settings from the user +// preference. +class PrefProvider : public ObservableProvider { + public: + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + + PrefProvider(PrefService* prefs, bool incognito); + ~PrefProvider() override; + + // ProviderInterface implementations. + RuleIterator* GetRuleIterator(ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + bool incognito) const override; + + bool SetWebsiteSetting(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + base::Value* value) override; + + void ClearAllContentSettingsRules(ContentSettingsType content_type) override; + + void ShutdownOnUIThread() override; + + // Records the last time the given pattern has used a certain content setting. + void UpdateLastUsage(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type); + + base::Time GetLastUsage(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type); + + // Gains ownership of |clock|. + void SetClockForTesting(scoped_ptr<base::Clock> clock); + + private: + friend class DeadlockCheckerThread; // For testing. + // Reads all content settings exceptions from the preference and load them + // into the |value_map_|. The |value_map_| is cleared first if |overwrite| is + // true. + void ReadContentSettingsFromPref(bool overwrite); + + // Callback for changes in the pref with the same name. + void OnContentSettingsPatternPairsChanged(); + + // Update the preference that stores content settings exceptions and syncs the + // value to the obsolete preference. When calling this function, |lock_| + // should not be held, since this function will send out notifications of + // preference changes. + void UpdatePref( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + const base::Value* value); + + // Migrate the old media setting into new mic/camera content settings. + void MigrateObsoleteMediaContentSetting(); + + static void CanonicalizeContentSettingsExceptions( + base::DictionaryValue* all_settings_dictionary); + + // In the debug mode, asserts that |lock_| is not held by this thread. It's + // ok if some other thread holds |lock_|, as long as it will eventually + // release it. + void AssertLockNotHeld() const; + + // Weak; owned by the Profile and reset in ShutdownOnUIThread. + PrefService* prefs_; + + // Can be set for testing. + scoped_ptr<base::Clock> clock_; + + bool is_incognito_; + + PrefChangeRegistrar pref_change_registrar_; + + // Whether we are currently updating preferences, this is used to ignore + // notifications from the preferences service that we triggered ourself. + bool updating_preferences_; + + OriginIdentifierValueMap value_map_; + + OriginIdentifierValueMap incognito_value_map_; + + // Used around accesses to the value map objects to guarantee thread safety. + mutable base::Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(PrefProvider); +}; + +} // namespace content_settings + +#endif // COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_PREF_PROVIDER_H_ diff --git a/components/content_settings/core/browser/content_settings_provider_unittest.cc b/components/content_settings/core/browser/content_settings_provider_unittest.cc new file mode 100644 index 0000000..a9fda79 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_provider_unittest.cc @@ -0,0 +1,104 @@ +// Copyright (c) 2011 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 "base/memory/scoped_ptr.h" +#include "components/content_settings/core/browser/content_settings_mock_provider.h" +#include "components/content_settings/core/browser/content_settings_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace content_settings { + +TEST(ContentSettingsProviderTest, Mock) { + ContentSettingsPattern pattern = + ContentSettingsPattern::FromString("[*.]youtube.com"); + GURL url("http://www.youtube.com"); + + MockProvider mock_provider(false); + mock_provider.SetWebsiteSetting( + pattern, + pattern, + CONTENT_SETTINGS_TYPE_PLUGINS, + "java_plugin", + new base::FundamentalValue(CONTENT_SETTING_BLOCK)); + + EXPECT_EQ(CONTENT_SETTING_BLOCK, + GetContentSetting(&mock_provider, url, url, + CONTENT_SETTINGS_TYPE_PLUGINS, "java_plugin", + false)); + scoped_ptr<base::Value> value_ptr( + GetContentSettingValue(&mock_provider, url, url, + CONTENT_SETTINGS_TYPE_PLUGINS, + "java_plugin", false)); + int int_value = -1; + value_ptr->GetAsInteger(&int_value); + EXPECT_EQ(CONTENT_SETTING_BLOCK, IntToContentSetting(int_value)); + + EXPECT_EQ(CONTENT_SETTING_DEFAULT, + GetContentSetting(&mock_provider, url, url, + CONTENT_SETTINGS_TYPE_PLUGINS, "flash_plugin", + false)); + EXPECT_EQ(NULL, + GetContentSettingValue(&mock_provider, url, url, + CONTENT_SETTINGS_TYPE_PLUGINS, + "flash_plugin", false)); + EXPECT_EQ(CONTENT_SETTING_DEFAULT, + GetContentSetting(&mock_provider, + url, + url, + CONTENT_SETTINGS_TYPE_GEOLOCATION, + std::string(), + false)); + EXPECT_EQ(NULL, + GetContentSettingValue(&mock_provider, + url, + url, + CONTENT_SETTINGS_TYPE_GEOLOCATION, + std::string(), + false)); + + bool owned = mock_provider.SetWebsiteSetting( + pattern, + pattern, + CONTENT_SETTINGS_TYPE_PLUGINS, + "java_plugin", + new base::FundamentalValue(CONTENT_SETTING_ALLOW)); + EXPECT_TRUE(owned); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + GetContentSetting(&mock_provider, url, url, + CONTENT_SETTINGS_TYPE_PLUGINS, "java_plugin", + false)); + + mock_provider.set_read_only(true); + scoped_ptr<base::Value> value( + new base::FundamentalValue(CONTENT_SETTING_BLOCK)); + owned = mock_provider.SetWebsiteSetting( + pattern, + pattern, + CONTENT_SETTINGS_TYPE_PLUGINS, + "java_plugin", + value.get()); + EXPECT_FALSE(owned); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + GetContentSetting(&mock_provider, url, url, + CONTENT_SETTINGS_TYPE_PLUGINS, "java_plugin", + false)); + + EXPECT_TRUE(mock_provider.read_only()); + + mock_provider.set_read_only(false); + owned = mock_provider.SetWebsiteSetting( + pattern, + pattern, + CONTENT_SETTINGS_TYPE_PLUGINS, + "java_plugin", + new base::FundamentalValue(CONTENT_SETTING_BLOCK)); + EXPECT_TRUE(owned); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + GetContentSetting(&mock_provider, url, url, + CONTENT_SETTINGS_TYPE_PLUGINS, "java_plugin", + false)); +} + +} // namespace content_settings diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc new file mode 100644 index 0000000..1a3f788 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_utils.cc @@ -0,0 +1,251 @@ +// Copyright (c) 2012 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 "components/content_settings/core/browser/content_settings_utils.h" + +#include <vector> + +#include "base/command_line.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/strings/string_split.h" +#include "base/values.h" +#include "components/content_settings/core/browser/content_settings_provider.h" +#include "components/content_settings/core/browser/content_settings_rule.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "url/gurl.h" + +namespace { + +// The names of the ContentSettingsType values, for use with dictionary prefs. +const char* kTypeNames[] = { + "cookies", + "images", + "javascript", + "plugins", + "popups", + "geolocation", + "notifications", + "auto-select-certificate", + "fullscreen", + "mouselock", + "mixed-script", + "media-stream", + "media-stream-mic", + "media-stream-camera", + "register-protocol-handler", + "ppapi-broker", + "multiple-automatic-downloads", + "midi-sysex", + "push-messaging", + "ssl-cert-decisions", +#if defined(OS_WIN) + "metro-switch-to-desktop", +#elif defined(OS_ANDROID) || defined(OS_CHROMEOS) + "protected-media-identifier", +#endif +#if defined(OS_ANDROID) + "app-banner", +#endif +}; +COMPILE_ASSERT(arraysize(kTypeNames) == CONTENT_SETTINGS_NUM_TYPES, + type_names_incorrect_size); + +const char kPatternSeparator[] = ","; + +} // namespace + +namespace content_settings { + +std::string GetTypeName(ContentSettingsType type) { + return std::string(kTypeNames[type]); +} + +bool GetTypeFromName(const std::string& name, + ContentSettingsType* return_setting) { + for (size_t type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) { + if (name.compare(kTypeNames[type]) == 0) { + *return_setting = static_cast<ContentSettingsType>(type); + return true; + } + } + return false; +} + +std::string ContentSettingToString(ContentSetting setting) { + switch (setting) { + case CONTENT_SETTING_ALLOW: + return "allow"; + case CONTENT_SETTING_ASK: + return "ask"; + case CONTENT_SETTING_BLOCK: + return "block"; + case CONTENT_SETTING_SESSION_ONLY: + return "session"; + case CONTENT_SETTING_DEFAULT: + return "default"; + case CONTENT_SETTING_NUM_SETTINGS: + NOTREACHED(); + } + + return std::string(); +} + +ContentSetting ContentSettingFromString(const std::string& name) { + if (name == "allow") + return CONTENT_SETTING_ALLOW; + if (name == "ask") + return CONTENT_SETTING_ASK; + if (name == "block") + return CONTENT_SETTING_BLOCK; + if (name == "session") + return CONTENT_SETTING_SESSION_ONLY; + + NOTREACHED() << name << " is not a recognized content setting."; + return CONTENT_SETTING_DEFAULT; +} + +std::string CreatePatternString( + const ContentSettingsPattern& item_pattern, + const ContentSettingsPattern& top_level_frame_pattern) { + return item_pattern.ToString() + + std::string(kPatternSeparator) + + top_level_frame_pattern.ToString(); +} + +PatternPair ParsePatternString(const std::string& pattern_str) { + std::vector<std::string> pattern_str_list; + base::SplitString(pattern_str, kPatternSeparator[0], &pattern_str_list); + + // If the |pattern_str| is an empty string then the |pattern_string_list| + // contains a single empty string. In this case the empty string will be + // removed to signal an invalid |pattern_str|. Invalid pattern strings are + // handle by the "if"-statment below. So the order of the if statements here + // must be preserved. + if (pattern_str_list.size() == 1) { + if (pattern_str_list[0].empty()) { + pattern_str_list.pop_back(); + } else { + pattern_str_list.push_back("*"); + } + } + + if (pattern_str_list.size() > 2 || + pattern_str_list.size() == 0) { + return PatternPair(ContentSettingsPattern(), + ContentSettingsPattern()); + } + + PatternPair pattern_pair; + pattern_pair.first = + ContentSettingsPattern::FromString(pattern_str_list[0]); + pattern_pair.second = + ContentSettingsPattern::FromString(pattern_str_list[1]); + return pattern_pair; +} + +ContentSetting ValueToContentSetting(const base::Value* value) { + ContentSetting setting = CONTENT_SETTING_DEFAULT; + bool valid = ParseContentSettingValue(value, &setting); + DCHECK(valid); + return setting; +} + +bool ParseContentSettingValue(const base::Value* value, + ContentSetting* setting) { + if (!value) { + *setting = CONTENT_SETTING_DEFAULT; + return true; + } + int int_value = -1; + if (!value->GetAsInteger(&int_value)) + return false; + *setting = IntToContentSetting(int_value); + return *setting != CONTENT_SETTING_DEFAULT; +} + +base::Value* GetContentSettingValueAndPatterns( + const ProviderInterface* provider, + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + bool include_incognito, + ContentSettingsPattern* primary_pattern, + ContentSettingsPattern* secondary_pattern) { + if (include_incognito) { + // Check incognito-only specific settings. It's essential that the + // |RuleIterator| gets out of scope before we get a rule iterator for the + // normal mode. + scoped_ptr<RuleIterator> incognito_rule_iterator( + provider->GetRuleIterator(content_type, resource_identifier, true)); + base::Value* value = GetContentSettingValueAndPatterns( + incognito_rule_iterator.get(), primary_url, secondary_url, + primary_pattern, secondary_pattern); + if (value) + return value; + } + // No settings from the incognito; use the normal mode. + scoped_ptr<RuleIterator> rule_iterator( + provider->GetRuleIterator(content_type, resource_identifier, false)); + return GetContentSettingValueAndPatterns( + rule_iterator.get(), primary_url, secondary_url, + primary_pattern, secondary_pattern); +} + +base::Value* GetContentSettingValueAndPatterns( + RuleIterator* rule_iterator, + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsPattern* primary_pattern, + ContentSettingsPattern* secondary_pattern) { + while (rule_iterator->HasNext()) { + const Rule& rule = rule_iterator->Next(); + if (rule.primary_pattern.Matches(primary_url) && + rule.secondary_pattern.Matches(secondary_url)) { + if (primary_pattern) + *primary_pattern = rule.primary_pattern; + if (secondary_pattern) + *secondary_pattern = rule.secondary_pattern; + return rule.value.get()->DeepCopy(); + } + } + return NULL; +} + +base::Value* GetContentSettingValue(const ProviderInterface* provider, + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + bool include_incognito) { + return GetContentSettingValueAndPatterns(provider, primary_url, secondary_url, + content_type, resource_identifier, + include_incognito, NULL, NULL); +} + +ContentSetting GetContentSetting(const ProviderInterface* provider, + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + bool include_incognito) { + scoped_ptr<base::Value> value( + GetContentSettingValue(provider, primary_url, secondary_url, + content_type, resource_identifier, + include_incognito)); + return ValueToContentSetting(value.get()); +} + +void GetRendererContentSettingRules(const HostContentSettingsMap* map, + RendererContentSettingRules* rules) { + map->GetSettingsForOneType( + CONTENT_SETTINGS_TYPE_IMAGES, std::string(), &(rules->image_rules)); + map->GetSettingsForOneType( + CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(), &(rules->script_rules)); +} + +} // namespace content_settings diff --git a/components/content_settings/core/browser/content_settings_utils.h b/components/content_settings/core/browser/content_settings_utils.h new file mode 100644 index 0000000..5aee075 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_utils.h @@ -0,0 +1,94 @@ +// Copyright (c) 2012 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. + +#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_UTILS_H_ +#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_UTILS_H_ + +#include <string> +#include <utility> + +#include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/content_settings/core/common/content_settings_types.h" + +namespace base { +class Value; +} + +class GURL; +class HostContentSettingsMap; + +namespace content_settings { + +class ProviderInterface; +class RuleIterator; + +typedef std::pair<ContentSettingsPattern, ContentSettingsPattern> PatternPair; + +std::string GetTypeName(ContentSettingsType type); + +bool GetTypeFromName(const std::string& name, + ContentSettingsType* return_setting); + +std::string ContentSettingToString(ContentSetting setting); + +ContentSetting ContentSettingFromString(const std::string& name); + +// Converts |Value| to |ContentSetting|. +ContentSetting ValueToContentSetting(const base::Value* value); + +// Converts a |Value| to a |ContentSetting|. Returns true if |value| encodes +// a valid content setting, false otherwise. Note that |CONTENT_SETTING_DEFAULT| +// is encoded as a NULL value, so it is not allowed as an integer value. +bool ParseContentSettingValue(const base::Value* value, + ContentSetting* setting); + +PatternPair ParsePatternString(const std::string& pattern_str); + +std::string CreatePatternString( + const ContentSettingsPattern& item_pattern, + const ContentSettingsPattern& top_level_frame_pattern); + +// Caller takes the ownership of the returned |base::Value*|. +base::Value* GetContentSettingValueAndPatterns( + RuleIterator* rule_iterator, + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsPattern* primary_pattern, + ContentSettingsPattern* secondary_pattern); + +base::Value* GetContentSettingValueAndPatterns( + const ProviderInterface* provider, + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + bool include_incognito, + ContentSettingsPattern* primary_pattern, + ContentSettingsPattern* secondary_pattern); + +base::Value* GetContentSettingValue( + const ProviderInterface* provider, + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + bool include_incognito); + +ContentSetting GetContentSetting( + const ProviderInterface* provider, + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + bool include_incognito); + +// Populates |rules| with content setting rules for content types that are +// handled by the renderer. +void GetRendererContentSettingRules(const HostContentSettingsMap* map, + RendererContentSettingRules* rules); + +} // namespace content_settings + +#endif // COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_UTILS_H_ diff --git a/components/content_settings/core/browser/content_settings_utils_unittest.cc b/components/content_settings/core/browser/content_settings_utils_unittest.cc new file mode 100644 index 0000000..909a956 --- /dev/null +++ b/components/content_settings/core/browser/content_settings_utils_unittest.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2011 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 "components/content_settings/core/browser/content_settings_utils.h" + +#include <string> + +#include "testing/gtest/include/gtest/gtest.h" + +TEST(ContentSettingsUtilsTest, ParsePatternString) { + content_settings::PatternPair pattern_pair; + + pattern_pair = content_settings::ParsePatternString(std::string()); + EXPECT_FALSE(pattern_pair.first.IsValid()); + EXPECT_FALSE(pattern_pair.second.IsValid()); + + pattern_pair = content_settings::ParsePatternString(","); + EXPECT_FALSE(pattern_pair.first.IsValid()); + EXPECT_FALSE(pattern_pair.second.IsValid()); + + pattern_pair = content_settings::ParsePatternString("http://www.foo.com"); + EXPECT_TRUE(pattern_pair.first.IsValid()); + EXPECT_EQ(pattern_pair.second, ContentSettingsPattern::Wildcard()); + + // This inconsistency is to recover from some broken code. + pattern_pair = content_settings::ParsePatternString("http://www.foo.com,"); + EXPECT_TRUE(pattern_pair.first.IsValid()); + EXPECT_FALSE(pattern_pair.second.IsValid()); + + pattern_pair = content_settings::ParsePatternString( + "http://www.foo.com,http://www.bar.com"); + EXPECT_TRUE(pattern_pair.first.IsValid()); + EXPECT_TRUE(pattern_pair.second.IsValid()); + + pattern_pair = content_settings::ParsePatternString( + "http://www.foo.com,http://www.bar.com,"); + EXPECT_FALSE(pattern_pair.first.IsValid()); + EXPECT_FALSE(pattern_pair.second.IsValid()); + + pattern_pair = content_settings::ParsePatternString( + "http://www.foo.com,http://www.bar.com,http://www.error.com"); + EXPECT_FALSE(pattern_pair.first.IsValid()); + EXPECT_FALSE(pattern_pair.second.IsValid()); +} diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc new file mode 100644 index 0000000..ccddb0e --- /dev/null +++ b/components/content_settings/core/browser/host_content_settings_map.cc @@ -0,0 +1,752 @@ +// Copyright (c) 2012 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 "components/content_settings/core/browser/host_content_settings_map.h" + +#include <utility> + +#include "base/basictypes.h" +#include "base/command_line.h" +#include "base/prefs/pref_service.h" +#include "base/stl_util.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/time/clock.h" +#include "components/content_settings/core/browser/content_settings_default_provider.h" +#include "components/content_settings/core/browser/content_settings_details.h" +#include "components/content_settings/core/browser/content_settings_observable_provider.h" +#include "components/content_settings/core/browser/content_settings_policy_provider.h" +#include "components/content_settings/core/browser/content_settings_pref_provider.h" +#include "components/content_settings/core/browser/content_settings_provider.h" +#include "components/content_settings/core/browser/content_settings_rule.h" +#include "components/content_settings/core/browser/content_settings_utils.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/content_settings/core/common/pref_names.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "net/base/net_errors.h" +#include "net/base/static_cookie_policy.h" +#include "url/gurl.h" + +namespace { + +typedef std::vector<content_settings::Rule> Rules; + +typedef std::pair<std::string, std::string> StringPair; + +// TODO(bauerb): Expose constants. +const char* kProviderNames[] = { + "platform_app", + "policy", + "extension", + "override", + "preference", + "default" +}; + +// These constants are copied from extensions/common/extension_constants.h and +// content/public/common/url_constants.h to avoid complicated dependencies. +// TODO(vabr): Get these constants through the ContentSettingsClient. +const char kChromeDevToolsScheme[] = "chrome-devtools"; +const char kChromeUIScheme[] = "chrome"; + +#if defined(ENABLE_EXTENSIONS) +const char kExtensionScheme[] = "chrome-extension"; +#endif + +content_settings::SettingSource kProviderSourceMap[] = { + content_settings::SETTING_SOURCE_EXTENSION, + content_settings::SETTING_SOURCE_POLICY, + content_settings::SETTING_SOURCE_EXTENSION, + content_settings::SETTING_SOURCE_USER, + content_settings::SETTING_SOURCE_USER, + content_settings::SETTING_SOURCE_USER, +}; +COMPILE_ASSERT(arraysize(kProviderSourceMap) == + HostContentSettingsMap::NUM_PROVIDER_TYPES, + kProviderSourceMap_has_incorrect_size); + +// Returns true if the |content_type| supports a resource identifier. +// Resource identifiers are supported (but not required) for plug-ins. +bool SupportsResourceIdentifier(ContentSettingsType content_type) { + return content_type == CONTENT_SETTINGS_TYPE_PLUGINS; +} + +} // namespace + +HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs, + bool incognito) + : +#ifndef NDEBUG + used_from_thread_id_(base::PlatformThread::CurrentId()), +#endif + prefs_(prefs), + is_off_the_record_(incognito) { + content_settings::ObservableProvider* policy_provider = + new content_settings::PolicyProvider(prefs_); + policy_provider->AddObserver(this); + content_settings_providers_[POLICY_PROVIDER] = policy_provider; + + content_settings::ObservableProvider* pref_provider = + new content_settings::PrefProvider(prefs_, is_off_the_record_); + pref_provider->AddObserver(this); + content_settings_providers_[PREF_PROVIDER] = pref_provider; + + content_settings::ObservableProvider* default_provider = + new content_settings::DefaultProvider(prefs_, is_off_the_record_); + default_provider->AddObserver(this); + content_settings_providers_[DEFAULT_PROVIDER] = default_provider; + + content_settings_providers_[OVERRIDE_PROVIDER] = + new content_settings::OverrideProvider(prefs_, is_off_the_record_); +} + +// static +void HostContentSettingsMap::RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterIntegerPref( + prefs::kContentSettingsWindowLastTabIndex, + 0, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + + // Register the prefs for the content settings providers. + content_settings::DefaultProvider::RegisterProfilePrefs(registry); + content_settings::PrefProvider::RegisterProfilePrefs(registry); + content_settings::PolicyProvider::RegisterProfilePrefs(registry); + content_settings::OverrideProvider::RegisterProfilePrefs(registry); +} + +void HostContentSettingsMap::RegisterProvider( + ProviderType type, + scoped_ptr<content_settings::ObservableProvider> provider) { + DCHECK(!content_settings_providers_[type]); + provider->AddObserver(this); + content_settings_providers_[type] = provider.release(); + +#ifndef NDEBUG + DCHECK_NE(used_from_thread_id_, base::kInvalidThreadId) + << "Used from multiple threads before initialization complete."; +#endif + + OnContentSettingChanged(ContentSettingsPattern(), + ContentSettingsPattern(), + CONTENT_SETTINGS_TYPE_DEFAULT, + std::string()); +} + +ContentSetting HostContentSettingsMap::GetDefaultContentSettingFromProvider( + ContentSettingsType content_type, + content_settings::ProviderInterface* provider) const { + scoped_ptr<content_settings::RuleIterator> rule_iterator( + provider->GetRuleIterator(content_type, std::string(), false)); + + ContentSettingsPattern wildcard = ContentSettingsPattern::Wildcard(); + while (rule_iterator->HasNext()) { + content_settings::Rule rule = rule_iterator->Next(); + if (rule.primary_pattern == wildcard && + rule.secondary_pattern == wildcard) { + return content_settings::ValueToContentSetting(rule.value.get()); + } + } + return CONTENT_SETTING_DEFAULT; +} + +ContentSetting HostContentSettingsMap::GetDefaultContentSetting( + ContentSettingsType content_type, + std::string* provider_id) const { + UsedContentSettingsProviders(); + + // Iterate through the list of providers and return the first non-NULL value + // that matches |primary_url| and |secondary_url|. + for (ConstProviderIterator provider = content_settings_providers_.begin(); + provider != content_settings_providers_.end(); + ++provider) { + if (provider->first == PREF_PROVIDER || + provider->first == OVERRIDE_PROVIDER) + continue; + ContentSetting default_setting = + GetDefaultContentSettingFromProvider(content_type, provider->second); + if (default_setting != CONTENT_SETTING_DEFAULT) { + if (provider_id) + *provider_id = kProviderNames[provider->first]; + return default_setting; + } + } + + return CONTENT_SETTING_DEFAULT; +} + +ContentSetting HostContentSettingsMap::GetContentSetting( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier) const { + DCHECK(!ContentTypeHasCompoundValue(content_type)); + scoped_ptr<base::Value> value = GetWebsiteSetting( + primary_url, secondary_url, content_type, resource_identifier, NULL); + return content_settings::ValueToContentSetting(value.get()); +} + +void HostContentSettingsMap::GetSettingsForOneType( + ContentSettingsType content_type, + const std::string& resource_identifier, + ContentSettingsForOneType* settings) const { + DCHECK(SupportsResourceIdentifier(content_type) || + resource_identifier.empty()); + DCHECK(settings); + UsedContentSettingsProviders(); + + settings->clear(); + for (ConstProviderIterator provider = content_settings_providers_.begin(); + provider != content_settings_providers_.end(); + ++provider) { + if (provider->first == OVERRIDE_PROVIDER) + continue; + // For each provider, iterate first the incognito-specific rules, then the + // normal rules. + if (is_off_the_record_) { + AddSettingsForOneType(provider->second, + provider->first, + content_type, + resource_identifier, + settings, + true); + } + AddSettingsForOneType(provider->second, + provider->first, + content_type, + resource_identifier, + settings, + false); + } +} + +void HostContentSettingsMap::SetDefaultContentSetting( + ContentSettingsType content_type, + ContentSetting setting) { + DCHECK(IsSettingAllowedForType(prefs_, setting, content_type)); + + base::Value* value = NULL; + if (setting != CONTENT_SETTING_DEFAULT) + value = new base::FundamentalValue(setting); + SetWebsiteSetting( + ContentSettingsPattern::Wildcard(), + ContentSettingsPattern::Wildcard(), + content_type, + std::string(), + value); +} + +void HostContentSettingsMap::SetWebsiteSetting( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const std::string& resource_identifier, + base::Value* value) { + DCHECK(IsValueAllowedForType(prefs_, value, content_type)); + DCHECK(SupportsResourceIdentifier(content_type) || + resource_identifier.empty()); + UsedContentSettingsProviders(); + + for (ProviderIterator provider = content_settings_providers_.begin(); + provider != content_settings_providers_.end(); + ++provider) { + if (provider->second->SetWebsiteSetting(primary_pattern, + secondary_pattern, + content_type, + resource_identifier, + value)) { + return; + } + } + NOTREACHED(); +} + +void HostContentSettingsMap::SetNarrowestWebsiteSetting( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const std::string& resource_identifier, + ContentSetting setting, + content_settings::SettingInfo existing_info) { + ContentSettingsPattern narrow_primary = primary_pattern; + ContentSettingsPattern narrow_secondary = secondary_pattern; + + DCHECK_EQ(content_settings::SETTING_SOURCE_USER, existing_info.source); + ContentSettingsPattern::Relation r1 = + existing_info.primary_pattern.Compare(primary_pattern); + if (r1 == ContentSettingsPattern::PREDECESSOR) { + narrow_primary = existing_info.primary_pattern; + } else if (r1 == ContentSettingsPattern::IDENTITY) { + ContentSettingsPattern::Relation r2 = + existing_info.secondary_pattern.Compare(secondary_pattern); + DCHECK(r2 != ContentSettingsPattern::DISJOINT_ORDER_POST && + r2 != ContentSettingsPattern::DISJOINT_ORDER_PRE); + if (r2 == ContentSettingsPattern::PREDECESSOR) + narrow_secondary = existing_info.secondary_pattern; + } + + SetContentSetting( + narrow_primary, narrow_secondary, content_type, std::string(), setting); +} + +void HostContentSettingsMap::SetContentSetting( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const std::string& resource_identifier, + ContentSetting setting) { + DCHECK(!ContentTypeHasCompoundValue(content_type)); + + if (setting == CONTENT_SETTING_ALLOW && + (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION || + content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS)) { + UpdateLastUsageByPattern(primary_pattern, secondary_pattern, content_type); + } + + base::Value* value = NULL; + if (setting != CONTENT_SETTING_DEFAULT) + value = new base::FundamentalValue(setting); + SetWebsiteSetting(primary_pattern, + secondary_pattern, + content_type, + resource_identifier, + value); +} + +ContentSetting HostContentSettingsMap::GetContentSettingAndMaybeUpdateLastUsage( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier) { + DCHECK(thread_checker_.CalledOnValidThread()); + + ContentSetting setting = GetContentSetting( + primary_url, secondary_url, content_type, resource_identifier); + if (setting == CONTENT_SETTING_ALLOW) { + UpdateLastUsageByPattern( + ContentSettingsPattern::FromURLNoWildcard(primary_url), + ContentSettingsPattern::FromURLNoWildcard(secondary_url), + content_type); + } + return setting; +} + +void HostContentSettingsMap::UpdateLastUsage(const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type) { + UpdateLastUsageByPattern( + ContentSettingsPattern::FromURLNoWildcard(primary_url), + ContentSettingsPattern::FromURLNoWildcard(secondary_url), + content_type); +} + +void HostContentSettingsMap::UpdateLastUsageByPattern( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type) { + UsedContentSettingsProviders(); + + GetPrefProvider()->UpdateLastUsage( + primary_pattern, secondary_pattern, content_type); + + FOR_EACH_OBSERVER( + content_settings::Observer, + observers_, + OnContentSettingUsed(primary_pattern, secondary_pattern, content_type)); +} + +base::Time HostContentSettingsMap::GetLastUsage( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type) { + return GetLastUsageByPattern( + ContentSettingsPattern::FromURLNoWildcard(primary_url), + ContentSettingsPattern::FromURLNoWildcard(secondary_url), + content_type); +} + +base::Time HostContentSettingsMap::GetLastUsageByPattern( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type) { + UsedContentSettingsProviders(); + + return GetPrefProvider()->GetLastUsage( + primary_pattern, secondary_pattern, content_type); +} + +ContentSetting HostContentSettingsMap::GetContentSettingWithoutOverride( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier) { + scoped_ptr<base::Value> value(GetWebsiteSettingWithoutOverride( + primary_url, secondary_url, content_type, resource_identifier, NULL)); + return content_settings::ValueToContentSetting(value.get()); +} + +scoped_ptr<base::Value> +HostContentSettingsMap::GetWebsiteSettingWithoutOverride( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + content_settings::SettingInfo* info) const { + return GetWebsiteSettingInternal(primary_url, + secondary_url, + content_type, + resource_identifier, + info, + false); +} + +void HostContentSettingsMap::SetContentSettingOverride( + ContentSettingsType content_type, + bool is_enabled) { + UsedContentSettingsProviders(); + + content_settings::OverrideProvider* override = + static_cast<content_settings::OverrideProvider*>( + content_settings_providers_[OVERRIDE_PROVIDER]); + override->SetOverrideSetting(content_type, is_enabled); +} + +bool HostContentSettingsMap::GetContentSettingOverride( + ContentSettingsType content_type) { + UsedContentSettingsProviders(); + + content_settings::OverrideProvider* override = + static_cast<content_settings::OverrideProvider*>( + content_settings_providers_[OVERRIDE_PROVIDER]); + return override->IsEnabled(content_type); +} + +void HostContentSettingsMap::AddObserver(content_settings::Observer* observer) { + observers_.AddObserver(observer); +} + +void HostContentSettingsMap::RemoveObserver( + content_settings::Observer* observer) { + observers_.RemoveObserver(observer); +} + +void HostContentSettingsMap::SetPrefClockForTesting( + scoped_ptr<base::Clock> clock) { + UsedContentSettingsProviders(); + + GetPrefProvider()->SetClockForTesting(clock.Pass()); +} + +void HostContentSettingsMap::AddExceptionForURL( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + ContentSetting setting) { + // TODO(markusheintz): Until the UI supports pattern pairs, both urls must + // match. + DCHECK(primary_url == secondary_url); + DCHECK(!ContentTypeHasCompoundValue(content_type)); + + // Make sure there is no entry that would override the pattern we are about + // to insert for exactly this URL. + SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(primary_url), + ContentSettingsPattern::Wildcard(), + content_type, + std::string(), + CONTENT_SETTING_DEFAULT); + + SetContentSetting(ContentSettingsPattern::FromURL(primary_url), + ContentSettingsPattern::Wildcard(), + content_type, + std::string(), + setting); +} + +void HostContentSettingsMap::ClearSettingsForOneType( + ContentSettingsType content_type) { + UsedContentSettingsProviders(); + for (ProviderIterator provider = content_settings_providers_.begin(); + provider != content_settings_providers_.end(); + ++provider) { + provider->second->ClearAllContentSettingsRules(content_type); + } +} + +bool HostContentSettingsMap::IsValueAllowedForType( + PrefService* prefs, const base::Value* value, ContentSettingsType type) { + return ContentTypeHasCompoundValue(type) || IsSettingAllowedForType( + prefs, content_settings::ValueToContentSetting(value), type); +} + +// static +bool HostContentSettingsMap::IsSettingAllowedForType( + PrefService* prefs, + ContentSetting setting, + ContentSettingsType content_type) { + // We don't yet support stored content settings for mixed scripting. + if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) + return false; + + // BLOCK semantics are not implemented for fullscreen. + if (content_type == CONTENT_SETTINGS_TYPE_FULLSCREEN && + setting == CONTENT_SETTING_BLOCK) { + return false; + } + + // We don't support ALLOW for media default setting. + if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM && + setting == CONTENT_SETTING_ALLOW) { + return false; + } + +#if defined(OS_ANDROID) + // App banners store a dictionary. + if (content_type == CONTENT_SETTINGS_TYPE_APP_BANNER) + return false; +#endif + + // DEFAULT, ALLOW and BLOCK are always allowed. + if (setting == CONTENT_SETTING_DEFAULT || + setting == CONTENT_SETTING_ALLOW || + setting == CONTENT_SETTING_BLOCK) { + return true; + } + switch (content_type) { + case CONTENT_SETTINGS_TYPE_COOKIES: + return setting == CONTENT_SETTING_SESSION_ONLY; + case CONTENT_SETTINGS_TYPE_PLUGINS: + case CONTENT_SETTINGS_TYPE_GEOLOCATION: + case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: + case CONTENT_SETTINGS_TYPE_MOUSELOCK: + case CONTENT_SETTINGS_TYPE_MEDIASTREAM: + case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: + case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: + case CONTENT_SETTINGS_TYPE_PPAPI_BROKER: + case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS: + case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: + return setting == CONTENT_SETTING_ASK; + default: + return false; + } +} + +// static +bool HostContentSettingsMap::ContentTypeHasCompoundValue( + ContentSettingsType type) { + // Values for content type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, + // CONTENT_SETTINGS_TYPE_MEDIASTREAM, and + // CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS are of type dictionary/map. + // Compound types like dictionaries can't be mapped to the type + // |ContentSetting|. +#if defined(OS_ANDROID) + if (type == CONTENT_SETTINGS_TYPE_APP_BANNER) + return true; +#endif + + return (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE || + type == CONTENT_SETTINGS_TYPE_MEDIASTREAM || + type == CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS); +} + +void HostContentSettingsMap::OnContentSettingChanged( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + std::string resource_identifier) { + FOR_EACH_OBSERVER(content_settings::Observer, + observers_, + OnContentSettingChanged(primary_pattern, + secondary_pattern, + content_type, + resource_identifier)); +} + +HostContentSettingsMap::~HostContentSettingsMap() { + DCHECK(!prefs_); + STLDeleteValues(&content_settings_providers_); +} + +void HostContentSettingsMap::ShutdownOnUIThread() { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(prefs_); + prefs_ = NULL; + for (ProviderIterator it = content_settings_providers_.begin(); + it != content_settings_providers_.end(); + ++it) { + it->second->ShutdownOnUIThread(); + } +} + +void HostContentSettingsMap::AddSettingsForOneType( + const content_settings::ProviderInterface* provider, + ProviderType provider_type, + ContentSettingsType content_type, + const std::string& resource_identifier, + ContentSettingsForOneType* settings, + bool incognito) const { + scoped_ptr<content_settings::RuleIterator> rule_iterator( + provider->GetRuleIterator(content_type, + resource_identifier, + incognito)); + while (rule_iterator->HasNext()) { + const content_settings::Rule& rule = rule_iterator->Next(); + ContentSetting setting_value = CONTENT_SETTING_DEFAULT; + // TODO(bauerb): Return rules as a list of values, not content settings. + // Handle the case using compound values for its exceptions and arbitrary + // values for its default setting. Here we assume all the exceptions + // are granted as |CONTENT_SETTING_ALLOW|. + if (ContentTypeHasCompoundValue(content_type) && + rule.value.get() && + rule.primary_pattern != ContentSettingsPattern::Wildcard()) { + setting_value = CONTENT_SETTING_ALLOW; + } else { + setting_value = content_settings::ValueToContentSetting(rule.value.get()); + } + settings->push_back(ContentSettingPatternSource( + rule.primary_pattern, rule.secondary_pattern, + setting_value, + kProviderNames[provider_type], + incognito)); + } +} + +void HostContentSettingsMap::UsedContentSettingsProviders() const { +#ifndef NDEBUG + if (used_from_thread_id_ == base::kInvalidThreadId) + return; + + if (base::PlatformThread::CurrentId() != used_from_thread_id_) + used_from_thread_id_ = base::kInvalidThreadId; +#endif +} + +bool HostContentSettingsMap::ShouldAllowAllContent( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type) { + if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS || + content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION || + content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) { + return false; + } +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) + if (content_type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) { + return false; + } +#endif + if (secondary_url.SchemeIs(kChromeUIScheme) && + content_type == CONTENT_SETTINGS_TYPE_COOKIES && + primary_url.SchemeIsSecure()) { + return true; + } +#if defined(ENABLE_EXTENSIONS) + if (primary_url.SchemeIs(kExtensionScheme)) { + switch (content_type) { + case CONTENT_SETTINGS_TYPE_PLUGINS: + case CONTENT_SETTINGS_TYPE_MEDIASTREAM: + case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: + case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: + return false; + case CONTENT_SETTINGS_TYPE_COOKIES: + return secondary_url.SchemeIs(kExtensionScheme); + default: + return true; + } + } +#endif + return primary_url.SchemeIs(kChromeDevToolsScheme) || + primary_url.SchemeIs(kChromeUIScheme); +} + +scoped_ptr<base::Value> HostContentSettingsMap::GetWebsiteSetting( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + content_settings::SettingInfo* info) const { + DCHECK(SupportsResourceIdentifier(content_type) || + resource_identifier.empty()); + + // Check if the scheme of the requesting url is whitelisted. + if (ShouldAllowAllContent(primary_url, secondary_url, content_type)) { + if (info) { + info->source = content_settings::SETTING_SOURCE_WHITELIST; + info->primary_pattern = ContentSettingsPattern::Wildcard(); + info->secondary_pattern = ContentSettingsPattern::Wildcard(); + } + return scoped_ptr<base::Value>( + new base::FundamentalValue(CONTENT_SETTING_ALLOW)); + } + + return GetWebsiteSettingInternal(primary_url, + secondary_url, + content_type, + resource_identifier, + info, + true); +} + +// static +HostContentSettingsMap::ProviderType +HostContentSettingsMap::GetProviderTypeFromSource(const std::string& source) { + for (size_t i = 0; i < arraysize(kProviderNames); ++i) { + if (source == kProviderNames[i]) + return static_cast<ProviderType>(i); + } + + NOTREACHED(); + return DEFAULT_PROVIDER; +} + +content_settings::PrefProvider* HostContentSettingsMap::GetPrefProvider() { + return static_cast<content_settings::PrefProvider*>( + content_settings_providers_[PREF_PROVIDER]); +} + +scoped_ptr<base::Value> HostContentSettingsMap::GetWebsiteSettingInternal( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + content_settings::SettingInfo* info, + bool get_override) const { + UsedContentSettingsProviders(); + ContentSettingsPattern* primary_pattern = NULL; + ContentSettingsPattern* secondary_pattern = NULL; + if (info) { + primary_pattern = &info->primary_pattern; + secondary_pattern = &info->secondary_pattern; + } + + // The list of |content_settings_providers_| is ordered according to their + // precedence. + for (ConstProviderIterator provider = content_settings_providers_.begin(); + provider != content_settings_providers_.end(); + ++provider) { + if (!get_override && provider->first == OVERRIDE_PROVIDER) + continue; + + scoped_ptr<base::Value> value( + content_settings::GetContentSettingValueAndPatterns(provider->second, + primary_url, + secondary_url, + content_type, + resource_identifier, + is_off_the_record_, + primary_pattern, + secondary_pattern)); + if (value) { + if (info) + info->source = kProviderSourceMap[provider->first]; + return value.Pass(); + } + } + + if (info) { + info->source = content_settings::SETTING_SOURCE_NONE; + info->primary_pattern = ContentSettingsPattern(); + info->secondary_pattern = ContentSettingsPattern(); + } + return scoped_ptr<base::Value>(); +} diff --git a/components/content_settings/core/browser/host_content_settings_map.h b/components/content_settings/core/browser/host_content_settings_map.h new file mode 100644 index 0000000..b5482b1 --- /dev/null +++ b/components/content_settings/core/browser/host_content_settings_map.h @@ -0,0 +1,363 @@ +// Copyright (c) 2012 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. + +// Maps hostnames to custom content settings. Written on the UI thread and read +// on any thread. One instance per profile. + +#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_HOST_CONTENT_SETTINGS_MAP_H_ +#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_HOST_CONTENT_SETTINGS_MAP_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/observer_list.h" +#include "base/prefs/pref_change_registrar.h" +#include "base/threading/platform_thread.h" +#include "base/threading/thread_checker.h" +#include "base/tuple.h" +#include "components/content_settings/core/browser/content_settings_observer.h" +#include "components/content_settings/core/browser/content_settings_override_provider.h" +#include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/content_settings/core/common/content_settings_types.h" + +class ExtensionService; +class GURL; +class PrefService; + +namespace base { +class Clock; +class Value; +} + +namespace content_settings { +class OverrideProvider; +class ObservableProvider; +class ProviderInterface; +class PrefProvider; +} + +namespace user_prefs { +class PrefRegistrySyncable; +} + +class HostContentSettingsMap + : public content_settings::Observer, + public base::RefCountedThreadSafe<HostContentSettingsMap> { + public: + enum ProviderType { + // EXTENSION names is a layering violation when this class will move to + // components. + // TODO(mukai): find the solution. + INTERNAL_EXTENSION_PROVIDER = 0, + POLICY_PROVIDER, + CUSTOM_EXTENSION_PROVIDER, + OVERRIDE_PROVIDER, + PREF_PROVIDER, + DEFAULT_PROVIDER, + NUM_PROVIDER_TYPES, + }; + + // This should be called on the UI thread, otherwise |thread_checker_| handles + // CalledOnValidThread() wrongly. + HostContentSettingsMap(PrefService* prefs, bool incognito); + + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + + // Adds a new provider for |type|. + void RegisterProvider( + ProviderType type, + scoped_ptr<content_settings::ObservableProvider> provider); + + // Returns the default setting for a particular content type. If |provider_id| + // is not NULL, the id of the provider which provided the default setting is + // assigned to it. + // + // This may be called on any thread. + ContentSetting GetDefaultContentSetting(ContentSettingsType content_type, + std::string* provider_id) const; + + // Returns a single |ContentSetting| which applies to the given URLs. Note + // that certain internal schemes are whitelisted. For |CONTENT_TYPE_COOKIES|, + // |CookieSettings| should be used instead. For content types that can't be + // converted to a |ContentSetting|, |GetContentSettingValue| should be called. + // If there is no content setting, returns CONTENT_SETTING_DEFAULT. + // + // May be called on any thread. + ContentSetting GetContentSetting( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier) const; + + // Returns a single content setting |Value| which applies to the given URLs. + // If |info| is not NULL, then the |source| field of |info| is set to the + // source of the returned |Value| (POLICY, EXTENSION, USER, ...) and the + // |primary_pattern| and the |secondary_pattern| fields of |info| are set to + // the patterns of the applying rule. Note that certain internal schemes are + // whitelisted. For whitelisted schemes the |source| field of |info| is set + // the |SETTING_SOURCE_WHITELIST| and the |primary_pattern| and + // |secondary_pattern| are set to a wildcard pattern. If there is no content + // setting, NULL is returned and the |source| field of |info| is set to + // |SETTING_SOURCE_NONE|. The pattern fiels of |info| are set to empty + // patterns. + // May be called on any thread. + scoped_ptr<base::Value> GetWebsiteSetting( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + content_settings::SettingInfo* info) const; + + // For a given content type, returns all patterns with a non-default setting, + // mapped to their actual settings, in the precedence order of the rules. + // |settings| must be a non-NULL outparam. + // + // This may be called on any thread. + void GetSettingsForOneType(ContentSettingsType content_type, + const std::string& resource_identifier, + ContentSettingsForOneType* settings) const; + + // Sets the default setting for a particular content type. This method must + // not be invoked on an incognito map. + // + // This should only be called on the UI thread. + void SetDefaultContentSetting(ContentSettingsType content_type, + ContentSetting setting); + + // Sets the content |setting| for the given patterns, |content_type| and + // |resource_identifier|. Setting the value to CONTENT_SETTING_DEFAULT causes + // the default setting for that type to be used when loading pages matching + // this pattern. + // NOTICE: This is just a convenience method for content types that use + // |CONTENT_SETTING| as their data type. For content types that use other + // data types please use the method SetWebsiteSetting. + // + // This should only be called on the UI thread. + void SetContentSetting(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const std::string& resource_identifier, + ContentSetting setting); + + // Sets the |value| for the given patterns, |content_type| and + // |resource_identifier|. Setting the value to NULL causes the default value + // for that type to be used when loading pages matching this pattern. + // + // Takes ownership of the passed value. + void SetWebsiteSetting(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const std::string& resource_identifier, + base::Value* value); + + // Sets the most specific rule that currently defines the permission for the + // given permission type. + void SetNarrowestWebsiteSetting( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const std::string& resource_identifier, + ContentSetting setting, + content_settings::SettingInfo existing_info); + + // Convenience method to add a content setting for the given URLs, making sure + // that there is no setting overriding it. + // + // This should only be called on the UI thread. + void AddExceptionForURL(const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + ContentSetting setting); + + // Clears all host-specific settings for one content type. + // + // This should only be called on the UI thread. + void ClearSettingsForOneType(ContentSettingsType content_type); + + static bool IsValueAllowedForType(PrefService* prefs, + const base::Value* value, + ContentSettingsType content_type); + static bool IsSettingAllowedForType(PrefService* prefs, + ContentSetting setting, + ContentSettingsType content_type); + + // Returns true if the values for content type are of type dictionary/map. + static bool ContentTypeHasCompoundValue(ContentSettingsType type); + + // Detaches the HostContentSettingsMap from all Profile-related objects like + // PrefService. This methods needs to be called before destroying the Profile. + // Afterwards, none of the methods above that should only be called on the UI + // thread should be called anymore. + void ShutdownOnUIThread(); + + // content_settings::Observer implementation. + void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + std::string resource_identifier) override; + + // Returns true if we should allow all content types for this URL. This is + // true for various internal objects like chrome:// URLs, so UI and other + // things users think of as "not webpages" don't break. + static bool ShouldAllowAllContent(const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type); + + // Returns the ProviderType associated with the given source string. + // TODO(estade): I regret adding this. At the moment there are no legitimate + // uses. We should stick to ProviderType rather than string so we don't have + // to convert backwards. + static ProviderType GetProviderTypeFromSource(const std::string& source); + + bool is_off_the_record() const { + return is_off_the_record_; + } + + // Returns a single |ContentSetting| which applies to the given URLs, just as + // |GetContentSetting| does. If the setting is allowed, it also records the + // last usage to preferences. + // + // This should only be called on the UI thread, unlike |GetContentSetting|. + ContentSetting GetContentSettingAndMaybeUpdateLastUsage( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier); + + // Sets the last time that a given content type has been used for the pattern + // which matches the URLs to the current time. + void UpdateLastUsage(const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type); + + // Sets the last time that a given content type has been used for a pattern + // pair to the current time. + void UpdateLastUsageByPattern(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type); + + // Returns the last time the pattern that matches the URL has requested + // permission for the |content_type| setting. + base::Time GetLastUsage(const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type); + + // Returns the last time the pattern has requested permission for the + // |content_type| setting. + base::Time GetLastUsageByPattern( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type); + + // Returns the content setting without considering the global on/off toggle + // for the content setting that matches the URLs. + ContentSetting GetContentSettingWithoutOverride( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier); + + // Returns the single content setting |value| without considering the + // global on/off toggle for the content setting that matches the given + // patterns. + scoped_ptr<base::Value> GetWebsiteSettingWithoutOverride( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + content_settings::SettingInfo* info) const; + + // Sets globally if a given |content_type| |is_enabled|. + void SetContentSettingOverride(ContentSettingsType content_type, + bool is_enabled); + + // Returns if a given |content_type| is enabled. + bool GetContentSettingOverride(ContentSettingsType content_type); + + // Adds/removes an observer for content settings changes. + void AddObserver(content_settings::Observer* observer); + void RemoveObserver(content_settings::Observer* observer); + + // Passes ownership of |clock|. + void SetPrefClockForTesting(scoped_ptr<base::Clock> clock); + + private: + friend class base::RefCountedThreadSafe<HostContentSettingsMap>; + friend class HostContentSettingsMapTest_NonDefaultSettings_Test; + + typedef std::map<ProviderType, content_settings::ProviderInterface*> + ProviderMap; + typedef ProviderMap::iterator ProviderIterator; + typedef ProviderMap::const_iterator ConstProviderIterator; + + ~HostContentSettingsMap() override; + + ContentSetting GetDefaultContentSettingFromProvider( + ContentSettingsType content_type, + content_settings::ProviderInterface* provider) const; + + // Adds content settings for |content_type| and |resource_identifier|, + // provided by |provider|, into |settings|. If |incognito| is true, adds only + // the content settings which are applicable to the incognito mode and differ + // from the normal mode. Otherwise, adds the content settings for the normal + // mode. + void AddSettingsForOneType( + const content_settings::ProviderInterface* provider, + ProviderType provider_type, + ContentSettingsType content_type, + const std::string& resource_identifier, + ContentSettingsForOneType* settings, + bool incognito) const; + + // Call UsedContentSettingsProviders() whenever you access + // content_settings_providers_ (apart from initialization and + // teardown), so that we can DCHECK in RegisterExtensionService that + // it is not being called too late. + void UsedContentSettingsProviders() const; + + // Returns the single content setting |value| with a toggle for if it + // takes the global on/off switch into account. + scoped_ptr<base::Value> GetWebsiteSettingInternal( + const GURL& primary_url, + const GURL& secondary_url, + ContentSettingsType content_type, + const std::string& resource_identifier, + content_settings::SettingInfo* info, + bool get_override) const; + + content_settings::PrefProvider* GetPrefProvider(); + +#ifndef NDEBUG + // This starts as the thread ID of the thread that constructs this + // object, and remains until used by a different thread, at which + // point it is set to base::kInvalidThreadId. This allows us to + // DCHECK on unsafe usage of content_settings_providers_ (they + // should be set up on a single thread, after which they are + // immutable). + mutable base::PlatformThreadId used_from_thread_id_; +#endif + + // Weak; owned by the Profile. + PrefService* prefs_; + + // Whether this settings map is for an OTR session. + bool is_off_the_record_; + + // Content setting providers. This is only modified at construction + // time and by RegisterExtensionService, both of which should happen + // before any other uses of it. + ProviderMap content_settings_providers_; + + base::ThreadChecker thread_checker_; + + ObserverList<content_settings::Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(HostContentSettingsMap); +}; + +#endif // COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_HOST_CONTENT_SETTINGS_MAP_H_ diff --git a/components/content_settings/core/common/BUILD.gn b/components/content_settings/core/common/BUILD.gn index 629c396..6e39d74 100644 --- a/components/content_settings/core/common/BUILD.gn +++ b/components/content_settings/core/common/BUILD.gn @@ -13,6 +13,8 @@ static_library("common") { "content_settings_types.h", "permission_request_id.h", "permission_request_id.cc", + "pref_names.h", + "pref_names.cc", ] deps = [ diff --git a/components/content_settings/core/common/pref_names.cc b/components/content_settings/core/common/pref_names.cc new file mode 100644 index 0000000..ef9b66c --- /dev/null +++ b/components/content_settings/core/common/pref_names.cc @@ -0,0 +1,81 @@ +// 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 "components/content_settings/core/common/pref_names.h" + +namespace prefs { + +// Version of the pattern format used to define content settings. +const char kContentSettingsVersion[] = "profile.content_settings.pref_version"; + +// Patterns for mapping origins to origin related settings. Default settings +// will be applied to origins that don't match any of the patterns. The pattern +// format used is defined by kContentSettingsVersion. +const char kContentSettingsPatternPairs[] = + "profile.content_settings.pattern_pairs"; + +// Integer that specifies the index of the tab the user was on when they +// last visited the content settings window. +const char kContentSettingsWindowLastTabIndex[] = + "content_settings_window.last_tab_index"; + +// Dictionary of content settings applied to all hosts by default. +const char kDefaultContentSettings[] = "profile.default_content_settings"; + +// 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. +const char kOverrideContentSettings[] = "profile.override_content_settings"; + +// Preferences that are exclusively used to store managed values for default +// content settings. +const char kManagedDefaultCookiesSetting[] = + "profile.managed_default_content_settings.cookies"; +const char kManagedDefaultImagesSetting[] = + "profile.managed_default_content_settings.images"; +const char kManagedDefaultJavaScriptSetting[] = + "profile.managed_default_content_settings.javascript"; +const char kManagedDefaultPluginsSetting[] = + "profile.managed_default_content_settings.plugins"; +const char kManagedDefaultPopupsSetting[] = + "profile.managed_default_content_settings.popups"; +const char kManagedDefaultGeolocationSetting[] = + "profile.managed_default_content_settings.geolocation"; +const char kManagedDefaultNotificationsSetting[] = + "profile.managed_default_content_settings.notifications"; +const char kManagedDefaultMediaStreamSetting[] = + "profile.managed_default_content_settings.media_stream"; + +// Preferences that are exclusively used to store managed +// content settings patterns. +const char kManagedCookiesAllowedForUrls[] = + "profile.managed_cookies_allowed_for_urls"; +const char kManagedCookiesBlockedForUrls[] = + "profile.managed_cookies_blocked_for_urls"; +const char kManagedCookiesSessionOnlyForUrls[] = + "profile.managed_cookies_sessiononly_for_urls"; +const char kManagedImagesAllowedForUrls[] = + "profile.managed_images_allowed_for_urls"; +const char kManagedImagesBlockedForUrls[] = + "profile.managed_images_blocked_for_urls"; +const char kManagedJavaScriptAllowedForUrls[] = + "profile.managed_javascript_allowed_for_urls"; +const char kManagedJavaScriptBlockedForUrls[] = + "profile.managed_javascript_blocked_for_urls"; +const char kManagedPluginsAllowedForUrls[] = + "profile.managed_plugins_allowed_for_urls"; +const char kManagedPluginsBlockedForUrls[] = + "profile.managed_plugins_blocked_for_urls"; +const char kManagedPopupsAllowedForUrls[] = + "profile.managed_popups_allowed_for_urls"; +const char kManagedPopupsBlockedForUrls[] = + "profile.managed_popups_blocked_for_urls"; +const char kManagedNotificationsAllowedForUrls[] = + "profile.managed_notifications_allowed_for_urls"; +const char kManagedNotificationsBlockedForUrls[] = + "profile.managed_notifications_blocked_for_urls"; +const char kManagedAutoSelectCertificateForUrls[] = + "profile.managed_auto_select_certificate_for_urls"; + +} // namespace prefs diff --git a/components/content_settings/core/common/pref_names.h b/components/content_settings/core/common/pref_names.h new file mode 100644 index 0000000..6bc4f45 --- /dev/null +++ b/components/content_settings/core/common/pref_names.h @@ -0,0 +1,42 @@ +// 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. + +#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_PREF_NAMES_H_ +#define COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_PREF_NAMES_H_ + +namespace prefs { + +extern const char kContentSettingsVersion[]; +extern const char kContentSettingsPatternPairs[]; +extern const char kContentSettingsWindowLastTabIndex[]; +extern const char kDefaultContentSettings[]; +extern const char kOverrideContentSettings[]; + +extern const char kManagedDefaultCookiesSetting[]; +extern const char kManagedDefaultImagesSetting[]; +extern const char kManagedDefaultJavaScriptSetting[]; +extern const char kManagedDefaultPluginsSetting[]; +extern const char kManagedDefaultPopupsSetting[]; +extern const char kManagedDefaultGeolocationSetting[]; +extern const char kManagedDefaultNotificationsSetting[]; +extern const char kManagedDefaultMediaStreamSetting[]; + +extern const char kManagedCookiesAllowedForUrls[]; +extern const char kManagedCookiesBlockedForUrls[]; +extern const char kManagedCookiesSessionOnlyForUrls[]; +extern const char kManagedImagesAllowedForUrls[]; +extern const char kManagedImagesBlockedForUrls[]; +extern const char kManagedJavaScriptAllowedForUrls[]; +extern const char kManagedJavaScriptBlockedForUrls[]; +extern const char kManagedPluginsAllowedForUrls[]; +extern const char kManagedPluginsBlockedForUrls[]; +extern const char kManagedPopupsAllowedForUrls[]; +extern const char kManagedPopupsBlockedForUrls[]; +extern const char kManagedNotificationsAllowedForUrls[]; +extern const char kManagedNotificationsBlockedForUrls[]; +extern const char kManagedAutoSelectCertificateForUrls[]; + +} // namespace prefs + +#endif // COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_PREF_NAMES_H_ |