• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ExtendedContentSettings()32 ExtendedContentSettings::ExtendedContentSettings() {}
33 
ExtendedContentSettings(const ExtendedContentSettings & rhs)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 
~ExtendedContentSettings()40 ExtendedContentSettings::~ExtendedContentSettings() {}
41 
BaseProvider(bool is_incognito)42 BaseProvider::BaseProvider(bool is_incognito)
43     : is_incognito_(is_incognito) {
44 }
45 
~BaseProvider()46 BaseProvider::~BaseProvider() {}
47 
RequiresResourceIdentifier(ContentSettingsType content_type) const48 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 
AllDefault(const ExtendedContentSettings & settings) const58 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 
GetContentSetting(const GURL & requesting_url,const GURL & embedding_url,ContentSettingsType content_type,const ResourceIdentifier & resource_identifier) const67 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 
GetAllContentSettingsRules(ContentSettingsType content_type,const ResourceIdentifier & resource_identifier,Rules * content_setting_rules) const141 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 
GetNonDefaultContentSettings(const GURL & url) const178 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 
UpdateContentSettingsMap(const ContentSettingsPattern & requesting_pattern,const ContentSettingsPattern & embedding_pattern,ContentSettingsType content_type,const ResourceIdentifier & resource_identifier,ContentSetting content_setting)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
ClickToPlayFixup(ContentSettingsType content_type,ContentSetting setting)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