summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-10 10:00:12 +0000
committerjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-10 10:00:12 +0000
commite4dabe9993a51a1c59b5423c71c6de8d77f84eca (patch)
tree8728b7d1abef2cf07c0679ff65650ce589bc6bf7
parent2b9d1feeaaeb0bb98e7bd5a6f1bdc29db9d37f9c (diff)
downloadchromium_src-e4dabe9993a51a1c59b5423c71c6de8d77f84eca.zip
chromium_src-e4dabe9993a51a1c59b5423c71c6de8d77f84eca.tar.gz
chromium_src-e4dabe9993a51a1c59b5423c71c6de8d77f84eca.tar.bz2
Implement preference and policy based content settings providers.
BUG=64753 TEST=*ContentSettings*.* Review URL: http://codereview.chromium.org/5528010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68834 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/content_settings/content_settings_provider.h16
-rw-r--r--chrome/browser/content_settings/host_content_settings_map.cc256
-rw-r--r--chrome/browser/content_settings/host_content_settings_map.h52
-rw-r--r--chrome/browser/content_settings/host_content_settings_map_unittest.cc105
-rw-r--r--chrome/browser/content_settings/host_content_settings_map_unittest.h49
-rw-r--r--chrome/browser/content_settings/mock_content_settings_provider.cc9
-rw-r--r--chrome/browser/content_settings/mock_content_settings_provider.h7
-rw-r--r--chrome/browser/content_settings/policy_content_settings_provider.cc204
-rw-r--r--chrome/browser/content_settings/policy_content_settings_provider.h78
-rw-r--r--chrome/browser/content_settings/policy_content_settings_provider_unittest.cc88
-rw-r--r--chrome/browser/content_settings/pref_content_settings_provider.cc263
-rw-r--r--chrome/browser/content_settings/pref_content_settings_provider.h88
-rw-r--r--chrome/browser/content_settings/pref_content_settings_provider_unittest.cc124
-rw-r--r--chrome/browser/cookies_tree_model_unittest.cc25
-rw-r--r--chrome/browser/prefs/browser_prefs.cc4
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/chrome_tests.gypi3
17 files changed, 1006 insertions, 369 deletions
diff --git a/chrome/browser/content_settings/content_settings_provider.h b/chrome/browser/content_settings/content_settings_provider.h
index 3229779a..2754bfc 100644
--- a/chrome/browser/content_settings/content_settings_provider.h
+++ b/chrome/browser/content_settings/content_settings_provider.h
@@ -12,14 +12,17 @@
class ContentSettingsProviderInterface {
public:
+ virtual ~ContentSettingsProviderInterface() {}
+
// True if this provider can provide a default setting for the |content_type|.
- virtual bool CanProvideDefaultSetting(ContentSettingsType content_type) = 0;
+ virtual bool CanProvideDefaultSetting(
+ ContentSettingsType content_type) const = 0;
// Returns the default content setting this provider has for the given
// |content_type|, or CONTENT_SETTING_DEFAULT if nothing be provided for this
// type.
virtual ContentSetting ProvideDefaultSetting(
- ContentSettingsType content_type) = 0;
+ ContentSettingsType content_type) const = 0;
// Notifies the provider that the host content settings map would like to
// update the default setting for the given |content_type|. The provider may
@@ -27,12 +30,13 @@ class ContentSettingsProviderInterface {
virtual void UpdateDefaultSetting(ContentSettingsType content_type,
ContentSetting setting) = 0;
+ // Resets the state of the provider to the default.
+ virtual void ResetToDefaults() = 0;
+
// True if the default setting for the |content_type| is policy managed, i.e.,
// there shouldn't be any UI shown to modify this setting.
- virtual bool DefaultSettingIsManaged(ContentSettingsType content_type) = 0;
-
- protected:
- virtual ~ContentSettingsProviderInterface() {};
+ virtual bool DefaultSettingIsManaged(
+ ContentSettingsType content_type) const = 0;
};
#endif // CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_PROVIDER_H_
diff --git a/chrome/browser/content_settings/host_content_settings_map.cc b/chrome/browser/content_settings/host_content_settings_map.cc
index c2dea38..7de7a80 100644
--- a/chrome/browser/content_settings/host_content_settings_map.cc
+++ b/chrome/browser/content_settings/host_content_settings_map.cc
@@ -9,6 +9,8 @@
#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/policy_content_settings_provider.h"
+#include "chrome/browser/content_settings/pref_content_settings_provider.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
@@ -20,19 +22,11 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "googleurl/src/gurl.h"
-#include "googleurl/src/url_canon.h"
-#include "googleurl/src/url_parse.h"
-#include "net/base/dns_util.h"
#include "net/base/net_util.h"
#include "net/base/static_cookie_policy.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 preference keys where resource identifiers are stored for
// ContentSettingsType values that support resource identifiers.
const char* kResourceTypeNames[CONTENT_SETTINGS_NUM_TYPES] = {
@@ -56,28 +50,6 @@ const char* kTypeNames[CONTENT_SETTINGS_NUM_TYPES] = {
NULL, // Not used for Notifications
};
-// 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
-};
-
-// The default setting for each content type.
-const ContentSetting kDefaultSettings[CONTENT_SETTINGS_NUM_TYPES] = {
- CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_COOKIES
- CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_IMAGES
- CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_JAVASCRIPT
- CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_PLUGINS
- CONTENT_SETTING_BLOCK, // CONTENT_SETTINGS_TYPE_POPUPS
- CONTENT_SETTING_ASK, // Not used for Geolocation
- CONTENT_SETTING_ASK, // Not used for Notifications
-};
-
// True if a given content settings type requires additional resource
// identifiers.
const bool kRequiresResourceIdentifier[CONTENT_SETTINGS_NUM_TYPES] = {
@@ -115,6 +87,12 @@ ContentSetting ClickToPlayFixup(ContentSettingsType content_type,
return setting;
}
+typedef std::vector<linked_ptr<ContentSettingsProviderInterface> >::iterator
+ provider_iterator;
+typedef
+ std::vector<linked_ptr<ContentSettingsProviderInterface> >::const_iterator
+ const_provider_iterator;
+
} // namespace
@@ -125,10 +103,20 @@ struct HostContentSettingsMap::ExtendedContentSettings {
HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
: profile_(profile),
- block_third_party_cookies_(false),
- is_block_third_party_cookies_managed_(false),
is_off_the_record_(profile_->IsOffTheRecord()),
- updating_preferences_(false) {
+ updating_preferences_(false),
+ block_third_party_cookies_(false),
+ is_block_third_party_cookies_managed_(false) {
+ // The order in which the content settings providers are created is critical,
+ // as providers that are further down in the list (i.e. added later) override
+ // providers further up.
+ content_settings_providers_.push_back(
+ linked_ptr<ContentSettingsProviderInterface>(
+ new PrefContentSettingsProvider(profile)));
+ content_settings_providers_.push_back(
+ linked_ptr<ContentSettingsProviderInterface>(
+ new PolicyContentSettingsProvider(profile)));
+
PrefService* prefs = profile_->GetPrefs();
MigrateObsoleteCookiePref(prefs);
@@ -137,11 +125,6 @@ HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
MigrateObsoletePerhostPref(prefs);
- // Read global defaults.
- DCHECK_EQ(arraysize(kTypeNames),
- static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES));
- ReadDefaultSettings(false);
-
// Read misc. global settings.
block_third_party_cookies_ =
prefs->GetBoolean(prefs::kBlockThirdPartyCookies);
@@ -165,29 +148,15 @@ HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
ReadExceptions(false);
pref_change_registrar_.Init(prefs);
- pref_change_registrar_.Add(prefs::kDefaultContentSettings, this);
pref_change_registrar_.Add(prefs::kContentSettingsPatterns, this);
pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this);
pref_change_registrar_.Add(prefs::kBlockNonsandboxedPlugins, this);
- // 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_));
}
// static
void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) {
- prefs->RegisterDictionaryPref(prefs::kDefaultContentSettings);
prefs->RegisterIntegerPref(prefs::kContentSettingsVersion,
ContentSettingsPattern::kContentSettingsPatternVersion);
prefs->RegisterDictionaryPref(prefs::kContentSettingsPatterns);
@@ -195,19 +164,6 @@ void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) {
prefs->RegisterBooleanPref(prefs::kBlockNonsandboxedPlugins, false);
prefs->RegisterIntegerPref(prefs::kContentSettingsWindowLastTabIndex, 0);
- // 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);
-
// Obsolete prefs, for migration:
prefs->RegisterIntegerPref(prefs::kCookieBehavior,
net::StaticCookiePolicy::ALLOW_ALL_COOKIES);
@@ -217,10 +173,21 @@ void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) {
ContentSetting HostContentSettingsMap::GetDefaultContentSetting(
ContentSettingsType content_type) const {
- AutoLock auto_lock(lock_);
- if (IsDefaultContentSettingManaged(content_type))
- return managed_default_content_settings_.settings[content_type];
- return default_content_settings_.settings[content_type];
+ ContentSetting setting = CONTENT_SETTING_DEFAULT;
+ for (const_provider_iterator provider = content_settings_providers_.begin();
+ provider != content_settings_providers_.end(); ++provider) {
+ if (!(*provider)->CanProvideDefaultSetting(content_type))
+ continue;
+ ContentSetting provided_setting =
+ (*provider)->ProvideDefaultSetting(content_type);
+ if (provided_setting != CONTENT_SETTING_DEFAULT)
+ setting = provided_setting;
+ }
+ // The method GetDefaultContentSetting always has to return an explicit
+ // value that is to be used as default. We here rely on the
+ // PrefContentSettingProvider to always provide a value.
+ CHECK_NE(CONTENT_SETTING_DEFAULT, setting);
+ return setting;
}
ContentSetting HostContentSettingsMap::GetContentSetting(
@@ -318,22 +285,17 @@ ContentSettings HostContentSettingsMap::GetContentSettings(
const GURL& url) const {
ContentSettings output = GetNonDefaultContentSettings(url);
- AutoLock auto_lock(lock_);
-
// If we require a resource identifier, set the content settings to default,
// otherwise make the defaults explicit.
for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
if (RequiresResourceIdentifier(ContentSettingsType(j))) {
output.settings[j] = CONTENT_SETTING_DEFAULT;
} else {
- if (output.settings[j] == CONTENT_SETTING_DEFAULT) {
- output.settings[j] = default_content_settings_.settings[j];
- }
// A managed default content setting has the highest priority and hence
// will overwrite any previously set value.
- if (IsDefaultContentSettingManaged(ContentSettingsType(j))) {
- output.settings[j] =
- managed_default_content_settings_.settings[j];
+ if ((output.settings[j] == CONTENT_SETTING_DEFAULT) ||
+ IsDefaultContentSettingManaged(ContentSettingsType(j))) {
+ output.settings[j] = GetDefaultContentSetting(ContentSettingsType(j));
}
}
}
@@ -441,7 +403,6 @@ void HostContentSettingsMap::SetDefaultContentSetting(
setting != CONTENT_SETTING_ASK ||
CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableClickToPlay));
- PrefService* prefs = profile_->GetPrefs();
// The default settings may not be directly modified for OTR sessions.
// Instead, they are synced to the main profile's setting.
@@ -450,29 +411,10 @@ void HostContentSettingsMap::SetDefaultContentSetting(
return;
}
- DictionaryValue* default_settings_dictionary =
- prefs->GetMutableDictionary(prefs::kDefaultContentSettings);
- std::string dictionary_path(kTypeNames[content_type]);
- updating_preferences_ = true;
- {
- AutoLock auto_lock(lock_);
- ScopedPrefUpdate update(prefs, prefs::kDefaultContentSettings);
- if ((setting == CONTENT_SETTING_DEFAULT) ||
- (setting == kDefaultSettings[content_type])) {
- default_content_settings_.settings[content_type] =
- kDefaultSettings[content_type];
- default_settings_dictionary->RemoveWithoutPathExpansion(dictionary_path,
- NULL);
- } else {
- default_content_settings_.settings[content_type] = setting;
- default_settings_dictionary->SetWithoutPathExpansion(
- dictionary_path, Value::CreateIntegerValue(setting));
- }
+ for (provider_iterator provider = content_settings_providers_.begin();
+ provider != content_settings_providers_.end(); ++provider) {
+ (*provider)->UpdateDefaultSetting(content_type, setting);
}
- updating_preferences_ = false;
-
- NotifyObservers(
- ContentSettingsDetails(ContentSettingsPattern(), content_type, ""));
}
void HostContentSettingsMap::SetContentSetting(
@@ -727,10 +669,10 @@ void HostContentSettingsMap::ResetToDefaults() {
{
AutoLock auto_lock(lock_);
- default_content_settings_ = ContentSettings();
- ForceDefaultsToBeExplicit();
- // Clear all content settings map except the
- // managed_default_content_settings.
+ for (provider_iterator provider = content_settings_providers_.begin();
+ provider != content_settings_providers_.end(); ++provider) {
+ (*provider)->ResetToDefaults();
+ }
host_content_settings_.clear();
off_the_record_settings_.clear();
// Don't reset block third party cookies if they are managed.
@@ -742,7 +684,6 @@ void HostContentSettingsMap::ResetToDefaults() {
if (!is_off_the_record_) {
PrefService* prefs = profile_->GetPrefs();
updating_preferences_ = true;
- prefs->ClearPref(prefs::kDefaultContentSettings);
prefs->ClearPref(prefs::kContentSettingsPatterns);
// If the block third party cookies preference is managed we still must
// clear it in order to restore the default value for later when the
@@ -761,46 +702,25 @@ void HostContentSettingsMap::Observe(NotificationType type,
const NotificationDetails& details) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (NotificationType::PREF_CHANGED == type) {
+ if (type == NotificationType::PREF_CHANGED) {
+ DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr());
if (updating_preferences_)
return;
std::string* name = Details<std::string>(details).ptr();
- if (prefs::kDefaultContentSettings == *name) {
- ReadDefaultSettings(true);
- } else if (prefs::kContentSettingsPatterns == *name) {
+ if (*name == prefs::kContentSettingsPatterns) {
ReadExceptions(true);
- } else if (prefs::kBlockThirdPartyCookies == *name) {
+ } else if (*name == prefs::kBlockThirdPartyCookies) {
AutoLock auto_lock(lock_);
block_third_party_cookies_ = profile_->GetPrefs()->GetBoolean(
prefs::kBlockThirdPartyCookies);
is_block_third_party_cookies_managed_ =
profile_->GetPrefs()->IsManagedPreference(
prefs::kBlockThirdPartyCookies);
- } else if (prefs::kBlockNonsandboxedPlugins == *name) {
+ } else if (*name == prefs::kBlockNonsandboxedPlugins) {
AutoLock auto_lock(lock_);
block_nonsandboxed_plugins_ = profile_->GetPrefs()->GetBoolean(
prefs::kBlockNonsandboxedPlugins);
- } else if (prefs::kManagedDefaultCookiesSetting == *name) {
- UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES,
- profile_->GetPrefs(),
- &managed_default_content_settings_);
- } else if (prefs::kManagedDefaultImagesSetting == *name) {
- UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_IMAGES,
- profile_->GetPrefs(),
- &managed_default_content_settings_);
- } else if (prefs::kManagedDefaultJavaScriptSetting == *name) {
- UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT,
- profile_->GetPrefs(),
- &managed_default_content_settings_);
- } else if (prefs::kManagedDefaultPluginsSetting == *name) {
- UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
- profile_->GetPrefs(),
- &managed_default_content_settings_);
- } else if (prefs::kManagedDefaultPopupsSetting == *name) {
- UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_POPUPS,
- profile_->GetPrefs(),
- &managed_default_content_settings_);
} else {
NOTREACHED() << "Unexpected preference observed";
return;
@@ -811,7 +731,8 @@ void HostContentSettingsMap::Observe(NotificationType type,
CONTENT_SETTINGS_TYPE_DEFAULT,
""));
}
- } else if (NotificationType::PROFILE_DESTROYED == type) {
+ } else if (type == NotificationType::PROFILE_DESTROYED) {
+ DCHECK_EQ(profile_, Source<Profile>(source).ptr());
UnregisterObservers();
} else {
NOTREACHED() << "Unexpected notification";
@@ -881,16 +802,6 @@ void HostContentSettingsMap::GetResourceSettingsFromDictionary(
}
}
-void HostContentSettingsMap::ForceDefaultsToBeExplicit() {
- DCHECK_EQ(arraysize(kDefaultSettings),
- static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES));
-
- for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
- if (default_content_settings_.settings[i] == CONTENT_SETTING_DEFAULT)
- default_content_settings_.settings[i] = kDefaultSettings[i];
- }
-}
-
bool HostContentSettingsMap::AllDefault(
const ExtendedContentSettings& settings) const {
for (size_t i = 0; i < arraysize(settings.content_settings.settings); ++i) {
@@ -900,64 +811,19 @@ bool HostContentSettingsMap::AllDefault(
return settings.content_settings_for_resources.empty();
}
-void HostContentSettingsMap::ReadDefaultSettings(bool overwrite) {
- PrefService* prefs = profile_->GetPrefs();
- const DictionaryValue* default_settings_dictionary =
- prefs->GetDictionary(prefs::kDefaultContentSettings);
-
- if (overwrite)
- default_content_settings_ = ContentSettings();
-
- // Careful: The returned value could be NULL if the pref has never been set.
- if (default_settings_dictionary != NULL) {
- GetSettingsFromDictionary(default_settings_dictionary,
- &default_content_settings_);
- }
- ForceDefaultsToBeExplicit();
-
- // Read managed default content settings.
- ReadManagedDefaultSettings(prefs, &managed_default_content_settings_);
-}
-
-void HostContentSettingsMap::ReadManagedDefaultSettings(
- const PrefService* prefs, ContentSettings* settings) {
- for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) {
- if (kPrefToManageType[type] == NULL) {
- // TODO(markusheintz): Handle Geolocation and notification separately.
- continue;
- }
- UpdateManagedDefaultSetting(ContentSettingsType(type), prefs, settings);
- }
-}
-
-void HostContentSettingsMap::UpdateManagedDefaultSetting(
- ContentSettingsType type,
- const PrefService* prefs,
- ContentSettings* settings) {
- // If a pref to manage a default-content-setting was not set (NOTICE:
- // "HasPrefPath" returns false if no value was set for a registered pref) then
- // the default value of the preference is used. The default value of a
- // preference to manage a default-content-settings is
- // CONTENT_SETTING_DEFAULT. This indicates that no managed value is set. If a
- // pref was set, than it MUST be managed.
- DCHECK(!prefs->HasPrefPath(kPrefToManageType[type]) ||
- prefs->IsManagedPreference(kPrefToManageType[type]));
- AutoLock auto_lock(lock_);
- settings->settings[type] = IntToContentSetting(
- prefs->GetInteger(kPrefToManageType[type]));
-}
-
bool HostContentSettingsMap::IsDefaultContentSettingManaged(
ContentSettingsType content_type) const {
- // All managed_default_content_settings_ are always set explicitly or
- // initialized to CONTENT_SETTINGS_DEFAULT. Hence each content settings type
- // that is set to CONTENT_SETTINGS_DEFAULT is not managed since it was not set
- // explicitly.
- return managed_default_content_settings_.settings[content_type] !=
- CONTENT_SETTING_DEFAULT;
+ for (const_provider_iterator provider = content_settings_providers_.begin();
+ provider != content_settings_providers_.end(); ++provider) {
+ if ((*provider)->DefaultSettingIsManaged(content_type))
+ return true;
+ }
+ return false;
}
void HostContentSettingsMap::ReadExceptions(bool overwrite) {
+ AutoLock lock(lock_);
+
PrefService* prefs = profile_->GetPrefs();
DictionaryValue* all_settings_dictionary =
prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
diff --git a/chrome/browser/content_settings/host_content_settings_map.h b/chrome/browser/content_settings/host_content_settings_map.h
index e19c125..915d974 100644
--- a/chrome/browser/content_settings/host_content_settings_map.h
+++ b/chrome/browser/content_settings/host_content_settings_map.h
@@ -15,6 +15,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/linked_ptr.h"
#include "base/lock.h"
#include "base/ref_counted.h"
#include "chrome/browser/browser_thread.h"
@@ -25,6 +26,7 @@
#include "chrome/common/notification_registrar.h"
class ContentSettingsDetails;
+class ContentSettingsProviderInterface;
class DictionaryValue;
class GURL;
class PrefService;
@@ -187,30 +189,9 @@ class HostContentSettingsMap
void GetResourceSettingsFromDictionary(const DictionaryValue* dictionary,
ResourceContentSettings* settings);
- // Forces the default settings to be explicitly set instead of themselves
- // being CONTENT_SETTING_DEFAULT.
- void ForceDefaultsToBeExplicit();
-
// Returns true if |settings| consists entirely of CONTENT_SETTING_DEFAULT.
bool AllDefault(const ExtendedContentSettings& settings) const;
- // Reads the default settings from the prefereces service. If |overwrite| is
- // true and the preference is missing, the local copy will be cleared as well.
- void ReadDefaultSettings(bool overwrite);
-
- // Reads managed default content settings from the preference service |prefs|.
- // |settings| is set to the respective content setting for managed settings,
- // and to CONTENT_SETTING_DEFAULT for other settings.
- void ReadManagedDefaultSettings(const PrefService* prefs,
- ContentSettings* settings);
-
- // Updates the managed setting of the default-content-settings-type |type|.
- // The updated setting is read from the preference service |prefs| and written
- // to |settings|.
- void UpdateManagedDefaultSetting(ContentSettingsType type,
- const PrefService* prefs,
- ContentSettings* settings);
-
// Reads the host exceptions from the prefereces service. If |overwrite| is
// true and the preference is missing, the local copy will be cleared as well.
void ReadExceptions(bool overwrite);
@@ -240,9 +221,22 @@ class HostContentSettingsMap
NotificationRegistrar notification_registrar_;
PrefChangeRegistrar pref_change_registrar_;
- // Copies of the pref data, so that we can read it on the IO thread.
- ContentSettings default_content_settings_;
- ContentSettings managed_default_content_settings_;
+ // Whether this settings map is for an OTR session.
+ bool is_off_the_record_;
+
+ // Whether we are currently updating preferences, this is used to ignore
+ // notifications from the preferences service that we triggered ourself.
+ bool updating_preferences_;
+
+ // Content setting providers.
+ std::vector<linked_ptr<ContentSettingsProviderInterface> >
+ content_settings_providers_;
+
+ // Used around accesses to the following objects to guarantee thread safety.
+ mutable Lock lock_;
+
+ // 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
@@ -254,16 +248,6 @@ class HostContentSettingsMap
bool is_block_third_party_cookies_managed_;
bool block_nonsandboxed_plugins_;
- // Used around accesses to the settings objects to guarantee thread safety.
- mutable Lock lock_;
-
- // Whether this settings map is for an OTR session.
- bool is_off_the_record_;
-
- // Whether we are currently updating preferences, this is used to ignore
- // notifications from the preferences service that we triggered ourself.
- bool updating_preferences_;
-
DISALLOW_COPY_AND_ASSIGN(HostContentSettingsMap);
};
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 280799b..2e0929e 100644
--- a/chrome/browser/content_settings/host_content_settings_map_unittest.cc
+++ b/chrome/browser/content_settings/host_content_settings_map_unittest.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/host_content_settings_map.h"
+#include "chrome/browser/content_settings/host_content_settings_map_unittest.h"
#include "base/auto_reset.h"
#include "base/command_line.h"
@@ -33,40 +33,6 @@ bool SettingsEqual(const ContentSettings& settings1,
return true;
}
-class StubSettingsObserver : public NotificationObserver {
- public:
- StubSettingsObserver() : last_notifier(NULL), counter(0) {
- registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
- NotificationService::AllSources());
- }
-
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- ++counter;
- Source<HostContentSettingsMap> content_settings(source);
- Details<ContentSettingsDetails> settings_details(details);
- last_notifier = content_settings.ptr();
- last_pattern = settings_details.ptr()->pattern();
- last_update_all = settings_details.ptr()->update_all();
- last_update_all_types = settings_details.ptr()->update_all_types();
- last_type = settings_details.ptr()->type();
- // This checks that calling a Get function from an observer doesn't
- // deadlock.
- last_notifier->GetContentSettings(GURL("http://random-hostname.com/"));
- }
-
- HostContentSettingsMap* last_notifier;
- ContentSettingsPattern last_pattern;
- bool last_update_all;
- bool last_update_all_types;
- int counter;
- ContentSettingsType last_type;
-
- private:
- NotificationRegistrar registrar_;
-};
-
class HostContentSettingsMapTest : public testing::Test {
public:
HostContentSettingsMapTest() : ui_thread_(BrowserThread::UI, &message_loop_) {
@@ -831,75 +797,6 @@ TEST_F(HostContentSettingsMapTest, OverwrittenDefaultContentSetting) {
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(HostContentSettingsMapTest, ObserveManagedSettingsChange) {
- TestingProfile profile;
- HostContentSettingsMap* host_content_settings_map =
- profile.GetHostContentSettingsMap();
- StubSettingsObserver observer;
- TestingPrefService* prefs = profile.GetTestingPrefService();
-
- // TODO(markusheintz): I think it would be better to send notifications only
- // for a specific content-settings-type.
-
- // Set the managed default-content-setting.
- prefs->SetManagedPref(prefs::kManagedDefaultImagesSetting,
- Value::CreateIntegerValue(CONTENT_SETTING_BLOCK));
- EXPECT_EQ(host_content_settings_map, 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(host_content_settings_map, 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);
-}
-
-// 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. In this test-case the actual managed
-// setting is the same. Just the managed status of the default-content-setting
-// changes.
-TEST_F(HostContentSettingsMapTest, ObserveManagedSettingsNoChange) {
- TestingProfile profile;
- HostContentSettingsMap* host_content_settings_map =
- profile.GetHostContentSettingsMap();
- StubSettingsObserver observer;
- TestingPrefService* prefs = profile.GetTestingPrefService();
-
- // TODO(markusheintz): I think it would be better to send notifications only
- // for a specific content-settings-type.
-
- // Set the managed default-content-setting. In this case the actual setting
- // does not change.
- prefs->SetManagedPref(prefs::kManagedDefaultImagesSetting,
- Value::CreateIntegerValue(CONTENT_SETTING_ALLOW));
- EXPECT_EQ(host_content_settings_map, 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(host_content_settings_map, 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);
-}
-
// If a setting for a default-content-setting-type is set while the type is
// managed, then the new setting should be preserved and used after the
// default-content-setting-type is not managed anymore.
diff --git a/chrome/browser/content_settings/host_content_settings_map_unittest.h b/chrome/browser/content_settings/host_content_settings_map_unittest.h
new file mode 100644
index 0000000..ba56ab4
--- /dev/null
+++ b/chrome/browser/content_settings/host_content_settings_map_unittest.h
@@ -0,0 +1,49 @@
+// 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.
+
+#ifndef CHROME_BROWSER_CONTENT_SETTINGS_HOST_CONTENT_SETTINGS_MAP_UNITTEST_H_
+#define CHROME_BROWSER_CONTENT_SETTINGS_HOST_CONTENT_SETTINGS_MAP_UNITTEST_H_
+#pragma once
+
+#include "chrome/browser/content_settings/content_settings_details.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/common/notification_service.h"
+#include "googleurl/src/gurl.h"
+
+class HostContentSettingsMap;
+
+class StubSettingsObserver : public NotificationObserver {
+ public:
+ StubSettingsObserver() : last_notifier(NULL), counter(0) {
+ registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
+ NotificationService::AllSources());
+ }
+
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ ++counter;
+ Source<HostContentSettingsMap> content_settings(source);
+ Details<ContentSettingsDetails> settings_details(details);
+ last_notifier = content_settings.ptr();
+ last_pattern = settings_details.ptr()->pattern();
+ last_update_all = settings_details.ptr()->update_all();
+ last_update_all_types = settings_details.ptr()->update_all_types();
+ last_type = settings_details.ptr()->type();
+ // This checks that calling a Get function from an observer doesn't
+ // deadlock.
+ last_notifier->GetContentSettings(GURL("http://random-hostname.com/"));
+ }
+
+ HostContentSettingsMap* last_notifier;
+ ContentSettingsPattern last_pattern;
+ bool last_update_all;
+ bool last_update_all_types;
+ int counter;
+ ContentSettingsType last_type;
+
+ private:
+ NotificationRegistrar registrar_;
+};
+#endif // CHROME_BROWSER_CONTENT_SETTINGS_HOST_CONTENT_SETTINGS_MAP_UNITTEST_H_
diff --git a/chrome/browser/content_settings/mock_content_settings_provider.cc b/chrome/browser/content_settings/mock_content_settings_provider.cc
index f93f7ce..ee3e845 100644
--- a/chrome/browser/content_settings/mock_content_settings_provider.cc
+++ b/chrome/browser/content_settings/mock_content_settings_provider.cc
@@ -19,12 +19,12 @@ MockContentSettingsProvider::~MockContentSettingsProvider() {
}
bool MockContentSettingsProvider::CanProvideDefaultSetting(
- ContentSettingsType content_type) {
+ ContentSettingsType content_type) const {
return content_type == content_type_;
}
ContentSetting MockContentSettingsProvider::ProvideDefaultSetting(
- ContentSettingsType content_type) {
+ ContentSettingsType content_type) const {
return content_type == content_type_ ? setting_ : CONTENT_SETTING_DEFAULT;
}
@@ -36,6 +36,9 @@ void MockContentSettingsProvider::UpdateDefaultSetting(
}
bool MockContentSettingsProvider::DefaultSettingIsManaged(
- ContentSettingsType content_type) {
+ ContentSettingsType content_type) const {
return content_type == content_type_ && is_managed_;
}
+
+void MockContentSettingsProvider::ResetToDefaults() {
+}
diff --git a/chrome/browser/content_settings/mock_content_settings_provider.h b/chrome/browser/content_settings/mock_content_settings_provider.h
index e716909..113a8ae 100644
--- a/chrome/browser/content_settings/mock_content_settings_provider.h
+++ b/chrome/browser/content_settings/mock_content_settings_provider.h
@@ -20,12 +20,13 @@ class MockContentSettingsProvider : public ContentSettingsProviderInterface {
virtual ~MockContentSettingsProvider();
// ContentSettingsProviderInterface implementation.
- virtual bool CanProvideDefaultSetting(ContentSettingsType content_type);
+ virtual bool CanProvideDefaultSetting(ContentSettingsType content_type) const;
virtual ContentSetting ProvideDefaultSetting(
- ContentSettingsType content_type);
+ ContentSettingsType content_type) const;
virtual void UpdateDefaultSetting(ContentSettingsType content_type,
ContentSetting setting);
- virtual bool DefaultSettingIsManaged(ContentSettingsType content_type);
+ virtual void ResetToDefaults();
+ virtual bool DefaultSettingIsManaged(ContentSettingsType content_type) const;
private:
ContentSettingsType content_type_;
diff --git a/chrome/browser/content_settings/policy_content_settings_provider.cc b/chrome/browser/content_settings/policy_content_settings_provider.cc
new file mode 100644
index 0000000..5bc8e9f
--- /dev/null
+++ b/chrome/browser/content_settings/policy_content_settings_provider.cc
@@ -0,0 +1,204 @@
+// 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 "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/chrome_switches.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
+
+PolicyContentSettingsProvider::PolicyContentSettingsProvider(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_));
+}
+
+PolicyContentSettingsProvider::~PolicyContentSettingsProvider() {
+ UnregisterObservers();
+}
+
+bool PolicyContentSettingsProvider::CanProvideDefaultSetting(
+ ContentSettingsType content_type) const {
+ AutoLock lock(lock_);
+ if (managed_default_content_settings_.settings[content_type] !=
+ CONTENT_SETTING_DEFAULT) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+ContentSetting PolicyContentSettingsProvider::ProvideDefaultSetting(
+ ContentSettingsType content_type) const {
+ AutoLock auto_lock(lock_);
+ return managed_default_content_settings_.settings[content_type];
+}
+
+void PolicyContentSettingsProvider::UpdateDefaultSetting(
+ ContentSettingsType content_type,
+ ContentSetting setting) {
+}
+
+bool PolicyContentSettingsProvider::DefaultSettingIsManaged(
+ ContentSettingsType content_type) const {
+ AutoLock lock(lock_);
+ if (managed_default_content_settings_.settings[content_type] !=
+ CONTENT_SETTING_DEFAULT) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void PolicyContentSettingsProvider::ResetToDefaults() {
+}
+
+void PolicyContentSettingsProvider::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 PolicyContentSettingsProvider::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 PolicyContentSettingsProvider::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 PolicyContentSettingsProvider::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 PolicyContentSettingsProvider::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]));
+ AutoLock auto_lock(lock_);
+ managed_default_content_settings_.settings[type] = IntToContentSetting(
+ prefs->GetInteger(kPrefToManageType[type]));
+}
+
+// static
+void PolicyContentSettingsProvider::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);
+}
diff --git a/chrome/browser/content_settings/policy_content_settings_provider.h b/chrome/browser/content_settings/policy_content_settings_provider.h
new file mode 100644
index 0000000..1844234
--- /dev/null
+++ b/chrome/browser/content_settings/policy_content_settings_provider.h
@@ -0,0 +1,78 @@
+// 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.
+
+#ifndef CHROME_BROWSER_CONTENT_SETTINGS_POLICY_CONTENT_SETTINGS_PROVIDER_H_
+#define CHROME_BROWSER_CONTENT_SETTINGS_POLICY_CONTENT_SETTINGS_PROVIDER_H_
+#pragma once
+
+// A content settings provider that takes its settings out of policies.
+
+#include "base/basictypes.h"
+#include "base/lock.h"
+#include "chrome/browser/content_settings/content_settings_provider.h"
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class ContentSettingsDetails;
+class DictionaryValue;
+class PrefService;
+class Profile;
+
+class PolicyContentSettingsProvider : public ContentSettingsProviderInterface,
+ public NotificationObserver {
+ public:
+ explicit PolicyContentSettingsProvider(Profile* profile);
+ virtual ~PolicyContentSettingsProvider();
+
+ // ContentSettingsProviderInterface implementation.
+ virtual bool CanProvideDefaultSetting(ContentSettingsType content_type) const;
+ virtual ContentSetting ProvideDefaultSetting(
+ ContentSettingsType content_type) const;
+ virtual void UpdateDefaultSetting(ContentSettingsType content_type,
+ ContentSetting setting);
+ virtual void ResetToDefaults();
+ virtual bool DefaultSettingIsManaged(ContentSettingsType content_type) const;
+
+ static void RegisterUserPrefs(PrefService* prefs);
+
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ private:
+ // Informs observers that content settings have changed. Make sure that
+ // |lock_| is not held when calling this, as listeners will usually call one
+ // of the GetSettings functions in response, which would then lead to a
+ // mutex deadlock.
+ void NotifyObservers(const ContentSettingsDetails& details);
+
+ void UnregisterObservers();
+
+ // Reads the policy managed default settings.
+ void ReadManagedDefaultSettings();
+
+ // Reads the policy controlled default settings for a specific content type.
+ void UpdateManagedDefaultSetting(ContentSettingsType content_type);
+
+ // Copies of the pref data, so that we can read it on the IO thread.
+ ContentSettings managed_default_content_settings_;
+
+ Profile* profile_;
+
+ // Whether this settings map is for an OTR session.
+ bool is_off_the_record_;
+
+ // Used around accesses to the managed_default_content_settings_ object to
+ // guarantee thread safety.
+ mutable Lock lock_;
+
+ PrefChangeRegistrar pref_change_registrar_;
+ NotificationRegistrar notification_registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(PolicyContentSettingsProvider);
+};
+
+#endif // CHROME_BROWSER_CONTENT_SETTINGS_POLICY_CONTENT_SETTINGS_PROVIDER_H_
diff --git a/chrome/browser/content_settings/policy_content_settings_provider_unittest.cc b/chrome/browser/content_settings/policy_content_settings_provider_unittest.cc
new file mode 100644
index 0000000..9c639ab
--- /dev/null
+++ b/chrome/browser/content_settings/policy_content_settings_provider_unittest.cc
@@ -0,0 +1,88 @@
+// 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/content_settings/host_content_settings_map_unittest.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 {
+
+class PolicyContentSettingsProviderTest : public testing::Test {
+ public:
+ PolicyContentSettingsProviderTest()
+ : ui_thread_(BrowserThread::UI, &message_loop_) {
+ }
+
+ protected:
+ MessageLoop message_loop_;
+ BrowserThread ui_thread_;
+};
+
+TEST_F(PolicyContentSettingsProviderTest, DefaultValues) {
+ TestingProfile profile;
+ PolicyContentSettingsProvider provider(&profile);
+ TestingPrefService* prefs = profile.GetTestingPrefService();
+
+ // By default, policies should be off.
+ ASSERT_FALSE(
+ provider.CanProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+ 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.CanProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+ 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.CanProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+ 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(PolicyContentSettingsProviderTest, 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
diff --git a/chrome/browser/content_settings/pref_content_settings_provider.cc b/chrome/browser/content_settings/pref_content_settings_provider.cc
new file mode 100644
index 0000000..01ac055
--- /dev/null
+++ b/chrome/browser/content_settings/pref_content_settings_provider.cc
@@ -0,0 +1,263 @@
+// 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/pref_content_settings_provider.h"
+
+#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/chrome_switches.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 {
+
+// The default setting for each content type.
+const ContentSetting kDefaultSettings[CONTENT_SETTINGS_NUM_TYPES] = {
+ CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_COOKIES
+ CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_IMAGES
+ CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_JAVASCRIPT
+ CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_PLUGINS
+ CONTENT_SETTING_BLOCK, // CONTENT_SETTINGS_TYPE_POPUPS
+ CONTENT_SETTING_ASK, // Not used for Geolocation
+ CONTENT_SETTING_ASK, // Not used for Notifications
+};
+
+// The names of the ContentSettingsType values, for use with dictionary prefs.
+const char* kTypeNames[CONTENT_SETTINGS_NUM_TYPES] = {
+ "cookies",
+ "images",
+ "javascript",
+ "plugins",
+ "popups",
+ NULL, // Not used for Geolocation
+ NULL, // 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;
+}
+
+} // namespace
+
+PrefContentSettingsProvider::PrefContentSettingsProvider(Profile* profile)
+ : profile_(profile),
+ is_off_the_record_(profile_->IsOffTheRecord()),
+ updating_preferences_(false) {
+ PrefService* prefs = profile->GetPrefs();
+
+ // Read global defaults.
+ DCHECK_EQ(arraysize(kTypeNames),
+ static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES));
+ ReadDefaultSettings(true);
+
+ pref_change_registrar_.Init(prefs);
+ pref_change_registrar_.Add(prefs::kDefaultContentSettings, this);
+ notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
+ Source<Profile>(profile_));
+}
+
+PrefContentSettingsProvider::~PrefContentSettingsProvider() {
+ UnregisterObservers();
+}
+
+bool PrefContentSettingsProvider::CanProvideDefaultSetting(
+ ContentSettingsType content_type) const {
+ return true;
+}
+
+ContentSetting PrefContentSettingsProvider::ProvideDefaultSetting(
+ ContentSettingsType content_type) const {
+ AutoLock lock(lock_);
+ return default_content_settings_.settings[content_type];
+}
+
+void PrefContentSettingsProvider::UpdateDefaultSetting(
+ ContentSettingsType content_type,
+ ContentSetting setting) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(kTypeNames[content_type] != NULL); // Don't call this for Geolocation.
+ DCHECK(content_type != CONTENT_SETTINGS_TYPE_PLUGINS ||
+ setting != CONTENT_SETTING_ASK ||
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableClickToPlay));
+
+ // The default settings may not be directly modified for OTR sessions.
+ // Instead, they are synced to the main profile's setting.
+ if (is_off_the_record_)
+ return;
+
+ PrefService* prefs = profile_->GetPrefs();
+
+ DictionaryValue* default_settings_dictionary =
+ prefs->GetMutableDictionary(prefs::kDefaultContentSettings);
+ std::string dictionary_path(kTypeNames[content_type]);
+ updating_preferences_ = true;
+ {
+ AutoLock lock(lock_);
+ ScopedPrefUpdate update(prefs, prefs::kDefaultContentSettings);
+ if ((setting == CONTENT_SETTING_DEFAULT) ||
+ (setting == kDefaultSettings[content_type])) {
+ default_content_settings_.settings[content_type] =
+ kDefaultSettings[content_type];
+ default_settings_dictionary->RemoveWithoutPathExpansion(dictionary_path,
+ NULL);
+ } else {
+ default_content_settings_.settings[content_type] = setting;
+ default_settings_dictionary->SetWithoutPathExpansion(
+ dictionary_path, Value::CreateIntegerValue(setting));
+ }
+ }
+ updating_preferences_ = false;
+
+ NotifyObservers(
+ ContentSettingsDetails(ContentSettingsPattern(), content_type, ""));
+}
+
+bool PrefContentSettingsProvider::DefaultSettingIsManaged(
+ ContentSettingsType content_type) const {
+ return false;
+}
+
+void PrefContentSettingsProvider::ResetToDefaults() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ AutoLock lock(lock_);
+ default_content_settings_ = ContentSettings();
+ ForceDefaultsToBeExplicit();
+
+ if (!is_off_the_record_) {
+ PrefService* prefs = profile_->GetPrefs();
+ updating_preferences_ = true;
+ prefs->ClearPref(prefs::kDefaultContentSettings);
+ updating_preferences_ = false;
+ }
+}
+
+void PrefContentSettingsProvider::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());
+ if (updating_preferences_)
+ return;
+
+ std::string* name = Details<std::string>(details).ptr();
+ if (*name == prefs::kDefaultContentSettings) {
+ ReadDefaultSettings(true);
+ } 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 PrefContentSettingsProvider::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 PrefContentSettingsProvider::ReadDefaultSettings(bool overwrite) {
+ PrefService* prefs = profile_->GetPrefs();
+ const DictionaryValue* default_settings_dictionary =
+ prefs->GetDictionary(prefs::kDefaultContentSettings);
+
+ AutoLock lock(lock_);
+
+ if (overwrite)
+ default_content_settings_ = ContentSettings();
+
+ // Careful: The returned value could be NULL if the pref has never been set.
+ if (default_settings_dictionary != NULL) {
+ GetSettingsFromDictionary(default_settings_dictionary,
+ &default_content_settings_);
+ }
+ ForceDefaultsToBeExplicit();
+}
+
+void PrefContentSettingsProvider::ForceDefaultsToBeExplicit() {
+ DCHECK_EQ(arraysize(kDefaultSettings),
+ static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES));
+
+ for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
+ if (default_content_settings_.settings[i] == CONTENT_SETTING_DEFAULT)
+ default_content_settings_.settings[i] = kDefaultSettings[i];
+ }
+}
+
+void PrefContentSettingsProvider::GetSettingsFromDictionary(
+ const DictionaryValue* dictionary,
+ ContentSettings* settings) {
+ for (DictionaryValue::key_iterator i(dictionary->begin_keys());
+ i != dictionary->end_keys(); ++i) {
+ const std::string& content_type(*i);
+ for (size_t type = 0; type < arraysize(kTypeNames); ++type) {
+ if ((kTypeNames[type] != NULL) && (kTypeNames[type] == content_type)) {
+ int setting = CONTENT_SETTING_DEFAULT;
+ bool found = dictionary->GetIntegerWithoutPathExpansion(content_type,
+ &setting);
+ DCHECK(found);
+ settings->settings[type] = IntToContentSetting(setting);
+ break;
+ }
+ }
+ }
+ // Migrate obsolete cookie prompt mode.
+ if (settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] ==
+ CONTENT_SETTING_ASK)
+ 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]);
+}
+
+void PrefContentSettingsProvider::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));
+}
+
+
+// static
+void PrefContentSettingsProvider::RegisterUserPrefs(PrefService* prefs) {
+ prefs->RegisterDictionaryPref(prefs::kDefaultContentSettings);
+}
diff --git a/chrome/browser/content_settings/pref_content_settings_provider.h b/chrome/browser/content_settings/pref_content_settings_provider.h
new file mode 100644
index 0000000..178e903
--- /dev/null
+++ b/chrome/browser/content_settings/pref_content_settings_provider.h
@@ -0,0 +1,88 @@
+// 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.
+
+#ifndef CHROME_BROWSER_CONTENT_SETTINGS_PREF_CONTENT_SETTINGS_PROVIDER_H_
+#define CHROME_BROWSER_CONTENT_SETTINGS_PREF_CONTENT_SETTINGS_PROVIDER_H_
+#pragma once
+
+// A content settings provider that takes its settings out of the pref service.
+
+#include "base/basictypes.h"
+#include "base/lock.h"
+#include "chrome/browser/content_settings/content_settings_provider.h"
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class ContentSettingsDetails;
+class DictionaryValue;
+class PrefService;
+class Profile;
+
+class PrefContentSettingsProvider : public ContentSettingsProviderInterface,
+ public NotificationObserver {
+ public:
+ explicit PrefContentSettingsProvider(Profile* profile);
+ virtual ~PrefContentSettingsProvider();
+
+ // ContentSettingsProviderInterface implementation.
+ virtual bool CanProvideDefaultSetting(ContentSettingsType content_type) const;
+ virtual ContentSetting ProvideDefaultSetting(
+ ContentSettingsType content_type) const;
+ virtual void UpdateDefaultSetting(ContentSettingsType content_type,
+ ContentSetting setting);
+ virtual void ResetToDefaults();
+ virtual bool DefaultSettingIsManaged(ContentSettingsType content_type) const;
+
+ static void RegisterUserPrefs(PrefService* prefs);
+
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ private:
+ // Informs observers that content settings have changed. Make sure that
+ // |lock_| is not held when calling this, as listeners will usually call one
+ // of the GetSettings functions in response, which would then lead to a
+ // mutex deadlock.
+ void NotifyObservers(const ContentSettingsDetails& details);
+
+ void UnregisterObservers();
+
+ // Sets the fields of |settings| based on the values in |dictionary|.
+ void GetSettingsFromDictionary(const DictionaryValue* dictionary,
+ ContentSettings* settings);
+
+ // Forces the default settings to be explicitly set instead of themselves
+ // being CONTENT_SETTING_DEFAULT.
+ void ForceDefaultsToBeExplicit();
+
+ // Reads the default settings from the preferences service. If |overwrite| is
+ // true and the preference is missing, the local copy will be cleared as well.
+ void ReadDefaultSettings(bool overwrite);
+
+ // Copies of the pref data, so that we can read it on the IO thread.
+ ContentSettings default_content_settings_;
+
+ Profile* profile_;
+
+ // Whether this settings map is for an OTR session.
+ bool is_off_the_record_;
+
+ // Used around accesses to the default_content_settings_ object to guarantee
+ // thread safety.
+ mutable Lock lock_;
+
+ PrefChangeRegistrar pref_change_registrar_;
+ NotificationRegistrar notification_registrar_;
+
+ // Whether we are currently updating preferences, this is used to ignore
+ // notifications from the preferences service that we triggered ourself.
+ bool updating_preferences_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrefContentSettingsProvider);
+};
+
+#endif // CHROME_BROWSER_CONTENT_SETTINGS_PREF_CONTENT_SETTINGS_PROVIDER_H_
diff --git a/chrome/browser/content_settings/pref_content_settings_provider_unittest.cc b/chrome/browser/content_settings/pref_content_settings_provider_unittest.cc
new file mode 100644
index 0000000..f4289f3
--- /dev/null
+++ b/chrome/browser/content_settings/pref_content_settings_provider_unittest.cc
@@ -0,0 +1,124 @@
+// 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/pref_content_settings_provider.h"
+
+#include "chrome/browser/content_settings/host_content_settings_map_unittest.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 {
+
+class PrefContentSettingsProviderTest : public testing::Test {
+ public:
+ PrefContentSettingsProviderTest()
+ : ui_thread_(BrowserThread::UI, &message_loop_) {
+ }
+
+ protected:
+ MessageLoop message_loop_;
+ BrowserThread ui_thread_;
+};
+
+TEST_F(PrefContentSettingsProviderTest, DefaultValues) {
+ TestingProfile profile;
+ PrefContentSettingsProvider provider(&profile);
+
+ ASSERT_TRUE(
+ provider.CanProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+ ASSERT_FALSE(
+ provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES));
+
+ // Check setting defaults.
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+ provider.UpdateDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES,
+ CONTENT_SETTING_BLOCK);
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+ provider.ResetToDefaults();
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+}
+
+TEST_F(PrefContentSettingsProviderTest, Observer) {
+ TestingProfile profile;
+ PrefContentSettingsProvider provider(&profile);
+ StubSettingsObserver observer;
+
+ provider.UpdateDefaultSetting(
+ CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_BLOCK);
+ EXPECT_EQ(profile.GetHostContentSettingsMap(), observer.last_notifier);
+ EXPECT_TRUE(observer.last_update_all);
+ EXPECT_FALSE(observer.last_update_all_types);
+ EXPECT_EQ(1, observer.counter);
+}
+
+TEST_F(PrefContentSettingsProviderTest, ObserveDefaultPref) {
+ TestingProfile profile;
+ PrefContentSettingsProvider provider(&profile);
+
+ PrefService* prefs = profile.GetPrefs();
+
+ // Make a copy of the default pref value so we can reset it later.
+ scoped_ptr<Value> default_value(prefs->FindPreference(
+ prefs::kDefaultContentSettings)->GetValue()->DeepCopy());
+
+ provider.UpdateDefaultSetting(
+ CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_BLOCK);
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+
+ // Make a copy of the pref's new value so we can reset it later.
+ scoped_ptr<Value> new_value(prefs->FindPreference(
+ prefs::kDefaultContentSettings)->GetValue()->DeepCopy());
+
+ // Clearing the backing pref should also clear the internal cache.
+ prefs->Set(prefs::kDefaultContentSettings, *default_value);
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+
+ // Reseting the pref to its previous value should update the cache.
+ prefs->Set(prefs::kDefaultContentSettings, *new_value);
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+}
+
+TEST_F(PrefContentSettingsProviderTest, OffTheRecord) {
+ TestingProfile profile;
+ PrefContentSettingsProvider provider(&profile);
+
+ profile.set_off_the_record(true);
+ PrefContentSettingsProvider otr_provider(&profile);
+ profile.set_off_the_record(false);
+
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ otr_provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+
+ // Changing content settings on the main provider should also affect the
+ // off-the-record map.
+ provider.UpdateDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES,
+ CONTENT_SETTING_BLOCK);
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ otr_provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+
+ // Changing content settings on the off-the-record provider should be ignored.
+ otr_provider.UpdateDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES,
+ CONTENT_SETTING_ALLOW);
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ otr_provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+}
+
+} // namespace
diff --git a/chrome/browser/cookies_tree_model_unittest.cc b/chrome/browser/cookies_tree_model_unittest.cc
index 0ba3960..aa5159a 100644
--- a/chrome/browser/cookies_tree_model_unittest.cc
+++ b/chrome/browser/cookies_tree_model_unittest.cc
@@ -6,8 +6,7 @@
#include <string>
-#include "chrome/browser/content_settings/content_settings_details.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/content_settings/host_content_settings_map_unittest.h"
#include "chrome/browser/mock_browsing_data_appcache_helper.h"
#include "chrome/browser/mock_browsing_data_database_helper.h"
#include "chrome/browser/mock_browsing_data_indexed_db_helper.h"
@@ -23,28 +22,6 @@
namespace {
-class StubSettingsObserver : public NotificationObserver {
- public:
- StubSettingsObserver() : counter(0) {
- registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
- NotificationService::AllSources());
- }
-
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- ++counter;
- Details<ContentSettingsDetails> settings_details(details);
- last_pattern = settings_details.ptr()->pattern();
- }
-
- ContentSettingsPattern last_pattern;
- int counter;
-
- private:
- NotificationRegistrar registrar_;
-};
-
class CookiesTreeModelTest : public testing::Test {
public:
CookiesTreeModelTest() : ui_thread_(BrowserThread::UI, &message_loop_),
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index df68921..b947969 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -12,6 +12,8 @@
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/content_settings/policy_content_settings_provider.h"
+#include "chrome/browser/content_settings/pref_content_settings_provider.h"
#include "chrome/browser/debugger/devtools_manager.h"
#include "chrome/browser/dom_ui/flags_ui.h"
#include "chrome/browser/dom_ui/new_tab_ui.h"
@@ -127,6 +129,8 @@ void RegisterUserPrefs(PrefService* user_prefs) {
PluginsUI::RegisterUserPrefs(user_prefs);
ProfileImpl::RegisterUserPrefs(user_prefs);
HostContentSettingsMap::RegisterUserPrefs(user_prefs);
+ PolicyContentSettingsProvider::RegisterUserPrefs(user_prefs);
+ PrefContentSettingsProvider::RegisterUserPrefs(user_prefs);
HostZoomMap::RegisterUserPrefs(user_prefs);
DevToolsManager::RegisterUserPrefs(user_prefs);
PinnedTabCodec::RegisterUserPrefs(user_prefs);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 6698c06..0469357 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -800,6 +800,10 @@
'browser/content_settings/content_settings_provider.h',
'browser/content_settings/host_content_settings_map.cc',
'browser/content_settings/host_content_settings_map.h',
+ 'browser/content_settings/policy_content_settings_provider.cc',
+ 'browser/content_settings/policy_content_settings_provider.h',
+ 'browser/content_settings/pref_content_settings_provider.cc',
+ 'browser/content_settings/pref_content_settings_provider.h',
'browser/cookies_tree_model.cc',
'browser/cookies_tree_model.h',
'browser/cross_site_request_manager.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 31ce387..88ca592 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1115,6 +1115,9 @@
'browser/content_settings/content_settings_pattern_unittest.cc',
'browser/content_settings/content_settings_provider_unittest.cc',
'browser/content_settings/host_content_settings_map_unittest.cc',
+ 'browser/content_settings/host_content_settings_map_unittest.h',
+ 'browser/content_settings/policy_content_settings_provider_unittest.cc',
+ 'browser/content_settings/pref_content_settings_provider_unittest.cc',
'browser/content_settings/mock_content_settings_provider.cc',
'browser/content_settings/mock_content_settings_provider.h',
'browser/cookies_tree_model_unittest.cc',