OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |