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 29 using content::BrowserThread; 30 using content::UserMetricsAction; 31 32 namespace { 33 34 bool IsValidSetting(ContentSetting setting) { 35 return (setting == CONTENT_SETTING_ALLOW || 36 setting == CONTENT_SETTING_SESSION_ONLY || 37 setting == CONTENT_SETTING_BLOCK); 38 } 39 40 bool 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 49 scoped_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 57 CookieSettings::Factory* CookieSettings::Factory::GetInstance() { 58 return Singleton<CookieSettings::Factory>::get(); 59 } 60 61 CookieSettings::Factory::Factory() 62 : RefcountedBrowserContextKeyedServiceFactory( 63 "CookieSettings", 64 BrowserContextDependencyManager::GetInstance()) { 65 } 66 67 CookieSettings::Factory::~Factory() {} 68 69 void CookieSettings::Factory::RegisterProfilePrefs( 70 user_prefs::PrefRegistrySyncable* registry) { 71 registry->RegisterBooleanPref( 72 prefs::kBlockThirdPartyCookies, 73 false, 74 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 75 } 76 77 content::BrowserContext* CookieSettings::Factory::GetBrowserContextToUse( 78 content::BrowserContext* context) const { 79 return chrome::GetBrowserContextRedirectedInIncognito(context); 80 } 81 82 scoped_refptr<RefcountedBrowserContextKeyedService> 83 CookieSettings::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 90 CookieSettings::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 111 ContentSetting 112 CookieSettings::GetDefaultCookieSetting(std::string* provider_id) const { 113 return host_content_settings_map_->GetDefaultContentSetting( 114 CONTENT_SETTINGS_TYPE_COOKIES, provider_id); 115 } 116 117 bool 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 123 bool 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 129 bool 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 135 void CookieSettings::GetCookieSettings( 136 ContentSettingsForOneType* settings) const { 137 return host_content_settings_map_->GetSettingsForOneType( 138 CONTENT_SETTINGS_TYPE_COOKIES, std::string(), settings); 139 } 140 141 void CookieSettings::SetDefaultCookieSetting(ContentSetting setting) { 142 DCHECK(IsValidSetting(setting)); 143 host_content_settings_map_->SetDefaultContentSetting( 144 CONTENT_SETTINGS_TYPE_COOKIES, setting); 145 } 146 147 void 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 162 void 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 172 void CookieSettings::ShutdownOnUIThread() { 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 174 pref_change_registrar_.RemoveAll(); 175 } 176 177 ContentSetting 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 223 CookieSettings::~CookieSettings() {} 224 225 void 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 233 bool CookieSettings::ShouldBlockThirdPartyCookies() const { 234 base::AutoLock auto_lock(lock_); 235 return block_third_party_cookies_; 236 } 237