| Index: chrome/browser/content_settings/pref_content_settings_provider.cc
|
| 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 0000000000000000000000000000000000000000..3d8d091a31d63aae63477db95108af749c94ecf0
|
| --- /dev/null
|
| +++ b/chrome/browser/content_settings/pref_content_settings_provider.cc
|
| @@ -0,0 +1,259 @@
|
| +// 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 auto_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 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));
|
| + }
|
| + }
|
| + 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 auto_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 (NotificationType::PREF_CHANGED == type) {
|
| + if (updating_preferences_)
|
| + return;
|
| +
|
| + std::string* name = Details<std::string>(details).ptr();
|
| + if (prefs::kDefaultContentSettings == *name) {
|
| + ReadDefaultSettings(true);
|
| + } else {
|
| + NOTREACHED() << "Unexpected preference observed";
|
| + return;
|
| + }
|
| +
|
| + if (!is_off_the_record_) {
|
| + NotifyObservers(ContentSettingsDetails(
|
| + ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, ""));
|
| + }
|
| + } else if (NotificationType::PROFILE_DESTROYED == type) {
|
| + 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);
|
| +
|
| + 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);
|
| +}
|
|
|