| Index: chrome/browser/content_settings/cookie_settings.cc
|
| diff --git a/chrome/browser/content_settings/cookie_settings.cc b/chrome/browser/content_settings/cookie_settings.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..18266fe7b7d0dde803ac67bb40824f754b91bf91
|
| --- /dev/null
|
| +++ b/chrome/browser/content_settings/cookie_settings.cc
|
| @@ -0,0 +1,311 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/content_settings/cookie_settings.h"
|
| +
|
| +#include "base/command_line.h"
|
| +#include "base/memory/singleton.h"
|
| +#include "chrome/browser/content_settings/content_settings_pattern.h"
|
| +#include "chrome/browser/content_settings/host_content_settings_map.h"
|
| +#include "chrome/browser/prefs/pref_service.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/profiles/profile_dependency_manager.h"
|
| +#include "chrome/browser/profiles/profile_keyed_service.h"
|
| +#include "chrome/browser/profiles/profile_keyed_service_factory.h"
|
| +#include "chrome/common/chrome_notification_types.h"
|
| +#include "chrome/common/chrome_switches.h"
|
| +#include "chrome/common/pref_names.h"
|
| +#include "content/browser/browser_thread.h"
|
| +#include "content/browser/user_metrics.h"
|
| +#include "content/common/notification_service.h"
|
| +#include "content/common/notification_source.h"
|
| +#include "googleurl/src/gurl.h"
|
| +#include "net/base/net_errors.h"
|
| +#include "net/base/static_cookie_policy.h"
|
| +
|
| +namespace {
|
| +
|
| +// ProfileKeyedFactory is the owner of the ProfileKeyedServices. This wrapper
|
| +// class allows others to hold shared pointers to CookieSettings.
|
| +class CookieSettingsWrapper : public ProfileKeyedService {
|
| + public:
|
| + explicit CookieSettingsWrapper(scoped_refptr<CookieSettings> cookie_settings)
|
| + : cookie_settings_(cookie_settings) {}
|
| + virtual ~CookieSettingsWrapper() {}
|
| +
|
| + CookieSettings* cookie_settings() { return cookie_settings_.get(); }
|
| +
|
| + private:
|
| + // ProfileKeyedService methods:
|
| + virtual void Shutdown() OVERRIDE {
|
| + cookie_settings_->ShutdownOnUIThread();
|
| + }
|
| +
|
| + scoped_refptr<CookieSettings> cookie_settings_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +class CookieSettings::Factory : public ProfileKeyedServiceFactory {
|
| + public:
|
| + static Factory* GetInstance();
|
| +
|
| + CookieSettingsWrapper* GetWrapperForProfile(Profile* profile);
|
| +
|
| + private:
|
| + friend struct DefaultSingletonTraits<Factory>;
|
| +
|
| + Factory();
|
| + virtual ~Factory() {}
|
| +
|
| + // PrefoileKeyedServiceFactory methods:
|
| + virtual CookieSettingsWrapper* BuildServiceInstanceFor(
|
| + Profile* profile) const OVERRIDE;
|
| + virtual bool ServiceRedirectedInIncognito() OVERRIDE { return true; }
|
| +};
|
| +
|
| +// static
|
| +CookieSettings::Factory* CookieSettings::Factory::GetInstance() {
|
| + return Singleton<CookieSettings::Factory>::get();
|
| +}
|
| +
|
| +CookieSettingsWrapper* CookieSettings::Factory::GetWrapperForProfile(
|
| + Profile* profile) {
|
| + return static_cast<CookieSettingsWrapper*>(
|
| + GetServiceForProfile(profile,true));
|
| +}
|
| +
|
| +CookieSettings::Factory::Factory()
|
| + : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) {
|
| +}
|
| +
|
| +CookieSettingsWrapper* CookieSettings::Factory::BuildServiceInstanceFor(
|
| + Profile* profile) const {
|
| + scoped_refptr<CookieSettings> cookie_settings = new CookieSettings(
|
| + profile->GetHostContentSettingsMap(),
|
| + profile->GetPrefs(),
|
| + profile->IsOffTheRecord());
|
| + return new CookieSettingsWrapper(cookie_settings);
|
| +}
|
| +
|
| +CookieSettings::CookieSettings(
|
| + HostContentSettingsMap* host_content_settings_map,
|
| + PrefService* prefs,
|
| + bool incognito)
|
| + : host_content_settings_map_(host_content_settings_map),
|
| + prefs_(prefs),
|
| + is_off_the_record_(incognito),
|
| + block_third_party_cookies_(false) {
|
| + block_third_party_cookies_ =
|
| + prefs_->GetBoolean(prefs::kBlockThirdPartyCookies);
|
| + if (block_third_party_cookies_) {
|
| + UserMetrics::RecordAction(
|
| + UserMetricsAction("ThirdPartyCookieBlockingEnabled"));
|
| + } else {
|
| + UserMetrics::RecordAction(
|
| + UserMetricsAction("ThirdPartyCookieBlockingDisabled"));
|
| + }
|
| +
|
| + pref_change_registrar_.Init(prefs_);
|
| + pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this);
|
| +}
|
| +
|
| +CookieSettings::~CookieSettings() {
|
| +}
|
| +
|
| +// static
|
| +CookieSettings* CookieSettings::GetForProfile(Profile* profile) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + CookieSettings* cookie_settings =
|
| + Factory::GetInstance()->GetWrapperForProfile(profile)->cookie_settings();
|
| + DCHECK(cookie_settings);
|
| + return cookie_settings;
|
| +}
|
| +
|
| +ContentSetting CookieSettings::GetDefaultSetting() const {
|
| + ContentSetting allow_or_block =
|
| + host_content_settings_map_->GetDefaultContentSetting(
|
| + CONTENT_SETTINGS_TYPE_COOKIES);
|
| + DCHECK(allow_or_block == CONTENT_SETTING_ALLOW ||
|
| + allow_or_block == CONTENT_SETTING_BLOCK);
|
| + if (allow_or_block == CONTENT_SETTING_BLOCK)
|
| + return allow_or_block;
|
| + ContentSetting session_only =
|
| + host_content_settings_map_->GetDefaultContentSetting(
|
| + CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY);
|
| + DCHECK(allow_or_block == CONTENT_SETTING_ALLOW ||
|
| + allow_or_block == CONTENT_SETTING_SESSION_ONLY);
|
| + return session_only;
|
| +}
|
| +
|
| +bool CookieSettings::IsReadingCookieAllowed(const GURL& url,
|
| + const GURL& first_party_url) const {
|
| + ContentSetting setting = GetCookieContentSetting(
|
| + url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, false);
|
| + DCHECK(setting == CONTENT_SETTING_ALLOW ||
|
| + setting == CONTENT_SETTING_BLOCK);
|
| + return setting == CONTENT_SETTING_ALLOW;
|
| +}
|
| +
|
| +bool CookieSettings::IsSettingCookieAllowed(const GURL& url,
|
| + const GURL& first_party_url) const {
|
| + ContentSetting setting = GetCookieContentSetting(
|
| + url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, true);
|
| + DCHECK(setting == CONTENT_SETTING_ALLOW ||
|
| + setting == CONTENT_SETTING_BLOCK);
|
| + return setting == CONTENT_SETTING_ALLOW;
|
| +}
|
| +
|
| +bool CookieSettings::IsCookieSessionOnly(const GURL& origin) const {
|
| + ContentSetting setting = GetCookieContentSetting(
|
| + origin, origin, CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, true);
|
| + DCHECK(setting == CONTENT_SETTING_ALLOW ||
|
| + setting == CONTENT_SETTING_SESSION_ONLY);
|
| + return (setting == CONTENT_SETTING_SESSION_ONLY);
|
| +}
|
| +
|
| +void CookieSettings::SetDefaultSetting(ContentSetting setting) {
|
| + DCHECK(setting == CONTENT_SETTING_ALLOW ||
|
| + setting == CONTENT_SETTING_SESSION_ONLY ||
|
| + setting == CONTENT_SETTING_BLOCK);
|
| + ContentSetting allowed = CONTENT_SETTING_BLOCK;
|
| + ContentSetting session_only = CONTENT_SETTING_ALLOW;
|
| + if (setting == CONTENT_SETTING_ALLOW ||
|
| + setting == CONTENT_SETTING_SESSION_ONLY)
|
| + allowed = CONTENT_SETTING_ALLOW;
|
| + if (setting == CONTENT_SETTING_SESSION_ONLY)
|
| + session_only = CONTENT_SETTING_SESSION_ONLY;
|
| + host_content_settings_map_->SetDefaultContentSetting(
|
| + CONTENT_SETTINGS_TYPE_COOKIES, allowed);
|
| + host_content_settings_map_->SetDefaultContentSetting(
|
| + CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, session_only);
|
| +}
|
| +
|
| +void CookieSettings::SetCookieSetting(
|
| + const ContentSettingsPattern& primary_pattern,
|
| + ContentSetting content_setting) {
|
| + DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
|
| + content_setting == CONTENT_SETTING_SESSION_ONLY ||
|
| + content_setting == CONTENT_SETTING_BLOCK);
|
| + bool allowed =
|
| + content_setting == CONTENT_SETTING_ALLOW ||
|
| + content_setting == CONTENT_SETTING_SESSION_ONLY;
|
| + bool session_only = (content_setting == CONTENT_SETTING_SESSION_ONLY);
|
| + host_content_settings_map_->SetContentSetting(
|
| + primary_pattern, ContentSettingsPattern::Wildcard(),
|
| + CONTENT_SETTINGS_TYPE_COOKIES, "",
|
| + allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK);
|
| + host_content_settings_map_->SetContentSetting(
|
| + primary_pattern, ContentSettingsPattern::Wildcard(),
|
| + CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, "",
|
| + session_only ? CONTENT_SETTING_SESSION_ONLY : CONTENT_SETTING_ALLOW);
|
| +}
|
| +
|
| +void CookieSettings::ResetCookieSetting(
|
| + const ContentSettingsPattern& primary_pattern) {
|
| + host_content_settings_map_->SetContentSetting(
|
| + primary_pattern, ContentSettingsPattern::Wildcard(),
|
| + CONTENT_SETTINGS_TYPE_COOKIES, "",
|
| + CONTENT_SETTING_DEFAULT);
|
| + host_content_settings_map_->SetContentSetting(
|
| + primary_pattern, ContentSettingsPattern::Wildcard(),
|
| + CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, "",
|
| + CONTENT_SETTING_DEFAULT);
|
| +}
|
| +
|
| +void CookieSettings::SetBlockThirdPartyCookies(bool block) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + DCHECK(prefs_);
|
| +
|
| + // This setting may not be directly modified for OTR sessions. Instead, it
|
| + // is synced to the main profile's setting.
|
| + if (is_off_the_record_) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| +
|
| + // If the preference block-third-party-cookies is managed then do not allow to
|
| + // change it.
|
| + if (prefs_->IsManagedPreference(prefs::kBlockThirdPartyCookies)) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| +
|
| + {
|
| + base::AutoLock auto_lock(lock_);
|
| + block_third_party_cookies_ = block;
|
| + }
|
| +
|
| + prefs_->SetBoolean(prefs::kBlockThirdPartyCookies, block);
|
| +}
|
| +
|
| +void CookieSettings::Observe(int type,
|
| + const NotificationSource& source,
|
| + const NotificationDetails& details) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + if (type == chrome::NOTIFICATION_PREF_CHANGED) {
|
| + DCHECK_EQ(prefs_, Source<PrefService>(source).ptr());
|
| +
|
| + std::string* name = Details<std::string>(details).ptr();
|
| + if (*name == prefs::kBlockThirdPartyCookies) {
|
| + base::AutoLock auto_lock(lock_);
|
| + block_third_party_cookies_ = prefs_->GetBoolean(
|
| + prefs::kBlockThirdPartyCookies);
|
| + } else {
|
| + NOTREACHED() << "Unexpected preference observed";
|
| + return;
|
| + }
|
| + } else {
|
| + NOTREACHED() << "Unexpected notification";
|
| + }
|
| +}
|
| +
|
| +void CookieSettings::ShutdownOnUIThread() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + pref_change_registrar_.RemoveAll();
|
| +}
|
| +
|
| +ContentSetting CookieSettings::GetCookieContentSetting(
|
| + const GURL& url,
|
| + const GURL& first_party_url,
|
| + ContentSettingsType content_type,
|
| + bool setting_cookie) const {
|
| + if (HostContentSettingsMap::ShouldAllowAllContent(
|
| + first_party_url, CONTENT_SETTINGS_TYPE_COOKIES))
|
| + return CONTENT_SETTING_ALLOW;
|
| +
|
| + // First get any host-specific settings.
|
| + ContentSetting setting =
|
| + host_content_settings_map_->GetNonDefaultContentSetting(
|
| + url, first_party_url, content_type, "");
|
| +
|
| + // Check if third-party cookie settings deny the cookie. This check makes
|
| + // sense only for the CONTENT_SETTINGS_TYPE_COOKIES, since the session only
|
| + // check is based on one url only.
|
| + if (content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
|
| + setting == CONTENT_SETTING_DEFAULT &&
|
| + ShouldBlockThirdPartyCookies()) {
|
| + bool strict = CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kBlockReadingThirdPartyCookies);
|
| + net::StaticCookiePolicy policy(strict ?
|
| + net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
|
| + net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
|
| + int rv;
|
| + if (setting_cookie)
|
| + rv = policy.CanSetCookie(url, first_party_url);
|
| + else
|
| + rv = policy.CanGetCookies(url, first_party_url);
|
| + DCHECK_NE(net::ERR_IO_PENDING, rv);
|
| + if (rv != net::OK)
|
| + setting = CONTENT_SETTING_BLOCK;
|
| + }
|
| +
|
| + // If no other policy has changed the setting, use the default.
|
| + if (setting == CONTENT_SETTING_DEFAULT) {
|
| + setting =
|
| + host_content_settings_map_->GetDefaultContentSetting(content_type);
|
| + }
|
| + return setting;
|
| +}
|
|
|