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

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