Home | History | Annotate | Download | only in content_settings
      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/host_content_settings_map.h"
      6 
      7 #include "base/command_line.h"
      8 #include "base/string_util.h"
      9 #include "base/utf_string_conversions.h"
     10 #include "chrome/browser/content_settings/content_settings_details.h"
     11 #include "chrome/browser/content_settings/content_settings_policy_provider.h"
     12 #include "chrome/browser/content_settings/content_settings_pref_provider.h"
     13 #include "chrome/browser/content_settings/content_settings_provider.h"
     14 #include "chrome/browser/metrics/user_metrics.h"
     15 #include "chrome/browser/prefs/pref_service.h"
     16 #include "chrome/browser/prefs/scoped_user_pref_update.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/common/chrome_switches.h"
     19 #include "chrome/common/pref_names.h"
     20 #include "chrome/common/url_constants.h"
     21 #include "content/browser/browser_thread.h"
     22 #include "content/common/notification_service.h"
     23 #include "content/common/notification_source.h"
     24 #include "content/common/notification_type.h"
     25 #include "googleurl/src/gurl.h"
     26 #include "net/base/net_util.h"
     27 #include "net/base/static_cookie_policy.h"
     28 
     29 namespace {
     30 
     31 // Returns true if we should allow all content types for this URL.  This is
     32 // true for various internal objects like chrome:// URLs, so UI and other
     33 // things users think of as "not webpages" don't break.
     34 static bool ShouldAllowAllContent(const GURL& url) {
     35   return url.SchemeIs(chrome::kChromeDevToolsScheme) ||
     36          url.SchemeIs(chrome::kChromeInternalScheme) ||
     37          url.SchemeIs(chrome::kChromeUIScheme) ||
     38          url.SchemeIs(chrome::kExtensionScheme) ||
     39          url.SchemeIs(chrome::kUserScriptScheme);
     40 }
     41 
     42 typedef linked_ptr<content_settings::DefaultProviderInterface>
     43     DefaultContentSettingsProviderPtr;
     44 typedef std::vector<DefaultContentSettingsProviderPtr>::iterator
     45     DefaultProviderIterator;
     46 typedef std::vector<DefaultContentSettingsProviderPtr>::const_iterator
     47     ConstDefaultProviderIterator;
     48 
     49 typedef linked_ptr<content_settings::ProviderInterface> ProviderPtr;
     50 typedef std::vector<ProviderPtr>::iterator ProviderIterator;
     51 typedef std::vector<ProviderPtr>::const_iterator ConstProviderIterator;
     52 
     53 typedef content_settings::ProviderInterface::Rules Rules;
     54 typedef content_settings::ProviderInterface::Rules::iterator
     55     rules_iterator;
     56 typedef content_settings::ProviderInterface::Rules::const_iterator
     57     const_rules_iterator;
     58 
     59 }  // namespace
     60 
     61 HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
     62     : profile_(profile),
     63       is_off_the_record_(profile_->IsOffTheRecord()),
     64       updating_preferences_(false),
     65       block_third_party_cookies_(false),
     66       is_block_third_party_cookies_managed_(false) {
     67   // The order in which the default content settings providers are created is
     68   // critical, as providers that are further down in the list (i.e. added later)
     69   // override providers further up.
     70   default_content_settings_providers_.push_back(
     71       DefaultContentSettingsProviderPtr(
     72           new content_settings::PrefDefaultProvider(profile)));
     73   default_content_settings_providers_.push_back(
     74       DefaultContentSettingsProviderPtr(
     75           new content_settings::PolicyDefaultProvider(profile)));
     76 
     77   PrefService* prefs = profile_->GetPrefs();
     78 
     79   // TODO(markusheintz): Discuss whether it is sensible to move migration code
     80   // to PrefContentSettingsProvider.
     81   MigrateObsoleteCookiePref(prefs);
     82 
     83   // Read misc. global settings.
     84   block_third_party_cookies_ =
     85       prefs->GetBoolean(prefs::kBlockThirdPartyCookies);
     86   if (block_third_party_cookies_) {
     87     UserMetrics::RecordAction(
     88         UserMetricsAction("ThirdPartyCookieBlockingEnabled"));
     89   } else {
     90     UserMetrics::RecordAction(
     91         UserMetricsAction("ThirdPartyCookieBlockingDisabled"));
     92   }
     93   is_block_third_party_cookies_managed_ =
     94       prefs->IsManagedPreference(prefs::kBlockThirdPartyCookies);
     95   block_nonsandboxed_plugins_ =
     96       prefs->GetBoolean(prefs::kBlockNonsandboxedPlugins);
     97 
     98   // User defined non default content settings are provided by the PrefProvider.
     99   // The order in which the content settings providers are created is critical,
    100   // as providers that are further up in the list (i.e. added earlier) override
    101   // providers further down.
    102   content_settings_providers_.push_back(
    103       make_linked_ptr(new content_settings::PolicyProvider(profile)));
    104   content_settings_providers_.push_back(
    105       make_linked_ptr(new content_settings::PrefProvider(profile)));
    106 
    107   pref_change_registrar_.Init(prefs);
    108   pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this);
    109   pref_change_registrar_.Add(prefs::kBlockNonsandboxedPlugins, this);
    110   notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
    111                               Source<Profile>(profile_));
    112 }
    113 
    114 // static
    115 void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) {
    116   prefs->RegisterBooleanPref(prefs::kBlockThirdPartyCookies, false);
    117   prefs->RegisterBooleanPref(prefs::kBlockNonsandboxedPlugins, false);
    118   prefs->RegisterIntegerPref(prefs::kContentSettingsWindowLastTabIndex, 0);
    119 
    120   // Obsolete prefs, for migration:
    121   prefs->RegisterIntegerPref(prefs::kCookieBehavior,
    122                              net::StaticCookiePolicy::ALLOW_ALL_COOKIES);
    123 
    124   // Register the prefs for the content settings providers.
    125   content_settings::PrefDefaultProvider::RegisterUserPrefs(prefs);
    126   content_settings::PolicyDefaultProvider::RegisterUserPrefs(prefs);
    127   content_settings::PrefProvider::RegisterUserPrefs(prefs);
    128   content_settings::PolicyProvider::RegisterUserPrefs(prefs);
    129 }
    130 
    131 ContentSetting HostContentSettingsMap::GetDefaultContentSetting(
    132     ContentSettingsType content_type) const {
    133   ContentSetting setting = CONTENT_SETTING_DEFAULT;
    134   for (ConstDefaultProviderIterator provider =
    135            default_content_settings_providers_.begin();
    136        provider != default_content_settings_providers_.end(); ++provider) {
    137     ContentSetting provided_setting =
    138         (*provider)->ProvideDefaultSetting(content_type);
    139     if (provided_setting != CONTENT_SETTING_DEFAULT)
    140       setting = provided_setting;
    141   }
    142   // The method GetDefaultContentSetting always has to return an explicit
    143   // value that is to be used as default. We here rely on the
    144   // PrefContentSettingProvider to always provide a value.
    145   CHECK_NE(CONTENT_SETTING_DEFAULT, setting);
    146   return setting;
    147 }
    148 
    149 ContentSetting HostContentSettingsMap::GetContentSetting(
    150     const GURL& url,
    151     ContentSettingsType content_type,
    152     const std::string& resource_identifier) const {
    153   ContentSetting setting = GetNonDefaultContentSetting(url,
    154                                                        content_type,
    155                                                        resource_identifier);
    156   if (setting == CONTENT_SETTING_DEFAULT)
    157     return GetDefaultContentSetting(content_type);
    158   return setting;
    159 }
    160 
    161 ContentSetting HostContentSettingsMap::GetNonDefaultContentSetting(
    162     const GURL& url,
    163     ContentSettingsType content_type,
    164     const std::string& resource_identifier) const {
    165   if (ShouldAllowAllContent(url))
    166     return CONTENT_SETTING_ALLOW;
    167 
    168   // Iterate through the list of providers and break when the first non default
    169   // setting is found.
    170   ContentSetting provided_setting(CONTENT_SETTING_DEFAULT);
    171   for (ConstProviderIterator provider = content_settings_providers_.begin();
    172        provider != content_settings_providers_.end();
    173        ++provider) {
    174     provided_setting = (*provider)->GetContentSetting(
    175         url, url, content_type, resource_identifier);
    176     bool isManaged = (*provider)->ContentSettingsTypeIsManaged(content_type);
    177     if (provided_setting != CONTENT_SETTING_DEFAULT || isManaged)
    178       return provided_setting;
    179   }
    180   return provided_setting;
    181 }
    182 
    183 ContentSettings HostContentSettingsMap::GetContentSettings(
    184     const GURL& url) const {
    185   ContentSettings output = GetNonDefaultContentSettings(url);
    186 
    187   // If we require a resource identifier, set the content settings to default,
    188   // otherwise make the defaults explicit.
    189   for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
    190     // A managed default content setting has the highest priority and hence
    191     // will overwrite any previously set value.
    192     if (output.settings[j] == CONTENT_SETTING_DEFAULT &&
    193         j != CONTENT_SETTINGS_TYPE_PLUGINS) {
    194       output.settings[j] = GetDefaultContentSetting(ContentSettingsType(j));
    195     }
    196   }
    197   return output;
    198 }
    199 
    200 ContentSettings HostContentSettingsMap::GetNonDefaultContentSettings(
    201     const GURL& url) const {
    202   if (ShouldAllowAllContent(url))
    203       return ContentSettings(CONTENT_SETTING_ALLOW);
    204 
    205   ContentSettings output(CONTENT_SETTING_DEFAULT);
    206   for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
    207     output.settings[j] = GetNonDefaultContentSetting(
    208         url, ContentSettingsType(j) , "");
    209   }
    210   return output;
    211 }
    212 
    213 void HostContentSettingsMap::GetSettingsForOneType(
    214     ContentSettingsType content_type,
    215     const std::string& resource_identifier,
    216     SettingsForOneType* settings) const {
    217   DCHECK(settings);
    218   settings->clear();
    219 
    220   // Collect content_settings::Rules for the given content_type and
    221   // resource_identifier from the content settings providers.
    222   Rules content_settings_rules;
    223   for (ConstProviderIterator provider = content_settings_providers_.begin();
    224        provider != content_settings_providers_.end();
    225        ++provider) {
    226     // TODO(markusheintz): Only the rules that are applied should be collected.
    227     // Merge rules.
    228     // TODO(markusheintz): GetAllContentSettingsRules should maybe not clear the
    229     // passed vector in case rule sets are just unified.
    230     Rules rules;
    231     (*provider)->GetAllContentSettingsRules(
    232         content_type, resource_identifier, &rules);
    233     content_settings_rules.insert(content_settings_rules.end(),
    234                                   rules.begin(),
    235                                   rules.end());
    236   }
    237 
    238   // convert Rules to SettingsForOneType
    239   for (const_rules_iterator rule_iterator =
    240            content_settings_rules.begin();
    241        rule_iterator != content_settings_rules.end();
    242        ++rule_iterator) {
    243     settings->push_back(std::make_pair(ContentSettingsPattern(
    244         rule_iterator->requesting_url_pattern),
    245         rule_iterator->content_setting));
    246   }
    247 }
    248 
    249 void HostContentSettingsMap::SetDefaultContentSetting(
    250     ContentSettingsType content_type,
    251     ContentSetting setting) {
    252   for (DefaultProviderIterator provider =
    253            default_content_settings_providers_.begin();
    254        provider != default_content_settings_providers_.end(); ++provider) {
    255     (*provider)->UpdateDefaultSetting(content_type, setting);
    256   }
    257 }
    258 
    259 void HostContentSettingsMap::SetContentSetting(
    260     const ContentSettingsPattern& pattern,
    261     ContentSettingsType content_type,
    262     const std::string& resource_identifier,
    263     ContentSetting setting) {
    264   for (ProviderIterator provider = content_settings_providers_.begin();
    265        provider != content_settings_providers_.end();
    266        ++provider) {
    267     (*provider)->SetContentSetting(
    268         pattern, pattern, content_type, resource_identifier, setting);
    269   }
    270 }
    271 
    272 void HostContentSettingsMap::AddExceptionForURL(
    273     const GURL& url,
    274     ContentSettingsType content_type,
    275     const std::string& resource_identifier,
    276     ContentSetting setting) {
    277   // Make sure there is no entry that would override the pattern we are about
    278   // to insert for exactly this URL.
    279   SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(url),
    280                     content_type,
    281                     resource_identifier,
    282                     CONTENT_SETTING_DEFAULT);
    283   SetContentSetting(ContentSettingsPattern::FromURL(url),
    284                     content_type,
    285                     resource_identifier,
    286                     setting);
    287 }
    288 
    289 void HostContentSettingsMap::ClearSettingsForOneType(
    290     ContentSettingsType content_type) {
    291   for (ProviderIterator provider = content_settings_providers_.begin();
    292        provider != content_settings_providers_.end();
    293        ++provider) {
    294     (*provider)->ClearAllContentSettingsRules(content_type);
    295   }
    296 }
    297 
    298 void HostContentSettingsMap::SetBlockThirdPartyCookies(bool block) {
    299   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    300 
    301   // This setting may not be directly modified for OTR sessions.  Instead, it
    302   // is synced to the main profile's setting.
    303   if (is_off_the_record_) {
    304     NOTREACHED();
    305     return;
    306   }
    307 
    308   PrefService* prefs = profile_->GetPrefs();
    309   // If the preference block-third-party-cookies is managed then do not allow to
    310   // change it.
    311   if (prefs->IsManagedPreference(prefs::kBlockThirdPartyCookies)) {
    312     NOTREACHED();
    313     return;
    314   }
    315 
    316   {
    317     base::AutoLock auto_lock(lock_);
    318     block_third_party_cookies_ = block;
    319   }
    320 
    321   if (block)
    322     prefs->SetBoolean(prefs::kBlockThirdPartyCookies, true);
    323   else
    324     prefs->ClearPref(prefs::kBlockThirdPartyCookies);
    325 }
    326 
    327 void HostContentSettingsMap::SetBlockNonsandboxedPlugins(bool block) {
    328   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    329 
    330   // This setting may not be directly modified for OTR sessions.  Instead, it
    331   // is synced to the main profile's setting.
    332   if (is_off_the_record_) {
    333     NOTREACHED();
    334     return;
    335   }
    336 
    337   {
    338     base::AutoLock auto_lock(lock_);
    339     block_nonsandboxed_plugins_ = block;
    340   }
    341 
    342   PrefService* prefs = profile_->GetPrefs();
    343   if (block) {
    344     UserMetrics::RecordAction(
    345         UserMetricsAction("BlockNonsandboxedPlugins_Enable"));
    346     prefs->SetBoolean(prefs::kBlockNonsandboxedPlugins, true);
    347   } else {
    348     UserMetrics::RecordAction(
    349         UserMetricsAction("BlockNonsandboxedPlugins_Disable"));
    350     prefs->ClearPref(prefs::kBlockNonsandboxedPlugins);
    351   }
    352 }
    353 
    354 void HostContentSettingsMap::ResetToDefaults() {
    355   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    356 
    357   {
    358     base::AutoLock auto_lock(lock_);
    359     for (DefaultProviderIterator provider =
    360              default_content_settings_providers_.begin();
    361          provider != default_content_settings_providers_.end(); ++provider) {
    362       (*provider)->ResetToDefaults();
    363     }
    364 
    365     for (ProviderIterator provider = content_settings_providers_.begin();
    366          provider != content_settings_providers_.end();
    367          ++provider) {
    368       (*provider)->ResetToDefaults();
    369     }
    370 
    371     // Don't reset block third party cookies if they are managed.
    372     if (!IsBlockThirdPartyCookiesManaged())
    373       block_third_party_cookies_ = false;
    374     block_nonsandboxed_plugins_ = false;
    375   }
    376 
    377   if (!is_off_the_record_) {
    378     PrefService* prefs = profile_->GetPrefs();
    379     updating_preferences_ = true;
    380     // If the block third party cookies preference is managed we still must
    381     // clear it in order to restore the default value for later when the
    382     // preference is not managed anymore.
    383     prefs->ClearPref(prefs::kBlockThirdPartyCookies);
    384     prefs->ClearPref(prefs::kBlockNonsandboxedPlugins);
    385     updating_preferences_ = false;
    386     NotifyObservers(ContentSettingsDetails(ContentSettingsPattern(),
    387                                            CONTENT_SETTINGS_TYPE_DEFAULT,
    388                                            ""));
    389   }
    390 }
    391 
    392 void HostContentSettingsMap::Observe(NotificationType type,
    393                                      const NotificationSource& source,
    394                                      const NotificationDetails& details) {
    395   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    396 
    397   if (type == NotificationType::PREF_CHANGED) {
    398     DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr());
    399     if (updating_preferences_)
    400       return;
    401 
    402     std::string* name = Details<std::string>(details).ptr();
    403     if (*name == prefs::kBlockThirdPartyCookies) {
    404       base::AutoLock auto_lock(lock_);
    405       block_third_party_cookies_ = profile_->GetPrefs()->GetBoolean(
    406           prefs::kBlockThirdPartyCookies);
    407       is_block_third_party_cookies_managed_ =
    408           profile_->GetPrefs()->IsManagedPreference(
    409               prefs::kBlockThirdPartyCookies);
    410     } else if (*name == prefs::kBlockNonsandboxedPlugins) {
    411       base::AutoLock auto_lock(lock_);
    412       block_nonsandboxed_plugins_ = profile_->GetPrefs()->GetBoolean(
    413           prefs::kBlockNonsandboxedPlugins);
    414     } else {
    415       NOTREACHED() << "Unexpected preference observed";
    416       return;
    417     }
    418 
    419     if (!is_off_the_record_) {
    420       NotifyObservers(ContentSettingsDetails(ContentSettingsPattern(),
    421                                              CONTENT_SETTINGS_TYPE_DEFAULT,
    422                                              ""));
    423     }
    424   } else if (type == NotificationType::PROFILE_DESTROYED) {
    425     DCHECK_EQ(profile_, Source<Profile>(source).ptr());
    426     UnregisterObservers();
    427   } else {
    428     NOTREACHED() << "Unexpected notification";
    429   }
    430 }
    431 
    432 HostContentSettingsMap::~HostContentSettingsMap() {
    433   UnregisterObservers();
    434 }
    435 
    436 bool HostContentSettingsMap::IsDefaultContentSettingManaged(
    437     ContentSettingsType content_type) const {
    438   for (ConstDefaultProviderIterator provider =
    439            default_content_settings_providers_.begin();
    440        provider != default_content_settings_providers_.end(); ++provider) {
    441     if ((*provider)->DefaultSettingIsManaged(content_type))
    442       return true;
    443   }
    444   return false;
    445 }
    446 
    447 void HostContentSettingsMap::NotifyObservers(
    448     const ContentSettingsDetails& details) {
    449   NotificationService::current()->Notify(
    450       NotificationType::CONTENT_SETTINGS_CHANGED,
    451       Source<HostContentSettingsMap>(this),
    452       Details<const ContentSettingsDetails>(&details));
    453 }
    454 
    455 void HostContentSettingsMap::UnregisterObservers() {
    456   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    457   if (!profile_)
    458     return;
    459   pref_change_registrar_.RemoveAll();
    460   notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED,
    461                                  Source<Profile>(profile_));
    462   profile_ = NULL;
    463 }
    464 
    465 void HostContentSettingsMap::MigrateObsoleteCookiePref(PrefService* prefs) {
    466   if (prefs->HasPrefPath(prefs::kCookieBehavior)) {
    467     int cookie_behavior = prefs->GetInteger(prefs::kCookieBehavior);
    468     prefs->ClearPref(prefs::kCookieBehavior);
    469     if (!prefs->HasPrefPath(prefs::kDefaultContentSettings)) {
    470         SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES,
    471             (cookie_behavior == net::StaticCookiePolicy::BLOCK_ALL_COOKIES) ?
    472                 CONTENT_SETTING_BLOCK : CONTENT_SETTING_ALLOW);
    473     }
    474     if (!prefs->HasPrefPath(prefs::kBlockThirdPartyCookies)) {
    475       SetBlockThirdPartyCookies(cookie_behavior ==
    476           net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
    477     }
    478   }
    479 }
    480