Version 7 golden file for safe-browsing test.
[chromium-blink-merge.git] / chrome / renderer / content_settings_observer.cc
blobf5489a07f70d2ccaa399358f20f14dfad50041af
1 // Copyright (c) 2012 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.
5 #include "chrome/renderer/content_settings_observer.h"
7 #include "base/command_line.h"
8 #include "base/metrics/histogram.h"
9 #include "chrome/common/chrome_switches.h"
10 #include "chrome/common/render_messages.h"
11 #include "chrome/common/url_constants.h"
12 #include "chrome/renderer/extensions/dispatcher.h"
13 #include "content/public/renderer/document_state.h"
14 #include "content/public/renderer/navigation_state.h"
15 #include "content/public/renderer/render_frame.h"
16 #include "content/public/renderer/render_view.h"
17 #include "extensions/common/constants.h"
18 #include "third_party/WebKit/public/platform/WebURL.h"
19 #include "third_party/WebKit/public/web/WebDataSource.h"
20 #include "third_party/WebKit/public/web/WebDocument.h"
21 #include "third_party/WebKit/public/web/WebFrame.h"
22 #include "third_party/WebKit/public/web/WebFrameClient.h"
23 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
24 #include "third_party/WebKit/public/web/WebView.h"
25 #include "webkit/child/weburlresponse_extradata_impl.h"
27 using blink::WebDataSource;
28 using blink::WebDocument;
29 using blink::WebFrame;
30 using blink::WebFrameClient;
31 using blink::WebSecurityOrigin;
32 using blink::WebString;
33 using blink::WebURL;
34 using blink::WebView;
35 using content::DocumentState;
36 using content::NavigationState;
37 using extensions::APIPermission;
39 namespace {
41 enum {
42 INSECURE_CONTENT_DISPLAY = 0,
43 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE,
44 INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE,
45 INSECURE_CONTENT_DISPLAY_HTML,
46 INSECURE_CONTENT_RUN,
47 INSECURE_CONTENT_RUN_HOST_GOOGLE,
48 INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE,
49 INSECURE_CONTENT_RUN_TARGET_YOUTUBE,
50 INSECURE_CONTENT_RUN_JS,
51 INSECURE_CONTENT_RUN_CSS,
52 INSECURE_CONTENT_RUN_SWF,
53 INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE,
54 INSECURE_CONTENT_RUN_HOST_YOUTUBE,
55 INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT,
56 INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE,
57 INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE,
58 INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE,
59 INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE,
60 INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE,
61 INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE,
62 INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE,
63 INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE,
64 INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE,
65 INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE,
66 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER,
67 INSECURE_CONTENT_RUN_HOST_GOOGLE_READER,
68 INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE,
69 INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE,
70 INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE,
71 INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE,
72 INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE,
73 INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE,
74 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT,
75 INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT,
76 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL,
77 INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL,
78 INSECURE_CONTENT_NUM_EVENTS
81 // Constants for UMA statistic collection.
82 static const char kWWWDotGoogleDotCom[] = "www.google.com";
83 static const char kMailDotGoogleDotCom[] = "mail.google.com";
84 static const char kPlusDotGoogleDotCom[] = "plus.google.com";
85 static const char kDocsDotGoogleDotCom[] = "docs.google.com";
86 static const char kSitesDotGoogleDotCom[] = "sites.google.com";
87 static const char kPicasawebDotGoogleDotCom[] = "picasaweb.google.com";
88 static const char kCodeDotGoogleDotCom[] = "code.google.com";
89 static const char kGroupsDotGoogleDotCom[] = "groups.google.com";
90 static const char kMapsDotGoogleDotCom[] = "maps.google.com";
91 static const char kWWWDotYoutubeDotCom[] = "www.youtube.com";
92 static const char kDotGoogleUserContentDotCom[] = ".googleusercontent.com";
93 static const char kGoogleReaderPathPrefix[] = "/reader/";
94 static const char kGoogleSupportPathPrefix[] = "/support/";
95 static const char kGoogleIntlPathPrefix[] = "/intl/";
96 static const char kDotJS[] = ".js";
97 static const char kDotCSS[] = ".css";
98 static const char kDotSWF[] = ".swf";
99 static const char kDotHTML[] = ".html";
101 // Constants for mixed-content blocking.
102 static const char kGoogleDotCom[] = "google.com";
104 static bool IsHostInDomain(const std::string& host, const std::string& domain) {
105 return (EndsWith(host, domain, false) &&
106 (host.length() == domain.length() ||
107 (host.length() > domain.length() &&
108 host[host.length() - domain.length() - 1] == '.')));
111 GURL GetOriginOrURL(const WebFrame* frame) {
112 WebString top_origin = frame->top()->document().securityOrigin().toString();
113 // The the |top_origin| is unique ("null") e.g., for file:// URLs. Use the
114 // document URL as the primary URL in those cases.
115 if (top_origin == "null")
116 return frame->top()->document().url();
117 return GURL(top_origin);
120 ContentSetting GetContentSettingFromRules(
121 const ContentSettingsForOneType& rules,
122 const WebFrame* frame,
123 const GURL& secondary_url) {
124 ContentSettingsForOneType::const_iterator it;
125 // If there is only one rule, it's the default rule and we don't need to match
126 // the patterns.
127 if (rules.size() == 1) {
128 DCHECK(rules[0].primary_pattern == ContentSettingsPattern::Wildcard());
129 DCHECK(rules[0].secondary_pattern == ContentSettingsPattern::Wildcard());
130 return rules[0].setting;
132 const GURL& primary_url = GetOriginOrURL(frame);
133 for (it = rules.begin(); it != rules.end(); ++it) {
134 if (it->primary_pattern.Matches(primary_url) &&
135 it->secondary_pattern.Matches(secondary_url)) {
136 return it->setting;
139 NOTREACHED();
140 return CONTENT_SETTING_DEFAULT;
143 } // namespace
145 ContentSettingsObserver::ContentSettingsObserver(
146 content::RenderFrame* render_frame,
147 extensions::Dispatcher* extension_dispatcher)
148 : content::RenderFrameObserver(render_frame),
149 content::RenderFrameObserverTracker<ContentSettingsObserver>(
150 render_frame),
151 extension_dispatcher_(extension_dispatcher),
152 allow_displaying_insecure_content_(false),
153 allow_running_insecure_content_(false),
154 content_setting_rules_(NULL),
155 is_interstitial_page_(false),
156 npapi_plugins_blocked_(false) {
157 ClearBlockedContentSettings();
158 render_frame->GetWebFrame()->setPermissionClient(this);
161 ContentSettingsObserver::~ContentSettingsObserver() {
164 void ContentSettingsObserver::SetContentSettingRules(
165 const RendererContentSettingRules* content_setting_rules) {
166 content_setting_rules_ = content_setting_rules;
169 bool ContentSettingsObserver::IsPluginTemporarilyAllowed(
170 const std::string& identifier) {
171 // If the empty string is in here, it means all plug-ins are allowed.
172 // TODO(bauerb): Remove this once we only pass in explicit identifiers.
173 return (temporarily_allowed_plugins_.find(identifier) !=
174 temporarily_allowed_plugins_.end()) ||
175 (temporarily_allowed_plugins_.find(std::string()) !=
176 temporarily_allowed_plugins_.end());
179 void ContentSettingsObserver::DidBlockContentType(
180 ContentSettingsType settings_type) {
181 if (!content_blocked_[settings_type]) {
182 content_blocked_[settings_type] = true;
183 Send(new ChromeViewHostMsg_ContentBlocked(routing_id(), settings_type));
187 bool ContentSettingsObserver::OnMessageReceived(const IPC::Message& message) {
188 bool handled = true;
189 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message)
190 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAsInterstitial, OnSetAsInterstitial)
191 IPC_MESSAGE_HANDLER(ChromeViewMsg_NPAPINotSupported, OnNPAPINotSupported)
192 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowDisplayingInsecureContent,
193 OnSetAllowDisplayingInsecureContent)
194 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowRunningInsecureContent,
195 OnSetAllowRunningInsecureContent)
196 IPC_MESSAGE_HANDLER(ChromeViewMsg_ReloadFrame, OnReloadFrame);
197 IPC_MESSAGE_UNHANDLED(handled = false)
198 IPC_END_MESSAGE_MAP()
199 if (handled)
200 return true;
202 // Don't swallow LoadBlockedPlugins messages, as they're sent to every
203 // blocked plugin.
204 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message)
205 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins)
206 IPC_END_MESSAGE_MAP()
208 return false;
211 void ContentSettingsObserver::DidCommitProvisionalLoad(bool is_new_navigation) {
212 WebFrame* frame = render_frame()->GetWebFrame();
213 if (frame->parent())
214 return; // Not a top-level navigation.
216 DocumentState* document_state = DocumentState::FromDataSource(
217 frame->dataSource());
218 NavigationState* navigation_state = document_state->navigation_state();
219 if (!navigation_state->was_within_same_page()) {
220 // Clear "block" flags for the new page. This needs to happen before any of
221 // |allowScript()|, |allowScriptFromSource()|, |allowImage()|, or
222 // |allowPlugins()| is called for the new page so that these functions can
223 // correctly detect that a piece of content flipped from "not blocked" to
224 // "blocked".
225 ClearBlockedContentSettings();
226 temporarily_allowed_plugins_.clear();
229 GURL url = frame->document().url();
230 // If we start failing this DCHECK, please makes sure we don't regress
231 // this bug: http://code.google.com/p/chromium/issues/detail?id=79304
232 DCHECK(frame->document().securityOrigin().toString() == "null" ||
233 !url.SchemeIs(content::kDataScheme));
236 bool ContentSettingsObserver::allowDatabase(WebFrame* frame,
237 const WebString& name,
238 const WebString& display_name,
239 unsigned long estimated_size) {
240 if (frame->document().securityOrigin().isUnique() ||
241 frame->top()->document().securityOrigin().isUnique())
242 return false;
244 bool result = false;
245 Send(new ChromeViewHostMsg_AllowDatabase(
246 routing_id(), GURL(frame->document().securityOrigin().toString()),
247 GURL(frame->top()->document().securityOrigin().toString()),
248 name, display_name, &result));
249 return result;
252 bool ContentSettingsObserver::allowFileSystem(WebFrame* frame) {
253 if (frame->document().securityOrigin().isUnique() ||
254 frame->top()->document().securityOrigin().isUnique())
255 return false;
257 bool result = false;
258 Send(new ChromeViewHostMsg_AllowFileSystem(
259 routing_id(), GURL(frame->document().securityOrigin().toString()),
260 GURL(frame->top()->document().securityOrigin().toString()), &result));
261 return result;
264 bool ContentSettingsObserver::allowImage(WebFrame* frame,
265 bool enabled_per_settings,
266 const WebURL& image_url) {
267 bool allow = enabled_per_settings;
268 if (enabled_per_settings) {
269 if (is_interstitial_page_)
270 return true;
271 if (IsWhitelistedForContentSettings(frame))
272 return true;
274 if (content_setting_rules_) {
275 GURL secondary_url(image_url);
276 allow = GetContentSettingFromRules(
277 content_setting_rules_->image_rules,
278 frame, secondary_url) != CONTENT_SETTING_BLOCK;
281 if (!allow)
282 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES);
283 return allow;
286 bool ContentSettingsObserver::allowIndexedDB(WebFrame* frame,
287 const WebString& name,
288 const WebSecurityOrigin& origin) {
289 if (frame->document().securityOrigin().isUnique() ||
290 frame->top()->document().securityOrigin().isUnique())
291 return false;
293 bool result = false;
294 Send(new ChromeViewHostMsg_AllowIndexedDB(
295 routing_id(), GURL(frame->document().securityOrigin().toString()),
296 GURL(frame->top()->document().securityOrigin().toString()),
297 name, &result));
298 return result;
301 bool ContentSettingsObserver::allowPlugins(WebFrame* frame,
302 bool enabled_per_settings) {
303 return enabled_per_settings;
306 bool ContentSettingsObserver::allowScript(WebFrame* frame,
307 bool enabled_per_settings) {
308 if (!enabled_per_settings)
309 return false;
310 if (is_interstitial_page_)
311 return true;
313 std::map<WebFrame*, bool>::const_iterator it =
314 cached_script_permissions_.find(frame);
315 if (it != cached_script_permissions_.end())
316 return it->second;
318 // Evaluate the content setting rules before
319 // |IsWhitelistedForContentSettings|; if there is only the default rule
320 // allowing all scripts, it's quicker this way.
321 bool allow = true;
322 if (content_setting_rules_) {
323 ContentSetting setting = GetContentSettingFromRules(
324 content_setting_rules_->script_rules,
325 frame,
326 GURL(frame->document().securityOrigin().toString()));
327 allow = setting != CONTENT_SETTING_BLOCK;
329 allow = allow || IsWhitelistedForContentSettings(frame);
331 cached_script_permissions_[frame] = allow;
332 return allow;
335 bool ContentSettingsObserver::allowScriptFromSource(
336 WebFrame* frame,
337 bool enabled_per_settings,
338 const blink::WebURL& script_url) {
339 if (!enabled_per_settings)
340 return false;
341 if (is_interstitial_page_)
342 return true;
344 bool allow = true;
345 if (content_setting_rules_) {
346 ContentSetting setting = GetContentSettingFromRules(
347 content_setting_rules_->script_rules,
348 frame,
349 GURL(script_url));
350 allow = setting != CONTENT_SETTING_BLOCK;
352 return allow || IsWhitelistedForContentSettings(frame);
355 bool ContentSettingsObserver::allowStorage(WebFrame* frame, bool local) {
356 if (frame->document().securityOrigin().isUnique() ||
357 frame->top()->document().securityOrigin().isUnique())
358 return false;
359 bool result = false;
361 StoragePermissionsKey key(
362 GURL(frame->document().securityOrigin().toString()), local);
363 std::map<StoragePermissionsKey, bool>::const_iterator permissions =
364 cached_storage_permissions_.find(key);
365 if (permissions != cached_storage_permissions_.end())
366 return permissions->second;
368 Send(new ChromeViewHostMsg_AllowDOMStorage(
369 routing_id(), GURL(frame->document().securityOrigin().toString()),
370 GURL(frame->top()->document().securityOrigin().toString()),
371 local, &result));
372 cached_storage_permissions_[key] = result;
373 return result;
376 bool ContentSettingsObserver::allowReadFromClipboard(WebFrame* frame,
377 bool default_value) {
378 bool allowed = false;
379 // TODO(dcheng): Should we consider a toURL() method on WebSecurityOrigin?
380 Send(new ChromeViewHostMsg_CanTriggerClipboardRead(
381 GURL(frame->document().securityOrigin().toString().utf8()), &allowed));
382 return allowed;
385 bool ContentSettingsObserver::allowWriteToClipboard(WebFrame* frame,
386 bool default_value) {
387 bool allowed = false;
388 Send(new ChromeViewHostMsg_CanTriggerClipboardWrite(
389 GURL(frame->document().securityOrigin().toString().utf8()), &allowed));
390 return allowed;
393 bool ContentSettingsObserver::allowWebComponents(WebFrame* frame,
394 bool defaultValue) {
395 if (defaultValue)
396 return true;
398 WebSecurityOrigin origin = frame->document().securityOrigin();
399 if (EqualsASCII(origin.protocol(), content::kChromeUIScheme))
400 return true;
402 if (const extensions::Extension* extension = GetExtension(origin)) {
403 if (extension->HasAPIPermission(APIPermission::kExperimental))
404 return true;
407 return false;
410 bool ContentSettingsObserver::allowMutationEvents(WebFrame* frame,
411 bool default_value) {
412 WebSecurityOrigin origin = frame->document().securityOrigin();
413 const extensions::Extension* extension = GetExtension(origin);
414 if (extension && extension->is_platform_app())
415 return false;
416 return default_value;
419 bool ContentSettingsObserver::allowPushState(WebFrame* frame) {
420 WebSecurityOrigin origin = frame->document().securityOrigin();
421 const extensions::Extension* extension = GetExtension(origin);
422 return !extension || !extension->is_platform_app();
425 static void SendInsecureContentSignal(int signal) {
426 UMA_HISTOGRAM_ENUMERATION("SSL.InsecureContent", signal,
427 INSECURE_CONTENT_NUM_EVENTS);
430 bool ContentSettingsObserver::allowDisplayingInsecureContent(
431 blink::WebFrame* frame,
432 bool allowed_per_settings,
433 const blink::WebSecurityOrigin& origin,
434 const blink::WebURL& resource_url) {
435 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY);
437 std::string origin_host(origin.host().utf8());
438 GURL frame_gurl(frame->document().url());
439 if (IsHostInDomain(origin_host, kGoogleDotCom)) {
440 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE);
441 if (StartsWithASCII(frame_gurl.path(), kGoogleSupportPathPrefix, false)) {
442 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT);
443 } else if (StartsWithASCII(frame_gurl.path(),
444 kGoogleIntlPathPrefix,
445 false)) {
446 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL);
450 if (origin_host == kWWWDotGoogleDotCom) {
451 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE);
452 if (StartsWithASCII(frame_gurl.path(), kGoogleReaderPathPrefix, false))
453 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER);
454 } else if (origin_host == kMailDotGoogleDotCom) {
455 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE);
456 } else if (origin_host == kPlusDotGoogleDotCom) {
457 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE);
458 } else if (origin_host == kDocsDotGoogleDotCom) {
459 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE);
460 } else if (origin_host == kSitesDotGoogleDotCom) {
461 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE);
462 } else if (origin_host == kPicasawebDotGoogleDotCom) {
463 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE);
464 } else if (origin_host == kCodeDotGoogleDotCom) {
465 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE);
466 } else if (origin_host == kGroupsDotGoogleDotCom) {
467 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE);
468 } else if (origin_host == kMapsDotGoogleDotCom) {
469 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE);
470 } else if (origin_host == kWWWDotYoutubeDotCom) {
471 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE);
474 GURL resource_gurl(resource_url);
475 if (EndsWith(resource_gurl.path(), kDotHTML, false))
476 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HTML);
478 if (allowed_per_settings || allow_displaying_insecure_content_)
479 return true;
481 Send(new ChromeViewHostMsg_DidBlockDisplayingInsecureContent(routing_id()));
483 return false;
486 bool ContentSettingsObserver::allowRunningInsecureContent(
487 blink::WebFrame* frame,
488 bool allowed_per_settings,
489 const blink::WebSecurityOrigin& origin,
490 const blink::WebURL& resource_url) {
491 std::string origin_host(origin.host().utf8());
492 GURL frame_gurl(frame->document().url());
493 DCHECK_EQ(frame_gurl.host(), origin_host);
495 bool is_google = IsHostInDomain(origin_host, kGoogleDotCom);
496 if (is_google) {
497 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE);
498 if (StartsWithASCII(frame_gurl.path(), kGoogleSupportPathPrefix, false)) {
499 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT);
500 } else if (StartsWithASCII(frame_gurl.path(),
501 kGoogleIntlPathPrefix,
502 false)) {
503 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL);
507 if (origin_host == kWWWDotGoogleDotCom) {
508 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE);
509 if (StartsWithASCII(frame_gurl.path(), kGoogleReaderPathPrefix, false))
510 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_READER);
511 } else if (origin_host == kMailDotGoogleDotCom) {
512 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE);
513 } else if (origin_host == kPlusDotGoogleDotCom) {
514 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE);
515 } else if (origin_host == kDocsDotGoogleDotCom) {
516 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE);
517 } else if (origin_host == kSitesDotGoogleDotCom) {
518 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE);
519 } else if (origin_host == kPicasawebDotGoogleDotCom) {
520 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE);
521 } else if (origin_host == kCodeDotGoogleDotCom) {
522 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE);
523 } else if (origin_host == kGroupsDotGoogleDotCom) {
524 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE);
525 } else if (origin_host == kMapsDotGoogleDotCom) {
526 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE);
527 } else if (origin_host == kWWWDotYoutubeDotCom) {
528 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_YOUTUBE);
529 } else if (EndsWith(origin_host, kDotGoogleUserContentDotCom, false)) {
530 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT);
533 GURL resource_gurl(resource_url);
534 if (resource_gurl.host() == kWWWDotYoutubeDotCom)
535 SendInsecureContentSignal(INSECURE_CONTENT_RUN_TARGET_YOUTUBE);
537 if (EndsWith(resource_gurl.path(), kDotJS, false))
538 SendInsecureContentSignal(INSECURE_CONTENT_RUN_JS);
539 else if (EndsWith(resource_gurl.path(), kDotCSS, false))
540 SendInsecureContentSignal(INSECURE_CONTENT_RUN_CSS);
541 else if (EndsWith(resource_gurl.path(), kDotSWF, false))
542 SendInsecureContentSignal(INSECURE_CONTENT_RUN_SWF);
544 if (!allow_running_insecure_content_ && !allowed_per_settings) {
545 DidBlockContentType(CONTENT_SETTINGS_TYPE_MIXEDSCRIPT);
546 return false;
549 return true;
552 void ContentSettingsObserver::didNotAllowPlugins(WebFrame* frame) {
553 DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS);
556 void ContentSettingsObserver::didNotAllowScript(WebFrame* frame) {
557 DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
560 bool ContentSettingsObserver::AreNPAPIPluginsBlocked() const {
561 return npapi_plugins_blocked_;
564 void ContentSettingsObserver::OnLoadBlockedPlugins(
565 const std::string& identifier) {
566 temporarily_allowed_plugins_.insert(identifier);
569 void ContentSettingsObserver::OnSetAsInterstitial() {
570 is_interstitial_page_ = true;
573 void ContentSettingsObserver::OnNPAPINotSupported() {
574 npapi_plugins_blocked_ = true;
577 void ContentSettingsObserver::OnSetAllowDisplayingInsecureContent(bool allow) {
578 allow_displaying_insecure_content_ = allow;
581 void ContentSettingsObserver::OnSetAllowRunningInsecureContent(bool allow) {
582 allow_running_insecure_content_ = allow;
583 OnSetAllowDisplayingInsecureContent(allow);
586 void ContentSettingsObserver::OnReloadFrame() {
587 DCHECK(!render_frame()->GetWebFrame()->parent()) <<
588 "Should only be called on the main frame";
589 render_frame()->GetWebFrame()->reload();
592 void ContentSettingsObserver::ClearBlockedContentSettings() {
593 for (size_t i = 0; i < arraysize(content_blocked_); ++i)
594 content_blocked_[i] = false;
595 cached_storage_permissions_.clear();
596 cached_script_permissions_.clear();
599 const extensions::Extension* ContentSettingsObserver::GetExtension(
600 const WebSecurityOrigin& origin) const {
601 if (!EqualsASCII(origin.protocol(), extensions::kExtensionScheme))
602 return NULL;
604 const std::string extension_id = origin.host().utf8().data();
605 if (!extension_dispatcher_->IsExtensionActive(extension_id))
606 return NULL;
608 return extension_dispatcher_->extensions()->GetByID(extension_id);
611 bool ContentSettingsObserver::IsWhitelistedForContentSettings(WebFrame* frame) {
612 // Whitelist Instant processes.
613 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInstantProcess))
614 return true;
616 // Whitelist ftp directory listings, as they require JavaScript to function
617 // properly.
618 webkit_glue::WebURLResponseExtraDataImpl* extra_data =
619 static_cast<webkit_glue::WebURLResponseExtraDataImpl*>(
620 frame->dataSource()->response().extraData());
621 if (extra_data && extra_data->is_ftp_directory_listing())
622 return true;
623 return IsWhitelistedForContentSettings(frame->document().securityOrigin(),
624 frame->document().url());
627 bool ContentSettingsObserver::IsWhitelistedForContentSettings(
628 const WebSecurityOrigin& origin,
629 const GURL& document_url) {
630 if (document_url == GURL(content::kUnreachableWebDataURL))
631 return true;
633 if (origin.isUnique())
634 return false; // Uninitialized document?
636 if (EqualsASCII(origin.protocol(), content::kChromeUIScheme))
637 return true; // Browser UI elements should still work.
639 if (EqualsASCII(origin.protocol(), content::kChromeDevToolsScheme))
640 return true; // DevTools UI elements should still work.
642 if (EqualsASCII(origin.protocol(), extensions::kExtensionScheme))
643 return true;
645 // TODO(creis, fsamuel): Remove this once the concept of swapped out
646 // RenderFrames goes away.
647 if (document_url == GURL(content::kSwappedOutURL))
648 return true;
650 // If the scheme is file:, an empty file name indicates a directory listing,
651 // which requires JavaScript to function properly.
652 if (EqualsASCII(origin.protocol(), content::kFileScheme)) {
653 return document_url.SchemeIs(content::kFileScheme) &&
654 document_url.ExtractFileName().empty();
657 return false;