This source file includes following definitions.
- SupportsResourceIdentifier
- is_off_the_record_
- RegisterExtensionService
- RegisterProfilePrefs
- GetDefaultContentSettingFromProvider
- GetDefaultContentSetting
- GetContentSetting
- GetSettingsForOneType
- SetDefaultContentSetting
- SetWebsiteSetting
- SetContentSetting
- AddExceptionForURL
- ClearSettingsForOneType
- IsValueAllowedForType
- IsSettingAllowedForType
- ContentTypeHasCompoundValue
- OnContentSettingChanged
- ShutdownOnUIThread
- MigrateObsoleteClearOnExitPref
- AddSettingsForOneType
- UsedContentSettingsProviders
- ShouldAllowAllContent
- GetWebsiteSetting
- GetProviderTypeFromSource
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include <utility>
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/prefs/pref_service.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/content_settings_custom_extension_provider.h"
#include "chrome/browser/content_settings/content_settings_default_provider.h"
#include "chrome/browser/content_settings/content_settings_details.h"
#include "chrome/browser/content_settings/content_settings_internal_extension_provider.h"
#include "chrome/browser/content_settings/content_settings_observable_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/content_settings/content_settings_provider.h"
#include "chrome/browser/content_settings/content_settings_rule.h"
#include "chrome/browser/content_settings/content_settings_utils.h"
#include "chrome/browser/extensions/api/content_settings/content_settings_service.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/content_settings_pattern.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/common/constants.h"
#include "net/base/net_errors.h"
#include "net/base/static_cookie_policy.h"
#include "url/gurl.h"
using base::UserMetricsAction;
using content::BrowserThread;
namespace {
typedef std::vector<content_settings::Rule> Rules;
typedef std::pair<std::string, std::string> StringPair;
const char* kProviderNames[] = {
"platform_app",
"policy",
"extension",
"preference",
"default"
};
content_settings::SettingSource kProviderSourceMap[] = {
content_settings::SETTING_SOURCE_EXTENSION,
content_settings::SETTING_SOURCE_POLICY,
content_settings::SETTING_SOURCE_EXTENSION,
content_settings::SETTING_SOURCE_USER,
content_settings::SETTING_SOURCE_USER,
};
COMPILE_ASSERT(arraysize(kProviderSourceMap) ==
HostContentSettingsMap::NUM_PROVIDER_TYPES,
kProviderSourceMap_has_incorrect_size);
bool SupportsResourceIdentifier(ContentSettingsType content_type) {
return content_type == CONTENT_SETTINGS_TYPE_PLUGINS;
}
}
HostContentSettingsMap::HostContentSettingsMap(
PrefService* prefs,
bool incognito) :
#ifndef NDEBUG
used_from_thread_id_(base::PlatformThread::CurrentId()),
#endif
prefs_(prefs),
is_off_the_record_(incognito) {
content_settings::ObservableProvider* policy_provider =
new content_settings::PolicyProvider(prefs_);
policy_provider->AddObserver(this);
content_settings_providers_[POLICY_PROVIDER] = policy_provider;
content_settings::ObservableProvider* pref_provider =
new content_settings::PrefProvider(prefs_, is_off_the_record_);
pref_provider->AddObserver(this);
content_settings_providers_[PREF_PROVIDER] = pref_provider;
content_settings::ObservableProvider* default_provider =
new content_settings::DefaultProvider(prefs_, is_off_the_record_);
default_provider->AddObserver(this);
content_settings_providers_[DEFAULT_PROVIDER] = default_provider;
if (!is_off_the_record_) {
MigrateObsoleteClearOnExitPref();
}
}
#if defined(ENABLE_EXTENSIONS)
void HostContentSettingsMap::RegisterExtensionService(
ExtensionService* extension_service) {
DCHECK(extension_service);
DCHECK(!content_settings_providers_[INTERNAL_EXTENSION_PROVIDER]);
DCHECK(!content_settings_providers_[CUSTOM_EXTENSION_PROVIDER]);
content_settings::InternalExtensionProvider* internal_extension_provider =
new content_settings::InternalExtensionProvider(extension_service);
internal_extension_provider->AddObserver(this);
content_settings_providers_[INTERNAL_EXTENSION_PROVIDER] =
internal_extension_provider;
content_settings::ObservableProvider* custom_extension_provider =
new content_settings::CustomExtensionProvider(
extensions::ContentSettingsService::Get(
extension_service->GetBrowserContext())->content_settings_store(),
is_off_the_record_);
custom_extension_provider->AddObserver(this);
content_settings_providers_[CUSTOM_EXTENSION_PROVIDER] =
custom_extension_provider;
#ifndef NDEBUG
DCHECK(used_from_thread_id_ != base::kInvalidThreadId)
<< "Used from multiple threads before initialization complete.";
#endif
OnContentSettingChanged(ContentSettingsPattern(),
ContentSettingsPattern(),
CONTENT_SETTINGS_TYPE_DEFAULT,
std::string());
}
#endif
void HostContentSettingsMap::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterIntegerPref(
prefs::kContentSettingsWindowLastTabIndex,
0,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
registry->RegisterIntegerPref(
prefs::kContentSettingsDefaultWhitelistVersion,
0,
user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
registry->RegisterBooleanPref(
prefs::kContentSettingsClearOnExitMigrated,
false,
user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
content_settings::DefaultProvider::RegisterProfilePrefs(registry);
content_settings::PrefProvider::RegisterProfilePrefs(registry);
content_settings::PolicyProvider::RegisterProfilePrefs(registry);
}
ContentSetting HostContentSettingsMap::GetDefaultContentSettingFromProvider(
ContentSettingsType content_type,
content_settings::ProviderInterface* provider) const {
scoped_ptr<content_settings::RuleIterator> rule_iterator(
provider->GetRuleIterator(content_type, std::string(), false));
ContentSettingsPattern wildcard = ContentSettingsPattern::Wildcard();
while (rule_iterator->HasNext()) {
content_settings::Rule rule = rule_iterator->Next();
if (rule.primary_pattern == wildcard &&
rule.secondary_pattern == wildcard) {
return content_settings::ValueToContentSetting(rule.value.get());
}
}
return CONTENT_SETTING_DEFAULT;
}
ContentSetting HostContentSettingsMap::GetDefaultContentSetting(
ContentSettingsType content_type,
std::string* provider_id) const {
UsedContentSettingsProviders();
for (ConstProviderIterator provider = content_settings_providers_.begin();
provider != content_settings_providers_.end();
++provider) {
if (provider->first == PREF_PROVIDER)
continue;
ContentSetting default_setting =
GetDefaultContentSettingFromProvider(content_type, provider->second);
if (default_setting != CONTENT_SETTING_DEFAULT) {
if (provider_id)
*provider_id = kProviderNames[provider->first];
return default_setting;
}
}
NOTREACHED();
return CONTENT_SETTING_DEFAULT;
}
ContentSetting HostContentSettingsMap::GetContentSetting(
const GURL& primary_url,
const GURL& secondary_url,
ContentSettingsType content_type,
const std::string& resource_identifier) const {
DCHECK(!ContentTypeHasCompoundValue(content_type));
scoped_ptr<base::Value> value(GetWebsiteSetting(
primary_url, secondary_url, content_type, resource_identifier, NULL));
return content_settings::ValueToContentSetting(value.get());
}
void HostContentSettingsMap::GetSettingsForOneType(
ContentSettingsType content_type,
const std::string& resource_identifier,
ContentSettingsForOneType* settings) const {
DCHECK(SupportsResourceIdentifier(content_type) ||
resource_identifier.empty());
DCHECK(settings);
UsedContentSettingsProviders();
settings->clear();
for (ConstProviderIterator provider = content_settings_providers_.begin();
provider != content_settings_providers_.end();
++provider) {
if (is_off_the_record_) {
AddSettingsForOneType(provider->second,
provider->first,
content_type,
resource_identifier,
settings,
true);
}
AddSettingsForOneType(provider->second,
provider->first,
content_type,
resource_identifier,
settings,
false);
}
}
void HostContentSettingsMap::SetDefaultContentSetting(
ContentSettingsType content_type,
ContentSetting setting) {
DCHECK(IsSettingAllowedForType(prefs_, setting, content_type));
base::Value* value = NULL;
if (setting != CONTENT_SETTING_DEFAULT)
value = base::Value::CreateIntegerValue(setting);
SetWebsiteSetting(
ContentSettingsPattern::Wildcard(),
ContentSettingsPattern::Wildcard(),
content_type,
std::string(),
value);
}
void HostContentSettingsMap::SetWebsiteSetting(
const ContentSettingsPattern& primary_pattern,
const ContentSettingsPattern& secondary_pattern,
ContentSettingsType content_type,
const std::string& resource_identifier,
base::Value* value) {
DCHECK(IsValueAllowedForType(prefs_, value, content_type));
DCHECK(SupportsResourceIdentifier(content_type) ||
resource_identifier.empty());
UsedContentSettingsProviders();
for (ProviderIterator provider = content_settings_providers_.begin();
provider != content_settings_providers_.end();
++provider) {
if (provider->second->SetWebsiteSetting(primary_pattern,
secondary_pattern,
content_type,
resource_identifier,
value)) {
return;
}
}
NOTREACHED();
}
void HostContentSettingsMap::SetContentSetting(
const ContentSettingsPattern& primary_pattern,
const ContentSettingsPattern& secondary_pattern,
ContentSettingsType content_type,
const std::string& resource_identifier,
ContentSetting setting) {
DCHECK(!ContentTypeHasCompoundValue(content_type));
base::Value* value = NULL;
if (setting != CONTENT_SETTING_DEFAULT)
value = base::Value::CreateIntegerValue(setting);
SetWebsiteSetting(primary_pattern,
secondary_pattern,
content_type,
resource_identifier,
value);
}
void HostContentSettingsMap::AddExceptionForURL(
const GURL& primary_url,
const GURL& secondary_url,
ContentSettingsType content_type,
ContentSetting setting) {
DCHECK(primary_url == secondary_url);
DCHECK(!ContentTypeHasCompoundValue(content_type));
SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(primary_url),
ContentSettingsPattern::Wildcard(),
content_type,
std::string(),
CONTENT_SETTING_DEFAULT);
SetContentSetting(ContentSettingsPattern::FromURL(primary_url),
ContentSettingsPattern::Wildcard(),
content_type,
std::string(),
setting);
}
void HostContentSettingsMap::ClearSettingsForOneType(
ContentSettingsType content_type) {
UsedContentSettingsProviders();
for (ProviderIterator provider = content_settings_providers_.begin();
provider != content_settings_providers_.end();
++provider) {
provider->second->ClearAllContentSettingsRules(content_type);
}
}
bool HostContentSettingsMap::IsValueAllowedForType(
PrefService* prefs, const base::Value* value, ContentSettingsType type) {
return ContentTypeHasCompoundValue(type) || IsSettingAllowedForType(
prefs, content_settings::ValueToContentSetting(value), type);
}
bool HostContentSettingsMap::IsSettingAllowedForType(
PrefService* prefs,
ContentSetting setting,
ContentSettingsType content_type) {
if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT)
return false;
if (content_type == CONTENT_SETTINGS_TYPE_FULLSCREEN &&
setting == CONTENT_SETTING_BLOCK) {
return false;
}
if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM &&
setting == CONTENT_SETTING_ALLOW) {
return false;
}
#if defined(OS_ANDROID)
if (content_type == CONTENT_SETTINGS_TYPE_APP_BANNER)
return false;
#endif
if (setting == CONTENT_SETTING_DEFAULT ||
setting == CONTENT_SETTING_ALLOW ||
setting == CONTENT_SETTING_BLOCK) {
return true;
}
switch (content_type) {
case CONTENT_SETTINGS_TYPE_COOKIES:
return setting == CONTENT_SETTING_SESSION_ONLY;
case CONTENT_SETTINGS_TYPE_PLUGINS:
case CONTENT_SETTINGS_TYPE_GEOLOCATION:
case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
case CONTENT_SETTINGS_TYPE_MOUSELOCK:
case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
case CONTENT_SETTINGS_TYPE_PPAPI_BROKER:
case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
return setting == CONTENT_SETTING_ASK;
default:
return false;
}
}
bool HostContentSettingsMap::ContentTypeHasCompoundValue(
ContentSettingsType type) {
#if defined(OS_ANDROID)
if (type == CONTENT_SETTINGS_TYPE_APP_BANNER)
return true;
#endif
return (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
type == CONTENT_SETTINGS_TYPE_MEDIASTREAM);
}
void HostContentSettingsMap::OnContentSettingChanged(
const ContentSettingsPattern& primary_pattern,
const ContentSettingsPattern& secondary_pattern,
ContentSettingsType content_type,
std::string resource_identifier) {
const ContentSettingsDetails details(primary_pattern,
secondary_pattern,
content_type,
resource_identifier);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
content::Source<HostContentSettingsMap>(this),
content::Details<const ContentSettingsDetails>(&details));
}
HostContentSettingsMap::~HostContentSettingsMap() {
DCHECK(!prefs_);
STLDeleteValues(&content_settings_providers_);
}
void HostContentSettingsMap::ShutdownOnUIThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(prefs_);
prefs_ = NULL;
for (ProviderIterator it = content_settings_providers_.begin();
it != content_settings_providers_.end();
++it) {
it->second->ShutdownOnUIThread();
}
}
void HostContentSettingsMap::MigrateObsoleteClearOnExitPref() {
if (prefs_->HasPrefPath(prefs::kContentSettingsClearOnExitMigrated) &&
prefs_->GetBoolean(prefs::kContentSettingsClearOnExitMigrated)) {
return;
}
if (!prefs_->GetBoolean(prefs::kClearSiteDataOnExit)) {
prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true);
return;
}
ContentSetting default_setting = GetDefaultContentSettingFromProvider(
CONTENT_SETTINGS_TYPE_COOKIES,
content_settings_providers_[DEFAULT_PROVIDER]);
if (default_setting == CONTENT_SETTING_ALLOW) {
SetDefaultContentSetting(
CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_SESSION_ONLY);
}
ContentSettingsForOneType exceptions;
AddSettingsForOneType(content_settings_providers_[PREF_PROVIDER],
PREF_PROVIDER,
CONTENT_SETTINGS_TYPE_COOKIES,
std::string(),
&exceptions,
false);
for (ContentSettingsForOneType::iterator it = exceptions.begin();
it != exceptions.end(); ++it) {
if (it->setting != CONTENT_SETTING_ALLOW)
continue;
SetWebsiteSetting(it->primary_pattern,
it->secondary_pattern,
CONTENT_SETTINGS_TYPE_COOKIES,
std::string(),
base::Value::CreateIntegerValue(
CONTENT_SETTING_SESSION_ONLY));
}
prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true);
}
void HostContentSettingsMap::AddSettingsForOneType(
const content_settings::ProviderInterface* provider,
ProviderType provider_type,
ContentSettingsType content_type,
const std::string& resource_identifier,
ContentSettingsForOneType* settings,
bool incognito) const {
scoped_ptr<content_settings::RuleIterator> rule_iterator(
provider->GetRuleIterator(content_type,
resource_identifier,
incognito));
while (rule_iterator->HasNext()) {
const content_settings::Rule& rule = rule_iterator->Next();
ContentSetting setting_value = CONTENT_SETTING_DEFAULT;
if (ContentTypeHasCompoundValue(content_type) &&
rule.value.get() &&
rule.primary_pattern != ContentSettingsPattern::Wildcard()) {
setting_value = CONTENT_SETTING_ALLOW;
} else {
setting_value = content_settings::ValueToContentSetting(rule.value.get());
}
settings->push_back(ContentSettingPatternSource(
rule.primary_pattern, rule.secondary_pattern,
setting_value,
kProviderNames[provider_type],
incognito));
}
}
void HostContentSettingsMap::UsedContentSettingsProviders() const {
#ifndef NDEBUG
if (used_from_thread_id_ == base::kInvalidThreadId)
return;
if (base::PlatformThread::CurrentId() != used_from_thread_id_)
used_from_thread_id_ = base::kInvalidThreadId;
#endif
}
bool HostContentSettingsMap::ShouldAllowAllContent(
const GURL& primary_url,
const GURL& secondary_url,
ContentSettingsType content_type) {
if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS ||
content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
return false;
}
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
if (content_type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) {
return false;
}
#endif
if (secondary_url.SchemeIs(content::kChromeUIScheme) &&
content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
primary_url.SchemeIsSecure()) {
return true;
}
if (primary_url.SchemeIs(extensions::kExtensionScheme)) {
switch (content_type) {
case CONTENT_SETTINGS_TYPE_PLUGINS:
case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
return false;
case CONTENT_SETTINGS_TYPE_COOKIES:
return secondary_url.SchemeIs(extensions::kExtensionScheme);
default:
return true;
}
}
return primary_url.SchemeIs(content::kChromeDevToolsScheme) ||
primary_url.SchemeIs(content::kChromeUIScheme);
}
base::Value* HostContentSettingsMap::GetWebsiteSetting(
const GURL& primary_url,
const GURL& secondary_url,
ContentSettingsType content_type,
const std::string& resource_identifier,
content_settings::SettingInfo* info) const {
DCHECK(SupportsResourceIdentifier(content_type) ||
resource_identifier.empty());
if (ShouldAllowAllContent(primary_url, secondary_url, content_type)) {
if (info) {
info->source = content_settings::SETTING_SOURCE_WHITELIST;
info->primary_pattern = ContentSettingsPattern::Wildcard();
info->secondary_pattern = ContentSettingsPattern::Wildcard();
}
return base::Value::CreateIntegerValue(CONTENT_SETTING_ALLOW);
}
ContentSettingsPattern* primary_pattern = NULL;
ContentSettingsPattern* secondary_pattern = NULL;
if (info) {
primary_pattern = &info->primary_pattern;
secondary_pattern = &info->secondary_pattern;
}
for (ConstProviderIterator provider = content_settings_providers_.begin();
provider != content_settings_providers_.end();
++provider) {
base::Value* value = content_settings::GetContentSettingValueAndPatterns(
provider->second, primary_url, secondary_url, content_type,
resource_identifier, is_off_the_record_,
primary_pattern, secondary_pattern);
if (value) {
if (info)
info->source = kProviderSourceMap[provider->first];
return value;
}
}
if (info) {
info->source = content_settings::SETTING_SOURCE_NONE;
info->primary_pattern = ContentSettingsPattern();
info->secondary_pattern = ContentSettingsPattern();
}
return NULL;
}
HostContentSettingsMap::ProviderType
HostContentSettingsMap::GetProviderTypeFromSource(
const std::string& source) {
for (size_t i = 0; i < arraysize(kProviderNames); ++i) {
if (source == kProviderNames[i])
return static_cast<ProviderType>(i);
}
NOTREACHED();
return DEFAULT_PROVIDER;
}