diff options
author | Kristian Monsen <kristianm@google.com> | 2011-06-09 11:47:42 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2011-06-29 14:33:03 +0100 |
commit | dc0f95d653279beabeb9817299e2902918ba123e (patch) | |
tree | 32eb121cd532053a5b9cb0c390331349af8d6baa /chrome/browser/content_settings | |
parent | ba160cd4054d13d0cb0b1b46e61c3bed67095811 (diff) | |
download | external_chromium-dc0f95d653279beabeb9817299e2902918ba123e.zip external_chromium-dc0f95d653279beabeb9817299e2902918ba123e.tar.gz external_chromium-dc0f95d653279beabeb9817299e2902918ba123e.tar.bz2 |
Merge Chromium at r11.0.696.0: Initial merge by git
Change-Id: I273dde2843af0839dfc08b419bb443fbd449532d
Diffstat (limited to 'chrome/browser/content_settings')
19 files changed, 1330 insertions, 634 deletions
diff --git a/chrome/browser/content_settings/content_settings_base_provider.cc b/chrome/browser/content_settings/content_settings_base_provider.cc new file mode 100644 index 0000000..b0e7ced --- /dev/null +++ b/chrome/browser/content_settings/content_settings_base_provider.cc @@ -0,0 +1,255 @@ +// 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 "chrome/browser/content_settings/content_settings_base_provider.h" + +#include "base/command_line.h" +#include "base/logging.h" +#include "chrome/common/chrome_switches.h" +#include "googleurl/src/gurl.h" +#include "net/base/net_util.h" + +namespace { + +// True if a given content settings type requires additional resource +// identifiers. +const bool kRequiresResourceIdentifier[CONTENT_SETTINGS_NUM_TYPES] = { + false, // CONTENT_SETTINGS_TYPE_COOKIES + false, // CONTENT_SETTINGS_TYPE_IMAGES + false, // CONTENT_SETTINGS_TYPE_JAVASCRIPT + true, // CONTENT_SETTINGS_TYPE_PLUGINS + false, // CONTENT_SETTINGS_TYPE_POPUPS + false, // Not used for Geolocation + false, // Not used for Notifications +}; + +} // namespace + +namespace content_settings { + +ExtendedContentSettings::ExtendedContentSettings() {} + +ExtendedContentSettings::ExtendedContentSettings( + const ExtendedContentSettings& rhs) + : content_settings(rhs.content_settings), + content_settings_for_resources(rhs.content_settings_for_resources) { +} + +ExtendedContentSettings::~ExtendedContentSettings() {} + +BaseProvider::BaseProvider(bool is_otr) + : is_off_the_record_(is_otr) { +} + +BaseProvider::~BaseProvider() {} + +bool BaseProvider::RequiresResourceIdentifier( + ContentSettingsType content_type) const { + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableResourceContentSettings)) { + return kRequiresResourceIdentifier[content_type]; + } else { + return false; + } +} + +bool BaseProvider::AllDefault( + const ExtendedContentSettings& settings) const { + for (size_t i = 0; i < arraysize(settings.content_settings.settings); ++i) { + if (settings.content_settings.settings[i] != CONTENT_SETTING_DEFAULT) + return false; + } + return settings.content_settings_for_resources.empty(); +} + +ContentSetting BaseProvider::GetContentSetting( + const GURL& requesting_url, + const GURL& embedding_url, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier) const { + // Support for embedding_patterns is not implemented yet. + DCHECK(requesting_url == embedding_url); + + if (!RequiresResourceIdentifier(content_type) || + (RequiresResourceIdentifier(content_type) && resource_identifier.empty())) + return GetNonDefaultContentSettings(requesting_url).settings[content_type]; + + // Resolve content settings with resource identifier. + // 1. Check for pattern that exactly match the url/host + // 1.1 In the content-settings-map + // 1.2 In the off_the_record content-settings-map + // 3. Shorten the url subdomain by subdomain and try to find a pattern in + // 3.1 OTR content-settings-map + // 3.2 content-settings-map + base::AutoLock auto_lock(lock_); + const std::string host(net::GetHostOrSpecFromURL(requesting_url)); + ContentSettingsTypeResourceIdentifierPair + requested_setting(content_type, resource_identifier); + + // Check for exact matches first. + HostContentSettings::const_iterator i(host_content_settings_.find(host)); + if (i != host_content_settings_.end() && + i->second.content_settings_for_resources.find(requested_setting) != + i->second.content_settings_for_resources.end()) { + return i->second.content_settings_for_resources.find( + requested_setting)->second; + } + + // If this map is not for an off-the-record profile, these searches will never + // match. The additional off-the-record exceptions always overwrite the + // regular ones. + i = off_the_record_settings_.find(host); + if (i != off_the_record_settings_.end() && + i->second.content_settings_for_resources.find(requested_setting) != + i->second.content_settings_for_resources.end()) { + return i->second.content_settings_for_resources.find( + requested_setting)->second; + } + + // Match patterns starting with the most concrete pattern match. + for (std::string key = + std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) { + HostContentSettings::const_iterator i(off_the_record_settings_.find(key)); + if (i != off_the_record_settings_.end() && + i->second.content_settings_for_resources.find(requested_setting) != + i->second.content_settings_for_resources.end()) { + return i->second.content_settings_for_resources.find( + requested_setting)->second; + } + + i = host_content_settings_.find(key); + if (i != host_content_settings_.end() && + i->second.content_settings_for_resources.find(requested_setting) != + i->second.content_settings_for_resources.end()) { + return i->second.content_settings_for_resources.find( + requested_setting)->second; + } + + const size_t next_dot = + key.find('.', ContentSettingsPattern::kDomainWildcardLength); + if (next_dot == std::string::npos) + break; + key.erase(ContentSettingsPattern::kDomainWildcardLength, + next_dot - ContentSettingsPattern::kDomainWildcardLength + 1); + } + + return CONTENT_SETTING_DEFAULT; +} + +void BaseProvider::GetAllContentSettingsRules( + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + Rules* content_setting_rules) const { + DCHECK(content_setting_rules); + content_setting_rules->clear(); + + const HostContentSettings* map_to_return = + is_off_the_record_ ? &off_the_record_settings_ : &host_content_settings_; + ContentSettingsTypeResourceIdentifierPair requested_setting( + content_type, resource_identifier); + + base::AutoLock auto_lock(lock_); + for (HostContentSettings::const_iterator i(map_to_return->begin()); + i != map_to_return->end(); ++i) { + ContentSetting setting; + if (RequiresResourceIdentifier(content_type)) { + if (i->second.content_settings_for_resources.find(requested_setting) != + i->second.content_settings_for_resources.end()) { + setting = i->second.content_settings_for_resources.find( + requested_setting)->second; + } else { + setting = CONTENT_SETTING_DEFAULT; + } + } else { + setting = i->second.content_settings.settings[content_type]; + } + if (setting != CONTENT_SETTING_DEFAULT) { + // Use of push_back() relies on the map iterator traversing in order of + // ascending keys. + content_setting_rules->push_back(Rule(ContentSettingsPattern(i->first), + ContentSettingsPattern(i->first), + setting)); + } + } +} + +ContentSettings BaseProvider::GetNonDefaultContentSettings( + const GURL& url) const { + base::AutoLock auto_lock(lock_); + + const std::string host(net::GetHostOrSpecFromURL(url)); + ContentSettings output; + for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) + output.settings[j] = CONTENT_SETTING_DEFAULT; + + // Check for exact matches first. + HostContentSettings::const_iterator i(host_content_settings_.find(host)); + if (i != host_content_settings_.end()) + output = i->second.content_settings; + + // If this map is not for an off-the-record profile, these searches will never + // match. The additional off-the-record exceptions always overwrite the + // regular ones. + i = off_the_record_settings_.find(host); + if (i != off_the_record_settings_.end()) { + for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) + if (i->second.content_settings.settings[j] != CONTENT_SETTING_DEFAULT) + output.settings[j] = i->second.content_settings.settings[j]; + } + + // Match patterns starting with the most concrete pattern match. + for (std::string key = + std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) { + HostContentSettings::const_iterator i(off_the_record_settings_.find(key)); + if (i != off_the_record_settings_.end()) { + for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) { + if (output.settings[j] == CONTENT_SETTING_DEFAULT) + output.settings[j] = i->second.content_settings.settings[j]; + } + } + i = host_content_settings_.find(key); + if (i != host_content_settings_.end()) { + for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) { + if (output.settings[j] == CONTENT_SETTING_DEFAULT) + output.settings[j] = i->second.content_settings.settings[j]; + } + } + const size_t next_dot = + key.find('.', ContentSettingsPattern::kDomainWildcardLength); + if (next_dot == std::string::npos) + break; + key.erase(ContentSettingsPattern::kDomainWildcardLength, + next_dot - ContentSettingsPattern::kDomainWildcardLength + 1); + } + + return output; +} + +void BaseProvider::UpdateContentSettingsMap( + const ContentSettingsPattern& requesting_pattern, + const ContentSettingsPattern& embedding_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + ContentSetting content_setting) { + std::string pattern_str(requesting_pattern.CanonicalizePattern()); + HostContentSettings* content_settings_map = host_content_settings(); + ExtendedContentSettings& extended_settings = + (*content_settings_map)[pattern_str]; + extended_settings.content_settings.settings[content_type] = content_setting; +} + +// static +ContentSetting BaseProvider::ClickToPlayFixup(ContentSettingsType content_type, + ContentSetting setting) { + if (setting == CONTENT_SETTING_ASK && + content_type == CONTENT_SETTINGS_TYPE_PLUGINS && + !CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableClickToPlay)) { + return CONTENT_SETTING_BLOCK; + } + return setting; +} + +} // namespace content_settings diff --git a/chrome/browser/content_settings/content_settings_base_provider.h b/chrome/browser/content_settings/content_settings_base_provider.h new file mode 100644 index 0000000..1e6c9e4 --- /dev/null +++ b/chrome/browser/content_settings/content_settings_base_provider.h @@ -0,0 +1,134 @@ +// 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 CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_BASE_PROVIDER_H_ +#define CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_BASE_PROVIDER_H_ +#pragma once + +#include <map> +#include <string> +#include <utility> + +#include "base/synchronization/lock.h" +#include "chrome/browser/content_settings/content_settings_provider.h" + +namespace content_settings { + +typedef std::pair<ContentSettingsType, std::string> + ContentSettingsTypeResourceIdentifierPair; +typedef std::map<ContentSettingsTypeResourceIdentifierPair, ContentSetting> + ResourceContentSettings; + +struct ExtendedContentSettings { + ExtendedContentSettings(); + ExtendedContentSettings(const ExtendedContentSettings& rhs); + ~ExtendedContentSettings(); + + ContentSettings content_settings; + ResourceContentSettings content_settings_for_resources; +}; + +// Map for ContentSettings. +typedef std::map<std::string, ExtendedContentSettings> HostContentSettings; + +// BaseProvider is the abstract base class for all content-settings-provider +// classes. +class BaseProvider : public ProviderInterface { + public: + // Maps CONTENT_SETTING_ASK for the CONTENT_SETTINGS_TYPE_PLUGINS to + // CONTENT_SETTING_BLOCK if click-to-play is not enabled. + static ContentSetting ClickToPlayFixup(ContentSettingsType content_type, + ContentSetting setting); + + explicit BaseProvider(bool is_otr); + virtual ~BaseProvider(); + + + // Initializes the Provider. + virtual void Init() = 0; + + // ProviderInterface Implementation + virtual bool ContentSettingsTypeIsManaged( + ContentSettingsType content_type) = 0; + + virtual ContentSetting GetContentSetting( + const GURL& requesting_url, + const GURL& embedding_url, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier) const; + + virtual void SetContentSetting( + const ContentSettingsPattern& requesting_pattern, + const ContentSettingsPattern& embedding_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + ContentSetting content_setting) = 0; + + virtual void GetAllContentSettingsRules( + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + Rules* content_setting_rules) const; + + virtual void ClearAllContentSettingsRules( + ContentSettingsType content_type) = 0; + + virtual void ResetToDefaults() = 0; + + protected: + // Returns true if the |content_type| requires a resource identifier. + bool RequiresResourceIdentifier( + ContentSettingsType content_type) const; + + // Returns true if the passed |settings| object contains only + // CONTENT_SETTING_DEFAULT values. + bool AllDefault(const ExtendedContentSettings& settings) const; + + void UpdateContentSettingsMap( + const ContentSettingsPattern& requesting_pattern, + const ContentSettingsPattern& embedding_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + ContentSetting content_setting); + + // TODO(markusheintz): LEGACY method. Will be removed in a future re-factoring + // step. + ContentSettings GetNonDefaultContentSettings(const GURL& url) const; + + // Accessors + HostContentSettings* host_content_settings() { + return &host_content_settings_; + } + + HostContentSettings* off_the_record_settings() { + return &off_the_record_settings_; + } + + base::Lock& lock() const { + return lock_; + } + + bool is_off_the_record() const { + return is_off_the_record_; + } + + private: + // Copies of the pref data, so that we can read it on threads other than the + // UI thread. + HostContentSettings host_content_settings_; + + // Whether this settings map is for an OTR session. + bool is_off_the_record_; + + // Differences to the preference-stored host content settings for + // off-the-record settings. + HostContentSettings off_the_record_settings_; + + // Used around accesses to the content_settings_ object to guarantee + // thread safety. + mutable base::Lock lock_; +}; + +} // namespace content_settings + +#endif // CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_BASE_PROVIDER_H_ diff --git a/chrome/browser/content_settings/mock_content_settings_provider.cc b/chrome/browser/content_settings/content_settings_mock_provider.cc index f73280f..c166dd6 100644 --- a/chrome/browser/content_settings/mock_content_settings_provider.cc +++ b/chrome/browser/content_settings/content_settings_mock_provider.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/content_settings/mock_content_settings_provider.h" +#include "chrome/browser/content_settings/content_settings_mock_provider.h" namespace content_settings { @@ -46,20 +46,23 @@ MockProvider::MockProvider() content_type_(CONTENT_SETTINGS_TYPE_COOKIES), resource_identifier_(""), setting_(CONTENT_SETTING_DEFAULT), - read_only_(false) {} + read_only_(false), + is_managed_(false) {} MockProvider::MockProvider(ContentSettingsPattern requesting_url_pattern, ContentSettingsPattern embedding_url_pattern, ContentSettingsType content_type, ResourceIdentifier resource_identifier, ContentSetting setting, - bool read_only) + bool read_only, + bool is_managed) : requesting_url_pattern_(requesting_url_pattern), embedding_url_pattern_(embedding_url_pattern), content_type_(content_type), resource_identifier_(resource_identifier), setting_(setting), - read_only_(read_only) {} + read_only_(read_only), + is_managed_(is_managed) {} MockProvider::~MockProvider() {} @@ -91,4 +94,11 @@ void MockProvider::SetContentSetting( setting_ = content_setting; } +bool MockProvider::ContentSettingsTypeIsManaged(ContentSettingsType type) { + if (type == content_type_) { + return is_managed_; + } + return false; +} + } // namespace content_settings diff --git a/chrome/browser/content_settings/mock_content_settings_provider.h b/chrome/browser/content_settings/content_settings_mock_provider.h index 4393868..17ced25 100644 --- a/chrome/browser/content_settings/mock_content_settings_provider.h +++ b/chrome/browser/content_settings/content_settings_mock_provider.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CONTENT_SETTINGS_MOCK_CONTENT_SETTINGS_PROVIDER_H_ -#define CHROME_BROWSER_CONTENT_SETTINGS_MOCK_CONTENT_SETTINGS_PROVIDER_H_ +#ifndef CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_MOCK_PROVIDER_H_ +#define CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_MOCK_PROVIDER_H_ #pragma once #include "base/basictypes.h" @@ -49,9 +49,12 @@ class MockProvider : public ProviderInterface { ContentSettingsType content_type, ResourceIdentifier resource_identifier, ContentSetting setting, - bool read_only); + bool read_only, + bool is_managed); virtual ~MockProvider(); + virtual bool ContentSettingsTypeIsManaged(ContentSettingsType type); + // ProviderInterface implementation virtual ContentSetting GetContentSetting( const GURL& requesting_url, @@ -83,7 +86,7 @@ class MockProvider : public ProviderInterface { requesting_url_pattern_ = pattern; } - ContentSettingsPattern requesting_url_pattern() { + ContentSettingsPattern requesting_url_pattern() const { return requesting_url_pattern_; } @@ -91,7 +94,7 @@ class MockProvider : public ProviderInterface { embedding_url_pattern_ = pattern; } - ContentSettingsPattern embedding_url_pattern() { + ContentSettingsPattern embedding_url_pattern() const { return embedding_url_pattern_; } @@ -99,7 +102,7 @@ class MockProvider : public ProviderInterface { content_type_ = content_type; } - ContentSettingsType content_type() { + ContentSettingsType content_type() const { return content_type_; } @@ -107,7 +110,7 @@ class MockProvider : public ProviderInterface { resource_identifier_ = resource_identifier; } - ResourceIdentifier resource_identifier() { + ResourceIdentifier resource_identifier() const { return resource_identifier_; } @@ -115,7 +118,7 @@ class MockProvider : public ProviderInterface { setting_ = setting; } - ContentSetting setting() { + ContentSetting setting() const { return setting_; } @@ -123,10 +126,18 @@ class MockProvider : public ProviderInterface { read_only_ = read_only; } - bool read_only() { + bool read_only() const { return read_only_; } + void set_is_managed(bool is_managed) { + is_managed_ = is_managed; + } + + bool is_managed() const { + return is_managed_; + } + private: ContentSettingsPattern requesting_url_pattern_; ContentSettingsPattern embedding_url_pattern_; @@ -134,10 +145,11 @@ class MockProvider : public ProviderInterface { ResourceIdentifier resource_identifier_; ContentSetting setting_; bool read_only_; + bool is_managed_; DISALLOW_COPY_AND_ASSIGN(MockProvider); }; } // namespace content_settings -#endif // CHROME_BROWSER_CONTENT_SETTINGS_MOCK_CONTENT_SETTINGS_PROVIDER_H_ +#endif // CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_MOCK_PROVIDER_H_ diff --git a/chrome/browser/content_settings/content_settings_pattern.cc b/chrome/browser/content_settings/content_settings_pattern.cc index ba93ff4..ef759a8 100644 --- a/chrome/browser/content_settings/content_settings_pattern.cc +++ b/chrome/browser/content_settings/content_settings_pattern.cc @@ -5,10 +5,20 @@ #include "chrome/browser/content_settings/content_settings_pattern.h" #include "base/string_util.h" +#include "chrome/common/url_constants.h" #include "net/base/net_util.h" #include "googleurl/src/gurl.h" #include "googleurl/src/url_canon.h" +namespace { +bool IsValidHostlessPattern(const std::string& pattern) { + std::string file_scheme_plus_separator(chrome::kFileScheme); + file_scheme_plus_separator += chrome::kStandardSchemeSeparator; + + return StartsWithASCII(pattern, file_scheme_plus_separator, false); +} +} // namespace + // The version of the pattern format implemented. Version 1 includes the // following patterns: // - [*.]domain.tld (matches domain.tld and all sub-domains) @@ -40,6 +50,9 @@ bool ContentSettingsPattern::IsValid() const { if (pattern_.empty()) return false; + if (IsValidHostlessPattern(pattern_)) + return true; + const std::string host(pattern_.length() > kDomainWildcardLength && StartsWithASCII(pattern_, kDomainWildcard, false) ? pattern_.substr(kDomainWildcardLength) : @@ -67,9 +80,11 @@ bool ContentSettingsPattern::Matches(const GURL& url) const { } std::string ContentSettingsPattern::CanonicalizePattern() const { - if (!IsValid()) { + if (!IsValid()) return ""; - } + + if (IsValidHostlessPattern(pattern_)) + return GURL(pattern_).spec(); bool starts_with_wildcard = pattern_.length() > kDomainWildcardLength && StartsWithASCII(pattern_, kDomainWildcard, false); diff --git a/chrome/browser/content_settings/content_settings_pattern_unittest.cc b/chrome/browser/content_settings/content_settings_pattern_unittest.cc index 88b42dc..4882e34 100644 --- a/chrome/browser/content_settings/content_settings_pattern_unittest.cc +++ b/chrome/browser/content_settings/content_settings_pattern_unittest.cc @@ -14,6 +14,7 @@ TEST(ContentSettingsPatternTest, PatternSupport) { EXPECT_TRUE(ContentSettingsPattern("example.com").IsValid()); EXPECT_TRUE(ContentSettingsPattern("192.168.0.1").IsValid()); EXPECT_TRUE(ContentSettingsPattern("[::1]").IsValid()); + EXPECT_TRUE(ContentSettingsPattern("file:///tmp/test.html").IsValid()); EXPECT_FALSE(ContentSettingsPattern("*example.com").IsValid()); EXPECT_FALSE(ContentSettingsPattern("example.*").IsValid()); EXPECT_FALSE(ContentSettingsPattern("http://example.com").IsValid()); @@ -24,12 +25,18 @@ TEST(ContentSettingsPatternTest, PatternSupport) { GURL("http://www.example.com/"))); EXPECT_TRUE(ContentSettingsPattern("www.example.com").Matches( GURL("http://www.example.com/"))); + EXPECT_TRUE(ContentSettingsPattern("file:///tmp/test.html").Matches( + GURL("file:///tmp/test.html"))); EXPECT_FALSE(ContentSettingsPattern("").Matches( GURL("http://www.example.com/"))); EXPECT_FALSE(ContentSettingsPattern("[*.]example.com").Matches( GURL("http://example.org/"))); EXPECT_FALSE(ContentSettingsPattern("example.com").Matches( GURL("http://example.org/"))); + EXPECT_FALSE(ContentSettingsPattern("file:///tmp/test.html").Matches( + GURL("file:///tmp/other.html"))); + EXPECT_FALSE(ContentSettingsPattern("file:///tmp/test.html").Matches( + GURL("http://example.org/"))); } TEST(ContentSettingsPatternTest, CanonicalizePattern) { @@ -42,19 +49,21 @@ TEST(ContentSettingsPatternTest, CanonicalizePattern) { .CanonicalizePattern().c_str()); EXPECT_STREQ("[::1]", ContentSettingsPattern("[::1]") .CanonicalizePattern().c_str()); - // IsValid returns false for file:/// patterns. - EXPECT_STREQ("", ContentSettingsPattern( - "file:///temp/file.html").CanonicalizePattern().c_str()); + EXPECT_STREQ("file:///tmp/file.html", ContentSettingsPattern( + "file:///tmp/file.html").CanonicalizePattern().c_str()); // UTF-8 patterns. EXPECT_STREQ("[*.]xn--ira-ppa.com", ContentSettingsPattern( "[*.]\xC4\x87ira.com").CanonicalizePattern().c_str()); EXPECT_STREQ("xn--ira-ppa.com", ContentSettingsPattern( "\xC4\x87ira.com").CanonicalizePattern().c_str()); - // IsValid returns false for file:/// patterns. - EXPECT_STREQ("", ContentSettingsPattern( + EXPECT_STREQ("file:///%C4%87ira.html", ContentSettingsPattern( "file:///\xC4\x87ira.html").CanonicalizePattern().c_str()); + // file:/// normalization. + EXPECT_STREQ("file:///tmp/test.html", ContentSettingsPattern( + "file:///tmp/bar/../test.html").CanonicalizePattern().c_str()); + // Invalid patterns. EXPECT_STREQ("", ContentSettingsPattern( "*example.com").CanonicalizePattern().c_str()); diff --git a/chrome/browser/content_settings/content_settings_policy_provider.cc b/chrome/browser/content_settings/content_settings_policy_provider.cc new file mode 100644 index 0000000..a8ab96a --- /dev/null +++ b/chrome/browser/content_settings/content_settings_policy_provider.cc @@ -0,0 +1,482 @@ +// Copyright (c) 2010 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 "chrome/browser/content_settings/content_settings_policy_provider.h" + +#include <string> +#include <vector> + +#include "base/command_line.h" +#include "chrome/browser/content_settings/content_settings_details.h" +#include "chrome/browser/content_settings/content_settings_pattern.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/prefs/scoped_user_pref_update.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/notification_details.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_source.h" +#include "chrome/common/pref_names.h" +#include "content/browser/browser_thread.h" +#include "webkit/plugins/npapi/plugin_group.h" +#include "webkit/plugins/npapi/plugin_list.h" + +namespace { + +// Base pref path of the prefs that contain the managed default content +// settings values. +const std::string kManagedSettings = + "profile.managed_default_content_settings"; + +// The preferences used to manage ContentSettingsTypes. +const char* kPrefToManageType[CONTENT_SETTINGS_NUM_TYPES] = { + prefs::kManagedDefaultCookiesSetting, + prefs::kManagedDefaultImagesSetting, + prefs::kManagedDefaultJavaScriptSetting, + prefs::kManagedDefaultPluginsSetting, + prefs::kManagedDefaultPopupsSetting, + NULL, // Not used for Geolocation + NULL, // Not used for Notifications +}; + +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 + } +}; + +const std::string NO_IDENTIFIER = ""; + +} // namespace + +namespace content_settings { + +PolicyDefaultProvider::PolicyDefaultProvider(Profile* profile) + : profile_(profile), + is_off_the_record_(profile_->IsOffTheRecord()) { + PrefService* prefs = profile->GetPrefs(); + + // Read global defaults. + DCHECK_EQ(arraysize(kPrefToManageType), + static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); + ReadManagedDefaultSettings(); + + pref_change_registrar_.Init(prefs); + // 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 perferences 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 excpetions + // (patterns) for this type are ignored. + pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, this); + notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, + Source<Profile>(profile_)); +} + +PolicyDefaultProvider::~PolicyDefaultProvider() { + UnregisterObservers(); +} + +ContentSetting PolicyDefaultProvider::ProvideDefaultSetting( + ContentSettingsType content_type) const { + base::AutoLock auto_lock(lock_); + return managed_default_content_settings_.settings[content_type]; +} + +void PolicyDefaultProvider::UpdateDefaultSetting( + ContentSettingsType content_type, + ContentSetting setting) { +} + +bool PolicyDefaultProvider::DefaultSettingIsManaged( + ContentSettingsType content_type) const { + base::AutoLock lock(lock_); + if (managed_default_content_settings_.settings[content_type] != + CONTENT_SETTING_DEFAULT) { + return true; + } else { + return false; + } +} + +void PolicyDefaultProvider::ResetToDefaults() { +} + +void PolicyDefaultProvider::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (type == NotificationType::PREF_CHANGED) { + DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr()); + std::string* name = Details<std::string>(details).ptr(); + 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 { + NOTREACHED() << "Unexpected preference observed"; + return; + } + + if (!is_off_the_record_) { + NotifyObservers(ContentSettingsDetails( + ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, "")); + } + } else if (type == NotificationType::PROFILE_DESTROYED) { + DCHECK_EQ(profile_, Source<Profile>(source).ptr()); + UnregisterObservers(); + } else { + NOTREACHED() << "Unexpected notification"; + } +} + +void PolicyDefaultProvider::UnregisterObservers() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!profile_) + return; + pref_change_registrar_.RemoveAll(); + notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED, + Source<Profile>(profile_)); + profile_ = NULL; +} + + +void PolicyDefaultProvider::NotifyObservers( + const ContentSettingsDetails& details) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (profile_ == NULL) + return; + NotificationService::current()->Notify( + NotificationType::CONTENT_SETTINGS_CHANGED, + Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()), + Details<const ContentSettingsDetails>(&details)); +} + +void PolicyDefaultProvider::ReadManagedDefaultSettings() { + for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) { + if (kPrefToManageType[type] == NULL) { + continue; + } + UpdateManagedDefaultSetting(ContentSettingsType(type)); + } +} + +void PolicyDefaultProvider::UpdateManagedDefaultSetting( + ContentSettingsType 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. + PrefService* prefs = profile_->GetPrefs(); + DCHECK(!prefs->HasPrefPath(kPrefToManageType[type]) || + prefs->IsManagedPreference(kPrefToManageType[type])); + base::AutoLock auto_lock(lock_); + managed_default_content_settings_.settings[type] = IntToContentSetting( + prefs->GetInteger(kPrefToManageType[type])); +} + +// static +void PolicyDefaultProvider::RegisterUserPrefs(PrefService* prefs) { + // Preferences for default content setting policies. A policy is not set of + // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT. + prefs->RegisterIntegerPref(prefs::kManagedDefaultCookiesSetting, + CONTENT_SETTING_DEFAULT); + prefs->RegisterIntegerPref(prefs::kManagedDefaultImagesSetting, + CONTENT_SETTING_DEFAULT); + prefs->RegisterIntegerPref(prefs::kManagedDefaultJavaScriptSetting, + CONTENT_SETTING_DEFAULT); + prefs->RegisterIntegerPref(prefs::kManagedDefaultPluginsSetting, + CONTENT_SETTING_DEFAULT); + prefs->RegisterIntegerPref(prefs::kManagedDefaultPopupsSetting, + CONTENT_SETTING_DEFAULT); +} + +// //////////////////////////////////////////////////////////////////////////// +// PolicyProvider + +// static +void PolicyProvider::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterListPref(prefs::kManagedCookiesAllowedForUrls); + prefs->RegisterListPref(prefs::kManagedCookiesBlockedForUrls); + prefs->RegisterListPref(prefs::kManagedCookiesSessionOnlyForUrls); + prefs->RegisterListPref(prefs::kManagedImagesAllowedForUrls); + prefs->RegisterListPref(prefs::kManagedImagesBlockedForUrls); + prefs->RegisterListPref(prefs::kManagedJavaScriptAllowedForUrls); + prefs->RegisterListPref(prefs::kManagedJavaScriptBlockedForUrls); + prefs->RegisterListPref(prefs::kManagedPluginsAllowedForUrls); + prefs->RegisterListPref(prefs::kManagedPluginsBlockedForUrls); + prefs->RegisterListPref(prefs::kManagedPopupsAllowedForUrls); + prefs->RegisterListPref(prefs::kManagedPopupsBlockedForUrls); +} + +PolicyProvider::PolicyProvider(Profile* profile) + : BaseProvider(profile->IsOffTheRecord()), + profile_(profile) { + Init(); +} + +PolicyProvider::~PolicyProvider() { + UnregisterObservers(); +} + +void PolicyProvider::ReadManagedContentSettingsTypes( + ContentSettingsType content_type) { + PrefService* prefs = profile_->GetPrefs(); + if (kPrefToManageType[content_type] == NULL) { + content_type_is_managed_[content_type] = false; + } else { + content_type_is_managed_[content_type] = + prefs->IsManagedPreference(kPrefToManageType[content_type]); + } +} + +void PolicyProvider::Init() { + PrefService* prefs = profile_->GetPrefs(); + + ReadManagedContentSettings(false); + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) + ReadManagedContentSettingsTypes(ContentSettingsType(i)); + + pref_change_registrar_.Init(prefs); + pref_change_registrar_.Add(prefs::kManagedCookiesBlockedForUrls, this); + pref_change_registrar_.Add(prefs::kManagedCookiesAllowedForUrls, this); + pref_change_registrar_.Add(prefs::kManagedCookiesSessionOnlyForUrls, this); + pref_change_registrar_.Add(prefs::kManagedImagesBlockedForUrls, this); + pref_change_registrar_.Add(prefs::kManagedImagesAllowedForUrls, this); + pref_change_registrar_.Add(prefs::kManagedJavaScriptBlockedForUrls, this); + pref_change_registrar_.Add(prefs::kManagedJavaScriptAllowedForUrls, this); + pref_change_registrar_.Add(prefs::kManagedPluginsBlockedForUrls, this); + pref_change_registrar_.Add(prefs::kManagedPluginsAllowedForUrls, this); + pref_change_registrar_.Add(prefs::kManagedPopupsBlockedForUrls, this); + pref_change_registrar_.Add(prefs::kManagedPopupsAllowedForUrls, this); + + pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, this); + + notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, + Source<Profile>(profile_)); +} + +bool PolicyProvider::ContentSettingsTypeIsManaged( + ContentSettingsType content_type) { + return content_type_is_managed_[content_type]; +} + +void PolicyProvider::GetContentSettingsFromPreferences( + PrefService* prefs, + ContentSettingsRules* rules) { + 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->IsManaged()); + DCHECK_EQ(Value::TYPE_LIST, pref->GetType()); + + const ListValue* pattern_str_list = + static_cast<const ListValue*>(pref->GetValue()); + for (size_t j = 0; j < pattern_str_list->GetSize(); ++j) { + std::string original_pattern_str; + pattern_str_list->GetString(j, &original_pattern_str); + ContentSettingsPattern pattern(original_pattern_str); + // Ignore invalid patterns. + if (!pattern.IsValid()) { + VLOG(1) << "Ignoring invalid content settings pattern: " << + pattern.AsString(); + continue; + } + rules->push_back(MakeTuple( + pattern, + pattern, + kPrefsForManagedContentSettingsMap[i].content_type, + NO_IDENTIFIER, + kPrefsForManagedContentSettingsMap[i].setting)); + } + } +} + +void PolicyProvider::ReadManagedContentSettings(bool overwrite) { + ContentSettingsRules rules; + PrefService* prefs = profile_->GetPrefs(); + GetContentSettingsFromPreferences(prefs, &rules); + { + base::AutoLock auto_lock(lock()); + HostContentSettings* content_settings_map = host_content_settings(); + if (overwrite) + content_settings_map->clear(); + for (ContentSettingsRules::iterator rule = rules.begin(); + rule != rules.end(); + ++rule) { + DispatchToMethod(this, &PolicyProvider::UpdateContentSettingsMap, *rule); + } + } +} + +// Since the PolicyProvider is a read only content settings provider, all +// methodes of the ProviderInterface that set or delete any settings do nothing. +void PolicyProvider::SetContentSetting( + const ContentSettingsPattern& requesting_pattern, + const ContentSettingsPattern& embedding_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + ContentSetting content_setting) { +} + +ContentSetting PolicyProvider::GetContentSetting( + const GURL& requesting_url, + const GURL& embedding_url, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier) const { + return BaseProvider::GetContentSetting( + requesting_url, + embedding_url, + content_type, + NO_IDENTIFIER); +} + +void PolicyProvider::ClearAllContentSettingsRules( + ContentSettingsType content_type) { +} + +void PolicyProvider::ResetToDefaults() { +} + +void PolicyProvider::UnregisterObservers() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!profile_) + return; + pref_change_registrar_.RemoveAll(); + notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED, + Source<Profile>(profile_)); + profile_ = NULL; +} + +void PolicyProvider::NotifyObservers( + const ContentSettingsDetails& details) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (profile_ == NULL) + return; + NotificationService::current()->Notify( + NotificationType::CONTENT_SETTINGS_CHANGED, + Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()), + Details<const ContentSettingsDetails>(&details)); +} + +void PolicyProvider::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (type == NotificationType::PREF_CHANGED) { + DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr()); + std::string* name = Details<std::string>(details).ptr(); + if (*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) { + ReadManagedContentSettings(true); + NotifyObservers(ContentSettingsDetails( + ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, "")); + // We do not want to sent a notification when managed default content + // settings change. The DefaultProvider will take care of that. We are + // only a passive observer. + // TODO(markusheintz): NOTICE: This is still work in progress and part of + // a larger refactoring. The code will change and be much cleaner and + // clearer in the end. + } else if (*name == prefs::kManagedDefaultCookiesSetting) { + ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_COOKIES); + } else if (*name == prefs::kManagedDefaultImagesSetting) { + ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_IMAGES); + } else if (*name == prefs::kManagedDefaultJavaScriptSetting) { + ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_JAVASCRIPT); + } else if (*name == prefs::kManagedDefaultPluginsSetting) { + ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_PLUGINS); + } else if (*name == prefs::kManagedDefaultPopupsSetting) { + ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_POPUPS); + } + } else if (type == NotificationType::PROFILE_DESTROYED) { + DCHECK_EQ(profile_, Source<Profile>(source).ptr()); + UnregisterObservers(); + } else { + NOTREACHED() << "Unexpected notification"; + } +} + +} // namespace content_settings diff --git a/chrome/browser/content_settings/policy_content_settings_provider.h b/chrome/browser/content_settings/content_settings_policy_provider.h index b63e19b..96dd115 100644 --- a/chrome/browser/content_settings/policy_content_settings_provider.h +++ b/chrome/browser/content_settings/content_settings_policy_provider.h @@ -2,15 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CONTENT_SETTINGS_POLICY_CONTENT_SETTINGS_PROVIDER_H_ -#define CHROME_BROWSER_CONTENT_SETTINGS_POLICY_CONTENT_SETTINGS_PROVIDER_H_ +#ifndef CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_POLICY_PROVIDER_H_ +#define CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_POLICY_PROVIDER_H_ #pragma once // A content settings provider that takes its settings out of policies. +#include <vector> + #include "base/basictypes.h" #include "base/synchronization/lock.h" +#include "base/tuple.h" #include "chrome/browser/content_settings/content_settings_provider.h" +#include "chrome/browser/content_settings/content_settings_base_provider.h" #include "chrome/browser/prefs/pref_change_registrar.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" @@ -76,6 +80,75 @@ class PolicyDefaultProvider : public DefaultProviderInterface, DISALLOW_COPY_AND_ASSIGN(PolicyDefaultProvider); }; +// PolicyProvider that provider managed content-settings. +class PolicyProvider : public BaseProvider, + public NotificationObserver { + public: + explicit PolicyProvider(Profile* profile); + ~PolicyProvider(); + static void RegisterUserPrefs(PrefService* prefs); + + // BaseProvider Implementation + virtual void Init(); + + // ProviderInterface Implementation + virtual bool ContentSettingsTypeIsManaged( + ContentSettingsType content_type); + + virtual void SetContentSetting( + const ContentSettingsPattern& requesting_pattern, + const ContentSettingsPattern& embedding_pattern, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier, + ContentSetting content_setting); + + virtual ContentSetting GetContentSetting( + const GURL& requesting_url, + const GURL& embedding_url, + ContentSettingsType content_type, + const ResourceIdentifier& resource_identifier) const; + + virtual void ClearAllContentSettingsRules( + ContentSettingsType content_type); + + virtual void ResetToDefaults(); + + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + private: + typedef Tuple5< + ContentSettingsPattern, + ContentSettingsPattern, + ContentSettingsType, + content_settings::ProviderInterface::ResourceIdentifier, + ContentSetting> ContentSettingsRule; + + typedef std::vector<ContentSettingsRule> ContentSettingsRules; + + void ReadManagedContentSettings(bool overwrite); + + void GetContentSettingsFromPreferences(PrefService* prefs, + ContentSettingsRules* rules); + + void ReadManagedContentSettingsTypes( + ContentSettingsType content_type); + + void NotifyObservers(const ContentSettingsDetails& details); + + void UnregisterObservers(); + + Profile* profile_; + + bool content_type_is_managed_[CONTENT_SETTINGS_NUM_TYPES]; + + PrefChangeRegistrar pref_change_registrar_; + NotificationRegistrar notification_registrar_; + + DISALLOW_COPY_AND_ASSIGN(PolicyProvider); +}; + } // namespace content_settings -#endif // CHROME_BROWSER_CONTENT_SETTINGS_POLICY_CONTENT_SETTINGS_PROVIDER_H_ +#endif // CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_POLICY_PROVIDER_H_ diff --git a/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc b/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc new file mode 100644 index 0000000..1d1053c --- /dev/null +++ b/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc @@ -0,0 +1,185 @@ +// Copyright (c) 2010 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 "chrome/browser/content_settings/content_settings_policy_provider.h" + +#include "base/auto_reset.h" +#include "base/command_line.h" +#include "chrome/browser/content_settings/stub_settings_observer.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/testing_browser_process_test.h" +#include "chrome/test/testing_pref_service.h" +#include "chrome/test/testing_profile.h" +#include "content/browser/browser_thread.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "googleurl/src/gurl.h" + +namespace content_settings { + +class PolicyDefaultProviderTest : public TestingBrowserProcessTest { + public: + PolicyDefaultProviderTest() + : ui_thread_(BrowserThread::UI, &message_loop_) { + } + + protected: + MessageLoop message_loop_; + BrowserThread ui_thread_; +}; + +TEST_F(PolicyDefaultProviderTest, DefaultValues) { + TestingProfile profile; + PolicyDefaultProvider provider(&profile); + TestingPrefService* prefs = profile.GetTestingPrefService(); + + // By default, policies should be off. + ASSERT_FALSE( + provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES)); + + // Set managed-default-content-setting through the coresponding preferences. + prefs->SetManagedPref(prefs::kManagedDefaultCookiesSetting, + Value::CreateIntegerValue(CONTENT_SETTING_BLOCK)); + ASSERT_TRUE( + provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES)); + ASSERT_EQ(CONTENT_SETTING_BLOCK, + provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES)); + + // Remove managed-default-content-settings-preferences. + prefs->RemoveManagedPref(prefs::kManagedDefaultCookiesSetting); + ASSERT_FALSE( + provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES)); +} + +// When a default-content-setting is set to a managed setting a +// CONTENT_SETTINGS_CHANGED notification should be fired. The same should happen +// if the managed setting is removed. +TEST_F(PolicyDefaultProviderTest, ObserveManagedSettingsChange) { + TestingProfile profile; + StubSettingsObserver observer; + // Make sure the content settings map exists. + profile.GetHostContentSettingsMap(); + TestingPrefService* prefs = profile.GetTestingPrefService(); + + // Set the managed default-content-setting. + prefs->SetManagedPref(prefs::kManagedDefaultImagesSetting, + Value::CreateIntegerValue(CONTENT_SETTING_BLOCK)); + EXPECT_EQ(profile.GetHostContentSettingsMap(), observer.last_notifier); + EXPECT_EQ(ContentSettingsPattern(), observer.last_pattern); + EXPECT_EQ(CONTENT_SETTINGS_TYPE_DEFAULT, observer.last_type); + EXPECT_TRUE(observer.last_update_all); + EXPECT_TRUE(observer.last_update_all_types); + EXPECT_EQ(1, observer.counter); + + // Remove the managed default-content-setting. + prefs->RemoveManagedPref(prefs::kManagedDefaultImagesSetting); + EXPECT_EQ(profile.GetHostContentSettingsMap(), observer.last_notifier); + EXPECT_EQ(CONTENT_SETTINGS_TYPE_DEFAULT, observer.last_type); + EXPECT_EQ(ContentSettingsPattern(), observer.last_pattern); + EXPECT_TRUE(observer.last_update_all); + EXPECT_TRUE(observer.last_update_all_types); + EXPECT_EQ(2, observer.counter); +} + +class PolicyProviderTest : public testing::Test { + public: + PolicyProviderTest() + : ui_thread_(BrowserThread::UI, &message_loop_) { + } + + protected: + // TODO(markusheintz): Check if it's possible to derive the provider class + // from NonThreadSafe and to use native thread identifiers instead of + // BrowserThread IDs. Then we could get rid of the message_loop and ui_thread + // fields. + MessageLoop message_loop_; + BrowserThread ui_thread_; +}; + +TEST_F(PolicyProviderTest, Default) { + TestingProfile profile; + TestingPrefService* prefs = profile.GetTestingPrefService(); + + ListValue* value = new ListValue(); + value->Append(Value::CreateStringValue("[*.]google.com")); + prefs->SetManagedPref(prefs::kManagedImagesBlockedForUrls, + value); + + PolicyProvider provider(static_cast<Profile*>(&profile)); + + ContentSettingsPattern yt_url_pattern("www.youtube.com"); + GURL youtube_url("http://www.youtube.com"); + GURL google_url("http://mail.google.com"); + + EXPECT_EQ(CONTENT_SETTING_DEFAULT, + provider.GetContentSetting( + youtube_url, youtube_url, CONTENT_SETTINGS_TYPE_COOKIES, "")); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + provider.GetContentSetting( + google_url, google_url, CONTENT_SETTINGS_TYPE_IMAGES, "")); + + provider.SetContentSetting( + yt_url_pattern, + yt_url_pattern, + CONTENT_SETTINGS_TYPE_COOKIES, + "", + CONTENT_SETTING_BLOCK); + EXPECT_EQ(CONTENT_SETTING_DEFAULT, + provider.GetContentSetting( + youtube_url, youtube_url, CONTENT_SETTINGS_TYPE_COOKIES, "")); +} + +TEST_F(PolicyProviderTest, ResourceIdentifier) { + CommandLine* cmd = CommandLine::ForCurrentProcess(); + AutoReset<CommandLine> auto_reset(cmd, *cmd); + cmd->AppendSwitch(switches::kEnableResourceContentSettings); + + TestingProfile profile; + TestingPrefService* prefs = profile.GetTestingPrefService(); + + ListValue* value = new ListValue(); + value->Append(Value::CreateStringValue("[*.]google.com")); + prefs->SetManagedPref(prefs::kManagedPluginsAllowedForUrls, + value); + + PolicyProvider provider(static_cast<Profile*>(&profile)); + + GURL youtube_url("http://www.youtube.com"); + GURL google_url("http://mail.google.com"); + + EXPECT_EQ(CONTENT_SETTING_DEFAULT, + provider.GetContentSetting( + youtube_url, + youtube_url, + CONTENT_SETTINGS_TYPE_PLUGINS, + "someplugin")); + + // There is no policy support for resource content settings until the feature + // is enabled by default. Resource identifiers are simply ignored by the + // PolicyProvider. + EXPECT_EQ(CONTENT_SETTING_ALLOW, + provider.GetContentSetting( + google_url, + google_url, + CONTENT_SETTINGS_TYPE_PLUGINS, + "")); + + EXPECT_EQ(CONTENT_SETTING_ALLOW, + provider.GetContentSetting( + google_url, + google_url, + CONTENT_SETTINGS_TYPE_PLUGINS, + "someplugin")); + + EXPECT_EQ(CONTENT_SETTING_ALLOW, + provider.GetContentSetting( + google_url, + google_url, + CONTENT_SETTINGS_TYPE_PLUGINS, + "anotherplugin")); +} + +} // namespace content_settings diff --git a/chrome/browser/content_settings/pref_content_settings_provider.cc b/chrome/browser/content_settings/content_settings_pref_provider.cc index bb6360e..aee1513 100644 --- a/chrome/browser/content_settings/pref_content_settings_provider.cc +++ b/chrome/browser/content_settings/content_settings_pref_provider.cc @@ -2,18 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/content_settings/pref_content_settings_provider.h" +#include "chrome/browser/content_settings/content_settings_pref_provider.h" #include <string> #include <vector> #include <utility> #include "base/command_line.h" -#include "chrome/browser/browser_thread.h" #include "chrome/browser/content_settings/content_settings_details.h" #include "chrome/browser/content_settings/content_settings_pattern.h" #include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/prefs/scoped_pref_update.h" +#include "chrome/browser/prefs/scoped_user_pref_update.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/content_settings.h" @@ -21,6 +20,7 @@ #include "chrome/common/notification_service.h" #include "chrome/common/notification_source.h" #include "chrome/common/pref_names.h" +#include "content/browser/browser_thread.h" #include "googleurl/src/gurl.h" #include "net/base/net_util.h" @@ -28,7 +28,7 @@ namespace { // The preference keys where resource identifiers are stored for // ContentSettingsType values that support resource identifiers. -const char* kResourceTypeNames[CONTENT_SETTINGS_NUM_TYPES] = { +const char* kResourceTypeNames[] = { NULL, NULL, NULL, @@ -36,10 +36,13 @@ const char* kResourceTypeNames[CONTENT_SETTINGS_NUM_TYPES] = { NULL, NULL, // Not used for Geolocation NULL, // Not used for Notifications + NULL, // Not used for Prerender. }; +COMPILE_ASSERT(arraysize(kResourceTypeNames) == CONTENT_SETTINGS_NUM_TYPES, + resource_type_names_incorrect_size); // The default setting for each content type. -const ContentSetting kDefaultSettings[CONTENT_SETTINGS_NUM_TYPES] = { +const ContentSetting kDefaultSettings[] = { CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_COOKIES CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_IMAGES CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_JAVASCRIPT @@ -47,10 +50,13 @@ const ContentSetting kDefaultSettings[CONTENT_SETTINGS_NUM_TYPES] = { CONTENT_SETTING_BLOCK, // CONTENT_SETTINGS_TYPE_POPUPS CONTENT_SETTING_ASK, // Not used for Geolocation CONTENT_SETTING_ASK, // Not used for Notifications + CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_PRERENDER }; +COMPILE_ASSERT(arraysize(kDefaultSettings) == CONTENT_SETTINGS_NUM_TYPES, + default_settings_incorrect_size); // The names of the ContentSettingsType values, for use with dictionary prefs. -const char* kTypeNames[CONTENT_SETTINGS_NUM_TYPES] = { +const char* kTypeNames[] = { "cookies", "images", "javascript", @@ -58,42 +64,15 @@ const char* kTypeNames[CONTENT_SETTINGS_NUM_TYPES] = { "popups", NULL, // Not used for Geolocation NULL, // Not used for Notifications + NULL, // Not used for Prerender }; - -// True if a given content settings type requires additional resource -// identifiers. -const bool kRequiresResourceIdentifier[CONTENT_SETTINGS_NUM_TYPES] = { - false, // CONTENT_SETTINGS_TYPE_COOKIES - false, // CONTENT_SETTINGS_TYPE_IMAGES - false, // CONTET_SETTINGS_TYPE_JAVASCRIPT - true, // CONTENT_SETTINGS_TYPE_PLUGINS - false, // CONTENT_SETTINGS_TYPE_POPUPS - false, // Not used for Geolocation - false, // Not used for Notifications -}; - -// Map ASK for the plugins content type to BLOCK if click-to-play is -// not enabled. -ContentSetting ClickToPlayFixup(ContentSettingsType content_type, - ContentSetting setting) { - if (setting == CONTENT_SETTING_ASK && - content_type == CONTENT_SETTINGS_TYPE_PLUGINS && - !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableClickToPlay)) { - return CONTENT_SETTING_BLOCK; - } - return setting; -} +COMPILE_ASSERT(arraysize(kTypeNames) == CONTENT_SETTINGS_NUM_TYPES, + type_names_incorrect_size); } // namespace namespace content_settings { -struct PrefProvider::ExtendedContentSettings { - ContentSettings content_settings; - ResourceContentSettings content_settings_for_resources; -}; - PrefDefaultProvider::PrefDefaultProvider(Profile* profile) : profile_(profile), is_off_the_record_(profile_->IsOffTheRecord()), @@ -144,7 +123,7 @@ void PrefDefaultProvider::UpdateDefaultSetting( updating_preferences_ = true; { base::AutoLock lock(lock_); - ScopedPrefUpdate update(prefs, prefs::kDefaultContentSettings); + ScopedUserPrefUpdate update(prefs, prefs::kDefaultContentSettings); if ((setting == CONTENT_SETTING_DEFAULT) || (setting == kDefaultSettings[content_type])) { default_content_settings_.settings[content_type] = @@ -273,8 +252,9 @@ void PrefDefaultProvider::GetSettingsFromDictionary( settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] = CONTENT_SETTING_BLOCK; settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS] = - ClickToPlayFixup(CONTENT_SETTINGS_TYPE_PLUGINS, - settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS]); + BaseProvider::ClickToPlayFixup( + CONTENT_SETTINGS_TYPE_PLUGINS, + settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS]); } void PrefDefaultProvider::NotifyObservers( @@ -288,14 +268,13 @@ void PrefDefaultProvider::NotifyObservers( Details<const ContentSettingsDetails>(&details)); } - // static void PrefDefaultProvider::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterDictionaryPref(prefs::kDefaultContentSettings); } // //////////////////////////////////////////////////////////////////////////// -// PrefProvider:: +// PrefProvider: // // static @@ -310,9 +289,13 @@ void PrefProvider::RegisterUserPrefs(PrefService* prefs) { } PrefProvider::PrefProvider(Profile* profile) - : profile_(profile), - is_off_the_record_(profile_->IsOffTheRecord()), + : BaseProvider(profile->IsOffTheRecord()), + profile_(profile), updating_preferences_(false) { + Init(); +} + +void PrefProvider::Init() { initializing_ = true; PrefService* prefs = profile_->GetPrefs(); @@ -347,81 +330,6 @@ bool PrefProvider::ContentSettingsTypeIsManaged( return false; } -ContentSetting PrefProvider::GetContentSetting( - const GURL& requesting_url, - const GURL& embedding_url, - ContentSettingsType content_type, - const ResourceIdentifier& resource_identifier) const { - // Support for embedding_patterns is not implemented yet. - DCHECK(requesting_url == embedding_url); - - if (!RequiresResourceIdentifier(content_type)) - return GetNonDefaultContentSettings(requesting_url).settings[content_type]; - - if (RequiresResourceIdentifier(content_type) && resource_identifier.empty()) - return CONTENT_SETTING_DEFAULT; - - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableResourceContentSettings)) { - DCHECK(!resource_identifier.empty()); - } - - base::AutoLock auto_lock(lock_); - - const std::string host(net::GetHostOrSpecFromURL(requesting_url)); - ContentSettingsTypeResourceIdentifierPair - requested_setting(content_type, resource_identifier); - - // Check for exact matches first. - HostContentSettings::const_iterator i(host_content_settings_.find(host)); - if (i != host_content_settings_.end() && - i->second.content_settings_for_resources.find(requested_setting) != - i->second.content_settings_for_resources.end()) { - return i->second.content_settings_for_resources.find( - requested_setting)->second; - } - - // If this map is not for an off-the-record profile, these searches will never - // match. The additional off-the-record exceptions always overwrite the - // regular ones. - i = off_the_record_settings_.find(host); - if (i != off_the_record_settings_.end() && - i->second.content_settings_for_resources.find(requested_setting) != - i->second.content_settings_for_resources.end()) { - return i->second.content_settings_for_resources.find( - requested_setting)->second; - } - - // Match patterns starting with the most concrete pattern match. - for (std::string key = - std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) { - HostContentSettings::const_iterator i(off_the_record_settings_.find(key)); - if (i != off_the_record_settings_.end() && - i->second.content_settings_for_resources.find(requested_setting) != - i->second.content_settings_for_resources.end()) { - return i->second.content_settings_for_resources.find( - requested_setting)->second; - } - - i = host_content_settings_.find(key); - if (i != host_content_settings_.end() && - i->second.content_settings_for_resources.find(requested_setting) != - i->second.content_settings_for_resources.end()) { - return i->second.content_settings_for_resources.find( - requested_setting)->second; - } - - const size_t next_dot = - key.find('.', ContentSettingsPattern::kDomainWildcardLength); - if (next_dot == std::string::npos) - break; - key.erase(ContentSettingsPattern::kDomainWildcardLength, - next_dot - ContentSettingsPattern::kDomainWildcardLength + 1); - } - - return CONTENT_SETTING_DEFAULT; -} - void PrefProvider::SetContentSetting( const ContentSettingsPattern& requesting_pattern, const ContentSettingsPattern& embedding_pattern, @@ -447,16 +355,20 @@ void PrefProvider::SetContentSetting( std::string pattern_str(pattern.AsString()); PrefService* prefs = NULL; DictionaryValue* all_settings_dictionary = NULL; - HostContentSettings* map_to_modify = &off_the_record_settings_; - if (!is_off_the_record_) { + + // Select content-settings-map to write to. + HostContentSettings* map_to_modify = off_the_record_settings(); + if (!is_off_the_record()) { prefs = profile_->GetPrefs(); all_settings_dictionary = prefs->GetMutableDictionary(prefs::kContentSettingsPatterns); - map_to_modify = &host_content_settings_; + + map_to_modify = host_content_settings(); } + // Update content-settings-map. { - base::AutoLock auto_lock(lock_); + base::AutoLock auto_lock(lock()); if (!map_to_modify->count(pattern_str)) (*map_to_modify)[pattern_str].content_settings = ContentSettings(); HostContentSettings::iterator i( @@ -482,11 +394,12 @@ void PrefProvider::SetContentSetting( all_settings_dictionary->RemoveWithoutPathExpansion(pattern_str, NULL); // We can't just return because |NotifyObservers()| needs to be called, - // without |lock_| being held. + // without lock() being held. early_exit = true; } } + // Update the content_settings preference. if (!early_exit && all_settings_dictionary) { DictionaryValue* host_settings_dictionary = NULL; bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion( @@ -526,62 +439,23 @@ void PrefProvider::SetContentSetting( } updating_preferences_ = true; - if (!is_off_the_record_) - ScopedPrefUpdate update(prefs, prefs::kContentSettingsPatterns); + if (!is_off_the_record()) + ScopedUserPrefUpdate update(prefs, prefs::kContentSettingsPatterns); updating_preferences_ = false; NotifyObservers(ContentSettingsDetails(pattern, content_type, "")); } -void PrefProvider::GetAllContentSettingsRules( - ContentSettingsType content_type, - const ResourceIdentifier& resource_identifier, - Rules* content_setting_rules) const { - DCHECK(RequiresResourceIdentifier(content_type) != - resource_identifier.empty()); - DCHECK(content_setting_rules); - content_setting_rules->clear(); - - const HostContentSettings* map_to_return = - is_off_the_record_ ? &off_the_record_settings_ : &host_content_settings_; - ContentSettingsTypeResourceIdentifierPair requested_setting( - content_type, resource_identifier); - - base::AutoLock auto_lock(lock_); - for (HostContentSettings::const_iterator i(map_to_return->begin()); - i != map_to_return->end(); ++i) { - ContentSetting setting; - if (RequiresResourceIdentifier(content_type)) { - if (i->second.content_settings_for_resources.find(requested_setting) != - i->second.content_settings_for_resources.end()) { - setting = i->second.content_settings_for_resources.find( - requested_setting)->second; - } else { - setting = CONTENT_SETTING_DEFAULT; - } - } else { - setting = i->second.content_settings.settings[content_type]; - } - if (setting != CONTENT_SETTING_DEFAULT) { - // Use of push_back() relies on the map iterator traversing in order of - // ascending keys. - content_setting_rules->push_back(Rule(ContentSettingsPattern(i->first), - ContentSettingsPattern(i->first), - setting)); - } - } -} - void PrefProvider::ResetToDefaults() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); { - base::AutoLock auto_lock(lock_); - host_content_settings_.clear(); - off_the_record_settings_.clear(); + base::AutoLock auto_lock(lock()); + host_content_settings()->clear(); + off_the_record_settings()->clear(); } - if (!is_off_the_record_) { + if (!is_off_the_record()) { PrefService* prefs = profile_->GetPrefs(); updating_preferences_ = true; prefs->ClearPref(prefs::kContentSettingsPatterns); @@ -595,22 +469,22 @@ void PrefProvider::ClearAllContentSettingsRules( PrefService* prefs = NULL; DictionaryValue* all_settings_dictionary = NULL; - HostContentSettings* map_to_modify = &off_the_record_settings_; + HostContentSettings* map_to_modify = off_the_record_settings(); - if (!is_off_the_record_) { + if (!is_off_the_record()) { prefs = profile_->GetPrefs(); all_settings_dictionary = prefs->GetMutableDictionary(prefs::kContentSettingsPatterns); - map_to_modify = &host_content_settings_; + map_to_modify = host_content_settings(); } { - base::AutoLock auto_lock(lock_); + base::AutoLock auto_lock(lock()); for (HostContentSettings::iterator i(map_to_modify->begin()); i != map_to_modify->end(); ) { if (RequiresResourceIdentifier(content_type) || i->second.content_settings.settings[content_type] != - CONTENT_SETTING_DEFAULT) { + CONTENT_SETTING_DEFAULT) { if (RequiresResourceIdentifier(content_type)) i->second.content_settings_for_resources.clear(); i->second.content_settings.settings[content_type] = @@ -637,8 +511,8 @@ void PrefProvider::ClearAllContentSettingsRules( } updating_preferences_ = true; - if (!is_off_the_record_) - ScopedPrefUpdate update(prefs, prefs::kContentSettingsPatterns); + if (!is_off_the_record()) + ScopedUserPrefUpdate update(prefs, prefs::kContentSettingsPatterns); updating_preferences_ = false; NotifyObservers( @@ -664,7 +538,7 @@ void PrefProvider::Observe( return; } - if (!is_off_the_record_) { + if (!is_off_the_record()) { NotifyObservers(ContentSettingsDetails(ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, "")); @@ -684,34 +558,15 @@ PrefProvider::~PrefProvider() { // //////////////////////////////////////////////////////////////////////////// // Private -bool PrefProvider::RequiresResourceIdentifier( - ContentSettingsType content_type) const { - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableResourceContentSettings)) { - return kRequiresResourceIdentifier[content_type]; - } else { - return false; - } -} - -bool PrefProvider::AllDefault( - const ExtendedContentSettings& settings) const { - for (size_t i = 0; i < arraysize(settings.content_settings.settings); ++i) { - if (settings.content_settings.settings[i] != CONTENT_SETTING_DEFAULT) - return false; - } - return settings.content_settings_for_resources.empty(); -} - void PrefProvider::ReadExceptions(bool overwrite) { - base::AutoLock lock(lock_); + base::AutoLock auto_lock(lock()); PrefService* prefs = profile_->GetPrefs(); DictionaryValue* all_settings_dictionary = prefs->GetMutableDictionary(prefs::kContentSettingsPatterns); if (overwrite) - host_content_settings_.clear(); + host_content_settings()->clear(); // Careful: The returned value could be NULL if the pref has never been set. if (all_settings_dictionary != NULL) { @@ -727,12 +582,15 @@ void PrefProvider::ReadExceptions(bool overwrite) { bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion( pattern, &pattern_settings_dictionary); DCHECK(found); - ContentSettings settings; - GetSettingsFromDictionary(pattern_settings_dictionary, &settings); - host_content_settings_[pattern].content_settings = settings; + + ExtendedContentSettings extended_settings; + GetSettingsFromDictionary(pattern_settings_dictionary, + &extended_settings.content_settings); GetResourceSettingsFromDictionary( pattern_settings_dictionary, - &host_content_settings_[pattern].content_settings_for_resources); + &extended_settings.content_settings_for_resources); + + (*host_content_settings())[pattern] = extended_settings; } } } @@ -911,60 +769,4 @@ void PrefProvider::MigrateObsoletePopupsPref(PrefService* prefs) { } } -// //////////////////////////////////////////////////////////////////////////// -// LEGACY TBR -// - -ContentSettings PrefProvider::GetNonDefaultContentSettings( - const GURL& url) const { - base::AutoLock auto_lock(lock_); - - const std::string host(net::GetHostOrSpecFromURL(url)); - ContentSettings output; - for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) - output.settings[j] = CONTENT_SETTING_DEFAULT; - - // Check for exact matches first. - HostContentSettings::const_iterator i(host_content_settings_.find(host)); - if (i != host_content_settings_.end()) - output = i->second.content_settings; - - // If this map is not for an off-the-record profile, these searches will never - // match. The additional off-the-record exceptions always overwrite the - // regular ones. - i = off_the_record_settings_.find(host); - if (i != off_the_record_settings_.end()) { - for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) - if (i->second.content_settings.settings[j] != CONTENT_SETTING_DEFAULT) - output.settings[j] = i->second.content_settings.settings[j]; - } - - // Match patterns starting with the most concrete pattern match. - for (std::string key = - std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) { - HostContentSettings::const_iterator i(off_the_record_settings_.find(key)); - if (i != off_the_record_settings_.end()) { - for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) { - if (output.settings[j] == CONTENT_SETTING_DEFAULT) - output.settings[j] = i->second.content_settings.settings[j]; - } - } - i = host_content_settings_.find(key); - if (i != host_content_settings_.end()) { - for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) { - if (output.settings[j] == CONTENT_SETTING_DEFAULT) - output.settings[j] = i->second.content_settings.settings[j]; - } - } - const size_t next_dot = - key.find('.', ContentSettingsPattern::kDomainWildcardLength); - if (next_dot == std::string::npos) - break; - key.erase(ContentSettingsPattern::kDomainWildcardLength, - next_dot - ContentSettingsPattern::kDomainWildcardLength + 1); - } - - return output; -} - } // namespace content_settings diff --git a/chrome/browser/content_settings/pref_content_settings_provider.h b/chrome/browser/content_settings/content_settings_pref_provider.h index b4631b8..95a4e75 100644 --- a/chrome/browser/content_settings/pref_content_settings_provider.h +++ b/chrome/browser/content_settings/content_settings_pref_provider.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CONTENT_SETTINGS_PREF_CONTENT_SETTINGS_PROVIDER_H_ -#define CHROME_BROWSER_CONTENT_SETTINGS_PREF_CONTENT_SETTINGS_PROVIDER_H_ +#ifndef CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_PREF_PROVIDER_H_ +#define CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_PREF_PROVIDER_H_ #pragma once // A content settings provider that takes its settings out of the pref service. @@ -14,6 +14,7 @@ #include "base/basictypes.h" #include "base/synchronization/lock.h" +#include "chrome/browser/content_settings/content_settings_base_provider.h" #include "chrome/browser/content_settings/content_settings_provider.h" #include "chrome/browser/prefs/pref_change_registrar.h" #include "chrome/common/notification_observer.h" @@ -90,7 +91,9 @@ class PrefDefaultProvider : public DefaultProviderInterface, DISALLOW_COPY_AND_ASSIGN(PrefDefaultProvider); }; -class PrefProvider : public ProviderInterface, +// Content settings provider that provides content settings from the user +// preference. +class PrefProvider : public BaseProvider, public NotificationObserver { public: static void RegisterUserPrefs(PrefService* prefs); @@ -102,12 +105,6 @@ class PrefProvider : public ProviderInterface, virtual bool ContentSettingsTypeIsManaged( ContentSettingsType content_type); - virtual ContentSetting GetContentSetting( - const GURL& requesting_url, - const GURL& embedding_url, - ContentSettingsType content_type, - const ResourceIdentifier& resource_identifier) const; - virtual void SetContentSetting( const ContentSettingsPattern& requesting_pattern, const ContentSettingsPattern& embedding_pattern, @@ -115,43 +112,27 @@ class PrefProvider : public ProviderInterface, const ResourceIdentifier& resource_identifier, ContentSetting content_setting); - virtual void GetAllContentSettingsRules( - ContentSettingsType content_type, - const ResourceIdentifier& resource_identifier, - Rules* content_setting_rules) const; - virtual void ClearAllContentSettingsRules( ContentSettingsType content_type); virtual void ResetToDefaults(); + // BaseProvider implementations. + virtual void Init(); + // NotificationObserver implementation. virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details); private: - typedef std::pair<ContentSettingsType, std::string> - ContentSettingsTypeResourceIdentifierPair; - typedef std::map<ContentSettingsTypeResourceIdentifierPair, ContentSetting> - ResourceContentSettings; - - struct ExtendedContentSettings; - - typedef std::map<std::string, ExtendedContentSettings> HostContentSettings; + void ReadExceptions(bool overwrite); // Various migration methods (old cookie, popup and per-host data gets // migrated to the new format). void MigrateObsoletePerhostPref(PrefService* prefs); void MigrateObsoletePopupsPref(PrefService* prefs); - bool AllDefault(const ExtendedContentSettings& settings) const; - - void ReadExceptions(bool overwrite); - - bool RequiresResourceIdentifier( - ContentSettingsType content_type) const; - void CanonicalizeContentSettingsExceptions( DictionaryValue* all_settings_dictionary); @@ -169,24 +150,9 @@ class PrefProvider : public ProviderInterface, Profile* profile_; - // Whether this settings map is for an OTR session. - bool is_off_the_record_; - - // Used around accesses to the content_settings_ object to guarantee - // thread safety. - mutable base::Lock lock_; - PrefChangeRegistrar pref_change_registrar_; NotificationRegistrar notification_registrar_; - // Copies of the pref data, so that we can read it on threads other than the - // UI thread. - HostContentSettings host_content_settings_; - - // Differences to the preference-stored host content settings for - // off-the-record settings. - HostContentSettings off_the_record_settings_; - // Whether we are currently updating preferences, this is used to ignore // notifications from the preferences service that we triggered ourself. bool updating_preferences_; @@ -194,12 +160,9 @@ class PrefProvider : public ProviderInterface, // Do not fire any Notifications as long as we are in the constructor. bool initializing_; - // LEGACY: TBR - ContentSettings GetNonDefaultContentSettings(const GURL& url) const; - DISALLOW_COPY_AND_ASSIGN(PrefProvider); }; } // namespace content_settings -#endif // CHROME_BROWSER_CONTENT_SETTINGS_PREF_CONTENT_SETTINGS_PROVIDER_H_ +#endif // CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_PREF_PROVIDER_H_ diff --git a/chrome/browser/content_settings/pref_content_settings_provider_unittest.cc b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc index 80b62c3..fda116d 100644 --- a/chrome/browser/content_settings/pref_content_settings_provider_unittest.cc +++ b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc @@ -2,24 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/content_settings/pref_content_settings_provider.h" +#include "chrome/browser/content_settings/content_settings_pref_provider.h" #include "base/auto_reset.h" #include "base/command_line.h" -#include "chrome/browser/browser_thread.h" #include "chrome/browser/content_settings/stub_settings_observer.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" +#include "chrome/test/testing_browser_process_test.h" #include "chrome/test/testing_pref_service.h" #include "chrome/test/testing_profile.h" +#include "content/browser/browser_thread.h" #include "googleurl/src/gurl.h" #include "testing/gtest/include/gtest/gtest.h" namespace content_settings { -class PrefDefaultProviderTest : public testing::Test { +class PrefDefaultProviderTest : public TestingBrowserProcessTest { public: PrefDefaultProviderTest() : ui_thread_(BrowserThread::UI, &message_loop_) { @@ -136,7 +137,7 @@ bool SettingsEqual(const ContentSettings& settings1, return true; } -class PrefProviderTest : public testing::Test { +class PrefProviderTest : public TestingBrowserProcessTest { public: PrefProviderTest() : ui_thread_( BrowserThread::UI, &message_loop_) { @@ -175,8 +176,10 @@ TEST_F(PrefProviderTest, Patterns) { GURL host1("http://example.com/"); GURL host2("http://www.example.com/"); GURL host3("http://example.org/"); + GURL host4("file:///tmp/test.html"); ContentSettingsPattern pattern1("[*.]example.com"); ContentSettingsPattern pattern2("example.org"); + ContentSettingsPattern pattern3("file:///tmp/test.html"); EXPECT_EQ(CONTENT_SETTING_DEFAULT, pref_content_settings_provider.GetContentSetting( @@ -206,6 +209,19 @@ TEST_F(PrefProviderTest, Patterns) { EXPECT_EQ(CONTENT_SETTING_BLOCK, pref_content_settings_provider.GetContentSetting( host3, host3, CONTENT_SETTINGS_TYPE_IMAGES, "")); + + EXPECT_EQ(CONTENT_SETTING_DEFAULT, + pref_content_settings_provider.GetContentSetting( + host4, host4, CONTENT_SETTINGS_TYPE_IMAGES, "")); + pref_content_settings_provider.SetContentSetting( + pattern3, + pattern3, + CONTENT_SETTINGS_TYPE_IMAGES, + "", + CONTENT_SETTING_BLOCK); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + pref_content_settings_provider.GetContentSetting( + host4, host4, CONTENT_SETTINGS_TYPE_IMAGES, "")); } TEST_F(PrefProviderTest, ResourceIdentifier) { diff --git a/chrome/browser/content_settings/content_settings_provider.h b/chrome/browser/content_settings/content_settings_provider.h index 621c522..eff1443 100644 --- a/chrome/browser/content_settings/content_settings_provider.h +++ b/chrome/browser/content_settings/content_settings_provider.h @@ -65,6 +65,11 @@ class ProviderInterface { virtual ~ProviderInterface() {} + // Returns true whether the content settings provider manages the + // |content_type|. + virtual bool ContentSettingsTypeIsManaged( + ContentSettingsType content_type) = 0; + // Returns a single ContentSetting which applies to a given |requesting_url|, // |embedding_url| pair or CONTENT_SETTING_DEFAULT, if no rule applies. For // ContentSettingsTypes that require a resource identifier to be specified, diff --git a/chrome/browser/content_settings/content_settings_provider_unittest.cc b/chrome/browser/content_settings/content_settings_provider_unittest.cc index 71cded4..11c0284 100644 --- a/chrome/browser/content_settings/content_settings_provider_unittest.cc +++ b/chrome/browser/content_settings/content_settings_provider_unittest.cc @@ -4,7 +4,7 @@ #include "testing/gtest/include/gtest/gtest.h" -#include "chrome/browser/content_settings/mock_content_settings_provider.h" +#include "chrome/browser/content_settings/content_settings_mock_provider.h" #include "googleurl/src/gurl.h" namespace content_settings { @@ -34,7 +34,9 @@ TEST(ContentSettingsProviderTest, Mock) { CONTENT_SETTINGS_TYPE_PLUGINS, "java_plugin", CONTENT_SETTING_BLOCK, + false, false); + EXPECT_EQ(CONTENT_SETTING_BLOCK, mock_provider.GetContentSetting( url, url, CONTENT_SETTINGS_TYPE_PLUGINS, "java_plugin")); EXPECT_EQ(CONTENT_SETTING_DEFAULT, mock_provider.GetContentSetting( diff --git a/chrome/browser/content_settings/host_content_settings_map.cc b/chrome/browser/content_settings/host_content_settings_map.cc index bcdd538..93dac5f 100644 --- a/chrome/browser/content_settings/host_content_settings_map.cc +++ b/chrome/browser/content_settings/host_content_settings_map.cc @@ -7,21 +7,21 @@ #include "base/command_line.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser_thread.h" #include "chrome/browser/content_settings/content_settings_details.h" #include "chrome/browser/content_settings/content_settings_provider.h" -#include "chrome/browser/content_settings/policy_content_settings_provider.h" -#include "chrome/browser/content_settings/pref_content_settings_provider.h" +#include "chrome/browser/content_settings/content_settings_policy_provider.h" +#include "chrome/browser/content_settings/content_settings_pref_provider.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/prefs/scoped_pref_update.h" +#include "chrome/browser/prefs/scoped_user_pref_update.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_source.h" #include "chrome/common/notification_type.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" +#include "content/browser/browser_thread.h" #include "googleurl/src/gurl.h" #include "net/base/net_util.h" #include "net/base/static_cookie_policy.h" @@ -100,8 +100,10 @@ HostContentSettingsMap::HostContentSettingsMap(Profile* profile) // The order in which the content settings providers are created is critical, // as providers that are further up in the list (i.e. added earlier) override // providers further down. - content_settings_providers_.push_back(ProviderPtr( - new content_settings::PrefProvider(profile))); + content_settings_providers_.push_back( + make_linked_ptr(new content_settings::PolicyProvider(profile))); + content_settings_providers_.push_back( + make_linked_ptr(new content_settings::PrefProvider(profile))); pref_change_registrar_.Init(prefs); pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this); @@ -124,6 +126,7 @@ void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) { content_settings::PrefDefaultProvider::RegisterUserPrefs(prefs); content_settings::PolicyDefaultProvider::RegisterUserPrefs(prefs); content_settings::PrefProvider::RegisterUserPrefs(prefs); + content_settings::PolicyProvider::RegisterUserPrefs(prefs); } ContentSetting HostContentSettingsMap::GetDefaultContentSetting( @@ -151,10 +154,8 @@ ContentSetting HostContentSettingsMap::GetContentSetting( ContentSetting setting = GetNonDefaultContentSetting(url, content_type, resource_identifier); - if (setting == CONTENT_SETTING_DEFAULT || - IsDefaultContentSettingManaged(content_type)) { + if (setting == CONTENT_SETTING_DEFAULT) return GetDefaultContentSetting(content_type); - } return setting; } @@ -173,8 +174,9 @@ ContentSetting HostContentSettingsMap::GetNonDefaultContentSetting( ++provider) { provided_setting = (*provider)->GetContentSetting( url, url, content_type, resource_identifier); - if (provided_setting != CONTENT_SETTING_DEFAULT) - break; + bool isManaged = (*provider)->ContentSettingsTypeIsManaged(content_type); + if (provided_setting != CONTENT_SETTING_DEFAULT || isManaged) + return provided_setting; } return provided_setting; } @@ -188,9 +190,8 @@ ContentSettings HostContentSettingsMap::GetContentSettings( for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) { // A managed default content setting has the highest priority and hence // will overwrite any previously set value. - if ((output.settings[j] == CONTENT_SETTING_DEFAULT && - j != CONTENT_SETTINGS_TYPE_PLUGINS) || - IsDefaultContentSettingManaged(ContentSettingsType(j))) { + if (output.settings[j] == CONTENT_SETTING_DEFAULT && + j != CONTENT_SETTINGS_TYPE_PLUGINS) { output.settings[j] = GetDefaultContentSetting(ContentSettingsType(j)); } } @@ -225,8 +226,14 @@ void HostContentSettingsMap::GetSettingsForOneType( ++provider) { // TODO(markusheintz): Only the rules that are applied should be collected. // Merge rules. + // TODO(markusheintz): GetAllContentSettingsRules should maybe not clear the + // passed vector in case rule sets are just unified. + Rules rules; (*provider)->GetAllContentSettingsRules( - content_type, resource_identifier, &content_settings_rules); + content_type, resource_identifier, &rules); + content_settings_rules.insert(content_settings_rules.end(), + rules.begin(), + rules.end()); } // convert Rules to SettingsForOneType diff --git a/chrome/browser/content_settings/host_content_settings_map.h b/chrome/browser/content_settings/host_content_settings_map.h index c2658e8..cf326d7 100644 --- a/chrome/browser/content_settings/host_content_settings_map.h +++ b/chrome/browser/content_settings/host_content_settings_map.h @@ -18,12 +18,12 @@ #include "base/linked_ptr.h" #include "base/ref_counted.h" #include "base/synchronization/lock.h" -#include "chrome/browser/browser_thread.h" #include "chrome/browser/content_settings/content_settings_pattern.h" #include "chrome/browser/prefs/pref_change_registrar.h" #include "chrome/common/content_settings.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" +#include "content/browser/browser_thread.h" namespace content_settings { class DefaultProviderInterface; @@ -45,7 +45,6 @@ class HostContentSettingsMap typedef std::vector<PatternSettingPair> SettingsForOneType; explicit HostContentSettingsMap(Profile* profile); - ~HostContentSettingsMap(); static void RegisterUserPrefs(PrefService* prefs); @@ -171,7 +170,10 @@ class HostContentSettingsMap const NotificationDetails& details); private: - friend class base::RefCountedThreadSafe<HostContentSettingsMap>; + friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; + friend class DeleteTask<HostContentSettingsMap>; + + ~HostContentSettingsMap(); // Informs observers that content settings have changed. Make sure that // |lock_| is not held when calling this, as listeners will usually call one diff --git a/chrome/browser/content_settings/host_content_settings_map_unittest.cc b/chrome/browser/content_settings/host_content_settings_map_unittest.cc index 7de163d..7748406 100644 --- a/chrome/browser/content_settings/host_content_settings_map_unittest.cc +++ b/chrome/browser/content_settings/host_content_settings_map_unittest.cc @@ -13,6 +13,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" +#include "chrome/test/testing_browser_process_test.h" #include "chrome/test/testing_pref_service.h" #include "chrome/test/testing_profile.h" #include "googleurl/src/gurl.h" @@ -30,7 +31,7 @@ bool SettingsEqual(const ContentSettings& settings1, return true; } -class HostContentSettingsMapTest : public testing::Test { +class HostContentSettingsMapTest : public TestingBrowserProcessTest { public: HostContentSettingsMapTest() : ui_thread_(BrowserThread::UI, &message_loop_) { } @@ -121,6 +122,8 @@ TEST_F(HostContentSettingsMapTest, DefaultValues) { CONTENT_SETTING_ASK; desired_settings.settings[CONTENT_SETTINGS_TYPE_NOTIFICATIONS] = CONTENT_SETTING_ASK; + desired_settings.settings[CONTENT_SETTINGS_TYPE_PRERENDER] = + CONTENT_SETTING_ALLOW; ContentSettings settings = host_content_settings_map->GetContentSettings(host); EXPECT_TRUE(SettingsEqual(desired_settings, settings)); @@ -422,6 +425,8 @@ TEST_F(HostContentSettingsMapTest, NestedSettings) { CONTENT_SETTING_ASK; desired_settings.settings[CONTENT_SETTINGS_TYPE_NOTIFICATIONS] = CONTENT_SETTING_ASK; + desired_settings.settings[CONTENT_SETTINGS_TYPE_PRERENDER] = + CONTENT_SETTING_ALLOW; ContentSettings settings = host_content_settings_map->GetContentSettings(host); EXPECT_TRUE(SettingsEqual(desired_settings, settings)); diff --git a/chrome/browser/content_settings/policy_content_settings_provider.cc b/chrome/browser/content_settings/policy_content_settings_provider.cc deleted file mode 100644 index d39acef..0000000 --- a/chrome/browser/content_settings/policy_content_settings_provider.cc +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) 2010 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 "chrome/browser/content_settings/policy_content_settings_provider.h" - -#include <string> - -#include "base/command_line.h" -#include "chrome/browser/browser_thread.h" -#include "chrome/browser/content_settings/content_settings_details.h" -#include "chrome/browser/content_settings/content_settings_pattern.h" -#include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/prefs/scoped_pref_update.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/notification_details.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/notification_source.h" -#include "chrome/common/pref_names.h" - -namespace { - -// Base pref path of the prefs that contain the managed default content -// settings values. -const std::string kManagedSettings = - "profile.managed_default_content_settings"; - -// The preferences used to manage ContentSettingsTypes. -const char* kPrefToManageType[CONTENT_SETTINGS_NUM_TYPES] = { - prefs::kManagedDefaultCookiesSetting, - prefs::kManagedDefaultImagesSetting, - prefs::kManagedDefaultJavaScriptSetting, - prefs::kManagedDefaultPluginsSetting, - prefs::kManagedDefaultPopupsSetting, - NULL, // Not used for Geolocation - NULL, // Not used for Notifications -}; - -} // namespace - -namespace content_settings { - -PolicyDefaultProvider::PolicyDefaultProvider(Profile* profile) - : profile_(profile), - is_off_the_record_(profile_->IsOffTheRecord()) { - PrefService* prefs = profile->GetPrefs(); - - // Read global defaults. - DCHECK_EQ(arraysize(kPrefToManageType), - static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); - ReadManagedDefaultSettings(); - - pref_change_registrar_.Init(prefs); - // 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 perferences 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 excpetions - // (patterns) for this type are ignored. - pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, this); - pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, this); - pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, this); - pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, this); - pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, this); - notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, - Source<Profile>(profile_)); -} - -PolicyDefaultProvider::~PolicyDefaultProvider() { - UnregisterObservers(); -} - -ContentSetting PolicyDefaultProvider::ProvideDefaultSetting( - ContentSettingsType content_type) const { - base::AutoLock auto_lock(lock_); - return managed_default_content_settings_.settings[content_type]; -} - -void PolicyDefaultProvider::UpdateDefaultSetting( - ContentSettingsType content_type, - ContentSetting setting) { -} - -bool PolicyDefaultProvider::DefaultSettingIsManaged( - ContentSettingsType content_type) const { - base::AutoLock lock(lock_); - if (managed_default_content_settings_.settings[content_type] != - CONTENT_SETTING_DEFAULT) { - return true; - } else { - return false; - } -} - -void PolicyDefaultProvider::ResetToDefaults() { -} - -void PolicyDefaultProvider::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (type == NotificationType::PREF_CHANGED) { - DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr()); - std::string* name = Details<std::string>(details).ptr(); - 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 { - NOTREACHED() << "Unexpected preference observed"; - return; - } - - if (!is_off_the_record_) { - NotifyObservers(ContentSettingsDetails( - ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, "")); - } - } else if (type == NotificationType::PROFILE_DESTROYED) { - DCHECK_EQ(profile_, Source<Profile>(source).ptr()); - UnregisterObservers(); - } else { - NOTREACHED() << "Unexpected notification"; - } -} - -void PolicyDefaultProvider::UnregisterObservers() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!profile_) - return; - pref_change_registrar_.RemoveAll(); - notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED, - Source<Profile>(profile_)); - profile_ = NULL; -} - - -void PolicyDefaultProvider::NotifyObservers( - const ContentSettingsDetails& details) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (profile_ == NULL) - return; - NotificationService::current()->Notify( - NotificationType::CONTENT_SETTINGS_CHANGED, - Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()), - Details<const ContentSettingsDetails>(&details)); -} - -void PolicyDefaultProvider::ReadManagedDefaultSettings() { - for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) { - if (kPrefToManageType[type] == NULL) { - // TODO(markusheintz): Handle Geolocation and notification separately. - continue; - } - UpdateManagedDefaultSetting(ContentSettingsType(type)); - } -} - -void PolicyDefaultProvider::UpdateManagedDefaultSetting( - ContentSettingsType 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. - PrefService* prefs = profile_->GetPrefs(); - DCHECK(!prefs->HasPrefPath(kPrefToManageType[type]) || - prefs->IsManagedPreference(kPrefToManageType[type])); - base::AutoLock auto_lock(lock_); - managed_default_content_settings_.settings[type] = IntToContentSetting( - prefs->GetInteger(kPrefToManageType[type])); -} - -// static -void PolicyDefaultProvider::RegisterUserPrefs(PrefService* prefs) { - // Preferences for default content setting policies. A policy is not set of - // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT. - prefs->RegisterIntegerPref(prefs::kManagedDefaultCookiesSetting, - CONTENT_SETTING_DEFAULT); - prefs->RegisterIntegerPref(prefs::kManagedDefaultImagesSetting, - CONTENT_SETTING_DEFAULT); - prefs->RegisterIntegerPref(prefs::kManagedDefaultJavaScriptSetting, - CONTENT_SETTING_DEFAULT); - prefs->RegisterIntegerPref(prefs::kManagedDefaultPluginsSetting, - CONTENT_SETTING_DEFAULT); - prefs->RegisterIntegerPref(prefs::kManagedDefaultPopupsSetting, - CONTENT_SETTING_DEFAULT); -} - -} // namespace content_settings diff --git a/chrome/browser/content_settings/policy_content_settings_provider_unittest.cc b/chrome/browser/content_settings/policy_content_settings_provider_unittest.cc deleted file mode 100644 index 6aa9a88..0000000 --- a/chrome/browser/content_settings/policy_content_settings_provider_unittest.cc +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2010 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 "chrome/browser/content_settings/policy_content_settings_provider.h" - -#include "chrome/browser/browser_thread.h" -#include "chrome/browser/content_settings/stub_settings_observer.h" -#include "chrome/browser/prefs/pref_service.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/url_constants.h" -#include "chrome/test/testing_pref_service.h" -#include "chrome/test/testing_profile.h" -#include "testing/gtest/include/gtest/gtest.h" - - -namespace content_settings { - -class PolicyDefaultProviderTest : public testing::Test { - public: - PolicyDefaultProviderTest() - : ui_thread_(BrowserThread::UI, &message_loop_) { - } - - protected: - MessageLoop message_loop_; - BrowserThread ui_thread_; -}; - -TEST_F(PolicyDefaultProviderTest, DefaultValues) { - TestingProfile profile; - PolicyDefaultProvider provider(&profile); - TestingPrefService* prefs = profile.GetTestingPrefService(); - - // By default, policies should be off. - ASSERT_FALSE( - provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES)); - - // Set managed-default-content-setting through the coresponding preferences. - prefs->SetManagedPref(prefs::kManagedDefaultCookiesSetting, - Value::CreateIntegerValue(CONTENT_SETTING_BLOCK)); - ASSERT_TRUE( - provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES)); - ASSERT_EQ(CONTENT_SETTING_BLOCK, - provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES)); - - // Remove managed-default-content-settings-preferences. - prefs->RemoveManagedPref(prefs::kManagedDefaultCookiesSetting); - ASSERT_FALSE( - provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES)); -} - -// When a default-content-setting is set to a managed setting a -// CONTENT_SETTINGS_CHANGED notification should be fired. The same should happen -// if the managed setting is removed. -TEST_F(PolicyDefaultProviderTest, ObserveManagedSettingsChange) { - TestingProfile profile; - StubSettingsObserver observer; - // Make sure the content settings map exists. - profile.GetHostContentSettingsMap(); - TestingPrefService* prefs = profile.GetTestingPrefService(); - - // Set the managed default-content-setting. - prefs->SetManagedPref(prefs::kManagedDefaultImagesSetting, - Value::CreateIntegerValue(CONTENT_SETTING_BLOCK)); - EXPECT_EQ(profile.GetHostContentSettingsMap(), observer.last_notifier); - EXPECT_EQ(ContentSettingsPattern(), observer.last_pattern); - EXPECT_EQ(CONTENT_SETTINGS_TYPE_DEFAULT, observer.last_type); - EXPECT_TRUE(observer.last_update_all); - EXPECT_TRUE(observer.last_update_all_types); - EXPECT_EQ(1, observer.counter); - - // Remove the managed default-content-setting. - prefs->RemoveManagedPref(prefs::kManagedDefaultImagesSetting); - EXPECT_EQ(profile.GetHostContentSettingsMap(), observer.last_notifier); - EXPECT_EQ(CONTENT_SETTINGS_TYPE_DEFAULT, observer.last_type); - EXPECT_EQ(ContentSettingsPattern(), observer.last_pattern); - EXPECT_TRUE(observer.last_update_all); - EXPECT_TRUE(observer.last_update_all_types); - EXPECT_EQ(2, observer.counter); -} - -} // namespace content_settings |