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