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