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/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