summaryrefslogtreecommitdiffstats
path: root/components/content_settings
diff options
context:
space:
mode:
authormukai <mukai@chromium.org>2014-10-25 10:53:16 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-25 17:53:36 +0000
commit8eaec82caaae926faedbfd7df0beb4979c3f6792 (patch)
tree2b34a3065ebc7bfc8ec242139e20fea4184ccde7 /components/content_settings
parent0b7b27587319dbc86e363501eb83ea99f39f10df (diff)
downloadchromium_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')
-rw-r--r--components/content_settings/core/browser/BUILD.gn20
-rw-r--r--components/content_settings/core/browser/DEPS2
-rw-r--r--components/content_settings/core/browser/content_settings_default_provider.cc340
-rw-r--r--components/content_settings/core/browser/content_settings_default_provider.h92
-rw-r--r--components/content_settings/core/browser/content_settings_mock_provider.cc46
-rw-r--r--components/content_settings/core/browser/content_settings_mock_provider.h59
-rw-r--r--components/content_settings/core/browser/content_settings_override_provider.cc130
-rw-r--r--components/content_settings/core/browser/content_settings_override_provider.h79
-rw-r--r--components/content_settings/core/browser/content_settings_policy_provider.cc495
-rw-r--r--components/content_settings/core/browser/content_settings_policy_provider.h82
-rw-r--r--components/content_settings/core/browser/content_settings_pref_provider.cc657
-rw-r--r--components/content_settings/core/browser/content_settings_pref_provider.h126
-rw-r--r--components/content_settings/core/browser/content_settings_provider_unittest.cc104
-rw-r--r--components/content_settings/core/browser/content_settings_utils.cc251
-rw-r--r--components/content_settings/core/browser/content_settings_utils.h94
-rw-r--r--components/content_settings/core/browser/content_settings_utils_unittest.cc45
-rw-r--r--components/content_settings/core/browser/host_content_settings_map.cc752
-rw-r--r--components/content_settings/core/browser/host_content_settings_map.h363
-rw-r--r--components/content_settings/core/common/BUILD.gn2
-rw-r--r--components/content_settings/core/common/pref_names.cc81
-rw-r--r--components/content_settings/core/common/pref_names.h42
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_