OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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/memory/singleton.h" |
| 9 #include "chrome/browser/content_settings/content_settings_pattern.h" |
| 10 #include "chrome/browser/content_settings/host_content_settings_map.h" |
| 11 #include "chrome/browser/prefs/pref_service.h" |
| 12 #include "chrome/browser/profiles/profile.h" |
| 13 #include "chrome/browser/profiles/profile_dependency_manager.h" |
| 14 #include "chrome/browser/profiles/profile_keyed_service.h" |
| 15 #include "chrome/browser/profiles/profile_keyed_service_factory.h" |
| 16 #include "chrome/common/chrome_notification_types.h" |
| 17 #include "chrome/common/chrome_switches.h" |
| 18 #include "chrome/common/pref_names.h" |
| 19 #include "content/browser/browser_thread.h" |
| 20 #include "content/browser/user_metrics.h" |
| 21 #include "content/common/notification_service.h" |
| 22 #include "content/common/notification_source.h" |
| 23 #include "googleurl/src/gurl.h" |
| 24 #include "net/base/net_errors.h" |
| 25 #include "net/base/static_cookie_policy.h" |
| 26 |
| 27 namespace { |
| 28 |
| 29 // ProfileKeyedFactory is the owner of the ProfileKeyedServices. This wrapper |
| 30 // class allows others to hold shared pointers to CookieSettings. |
| 31 class CookieSettingsWrapper : public ProfileKeyedService { |
| 32 public: |
| 33 explicit CookieSettingsWrapper(scoped_refptr<CookieSettings> cookie_settings) |
| 34 : cookie_settings_(cookie_settings) {} |
| 35 virtual ~CookieSettingsWrapper() {} |
| 36 |
| 37 CookieSettings* cookie_settings() { return cookie_settings_.get(); } |
| 38 |
| 39 private: |
| 40 // ProfileKeyedService methods: |
| 41 virtual void Shutdown() OVERRIDE { |
| 42 cookie_settings_->ShutdownOnUIThread(); |
| 43 } |
| 44 |
| 45 scoped_refptr<CookieSettings> cookie_settings_; |
| 46 }; |
| 47 |
| 48 } // namespace |
| 49 |
| 50 class CookieSettings::Factory : public ProfileKeyedServiceFactory { |
| 51 public: |
| 52 static Factory* GetInstance(); |
| 53 |
| 54 CookieSettingsWrapper* GetWrapperForProfile(Profile* profile); |
| 55 |
| 56 private: |
| 57 friend struct DefaultSingletonTraits<Factory>; |
| 58 |
| 59 Factory(); |
| 60 virtual ~Factory() {} |
| 61 |
| 62 // PrefoileKeyedServiceFactory methods: |
| 63 virtual CookieSettingsWrapper* BuildServiceInstanceFor( |
| 64 Profile* profile) const OVERRIDE; |
| 65 virtual bool ServiceRedirectedInIncognito() OVERRIDE { return true; } |
| 66 }; |
| 67 |
| 68 // static |
| 69 CookieSettings::Factory* CookieSettings::Factory::GetInstance() { |
| 70 return Singleton<CookieSettings::Factory>::get(); |
| 71 } |
| 72 |
| 73 CookieSettingsWrapper* CookieSettings::Factory::GetWrapperForProfile( |
| 74 Profile* profile) { |
| 75 return static_cast<CookieSettingsWrapper*>( |
| 76 GetServiceForProfile(profile,true)); |
| 77 } |
| 78 |
| 79 CookieSettings::Factory::Factory() |
| 80 : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) { |
| 81 } |
| 82 |
| 83 CookieSettingsWrapper* CookieSettings::Factory::BuildServiceInstanceFor( |
| 84 Profile* profile) const { |
| 85 scoped_refptr<CookieSettings> cookie_settings = new CookieSettings( |
| 86 profile->GetHostContentSettingsMap(), |
| 87 profile->GetPrefs(), |
| 88 profile->IsOffTheRecord()); |
| 89 return new CookieSettingsWrapper(cookie_settings); |
| 90 } |
| 91 |
| 92 CookieSettings::CookieSettings( |
| 93 HostContentSettingsMap* host_content_settings_map, |
| 94 PrefService* prefs, |
| 95 bool incognito) |
| 96 : host_content_settings_map_(host_content_settings_map), |
| 97 prefs_(prefs), |
| 98 is_off_the_record_(incognito), |
| 99 block_third_party_cookies_(false) { |
| 100 block_third_party_cookies_ = |
| 101 prefs_->GetBoolean(prefs::kBlockThirdPartyCookies); |
| 102 if (block_third_party_cookies_) { |
| 103 UserMetrics::RecordAction( |
| 104 UserMetricsAction("ThirdPartyCookieBlockingEnabled")); |
| 105 } else { |
| 106 UserMetrics::RecordAction( |
| 107 UserMetricsAction("ThirdPartyCookieBlockingDisabled")); |
| 108 } |
| 109 |
| 110 pref_change_registrar_.Init(prefs_); |
| 111 pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this); |
| 112 } |
| 113 |
| 114 CookieSettings::~CookieSettings() { |
| 115 } |
| 116 |
| 117 // static |
| 118 CookieSettings* CookieSettings::GetForProfile(Profile* profile) { |
| 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 120 CookieSettings* cookie_settings = |
| 121 Factory::GetInstance()->GetWrapperForProfile(profile)->cookie_settings(); |
| 122 DCHECK(cookie_settings); |
| 123 return cookie_settings; |
| 124 } |
| 125 |
| 126 ContentSetting CookieSettings::GetDefaultSetting() const { |
| 127 ContentSetting allow_or_block = |
| 128 host_content_settings_map_->GetDefaultContentSetting( |
| 129 CONTENT_SETTINGS_TYPE_COOKIES); |
| 130 DCHECK(allow_or_block == CONTENT_SETTING_ALLOW || |
| 131 allow_or_block == CONTENT_SETTING_BLOCK); |
| 132 if (allow_or_block == CONTENT_SETTING_BLOCK) |
| 133 return allow_or_block; |
| 134 ContentSetting session_only = |
| 135 host_content_settings_map_->GetDefaultContentSetting( |
| 136 CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY); |
| 137 DCHECK(allow_or_block == CONTENT_SETTING_ALLOW || |
| 138 allow_or_block == CONTENT_SETTING_SESSION_ONLY); |
| 139 return session_only; |
| 140 } |
| 141 |
| 142 bool CookieSettings::IsReadingCookieAllowed(const GURL& url, |
| 143 const GURL& first_party_url) const { |
| 144 ContentSetting setting = GetCookieContentSetting( |
| 145 url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, false); |
| 146 DCHECK(setting == CONTENT_SETTING_ALLOW || |
| 147 setting == CONTENT_SETTING_BLOCK); |
| 148 return setting == CONTENT_SETTING_ALLOW; |
| 149 } |
| 150 |
| 151 bool CookieSettings::IsSettingCookieAllowed(const GURL& url, |
| 152 const GURL& first_party_url) const { |
| 153 ContentSetting setting = GetCookieContentSetting( |
| 154 url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, true); |
| 155 DCHECK(setting == CONTENT_SETTING_ALLOW || |
| 156 setting == CONTENT_SETTING_BLOCK); |
| 157 return setting == CONTENT_SETTING_ALLOW; |
| 158 } |
| 159 |
| 160 bool CookieSettings::IsCookieSessionOnly(const GURL& origin) const { |
| 161 ContentSetting setting = GetCookieContentSetting( |
| 162 origin, origin, CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, true); |
| 163 DCHECK(setting == CONTENT_SETTING_ALLOW || |
| 164 setting == CONTENT_SETTING_SESSION_ONLY); |
| 165 return (setting == CONTENT_SETTING_SESSION_ONLY); |
| 166 } |
| 167 |
| 168 void CookieSettings::SetDefaultSetting(ContentSetting setting) { |
| 169 DCHECK(setting == CONTENT_SETTING_ALLOW || |
| 170 setting == CONTENT_SETTING_SESSION_ONLY || |
| 171 setting == CONTENT_SETTING_BLOCK); |
| 172 ContentSetting allowed = CONTENT_SETTING_BLOCK; |
| 173 ContentSetting session_only = CONTENT_SETTING_ALLOW; |
| 174 if (setting == CONTENT_SETTING_ALLOW || |
| 175 setting == CONTENT_SETTING_SESSION_ONLY) |
| 176 allowed = CONTENT_SETTING_ALLOW; |
| 177 if (setting == CONTENT_SETTING_SESSION_ONLY) |
| 178 session_only = CONTENT_SETTING_SESSION_ONLY; |
| 179 host_content_settings_map_->SetDefaultContentSetting( |
| 180 CONTENT_SETTINGS_TYPE_COOKIES, allowed); |
| 181 host_content_settings_map_->SetDefaultContentSetting( |
| 182 CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, session_only); |
| 183 } |
| 184 |
| 185 void CookieSettings::SetCookieSetting( |
| 186 const ContentSettingsPattern& primary_pattern, |
| 187 ContentSetting content_setting) { |
| 188 DCHECK(content_setting == CONTENT_SETTING_ALLOW || |
| 189 content_setting == CONTENT_SETTING_SESSION_ONLY || |
| 190 content_setting == CONTENT_SETTING_BLOCK); |
| 191 bool allowed = |
| 192 content_setting == CONTENT_SETTING_ALLOW || |
| 193 content_setting == CONTENT_SETTING_SESSION_ONLY; |
| 194 bool session_only = (content_setting == CONTENT_SETTING_SESSION_ONLY); |
| 195 host_content_settings_map_->SetContentSetting( |
| 196 primary_pattern, ContentSettingsPattern::Wildcard(), |
| 197 CONTENT_SETTINGS_TYPE_COOKIES, "", |
| 198 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK); |
| 199 host_content_settings_map_->SetContentSetting( |
| 200 primary_pattern, ContentSettingsPattern::Wildcard(), |
| 201 CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, "", |
| 202 session_only ? CONTENT_SETTING_SESSION_ONLY : CONTENT_SETTING_ALLOW); |
| 203 } |
| 204 |
| 205 void CookieSettings::ResetCookieSetting( |
| 206 const ContentSettingsPattern& primary_pattern) { |
| 207 host_content_settings_map_->SetContentSetting( |
| 208 primary_pattern, ContentSettingsPattern::Wildcard(), |
| 209 CONTENT_SETTINGS_TYPE_COOKIES, "", |
| 210 CONTENT_SETTING_DEFAULT); |
| 211 host_content_settings_map_->SetContentSetting( |
| 212 primary_pattern, ContentSettingsPattern::Wildcard(), |
| 213 CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, "", |
| 214 CONTENT_SETTING_DEFAULT); |
| 215 } |
| 216 |
| 217 void CookieSettings::SetBlockThirdPartyCookies(bool block) { |
| 218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 219 DCHECK(prefs_); |
| 220 |
| 221 // This setting may not be directly modified for OTR sessions. Instead, it |
| 222 // is synced to the main profile's setting. |
| 223 if (is_off_the_record_) { |
| 224 NOTREACHED(); |
| 225 return; |
| 226 } |
| 227 |
| 228 // If the preference block-third-party-cookies is managed then do not allow to |
| 229 // change it. |
| 230 if (prefs_->IsManagedPreference(prefs::kBlockThirdPartyCookies)) { |
| 231 NOTREACHED(); |
| 232 return; |
| 233 } |
| 234 |
| 235 { |
| 236 base::AutoLock auto_lock(lock_); |
| 237 block_third_party_cookies_ = block; |
| 238 } |
| 239 |
| 240 prefs_->SetBoolean(prefs::kBlockThirdPartyCookies, block); |
| 241 } |
| 242 |
| 243 void CookieSettings::Observe(int type, |
| 244 const NotificationSource& source, |
| 245 const NotificationDetails& details) { |
| 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 247 |
| 248 if (type == chrome::NOTIFICATION_PREF_CHANGED) { |
| 249 DCHECK_EQ(prefs_, Source<PrefService>(source).ptr()); |
| 250 |
| 251 std::string* name = Details<std::string>(details).ptr(); |
| 252 if (*name == prefs::kBlockThirdPartyCookies) { |
| 253 base::AutoLock auto_lock(lock_); |
| 254 block_third_party_cookies_ = prefs_->GetBoolean( |
| 255 prefs::kBlockThirdPartyCookies); |
| 256 } else { |
| 257 NOTREACHED() << "Unexpected preference observed"; |
| 258 return; |
| 259 } |
| 260 } else { |
| 261 NOTREACHED() << "Unexpected notification"; |
| 262 } |
| 263 } |
| 264 |
| 265 void CookieSettings::ShutdownOnUIThread() { |
| 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 267 pref_change_registrar_.RemoveAll(); |
| 268 } |
| 269 |
| 270 ContentSetting CookieSettings::GetCookieContentSetting( |
| 271 const GURL& url, |
| 272 const GURL& first_party_url, |
| 273 ContentSettingsType content_type, |
| 274 bool setting_cookie) const { |
| 275 if (HostContentSettingsMap::ShouldAllowAllContent( |
| 276 first_party_url, CONTENT_SETTINGS_TYPE_COOKIES)) |
| 277 return CONTENT_SETTING_ALLOW; |
| 278 |
| 279 // First get any host-specific settings. |
| 280 ContentSetting setting = |
| 281 host_content_settings_map_->GetNonDefaultContentSetting( |
| 282 url, first_party_url, content_type, ""); |
| 283 |
| 284 // Check if third-party cookie settings deny the cookie. This check makes |
| 285 // sense only for the CONTENT_SETTINGS_TYPE_COOKIES, since the session only |
| 286 // check is based on one url only. |
| 287 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES && |
| 288 setting == CONTENT_SETTING_DEFAULT && |
| 289 ShouldBlockThirdPartyCookies()) { |
| 290 bool strict = CommandLine::ForCurrentProcess()->HasSwitch( |
| 291 switches::kBlockReadingThirdPartyCookies); |
| 292 net::StaticCookiePolicy policy(strict ? |
| 293 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES : |
| 294 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES); |
| 295 int rv; |
| 296 if (setting_cookie) |
| 297 rv = policy.CanSetCookie(url, first_party_url); |
| 298 else |
| 299 rv = policy.CanGetCookies(url, first_party_url); |
| 300 DCHECK_NE(net::ERR_IO_PENDING, rv); |
| 301 if (rv != net::OK) |
| 302 setting = CONTENT_SETTING_BLOCK; |
| 303 } |
| 304 |
| 305 // If no other policy has changed the setting, use the default. |
| 306 if (setting == CONTENT_SETTING_DEFAULT) { |
| 307 setting = |
| 308 host_content_settings_map_->GetDefaultContentSetting(content_type); |
| 309 } |
| 310 return setting; |
| 311 } |
OLD | NEW |