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

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: AllowScript -= cache 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 for (size_t i = 0; i < arraysize(kDirProtocols); ++i) { 43 for (size_t i = 0; i < arraysize(kDirProtocols); ++i) {
44 if (EqualsASCII(origin.protocol(), kDirProtocols[i])) { 44 if (EqualsASCII(origin.protocol(), kDirProtocols[i])) {
45 return document_url.SchemeIs(kDirProtocols[i]) && 45 return document_url.SchemeIs(kDirProtocols[i]) &&
46 document_url.ExtractFileName().empty(); 46 document_url.ExtractFileName().empty();
47 } 47 }
48 } 48 }
49 49
50 return false; 50 return false;
51 } 51 }
52 52
53 GURL GetOriginOrURL(const WebFrame* frame) { 53 inline 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();
Bernhard Bauer 2011/11/15 09:29:35 Ooh, is it on purpose that we use |frame->document
marja 2011/11/15 11:49:58 Hmm, I did it on purpose but I might have misinter
59 return GURL(top_origin); 59 return GURL(top_origin);
60 } 60 }
61 61
62 inline ContentSetting GetContentSettingFromRules(
Bernhard Bauer 2011/11/15 09:29:35 Why do you explicitly add an "inline" here? Are yo
marja 2011/11/15 11:49:58 Just because it seemed to be better in some of my
63 const ContentSettingsForOneType& rules,
64 const WebFrame* frame,
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 DCHECK(rules[0].primary_pattern == ContentSettingsPattern::Wildcard());
71 DCHECK(rules[0].secondary_pattern == ContentSettingsPattern::Wildcard());
72 return rules[0].setting;
73 }
74 const GURL& primary_url = GetOriginOrURL(frame);
75 for (it = rules.begin(); it != rules.end(); ++it) {
76 if (it->primary_pattern.Matches(primary_url) &&
77 it->secondary_pattern.Matches(secondary_url)) {
78 return it->setting;
79 }
80 }
81 NOTREACHED();
82 return CONTENT_SETTING_DEFAULT;
83 }
84
62 } // namespace 85 } // namespace
63 86
64 ContentSettingsObserver::ContentSettingsObserver( 87 ContentSettingsObserver::ContentSettingsObserver(
65 content::RenderView* render_view) 88 content::RenderView* render_view)
66 : content::RenderViewObserver(render_view), 89 : content::RenderViewObserver(render_view),
67 content::RenderViewObserverTracker<ContentSettingsObserver>(render_view), 90 content::RenderViewObserverTracker<ContentSettingsObserver>(render_view),
68 default_content_settings_(NULL), 91 content_setting_rules_(NULL),
69 image_setting_rules_(NULL),
70 plugins_temporarily_allowed_(false) { 92 plugins_temporarily_allowed_(false) {
71 ClearBlockedContentSettings(); 93 ClearBlockedContentSettings();
72 } 94 }
73 95
74 ContentSettingsObserver::~ContentSettingsObserver() { 96 ContentSettingsObserver::~ContentSettingsObserver() {
75 } 97 }
76 98
77 void ContentSettingsObserver::SetContentSettings( 99 void ContentSettingsObserver::SetContentSettingRules(
78 const ContentSettings& settings) { 100 const RendererContentSettingRules* content_setting_rules) {
79 current_content_settings_ = settings; 101 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 } 102 }
98 103
99 void ContentSettingsObserver::DidBlockContentType( 104 void ContentSettingsObserver::DidBlockContentType(
100 ContentSettingsType settings_type, 105 ContentSettingsType settings_type,
101 const std::string& resource_identifier) { 106 const std::string& resource_identifier) {
102 // Always send a message when |resource_identifier| is not empty, to tell the 107 // 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 108 // 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 109 // the first resource to be blocked, and none that are blocked at a later
105 // time). 110 // time).
106 if (!content_blocked_[settings_type] || !resource_identifier.empty()) { 111 if (!content_blocked_[settings_type] || !resource_identifier.empty()) {
107 content_blocked_[settings_type] = true; 112 content_blocked_[settings_type] = true;
108 Send(new ChromeViewHostMsg_ContentBlocked(routing_id(), settings_type, 113 Send(new ChromeViewHostMsg_ContentBlocked(routing_id(), settings_type,
109 resource_identifier)); 114 resource_identifier));
110 } 115 }
111 } 116 }
112 117
113 bool ContentSettingsObserver::OnMessageReceived(const IPC::Message& message) { 118 bool ContentSettingsObserver::OnMessageReceived(const IPC::Message& message) {
114 bool handled = true; 119 bool handled = true;
115 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message) 120 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message)
116 // Don't swallow LoadBlockedPlugins messages, as they're sent to every 121 // Don't swallow LoadBlockedPlugins messages, as they're sent to every
117 // blocked plugin. 122 // blocked plugin.
118 IPC_MESSAGE_HANDLER_GENERIC(ChromeViewMsg_LoadBlockedPlugins, 123 IPC_MESSAGE_HANDLER_GENERIC(ChromeViewMsg_LoadBlockedPlugins,
119 OnLoadBlockedPlugins(); handled = false) 124 OnLoadBlockedPlugins(); handled = false)
120 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingsForLoadingURL,
121 OnSetContentSettingsForLoadingURL)
122 IPC_MESSAGE_UNHANDLED(handled = false) 125 IPC_MESSAGE_UNHANDLED(handled = false)
123 IPC_END_MESSAGE_MAP() 126 IPC_END_MESSAGE_MAP()
124 return handled; 127 return handled;
125 } 128 }
126 129
127 void ContentSettingsObserver::DidCommitProvisionalLoad( 130 void ContentSettingsObserver::DidCommitProvisionalLoad(
128 WebFrame* frame, bool is_new_navigation) { 131 WebFrame* frame, bool is_new_navigation) {
129 if (frame->parent()) 132 if (frame->parent())
130 return; // Not a top-level navigation. 133 return; // Not a top-level navigation.
131 134
132 NavigationState* state = NavigationState::FromDataSource(frame->dataSource()); 135 NavigationState* state = NavigationState::FromDataSource(frame->dataSource());
133 if (!state->was_within_same_page()) { 136 if (!state->was_within_same_page()) {
134 // Clear "block" flags for the new page. This needs to happen before any of 137 // Clear "block" flags for the new page. This needs to happen before any of
135 // allowScripts(), allowImage(), allowPlugins() is called for the new page 138 // |AllowScript()|, |AllowScriptFromSource()|, |AllowImage()|, or
136 // so that these functions can correctly detect that a piece of content 139 // |AllowPlugins()| is called for the new page so that these functions can
137 // flipped from "not blocked" to "blocked". 140 // correctly detect that a piece of content flipped from "not blocked" to
141 // "blocked".
138 ClearBlockedContentSettings(); 142 ClearBlockedContentSettings();
139 plugins_temporarily_allowed_ = false; 143 plugins_temporarily_allowed_ = false;
140 } 144 }
141 145
142 GURL url = frame->document().url(); 146 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 147 // 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 148 // this bug: http://code.google.com/p/chromium/issues/detail?id=79304
160 DCHECK(!url.SchemeIs(chrome::kDataScheme)); 149 DCHECK(frame->document().securityOrigin().toString() == "null" ||
161 150 !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 } 151 }
184 152
185 bool ContentSettingsObserver::AllowDatabase(WebFrame* frame, 153 bool ContentSettingsObserver::AllowDatabase(WebFrame* frame,
186 const WebString& name, 154 const WebString& name,
187 const WebString& display_name, 155 const WebString& display_name,
188 unsigned long estimated_size) { 156 unsigned long estimated_size) {
189 if (frame->document().securityOrigin().isEmpty() || 157 if (frame->document().securityOrigin().isEmpty() ||
190 frame->top()->document().securityOrigin().isEmpty()) 158 frame->top()->document().securityOrigin().isEmpty())
191 return false; // Uninitialized document. 159 return false; // Uninitialized document.
192 160
(...skipping 17 matching lines...) Expand all
210 return result; 178 return result;
211 } 179 }
212 180
213 bool ContentSettingsObserver::AllowImage(WebFrame* frame, 181 bool ContentSettingsObserver::AllowImage(WebFrame* frame,
214 bool enabled_per_settings, 182 bool enabled_per_settings,
215 const WebURL& image_url) { 183 const WebURL& image_url) {
216 if (IsWhitelistedForContentSettings(frame)) 184 if (IsWhitelistedForContentSettings(frame))
217 return true; 185 return true;
218 186
219 bool allow = enabled_per_settings; 187 bool allow = enabled_per_settings;
220 const GURL& primary_url = GetOriginOrURL(frame); 188 if (content_setting_rules_ && enabled_per_settings) {
221 GURL secondary_url(image_url); 189 GURL secondary_url(image_url);
222 if (image_setting_rules_ && 190 allow = GetContentSettingFromRules(
223 enabled_per_settings) { 191 content_setting_rules_->image_rules,
224 ContentSettingsForOneType::const_iterator it; 192 frame, secondary_url) != CONTENT_SETTING_BLOCK;
225 for (it = image_setting_rules_->begin();
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 } 193 }
234 194
235 if (!allow) 195 if (!allow)
236 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES, std::string()); 196 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES, std::string());
237 return allow; 197 return allow;
238 } 198 }
239 199
240 bool ContentSettingsObserver::AllowIndexedDB(WebFrame* frame, 200 bool ContentSettingsObserver::AllowIndexedDB(WebFrame* frame,
241 const WebString& name, 201 const WebString& name,
242 const WebSecurityOrigin& origin) { 202 const WebSecurityOrigin& origin) {
243 if (frame->document().securityOrigin().isEmpty() || 203 if (frame->document().securityOrigin().isEmpty() ||
244 frame->top()->document().securityOrigin().isEmpty()) 204 frame->top()->document().securityOrigin().isEmpty())
245 return false; // Uninitialized document. 205 return false; // Uninitialized document.
246 206
247 bool result = false; 207 bool result = false;
248 Send(new ChromeViewHostMsg_AllowIndexedDB( 208 Send(new ChromeViewHostMsg_AllowIndexedDB(
249 routing_id(), GURL(frame->document().securityOrigin().toString()), 209 routing_id(), GURL(frame->document().securityOrigin().toString()),
250 GURL(frame->top()->document().securityOrigin().toString()), 210 GURL(frame->top()->document().securityOrigin().toString()),
251 name, &result)); 211 name, &result));
252 return result; 212 return result;
253 } 213 }
254 214
255 bool ContentSettingsObserver::AllowPlugins(WebFrame* frame, 215 bool ContentSettingsObserver::AllowPlugins(WebFrame* frame,
256 bool enabled_per_settings) { 216 bool enabled_per_settings) {
257 return enabled_per_settings; 217 return enabled_per_settings;
258 } 218 }
259 219
260 bool ContentSettingsObserver::AllowScript(WebFrame* frame, 220 bool ContentSettingsObserver::AllowScript(WebFrame* frame,
261 bool enabled_per_settings) { 221 bool enabled_per_settings) {
262 if (enabled_per_settings && 222 if (!enabled_per_settings)
263 AllowContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT)) { 223 return false;
264 return true; 224
225 // Evaluate the content setting rules before
226 // |IsWhitelistedForContentSettings|; if there is only the default rule
227 // allowing all scripts, it's quicker this way.
228 bool allow = true;
229 if (content_setting_rules_) {
230 ContentSetting setting = GetContentSettingFromRules(
231 content_setting_rules_->script_rules,
232 frame,
233 GURL(frame->document().securityOrigin().toString()));
234 allow = setting != CONTENT_SETTING_BLOCK;
265 } 235 }
236 return allow || IsWhitelistedForContentSettings(frame);
237 }
266 238
267 if (IsWhitelistedForContentSettings(frame)) 239 bool ContentSettingsObserver::AllowScriptFromSource(
268 return true; 240 WebFrame* frame,
241 bool enabled_per_settings,
242 const WebKit::WebURL& script_url) {
243 if (!enabled_per_settings)
244 return false;
269 245
270 return false; // Other protocols fall through here. 246 bool allow = true;
247 if (content_setting_rules_) {
248 ContentSetting setting = GetContentSettingFromRules(
249 content_setting_rules_->script_rules,
250 frame,
251 GURL(script_url));
252 allow = setting != CONTENT_SETTING_BLOCK;
253 }
254 return allow || IsWhitelistedForContentSettings(frame);
271 } 255 }
272 256
273 bool ContentSettingsObserver::AllowStorage(WebFrame* frame, bool local) { 257 bool ContentSettingsObserver::AllowStorage(WebFrame* frame, bool local) {
274 if (frame->document().securityOrigin().isEmpty() || 258 if (frame->document().securityOrigin().isEmpty() ||
275 frame->top()->document().securityOrigin().isEmpty()) 259 frame->top()->document().securityOrigin().isEmpty())
276 return false; // Uninitialized document. 260 return false; // Uninitialized document.
277 bool result = false; 261 bool result = false;
278 262
279 StoragePermissionsKey key( 263 StoragePermissionsKey key(
280 GURL(frame->document().securityOrigin().toString()), local); 264 GURL(frame->document().securityOrigin().toString()), local);
(...skipping 12 matching lines...) Expand all
293 } 277 }
294 278
295 void ContentSettingsObserver::DidNotAllowPlugins(WebFrame* frame) { 279 void ContentSettingsObserver::DidNotAllowPlugins(WebFrame* frame) {
296 DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, std::string()); 280 DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, std::string());
297 } 281 }
298 282
299 void ContentSettingsObserver::DidNotAllowScript(WebFrame* frame) { 283 void ContentSettingsObserver::DidNotAllowScript(WebFrame* frame) {
300 DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string()); 284 DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string());
301 } 285 }
302 286
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() { 287 void ContentSettingsObserver::OnLoadBlockedPlugins() {
310 plugins_temporarily_allowed_ = true; 288 plugins_temporarily_allowed_ = true;
311 } 289 }
312 290
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() { 291 void ContentSettingsObserver::ClearBlockedContentSettings() {
321 for (size_t i = 0; i < arraysize(content_blocked_); ++i) 292 for (size_t i = 0; i < arraysize(content_blocked_); ++i)
322 content_blocked_[i] = false; 293 content_blocked_[i] = false;
323 cached_storage_permissions_.clear(); 294 cached_storage_permissions_.clear();
324 } 295 }
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