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
;
35 using content::DocumentState
;
36 using content::NavigationState
;
37 using extensions::APIPermission
;
42 INSECURE_CONTENT_DISPLAY
= 0,
43 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE
,
44 INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE
,
45 INSECURE_CONTENT_DISPLAY_HTML
,
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
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
)) {
140 return CONTENT_SETTING_DEFAULT
;
145 ContentSettingsObserver::ContentSettingsObserver(
146 content::RenderFrame
* render_frame
,
147 extensions::Dispatcher
* extension_dispatcher
)
148 : content::RenderFrameObserver(render_frame
),
149 content::RenderFrameObserverTracker
<ContentSettingsObserver
>(
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
) {
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()
202 // Don't swallow LoadBlockedPlugins messages, as they're sent to every
204 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver
, message
)
205 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins
, OnLoadBlockedPlugins
)
206 IPC_END_MESSAGE_MAP()
211 void ContentSettingsObserver::DidCommitProvisionalLoad(bool is_new_navigation
) {
212 WebFrame
* frame
= render_frame()->GetWebFrame();
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
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())
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
));
252 bool ContentSettingsObserver::allowFileSystem(WebFrame
* frame
) {
253 if (frame
->document().securityOrigin().isUnique() ||
254 frame
->top()->document().securityOrigin().isUnique())
258 Send(new ChromeViewHostMsg_AllowFileSystem(
259 routing_id(), GURL(frame
->document().securityOrigin().toString()),
260 GURL(frame
->top()->document().securityOrigin().toString()), &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_
)
271 if (IsWhitelistedForContentSettings(frame
))
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
;
282 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES
);
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())
294 Send(new ChromeViewHostMsg_AllowIndexedDB(
295 routing_id(), GURL(frame
->document().securityOrigin().toString()),
296 GURL(frame
->top()->document().securityOrigin().toString()),
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
)
310 if (is_interstitial_page_
)
313 std::map
<WebFrame
*, bool>::const_iterator it
=
314 cached_script_permissions_
.find(frame
);
315 if (it
!= cached_script_permissions_
.end())
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.
322 if (content_setting_rules_
) {
323 ContentSetting setting
= GetContentSettingFromRules(
324 content_setting_rules_
->script_rules
,
326 GURL(frame
->document().securityOrigin().toString()));
327 allow
= setting
!= CONTENT_SETTING_BLOCK
;
329 allow
= allow
|| IsWhitelistedForContentSettings(frame
);
331 cached_script_permissions_
[frame
] = allow
;
335 bool ContentSettingsObserver::allowScriptFromSource(
337 bool enabled_per_settings
,
338 const blink::WebURL
& script_url
) {
339 if (!enabled_per_settings
)
341 if (is_interstitial_page_
)
345 if (content_setting_rules_
) {
346 ContentSetting setting
= GetContentSettingFromRules(
347 content_setting_rules_
->script_rules
,
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())
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()),
372 cached_storage_permissions_
[key
] = 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
));
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
));
393 bool ContentSettingsObserver::allowWebComponents(WebFrame
* frame
,
398 WebSecurityOrigin origin
= frame
->document().securityOrigin();
399 if (EqualsASCII(origin
.protocol(), content::kChromeUIScheme
))
402 if (const extensions::Extension
* extension
= GetExtension(origin
)) {
403 if (extension
->HasAPIPermission(APIPermission::kExperimental
))
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())
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
,
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_
)
481 Send(new ChromeViewHostMsg_DidBlockDisplayingInsecureContent(routing_id()));
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
);
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
,
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
);
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
))
604 const std::string extension_id
= origin
.host().utf8().data();
605 if (!extension_dispatcher_
->IsExtensionActive(extension_id
))
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
))
616 // Whitelist ftp directory listings, as they require JavaScript to function
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())
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
))
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
))
645 // TODO(creis, fsamuel): Remove this once the concept of swapped out
646 // RenderFrames goes away.
647 if (document_url
== GURL(content::kSwappedOutURL
))
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();