Home | History | Annotate | Download | only in content_settings
      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