1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/content_settings/cookie_settings.h" 6 7#include "base/command_line.h" 8#include "base/prefs/pref_service.h" 9#include "chrome/browser/chrome_notification_types.h" 10#include "chrome/browser/content_settings/content_settings_utils.h" 11#include "chrome/browser/content_settings/host_content_settings_map.h" 12#include "chrome/browser/profiles/incognito_helpers.h" 13#include "chrome/browser/profiles/profile.h" 14#include "chrome/common/chrome_switches.h" 15#include "chrome/common/content_settings_pattern.h" 16#include "chrome/common/pref_names.h" 17#include "components/browser_context_keyed_service/browser_context_dependency_manager.h" 18#include "components/browser_context_keyed_service/browser_context_keyed_service.h" 19#include "components/user_prefs/pref_registry_syncable.h" 20#include "content/public/browser/browser_thread.h" 21#include "content/public/browser/notification_service.h" 22#include "content/public/browser/notification_source.h" 23#include "content/public/browser/user_metrics.h" 24#include "extensions/common/constants.h" 25#include "net/base/net_errors.h" 26#include "net/base/static_cookie_policy.h" 27#include "url/gurl.h" 28 29using content::BrowserThread; 30using content::UserMetricsAction; 31 32namespace { 33 34bool IsValidSetting(ContentSetting setting) { 35 return (setting == CONTENT_SETTING_ALLOW || 36 setting == CONTENT_SETTING_SESSION_ONLY || 37 setting == CONTENT_SETTING_BLOCK); 38} 39 40bool IsAllowed(ContentSetting setting) { 41 DCHECK(IsValidSetting(setting)); 42 return (setting == CONTENT_SETTING_ALLOW || 43 setting == CONTENT_SETTING_SESSION_ONLY); 44} 45 46} // namespace 47 48// static 49scoped_refptr<CookieSettings> CookieSettings::Factory::GetForProfile( 50 Profile* profile) { 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 52 return static_cast<CookieSettings*>( 53 GetInstance()->GetServiceForBrowserContext(profile, true).get()); 54} 55 56// static 57CookieSettings::Factory* CookieSettings::Factory::GetInstance() { 58 return Singleton<CookieSettings::Factory>::get(); 59} 60 61CookieSettings::Factory::Factory() 62 : RefcountedBrowserContextKeyedServiceFactory( 63 "CookieSettings", 64 BrowserContextDependencyManager::GetInstance()) { 65} 66 67CookieSettings::Factory::~Factory() {} 68 69void CookieSettings::Factory::RegisterProfilePrefs( 70 user_prefs::PrefRegistrySyncable* registry) { 71 registry->RegisterBooleanPref( 72 prefs::kBlockThirdPartyCookies, 73 false, 74 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 75} 76 77content::BrowserContext* CookieSettings::Factory::GetBrowserContextToUse( 78 content::BrowserContext* context) const { 79 return chrome::GetBrowserContextRedirectedInIncognito(context); 80} 81 82scoped_refptr<RefcountedBrowserContextKeyedService> 83CookieSettings::Factory::BuildServiceInstanceFor( 84 content::BrowserContext* context) const { 85 Profile* profile = static_cast<Profile*>(context); 86 return new CookieSettings(profile->GetHostContentSettingsMap(), 87 profile->GetPrefs()); 88} 89 90CookieSettings::CookieSettings( 91 HostContentSettingsMap* host_content_settings_map, 92 PrefService* prefs) 93 : host_content_settings_map_(host_content_settings_map), 94 block_third_party_cookies_( 95 prefs->GetBoolean(prefs::kBlockThirdPartyCookies)) { 96 if (block_third_party_cookies_) { 97 content::RecordAction( 98 UserMetricsAction("ThirdPartyCookieBlockingEnabled")); 99 } else { 100 content::RecordAction( 101 UserMetricsAction("ThirdPartyCookieBlockingDisabled")); 102 } 103 104 pref_change_registrar_.Init(prefs); 105 pref_change_registrar_.Add( 106 prefs::kBlockThirdPartyCookies, 107 base::Bind(&CookieSettings::OnBlockThirdPartyCookiesChanged, 108 base::Unretained(this))); 109} 110 111ContentSetting 112CookieSettings::GetDefaultCookieSetting(std::string* provider_id) const { 113 return host_content_settings_map_->GetDefaultContentSetting( 114 CONTENT_SETTINGS_TYPE_COOKIES, provider_id); 115} 116 117bool CookieSettings::IsReadingCookieAllowed(const GURL& url, 118 const GURL& first_party_url) const { 119 ContentSetting setting = GetCookieSetting(url, first_party_url, false, NULL); 120 return IsAllowed(setting); 121} 122 123bool CookieSettings::IsSettingCookieAllowed(const GURL& url, 124 const GURL& first_party_url) const { 125 ContentSetting setting = GetCookieSetting(url, first_party_url, true, NULL); 126 return IsAllowed(setting); 127} 128 129bool CookieSettings::IsCookieSessionOnly(const GURL& origin) const { 130 ContentSetting setting = GetCookieSetting(origin, origin, true, NULL); 131 DCHECK(IsValidSetting(setting)); 132 return (setting == CONTENT_SETTING_SESSION_ONLY); 133} 134 135void CookieSettings::GetCookieSettings( 136 ContentSettingsForOneType* settings) const { 137 return host_content_settings_map_->GetSettingsForOneType( 138 CONTENT_SETTINGS_TYPE_COOKIES, std::string(), settings); 139} 140 141void CookieSettings::SetDefaultCookieSetting(ContentSetting setting) { 142 DCHECK(IsValidSetting(setting)); 143 host_content_settings_map_->SetDefaultContentSetting( 144 CONTENT_SETTINGS_TYPE_COOKIES, setting); 145} 146 147void CookieSettings::SetCookieSetting( 148 const ContentSettingsPattern& primary_pattern, 149 const ContentSettingsPattern& secondary_pattern, 150 ContentSetting setting) { 151 DCHECK(IsValidSetting(setting)); 152 if (setting == CONTENT_SETTING_SESSION_ONLY) { 153 DCHECK(secondary_pattern == ContentSettingsPattern::Wildcard()); 154 } 155 host_content_settings_map_->SetContentSetting(primary_pattern, 156 secondary_pattern, 157 CONTENT_SETTINGS_TYPE_COOKIES, 158 std::string(), 159 setting); 160} 161 162void CookieSettings::ResetCookieSetting( 163 const ContentSettingsPattern& primary_pattern, 164 const ContentSettingsPattern& secondary_pattern) { 165 host_content_settings_map_->SetContentSetting(primary_pattern, 166 secondary_pattern, 167 CONTENT_SETTINGS_TYPE_COOKIES, 168 std::string(), 169 CONTENT_SETTING_DEFAULT); 170} 171 172void CookieSettings::ShutdownOnUIThread() { 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 174 pref_change_registrar_.RemoveAll(); 175} 176 177ContentSetting CookieSettings::GetCookieSetting( 178 const GURL& url, 179 const GURL& first_party_url, 180 bool setting_cookie, 181 content_settings::SettingSource* source) const { 182 if (HostContentSettingsMap::ShouldAllowAllContent( 183 url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES)) 184 return CONTENT_SETTING_ALLOW; 185 186 // First get any host-specific settings. 187 content_settings::SettingInfo info; 188 scoped_ptr<base::Value> value(host_content_settings_map_->GetWebsiteSetting( 189 url, 190 first_party_url, 191 CONTENT_SETTINGS_TYPE_COOKIES, 192 std::string(), 193 &info)); 194 if (source) 195 *source = info.source; 196 197 // If no explicit exception has been made and third-party cookies are blocked 198 // by default, apply that rule. 199 if (info.primary_pattern.MatchesAllHosts() && 200 info.secondary_pattern.MatchesAllHosts() && 201 ShouldBlockThirdPartyCookies() && 202 !first_party_url.SchemeIs(extensions::kExtensionScheme)) { 203 bool not_strict = CommandLine::ForCurrentProcess()->HasSwitch( 204 switches::kOnlyBlockSettingThirdPartyCookies); 205 net::StaticCookiePolicy policy(not_strict ? 206 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES : 207 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES); 208 int rv; 209 if (setting_cookie) 210 rv = policy.CanSetCookie(url, first_party_url); 211 else 212 rv = policy.CanGetCookies(url, first_party_url); 213 DCHECK_NE(net::ERR_IO_PENDING, rv); 214 if (rv != net::OK) 215 return CONTENT_SETTING_BLOCK; 216 } 217 218 // We should always have a value, at least from the default provider. 219 DCHECK(value.get()); 220 return content_settings::ValueToContentSetting(value.get()); 221} 222 223CookieSettings::~CookieSettings() {} 224 225void CookieSettings::OnBlockThirdPartyCookiesChanged() { 226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 227 228 base::AutoLock auto_lock(lock_); 229 block_third_party_cookies_ = pref_change_registrar_.prefs()->GetBoolean( 230 prefs::kBlockThirdPartyCookies); 231} 232 233bool CookieSettings::ShouldBlockThirdPartyCookies() const { 234 base::AutoLock auto_lock(lock_); 235 return block_third_party_cookies_; 236} 237