Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: chrome/renderer/content_settings_observer.cc

Issue 8538004: Take script URLs into account when applying script content settings. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleanup + rebase. Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/content_settings_observer.h" 5 #include "chrome/renderer/content_settings_observer.h"
6 6
7 #include "chrome/common/render_messages.h" 7 #include "chrome/common/render_messages.h"
8 #include "chrome/common/url_constants.h" 8 #include "chrome/common/url_constants.h"
9 #include "content/public/renderer/navigation_state.h" 9 #include "content/public/renderer/navigation_state.h"
10 #include "content/public/renderer/render_view.h" 10 #include "content/public/renderer/render_view.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 52
53 GURL GetOriginOrURL(const WebFrame* frame) { 53 GURL GetOriginOrURL(const WebFrame* frame) {
54 WebString top_origin = frame->top()->document().securityOrigin().toString(); 54 WebString top_origin = frame->top()->document().securityOrigin().toString();
55 // The the |top_origin| is unique ("null") e.g., for file:// URLs. Use the 55 // The the |top_origin| is unique ("null") e.g., for file:// URLs. Use the
56 // document URL as the primary URL in those cases. 56 // document URL as the primary URL in those cases.
57 if (top_origin == "null") 57 if (top_origin == "null")
58 return frame->document().url(); 58 return frame->document().url();
59 return GURL(top_origin); 59 return GURL(top_origin);
60 } 60 }
61 61
62 ContentSetting GetContentSettingFromRules(
63 const ContentSettingsForOneType& rules,
64 const GURL& primary_url,
65 const GURL& secondary_url) {
66 ContentSettingsForOneType::const_iterator it;
67 // If there is only one rule, it's the default rule and we don't need to match
68 // the patterns.
69 if (rules.size() == 1)
70 return rules[0].setting;
Bernhard Bauer 2011/11/11 13:00:53 Can we have a DCHECK here that this rule applies?
marja 2011/11/11 14:25:10 Done. (Checked that it's a wildcard-wildcard rule.
71 for (it = rules.begin(); it != rules.end(); ++it) {
72 if (it->primary_pattern.Matches(primary_url) &&
73 it->secondary_pattern.Matches(secondary_url)) {
74 return it->setting;
75 }
76 }
77 NOTREACHED();
78 return CONTENT_SETTING_DEFAULT;
79 }
80
62 } // namespace 81 } // namespace
63 82
64 ContentSettingsObserver::ContentSettingsObserver( 83 ContentSettingsObserver::ContentSettingsObserver(
65 content::RenderView* render_view) 84 content::RenderView* render_view)
66 : content::RenderViewObserver(render_view), 85 : content::RenderViewObserver(render_view),
67 content::RenderViewObserverTracker<ContentSettingsObserver>(render_view), 86 content::RenderViewObserverTracker<ContentSettingsObserver>(render_view),
68 default_content_settings_(NULL), 87 content_setting_rules_(NULL),
69 image_setting_rules_(NULL),
70 plugins_temporarily_allowed_(false) { 88 plugins_temporarily_allowed_(false) {
71 ClearBlockedContentSettings(); 89 ClearBlockedContentSettings();
72 } 90 }
73 91
74 ContentSettingsObserver::~ContentSettingsObserver() { 92 ContentSettingsObserver::~ContentSettingsObserver() {
75 } 93 }
76 94
77 void ContentSettingsObserver::SetContentSettings( 95 void ContentSettingsObserver::SetContentSettingRules(
78 const ContentSettings& settings) { 96 const RendererContentSettingRules* content_setting_rules) {
79 current_content_settings_ = settings; 97 content_setting_rules_ = content_setting_rules;
80 }
81
82 void ContentSettingsObserver::SetDefaultContentSettings(
83 const ContentSettings* settings) {
84 default_content_settings_ = settings;
85 }
86
87 void ContentSettingsObserver::SetImageSettingRules(
88 const ContentSettingsForOneType* image_setting_rules) {
89 image_setting_rules_ = image_setting_rules;
90 }
91
92 ContentSetting ContentSettingsObserver::GetContentSetting(
93 ContentSettingsType type) {
94 // Don't call this for plug-ins.
95 DCHECK_NE(CONTENT_SETTINGS_TYPE_PLUGINS, type);
96 return current_content_settings_.settings[type];
97 } 98 }
98 99
99 void ContentSettingsObserver::DidBlockContentType( 100 void ContentSettingsObserver::DidBlockContentType(
100 ContentSettingsType settings_type, 101 ContentSettingsType settings_type,
101 const std::string& resource_identifier) { 102 const std::string& resource_identifier) {
102 // Always send a message when |resource_identifier| is not empty, to tell the 103 // Always send a message when |resource_identifier| is not empty, to tell the
103 // browser which resource was blocked (otherwise the browser will only show 104 // browser which resource was blocked (otherwise the browser will only show
104 // the first resource to be blocked, and none that are blocked at a later 105 // the first resource to be blocked, and none that are blocked at a later
105 // time). 106 // time).
106 if (!content_blocked_[settings_type] || !resource_identifier.empty()) { 107 if (!content_blocked_[settings_type] || !resource_identifier.empty()) {
107 content_blocked_[settings_type] = true; 108 content_blocked_[settings_type] = true;
108 Send(new ChromeViewHostMsg_ContentBlocked(routing_id(), settings_type, 109 Send(new ChromeViewHostMsg_ContentBlocked(routing_id(), settings_type,
109 resource_identifier)); 110 resource_identifier));
110 } 111 }
111 } 112 }
112 113
113 bool ContentSettingsObserver::OnMessageReceived(const IPC::Message& message) { 114 bool ContentSettingsObserver::OnMessageReceived(const IPC::Message& message) {
114 bool handled = true; 115 bool handled = true;
115 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message) 116 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message)
116 // Don't swallow LoadBlockedPlugins messages, as they're sent to every 117 // Don't swallow LoadBlockedPlugins messages, as they're sent to every
117 // blocked plugin. 118 // blocked plugin.
118 IPC_MESSAGE_HANDLER_GENERIC(ChromeViewMsg_LoadBlockedPlugins, 119 IPC_MESSAGE_HANDLER_GENERIC(ChromeViewMsg_LoadBlockedPlugins,
119 OnLoadBlockedPlugins(); handled = false) 120 OnLoadBlockedPlugins(); handled = false)
120 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingsForLoadingURL,
121 OnSetContentSettingsForLoadingURL)
122 IPC_MESSAGE_UNHANDLED(handled = false) 121 IPC_MESSAGE_UNHANDLED(handled = false)
123 IPC_END_MESSAGE_MAP() 122 IPC_END_MESSAGE_MAP()
124 return handled; 123 return handled;
125 } 124 }
126 125
127 void ContentSettingsObserver::DidCommitProvisionalLoad( 126 void ContentSettingsObserver::DidCommitProvisionalLoad(
128 WebFrame* frame, bool is_new_navigation) { 127 WebFrame* frame, bool is_new_navigation) {
129 if (frame->parent()) 128 if (frame->parent())
130 return; // Not a top-level navigation. 129 return; // Not a top-level navigation.
131 130
132 NavigationState* state = NavigationState::FromDataSource(frame->dataSource()); 131 NavigationState* state = NavigationState::FromDataSource(frame->dataSource());
133 if (!state->was_within_same_page()) { 132 if (!state->was_within_same_page()) {
134 // Clear "block" flags for the new page. This needs to happen before any of 133 // Clear "block" flags for the new page. This needs to happen before any of
135 // allowScripts(), allowImage(), allowPlugins() is called for the new page 134 // |AllowScript()|, |AllowScriptFromSource()|, |AllowImage()|, or
136 // so that these functions can correctly detect that a piece of content 135 // |AllowPlugins()| is called for the new page so that these functions can
137 // flipped from "not blocked" to "blocked". 136 // correctly detect that a piece of content flipped from "not blocked" to
137 // "blocked".
138 ClearBlockedContentSettings(); 138 ClearBlockedContentSettings();
139 plugins_temporarily_allowed_ = false; 139 plugins_temporarily_allowed_ = false;
140 } 140 }
141 141
142 GURL url = frame->document().url(); 142 GURL url = frame->document().url();
143
144 if (frame->document().securityOrigin().toString() == "null" &&
145 !url.SchemeIs(chrome::kFileScheme)) {
146 // The Frame has a unique security origin. Instead of granting the frame
147 // privileges based on it's URL, we fall back to the default content
148 // settings.
149
150 // We exempt file URLs here because we sandbox them by default, but folks
151 // might reasonably want to supply non-default content settings for various
152 // file URLs.
153 if (default_content_settings_)
154 SetContentSettings(*default_content_settings_);
155 return;
156 }
157
158 // If we start failing this DCHECK, please makes sure we don't regress 143 // If we start failing this DCHECK, please makes sure we don't regress
159 // this bug: http://code.google.com/p/chromium/issues/detail?id=79304 144 // this bug: http://code.google.com/p/chromium/issues/detail?id=79304
160 DCHECK(!url.SchemeIs(chrome::kDataScheme)); 145 DCHECK(frame->document().securityOrigin().toString() == "null" ||
161 146 !url.SchemeIs(chrome::kDataScheme));
162 // Set content settings. Default them from the parent window if one exists.
163 // This makes sure about:blank windows work as expected.
164 HostContentSettings::iterator host_content_settings =
165 host_content_settings_.find(url);
166 if (host_content_settings != host_content_settings_.end()) {
167 SetContentSettings(host_content_settings->second);
168
169 // These content settings were merely recorded transiently for this load.
170 // We can erase them now. If at some point we reload this page, the
171 // browser will send us new, up-to-date content settings.
172 host_content_settings_.erase(host_content_settings);
173 } else if (frame->opener()) {
174 // The opener's view is not guaranteed to be non-null (it could be
175 // detached from its page but not yet destructed).
176 if (WebView* opener_view = frame->opener()->view()) {
177 content::RenderView* opener =
178 content::RenderView::FromWebView(opener_view);
179 ContentSettingsObserver* observer = ContentSettingsObserver::Get(opener);
180 SetContentSettings(observer->current_content_settings_);
181 }
182 }
183 } 147 }
184 148
185 bool ContentSettingsObserver::AllowDatabase(WebFrame* frame, 149 bool ContentSettingsObserver::AllowDatabase(WebFrame* frame,
186 const WebString& name, 150 const WebString& name,
187 const WebString& display_name, 151 const WebString& display_name,
188 unsigned long estimated_size) { 152 unsigned long estimated_size) {
189 if (frame->document().securityOrigin().isEmpty() || 153 if (frame->document().securityOrigin().isEmpty() ||
190 frame->top()->document().securityOrigin().isEmpty()) 154 frame->top()->document().securityOrigin().isEmpty())
191 return false; // Uninitialized document. 155 return false; // Uninitialized document.
192 156
(...skipping 17 matching lines...) Expand all
210 return result; 174 return result;
211 } 175 }
212 176
213 bool ContentSettingsObserver::AllowImage(WebFrame* frame, 177 bool ContentSettingsObserver::AllowImage(WebFrame* frame,
214 bool enabled_per_settings, 178 bool enabled_per_settings,
215 const WebURL& image_url) { 179 const WebURL& image_url) {
216 if (IsWhitelistedForContentSettings(frame)) 180 if (IsWhitelistedForContentSettings(frame))
217 return true; 181 return true;
218 182
219 bool allow = enabled_per_settings; 183 bool allow = enabled_per_settings;
220 const GURL& primary_url = GetOriginOrURL(frame); 184 if (content_setting_rules_ && enabled_per_settings) {
221 GURL secondary_url(image_url); 185 const GURL& primary_url = GetOriginOrURL(frame);
222 if (image_setting_rules_ && 186 GURL secondary_url(image_url);
223 enabled_per_settings) { 187 allow = GetContentSettingFromRules(
224 ContentSettingsForOneType::const_iterator it; 188 content_setting_rules_->image_rules,
225 for (it = image_setting_rules_->begin(); 189 primary_url, secondary_url) != CONTENT_SETTING_BLOCK;
226 it != image_setting_rules_->end(); ++it) {
227 if (it->primary_pattern.Matches(primary_url) &&
228 it->secondary_pattern.Matches(secondary_url)) {
229 allow = (it->setting != CONTENT_SETTING_BLOCK);
230 break;
231 }
232 }
233 } 190 }
234 191
235 if (!allow) 192 if (!allow)
236 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES, std::string()); 193 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES, std::string());
237 return allow; 194 return allow;
238 } 195 }
239 196
240 bool ContentSettingsObserver::AllowIndexedDB(WebFrame* frame, 197 bool ContentSettingsObserver::AllowIndexedDB(WebFrame* frame,
241 const WebString& name, 198 const WebString& name,
242 const WebSecurityOrigin& origin) { 199 const WebSecurityOrigin& origin) {
243 if (frame->document().securityOrigin().isEmpty() || 200 if (frame->document().securityOrigin().isEmpty() ||
244 frame->top()->document().securityOrigin().isEmpty()) 201 frame->top()->document().securityOrigin().isEmpty())
245 return false; // Uninitialized document. 202 return false; // Uninitialized document.
246 203
247 bool result = false; 204 bool result = false;
248 Send(new ChromeViewHostMsg_AllowIndexedDB( 205 Send(new ChromeViewHostMsg_AllowIndexedDB(
249 routing_id(), GURL(frame->document().securityOrigin().toString()), 206 routing_id(), GURL(frame->document().securityOrigin().toString()),
250 GURL(frame->top()->document().securityOrigin().toString()), 207 GURL(frame->top()->document().securityOrigin().toString()),
251 name, &result)); 208 name, &result));
252 return result; 209 return result;
253 } 210 }
254 211
255 bool ContentSettingsObserver::AllowPlugins(WebFrame* frame, 212 bool ContentSettingsObserver::AllowPlugins(WebFrame* frame,
256 bool enabled_per_settings) { 213 bool enabled_per_settings) {
257 return enabled_per_settings; 214 return enabled_per_settings;
258 } 215 }
259 216
260 bool ContentSettingsObserver::AllowScript(WebFrame* frame, 217 bool ContentSettingsObserver::AllowScript(WebFrame* frame,
261 bool enabled_per_settings) { 218 bool enabled_per_settings) {
262 if (enabled_per_settings && 219 if (!enabled_per_settings)
263 AllowContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT)) { 220 return false;
264 return true; 221
222 // Evaluate the content setting rules before
223 // |IsWhitelistedForContentSettings|; if there is only the default rule
224 // allowing all scripts, it's quicker this way.
225 bool allow = true;
226 if (content_setting_rules_) {
227 // If there is only one rule, it's the default rule and we don't need to
228 // construct the GURLs or match the patterns.
229 const ContentSettingsForOneType& rules =
230 content_setting_rules_->script_rules;
231 if (rules.size() == 1) {
Bernhard Bauer 2011/11/11 13:00:53 Can you use |GetContentSettingFromRules| here?
marja 2011/11/11 14:25:10 Done. (Seems to not kill the perf if I modify the
232 allow = rules[0].setting != CONTENT_SETTING_BLOCK;
233 } else {
234 const GURL& primary_url = GetOriginOrURL(frame);
235 GURL secondary_url(frame->document().securityOrigin().toString());
236 ContentSettingsForOneType::const_iterator it;
237 for (it = rules.begin(); it != rules.end(); ++it) {
238 if (it->primary_pattern.Matches(primary_url) &&
239 it->secondary_pattern.Matches(secondary_url)) {
240 allow = it->setting != CONTENT_SETTING_BLOCK;
241 break;
242 }
243 }
244 }
265 } 245 }
246 return allow || IsWhitelistedForContentSettings(frame);
247 }
266 248
267 if (IsWhitelistedForContentSettings(frame)) 249 bool ContentSettingsObserver::AllowScriptFromSource(
268 return true; 250 WebFrame* frame,
251 bool enabled_per_settings,
252 const WebKit::WebURL& script_url) {
253 if (!enabled_per_settings)
254 return false;
269 255
270 return false; // Other protocols fall through here. 256 bool allow = true;
257 if (content_setting_rules_) {
258 // If there is only one rule, it's the default rule and we don't need to
259 // construct the GURLs or match the patterns.
260 const ContentSettingsForOneType& rules =
261 content_setting_rules_->script_rules;
262 if (rules.size() == 1) {
263 allow = rules[0].setting != CONTENT_SETTING_BLOCK;
264 } else {
265 const GURL& primary_url = GetOriginOrURL(frame);
266 GURL secondary_url(script_url);
267 ContentSettingsForOneType::const_iterator it;
268 for (it = rules.begin(); it != rules.end(); ++it) {
269 if (it->primary_pattern.Matches(primary_url) &&
270 it->secondary_pattern.Matches(secondary_url)) {
271 allow = it->setting != CONTENT_SETTING_BLOCK;
272 break;
273 }
274 }
275 }
276 }
277 return allow || IsWhitelistedForContentSettings(frame);
271 } 278 }
272 279
273 bool ContentSettingsObserver::AllowStorage(WebFrame* frame, bool local) { 280 bool ContentSettingsObserver::AllowStorage(WebFrame* frame, bool local) {
274 if (frame->document().securityOrigin().isEmpty() || 281 if (frame->document().securityOrigin().isEmpty() ||
275 frame->top()->document().securityOrigin().isEmpty()) 282 frame->top()->document().securityOrigin().isEmpty())
276 return false; // Uninitialized document. 283 return false; // Uninitialized document.
277 bool result = false; 284 bool result = false;
278 285
279 StoragePermissionsKey key( 286 StoragePermissionsKey key(
280 GURL(frame->document().securityOrigin().toString()), local); 287 GURL(frame->document().securityOrigin().toString()), local);
(...skipping 12 matching lines...) Expand all
293 } 300 }
294 301
295 void ContentSettingsObserver::DidNotAllowPlugins(WebFrame* frame) { 302 void ContentSettingsObserver::DidNotAllowPlugins(WebFrame* frame) {
296 DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, std::string()); 303 DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, std::string());
297 } 304 }
298 305
299 void ContentSettingsObserver::DidNotAllowScript(WebFrame* frame) { 306 void ContentSettingsObserver::DidNotAllowScript(WebFrame* frame) {
300 DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string()); 307 DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string());
301 } 308 }
302 309
303 void ContentSettingsObserver::OnSetContentSettingsForLoadingURL(
304 const GURL& url,
305 const ContentSettings& content_settings) {
306 host_content_settings_[url] = content_settings;
307 }
308
309 void ContentSettingsObserver::OnLoadBlockedPlugins() { 310 void ContentSettingsObserver::OnLoadBlockedPlugins() {
310 plugins_temporarily_allowed_ = true; 311 plugins_temporarily_allowed_ = true;
311 } 312 }
312 313
313 bool ContentSettingsObserver::AllowContentType(
314 ContentSettingsType settings_type) {
315 // CONTENT_SETTING_ASK is only valid for cookies.
316 return current_content_settings_.settings[settings_type] !=
317 CONTENT_SETTING_BLOCK;
318 }
319
320 void ContentSettingsObserver::ClearBlockedContentSettings() { 314 void ContentSettingsObserver::ClearBlockedContentSettings() {
321 for (size_t i = 0; i < arraysize(content_blocked_); ++i) 315 for (size_t i = 0; i < arraysize(content_blocked_); ++i)
322 content_blocked_[i] = false; 316 content_blocked_[i] = false;
323 cached_storage_permissions_.clear(); 317 cached_storage_permissions_.clear();
324 } 318 }
OLDNEW
« no previous file with comments | « chrome/renderer/content_settings_observer.h ('k') | chrome/renderer/content_settings_observer_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698