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 
      6 #include "chrome/browser/content_settings/content_settings_base_provider.h"
      7 
      8 #include "base/command_line.h"
      9 #include "base/logging.h"
     10 #include "chrome/common/chrome_switches.h"
     11 #include "googleurl/src/gurl.h"
     12 #include "net/base/net_util.h"
     13 
     14 namespace {
     15 
     16 // True if a given content settings type requires additional resource
     17 // identifiers.
     18 const bool kRequiresResourceIdentifier[CONTENT_SETTINGS_NUM_TYPES] = {
     19   false,  // CONTENT_SETTINGS_TYPE_COOKIES
     20   false,  // CONTENT_SETTINGS_TYPE_IMAGES
     21   false,  // CONTENT_SETTINGS_TYPE_JAVASCRIPT
     22   true,   // CONTENT_SETTINGS_TYPE_PLUGINS
     23   false,  // CONTENT_SETTINGS_TYPE_POPUPS
     24   false,  // Not used for Geolocation
     25   false,  // Not used for Notifications
     26 };
     27 
     28 }  // namespace
     29 
     30 namespace content_settings {
     31 
     32 ExtendedContentSettings::ExtendedContentSettings() {}
     33 
     34 ExtendedContentSettings::ExtendedContentSettings(
     35     const ExtendedContentSettings& rhs)
     36     : content_settings(rhs.content_settings),
     37       content_settings_for_resources(rhs.content_settings_for_resources) {
     38 }
     39 
     40 ExtendedContentSettings::~ExtendedContentSettings() {}
     41 
     42 BaseProvider::BaseProvider(bool is_incognito)
     43     : is_incognito_(is_incognito) {
     44 }
     45 
     46 BaseProvider::~BaseProvider() {}
     47 
     48 bool BaseProvider::RequiresResourceIdentifier(
     49     ContentSettingsType content_type) const {
     50   if (CommandLine::ForCurrentProcess()->HasSwitch(
     51       switches::kEnableResourceContentSettings)) {
     52     return kRequiresResourceIdentifier[content_type];
     53   } else {
     54     return false;
     55   }
     56 }
     57 
     58 bool BaseProvider::AllDefault(
     59     const ExtendedContentSettings& settings) const {
     60   for (size_t i = 0; i < arraysize(settings.content_settings.settings); ++i) {
     61     if (settings.content_settings.settings[i] != CONTENT_SETTING_DEFAULT)
     62       return false;
     63   }
     64   return settings.content_settings_for_resources.empty();
     65 }
     66 
     67 ContentSetting BaseProvider::GetContentSetting(
     68     const GURL& requesting_url,
     69     const GURL& embedding_url,
     70     ContentSettingsType content_type,
     71     const ResourceIdentifier& resource_identifier) const {
     72   // Support for embedding_patterns is not implemented yet.
     73   DCHECK(requesting_url == embedding_url);
     74 
     75   if (!RequiresResourceIdentifier(content_type) ||
     76       (RequiresResourceIdentifier(content_type) && resource_identifier.empty()))
     77     return GetNonDefaultContentSettings(requesting_url).settings[content_type];
     78 
     79   // Resolve content settings with resource identifier.
     80   // 1. Check for pattern that exactly match the url/host
     81   //     1.1 In the content-settings-map
     82   //     1.2 In the incognito content-settings-map
     83   // 3. Shorten the url subdomain by subdomain and try to find a pattern in
     84   //     3.1 OTR content-settings-map
     85   //     3.2 content-settings-map
     86   base::AutoLock auto_lock(lock_);
     87   const std::string host(net::GetHostOrSpecFromURL(requesting_url));
     88   ContentSettingsTypeResourceIdentifierPair
     89       requested_setting(content_type, resource_identifier);
     90 
     91   // Check for exact matches first.
     92   HostContentSettings::const_iterator i(host_content_settings_.find(host));
     93   if (i != host_content_settings_.end() &&
     94       i->second.content_settings_for_resources.find(requested_setting) !=
     95       i->second.content_settings_for_resources.end()) {
     96     return i->second.content_settings_for_resources.find(
     97         requested_setting)->second;
     98   }
     99 
    100   // If this map is not for an incognito profile, these searches will never
    101   // match. The additional incognito exceptions always overwrite the
    102   // regular ones.
    103   i = incognito_settings_.find(host);
    104   if (i != incognito_settings_.end() &&
    105       i->second.content_settings_for_resources.find(requested_setting) !=
    106       i->second.content_settings_for_resources.end()) {
    107     return i->second.content_settings_for_resources.find(
    108         requested_setting)->second;
    109   }
    110 
    111   // Match patterns starting with the most concrete pattern match.
    112   for (std::string key =
    113        std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) {
    114     HostContentSettings::const_iterator i(incognito_settings_.find(key));
    115     if (i != incognito_settings_.end() &&
    116         i->second.content_settings_for_resources.find(requested_setting) !=
    117         i->second.content_settings_for_resources.end()) {
    118       return i->second.content_settings_for_resources.find(
    119           requested_setting)->second;
    120     }
    121 
    122     i = host_content_settings_.find(key);
    123     if (i != host_content_settings_.end() &&
    124         i->second.content_settings_for_resources.find(requested_setting) !=
    125         i->second.content_settings_for_resources.end()) {
    126       return i->second.content_settings_for_resources.find(
    127           requested_setting)->second;
    128     }
    129 
    130     const size_t next_dot =
    131         key.find('.', ContentSettingsPattern::kDomainWildcardLength);
    132     if (next_dot == std::string::npos)
    133       break;
    134     key.erase(ContentSettingsPattern::kDomainWildcardLength,
    135               next_dot - ContentSettingsPattern::kDomainWildcardLength + 1);
    136   }
    137 
    138   return CONTENT_SETTING_DEFAULT;
    139 }
    140 
    141 void BaseProvider::GetAllContentSettingsRules(
    142     ContentSettingsType content_type,
    143     const ResourceIdentifier& resource_identifier,
    144     Rules* content_setting_rules) const {
    145   DCHECK(content_setting_rules);
    146   content_setting_rules->clear();
    147 
    148   const HostContentSettings* map_to_return =
    149       is_incognito_ ? &incognito_settings_ : &host_content_settings_;
    150   ContentSettingsTypeResourceIdentifierPair requested_setting(
    151       content_type, resource_identifier);
    152 
    153   base::AutoLock auto_lock(lock_);
    154   for (HostContentSettings::const_iterator i(map_to_return->begin());
    155        i != map_to_return->end(); ++i) {
    156     ContentSetting setting;
    157     if (RequiresResourceIdentifier(content_type)) {
    158       if (i->second.content_settings_for_resources.find(requested_setting) !=
    159           i->second.content_settings_for_resources.end()) {
    160         setting = i->second.content_settings_for_resources.find(
    161             requested_setting)->second;
    162       } else {
    163         setting = CONTENT_SETTING_DEFAULT;
    164       }
    165     } else {
    166      setting = i->second.content_settings.settings[content_type];
    167     }
    168     if (setting != CONTENT_SETTING_DEFAULT) {
    169       // Use of push_back() relies on the map iterator traversing in order of
    170       // ascending keys.
    171       content_setting_rules->push_back(Rule(ContentSettingsPattern(i->first),
    172                                             ContentSettingsPattern(i->first),
    173                                             setting));
    174     }
    175   }
    176 }
    177 
    178 ContentSettings BaseProvider::GetNonDefaultContentSettings(
    179     const GURL& url) const {
    180   base::AutoLock auto_lock(lock_);
    181 
    182   const std::string host(net::GetHostOrSpecFromURL(url));
    183   ContentSettings output;
    184   for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j)
    185     output.settings[j] = CONTENT_SETTING_DEFAULT;
    186 
    187   // Check for exact matches first.
    188   HostContentSettings::const_iterator i(host_content_settings_.find(host));
    189   if (i != host_content_settings_.end())
    190     output = i->second.content_settings;
    191 
    192   // If this map is not for an incognito profile, these searches will never
    193   // match. The additional incognito exceptions always overwrite the
    194   // regular ones.
    195   i = incognito_settings_.find(host);
    196   if (i != incognito_settings_.end()) {
    197     for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j)
    198       if (i->second.content_settings.settings[j] != CONTENT_SETTING_DEFAULT)
    199         output.settings[j] = i->second.content_settings.settings[j];
    200   }
    201 
    202   // Match patterns starting with the most concrete pattern match.
    203   for (std::string key =
    204        std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) {
    205     HostContentSettings::const_iterator i(incognito_settings_.find(key));
    206     if (i != incognito_settings_.end()) {
    207       for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
    208         if (output.settings[j] == CONTENT_SETTING_DEFAULT)
    209           output.settings[j] = i->second.content_settings.settings[j];
    210       }
    211     }
    212     i = host_content_settings_.find(key);
    213     if (i != host_content_settings_.end()) {
    214       for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
    215         if (output.settings[j] == CONTENT_SETTING_DEFAULT)
    216           output.settings[j] = i->second.content_settings.settings[j];
    217       }
    218     }
    219     const size_t next_dot =
    220         key.find('.', ContentSettingsPattern::kDomainWildcardLength);
    221     if (next_dot == std::string::npos)
    222       break;
    223     key.erase(ContentSettingsPattern::kDomainWildcardLength,
    224               next_dot - ContentSettingsPattern::kDomainWildcardLength + 1);
    225   }
    226 
    227   return output;
    228 }
    229 
    230 void BaseProvider::UpdateContentSettingsMap(
    231     const ContentSettingsPattern& requesting_pattern,
    232     const ContentSettingsPattern& embedding_pattern,
    233     ContentSettingsType content_type,
    234     const ResourceIdentifier& resource_identifier,
    235     ContentSetting content_setting) {
    236   std::string pattern_str(requesting_pattern.CanonicalizePattern());
    237   HostContentSettings* content_settings_map = host_content_settings();
    238   ExtendedContentSettings& extended_settings =
    239       (*content_settings_map)[pattern_str];
    240   extended_settings.content_settings.settings[content_type] = content_setting;
    241 }
    242 
    243 // static
    244 ContentSetting BaseProvider::ClickToPlayFixup(ContentSettingsType content_type,
    245                                               ContentSetting setting) {
    246   if (setting == CONTENT_SETTING_ASK &&
    247       content_type == CONTENT_SETTINGS_TYPE_PLUGINS &&
    248       !CommandLine::ForCurrentProcess()->HasSwitch(
    249           switches::kEnableClickToPlay)) {
    250     return CONTENT_SETTING_BLOCK;
    251   }
    252   return setting;
    253 }
    254 
    255 }  // namespace content_settings
    256