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 "components/content_settings/content/common/content_settings_messages.h"
10 #include "content/public/common/url_constants.h"
11 #include "content/public/renderer/document_state.h"
12 #include "content/public/renderer/render_frame.h"
13 #include "content/public/renderer/render_view.h"
14 #include "third_party/WebKit/public/platform/WebContentSettingCallbacks.h"
15 #include "third_party/WebKit/public/platform/WebURL.h"
16 #include "third_party/WebKit/public/web/WebDataSource.h"
17 #include "third_party/WebKit/public/web/WebDocument.h"
18 #include "third_party/WebKit/public/web/WebFrameClient.h"
19 #include "third_party/WebKit/public/web/WebLocalFrame.h"
20 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
21 #include "third_party/WebKit/public/web/WebView.h"
22 #include "url/url_constants.h"
24 #if defined(ENABLE_EXTENSIONS)
25 #include "extensions/common/constants.h"
26 #include "extensions/common/extension.h"
27 #include "extensions/common/permissions/api_permission.h"
28 #include "extensions/common/permissions/permissions_data.h"
29 #include "extensions/renderer/dispatcher.h"
30 #include "extensions/renderer/renderer_extension_registry.h"
33 using blink::WebContentSettingCallbacks
;
34 using blink::WebDataSource
;
35 using blink::WebDocument
;
36 using blink::WebFrame
;
37 using blink::WebSecurityOrigin
;
38 using blink::WebString
;
41 using content::DocumentState
;
42 using content::NavigationState
;
47 INSECURE_CONTENT_DISPLAY
= 0,
48 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE
,
49 INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE
,
50 INSECURE_CONTENT_DISPLAY_HTML
,
52 INSECURE_CONTENT_RUN_HOST_GOOGLE
,
53 INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE
,
54 INSECURE_CONTENT_RUN_TARGET_YOUTUBE
,
55 INSECURE_CONTENT_RUN_JS
,
56 INSECURE_CONTENT_RUN_CSS
,
57 INSECURE_CONTENT_RUN_SWF
,
58 INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE
,
59 INSECURE_CONTENT_RUN_HOST_YOUTUBE
,
60 INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT
,
61 INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE
,
62 INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE
,
63 INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE
,
64 INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE
,
65 INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE
,
66 INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE
,
67 INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE
,
68 INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE
,
69 INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE
,
70 INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE
,
71 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER
,
72 INSECURE_CONTENT_RUN_HOST_GOOGLE_READER
,
73 INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE
,
74 INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE
,
75 INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE
,
76 INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE
,
77 INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE
,
78 INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE
,
79 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT
,
80 INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT
,
81 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL
,
82 INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL
,
83 INSECURE_CONTENT_NUM_EVENTS
86 // Constants for UMA statistic collection.
87 static const char kWWWDotGoogleDotCom
[] = "www.google.com";
88 static const char kMailDotGoogleDotCom
[] = "mail.google.com";
89 static const char kPlusDotGoogleDotCom
[] = "plus.google.com";
90 static const char kDocsDotGoogleDotCom
[] = "docs.google.com";
91 static const char kSitesDotGoogleDotCom
[] = "sites.google.com";
92 static const char kPicasawebDotGoogleDotCom
[] = "picasaweb.google.com";
93 static const char kCodeDotGoogleDotCom
[] = "code.google.com";
94 static const char kGroupsDotGoogleDotCom
[] = "groups.google.com";
95 static const char kMapsDotGoogleDotCom
[] = "maps.google.com";
96 static const char kWWWDotYoutubeDotCom
[] = "www.youtube.com";
97 static const char kDotGoogleUserContentDotCom
[] = ".googleusercontent.com";
98 static const char kGoogleReaderPathPrefix
[] = "/reader/";
99 static const char kGoogleSupportPathPrefix
[] = "/support/";
100 static const char kGoogleIntlPathPrefix
[] = "/intl/";
101 static const char kDotJS
[] = ".js";
102 static const char kDotCSS
[] = ".css";
103 static const char kDotSWF
[] = ".swf";
104 static const char kDotHTML
[] = ".html";
106 // Constants for mixed-content blocking.
107 static const char kGoogleDotCom
[] = "google.com";
109 static bool IsHostInDomain(const std::string
& host
, const std::string
& domain
) {
110 return (base::EndsWith(host
, domain
, base::CompareCase::INSENSITIVE_ASCII
) &&
111 (host
.length() == domain
.length() ||
112 (host
.length() > domain
.length() &&
113 host
[host
.length() - domain
.length() - 1] == '.')));
116 GURL
GetOriginOrURL(const WebFrame
* frame
) {
117 WebString top_origin
= frame
->top()->securityOrigin().toString();
118 // The |top_origin| is unique ("null") e.g., for file:// URLs. Use the
119 // document URL as the primary URL in those cases.
120 // TODO(alexmos): This is broken for --site-per-process, since top() can be a
121 // WebRemoteFrame which does not have a document(), and the WebRemoteFrame's
122 // URL is not replicated.
123 if (top_origin
== "null")
124 return frame
->top()->document().url();
125 return GURL(top_origin
);
128 ContentSetting
GetContentSettingFromRules(
129 const ContentSettingsForOneType
& rules
,
130 const WebFrame
* frame
,
131 const GURL
& secondary_url
) {
132 ContentSettingsForOneType::const_iterator it
;
133 // If there is only one rule, it's the default rule and we don't need to match
135 if (rules
.size() == 1) {
136 DCHECK(rules
[0].primary_pattern
== ContentSettingsPattern::Wildcard());
137 DCHECK(rules
[0].secondary_pattern
== ContentSettingsPattern::Wildcard());
138 return rules
[0].setting
;
140 const GURL
& primary_url
= GetOriginOrURL(frame
);
141 for (it
= rules
.begin(); it
!= rules
.end(); ++it
) {
142 if (it
->primary_pattern
.Matches(primary_url
) &&
143 it
->secondary_pattern
.Matches(secondary_url
)) {
148 return CONTENT_SETTING_DEFAULT
;
153 ContentSettingsObserver::ContentSettingsObserver(
154 content::RenderFrame
* render_frame
,
155 extensions::Dispatcher
* extension_dispatcher
,
156 bool should_whitelist
)
157 : content::RenderFrameObserver(render_frame
),
158 content::RenderFrameObserverTracker
<ContentSettingsObserver
>(
160 #if defined(ENABLE_EXTENSIONS)
161 extension_dispatcher_(extension_dispatcher
),
163 allow_displaying_insecure_content_(false),
164 allow_running_insecure_content_(false),
165 content_setting_rules_(NULL
),
166 is_interstitial_page_(false),
167 npapi_plugins_blocked_(false),
168 current_request_id_(0),
169 should_whitelist_(should_whitelist
) {
170 ClearBlockedContentSettings();
171 render_frame
->GetWebFrame()->setContentSettingsClient(this);
173 content::RenderFrame
* main_frame
=
174 render_frame
->GetRenderView()->GetMainRenderFrame();
175 // TODO(nasko): The main frame is not guaranteed to be in the same process
176 // with this frame with --site-per-process. This code needs to be updated
177 // to handle this case. See https://crbug.com/496670.
178 if (main_frame
&& main_frame
!= render_frame
) {
179 // Copy all the settings from the main render frame to avoid race conditions
180 // when initializing this data. See https://crbug.com/333308.
181 ContentSettingsObserver
* parent
= ContentSettingsObserver::Get(main_frame
);
182 allow_displaying_insecure_content_
=
183 parent
->allow_displaying_insecure_content_
;
184 allow_running_insecure_content_
= parent
->allow_running_insecure_content_
;
185 temporarily_allowed_plugins_
= parent
->temporarily_allowed_plugins_
;
186 is_interstitial_page_
= parent
->is_interstitial_page_
;
187 npapi_plugins_blocked_
= parent
->npapi_plugins_blocked_
;
191 ContentSettingsObserver::~ContentSettingsObserver() {
194 void ContentSettingsObserver::SetContentSettingRules(
195 const RendererContentSettingRules
* content_setting_rules
) {
196 content_setting_rules_
= content_setting_rules
;
199 bool ContentSettingsObserver::IsPluginTemporarilyAllowed(
200 const std::string
& identifier
) {
201 // If the empty string is in here, it means all plugins are allowed.
202 // TODO(bauerb): Remove this once we only pass in explicit identifiers.
203 return (temporarily_allowed_plugins_
.find(identifier
) !=
204 temporarily_allowed_plugins_
.end()) ||
205 (temporarily_allowed_plugins_
.find(std::string()) !=
206 temporarily_allowed_plugins_
.end());
209 void ContentSettingsObserver::DidBlockContentType(
210 ContentSettingsType settings_type
) {
211 DidBlockContentType(settings_type
, base::string16());
214 void ContentSettingsObserver::DidBlockContentType(
215 ContentSettingsType settings_type
,
216 const base::string16
& details
) {
217 // Send multiple ContentBlocked messages if details are provided.
218 if (!content_blocked_
[settings_type
] || !details
.empty()) {
219 content_blocked_
[settings_type
] = true;
220 Send(new ChromeViewHostMsg_ContentBlocked(routing_id(), settings_type
,
225 bool ContentSettingsObserver::OnMessageReceived(const IPC::Message
& message
) {
227 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver
, message
)
228 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAsInterstitial
, OnSetAsInterstitial
)
229 IPC_MESSAGE_HANDLER(ChromeViewMsg_NPAPINotSupported
, OnNPAPINotSupported
)
230 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowDisplayingInsecureContent
,
231 OnSetAllowDisplayingInsecureContent
)
232 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowRunningInsecureContent
,
233 OnSetAllowRunningInsecureContent
)
234 IPC_MESSAGE_HANDLER(ChromeViewMsg_ReloadFrame
, OnReloadFrame
);
235 IPC_MESSAGE_HANDLER(ChromeViewMsg_RequestFileSystemAccessAsyncResponse
,
236 OnRequestFileSystemAccessAsyncResponse
)
237 IPC_MESSAGE_UNHANDLED(handled
= false)
238 IPC_END_MESSAGE_MAP()
242 // Don't swallow LoadBlockedPlugins messages, as they're sent to every
244 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver
, message
)
245 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins
, OnLoadBlockedPlugins
)
246 IPC_END_MESSAGE_MAP()
251 void ContentSettingsObserver::DidCommitProvisionalLoad(
252 bool is_new_navigation
,
253 bool is_same_page_navigation
) {
254 WebFrame
* frame
= render_frame()->GetWebFrame();
256 return; // Not a top-level navigation.
258 if (!is_same_page_navigation
) {
259 // Clear "block" flags for the new page. This needs to happen before any of
260 // |allowScript()|, |allowScriptFromSource()|, |allowImage()|, or
261 // |allowPlugins()| is called for the new page so that these functions can
262 // correctly detect that a piece of content flipped from "not blocked" to
264 ClearBlockedContentSettings();
265 temporarily_allowed_plugins_
.clear();
268 GURL url
= frame
->document().url();
269 // If we start failing this DCHECK, please makes sure we don't regress
270 // this bug: http://code.google.com/p/chromium/issues/detail?id=79304
271 DCHECK(frame
->document().securityOrigin().toString() == "null" ||
272 !url
.SchemeIs(url::kDataScheme
));
275 bool ContentSettingsObserver::allowDatabase(const WebString
& name
,
276 const WebString
& display_name
,
277 unsigned long estimated_size
) {
278 WebFrame
* frame
= render_frame()->GetWebFrame();
279 if (frame
->securityOrigin().isUnique() ||
280 frame
->top()->securityOrigin().isUnique())
284 Send(new ChromeViewHostMsg_AllowDatabase(
285 routing_id(), GURL(frame
->securityOrigin().toString()),
286 GURL(frame
->top()->securityOrigin().toString()), name
, display_name
,
291 void ContentSettingsObserver::requestFileSystemAccessAsync(
292 const WebContentSettingCallbacks
& callbacks
) {
293 WebFrame
* frame
= render_frame()->GetWebFrame();
294 if (frame
->securityOrigin().isUnique() ||
295 frame
->top()->securityOrigin().isUnique()) {
296 WebContentSettingCallbacks
permissionCallbacks(callbacks
);
297 permissionCallbacks
.doDeny();
300 ++current_request_id_
;
301 std::pair
<PermissionRequestMap::iterator
, bool> insert_result
=
302 permission_requests_
.insert(
303 std::make_pair(current_request_id_
, callbacks
));
305 // Verify there are no duplicate insertions.
306 DCHECK(insert_result
.second
);
308 Send(new ChromeViewHostMsg_RequestFileSystemAccessAsync(
309 routing_id(), current_request_id_
,
310 GURL(frame
->securityOrigin().toString()),
311 GURL(frame
->top()->securityOrigin().toString())));
314 bool ContentSettingsObserver::allowImage(bool enabled_per_settings
,
315 const WebURL
& image_url
) {
316 bool allow
= enabled_per_settings
;
317 if (enabled_per_settings
) {
318 if (is_interstitial_page_
)
321 if (IsWhitelistedForContentSettings())
324 if (content_setting_rules_
) {
325 GURL
secondary_url(image_url
);
327 GetContentSettingFromRules(content_setting_rules_
->image_rules
,
328 render_frame()->GetWebFrame(),
329 secondary_url
) != CONTENT_SETTING_BLOCK
;
333 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES
);
337 bool ContentSettingsObserver::allowIndexedDB(const WebString
& name
,
338 const WebSecurityOrigin
& origin
) {
339 WebFrame
* frame
= render_frame()->GetWebFrame();
340 if (frame
->securityOrigin().isUnique() ||
341 frame
->top()->securityOrigin().isUnique())
345 Send(new ChromeViewHostMsg_AllowIndexedDB(
346 routing_id(), GURL(frame
->securityOrigin().toString()),
347 GURL(frame
->top()->securityOrigin().toString()), name
, &result
));
351 bool ContentSettingsObserver::allowPlugins(bool enabled_per_settings
) {
352 return enabled_per_settings
;
355 bool ContentSettingsObserver::allowScript(bool enabled_per_settings
) {
356 if (!enabled_per_settings
)
358 if (is_interstitial_page_
)
361 WebFrame
* frame
= render_frame()->GetWebFrame();
362 std::map
<WebFrame
*, bool>::const_iterator it
=
363 cached_script_permissions_
.find(frame
);
364 if (it
!= cached_script_permissions_
.end())
367 // Evaluate the content setting rules before
368 // |IsWhitelistedForContentSettings|; if there is only the default rule
369 // allowing all scripts, it's quicker this way.
371 if (content_setting_rules_
) {
372 ContentSetting setting
= GetContentSettingFromRules(
373 content_setting_rules_
->script_rules
,
375 GURL(frame
->document().securityOrigin().toString()));
376 allow
= setting
!= CONTENT_SETTING_BLOCK
;
378 allow
= allow
|| IsWhitelistedForContentSettings();
380 cached_script_permissions_
[frame
] = allow
;
384 bool ContentSettingsObserver::allowScriptFromSource(
385 bool enabled_per_settings
,
386 const blink::WebURL
& script_url
) {
387 if (!enabled_per_settings
)
389 if (is_interstitial_page_
)
393 if (content_setting_rules_
) {
394 ContentSetting setting
=
395 GetContentSettingFromRules(content_setting_rules_
->script_rules
,
396 render_frame()->GetWebFrame(),
398 allow
= setting
!= CONTENT_SETTING_BLOCK
;
400 return allow
|| IsWhitelistedForContentSettings();
403 bool ContentSettingsObserver::allowStorage(bool local
) {
404 WebFrame
* frame
= render_frame()->GetWebFrame();
405 if (frame
->securityOrigin().isUnique() ||
406 frame
->top()->securityOrigin().isUnique())
410 StoragePermissionsKey
key(
411 GURL(frame
->document().securityOrigin().toString()), local
);
412 std::map
<StoragePermissionsKey
, bool>::const_iterator permissions
=
413 cached_storage_permissions_
.find(key
);
414 if (permissions
!= cached_storage_permissions_
.end())
415 return permissions
->second
;
417 Send(new ChromeViewHostMsg_AllowDOMStorage(
418 routing_id(), GURL(frame
->securityOrigin().toString()),
419 GURL(frame
->top()->securityOrigin().toString()), local
, &result
));
420 cached_storage_permissions_
[key
] = result
;
424 bool ContentSettingsObserver::allowReadFromClipboard(bool default_value
) {
425 bool allowed
= default_value
;
426 #if defined(ENABLE_EXTENSIONS)
427 extensions::ScriptContext
* calling_context
=
428 extension_dispatcher_
->script_context_set().GetCalling();
429 if (calling_context
) {
430 allowed
|= calling_context
->HasAPIPermission(
431 extensions::APIPermission::kClipboardRead
);
437 bool ContentSettingsObserver::allowWriteToClipboard(bool default_value
) {
438 bool allowed
= default_value
;
439 #if defined(ENABLE_EXTENSIONS)
440 // All blessed extension pages could historically write to the clipboard, so
441 // preserve that for compatibility.
442 extensions::ScriptContext
* calling_context
=
443 extension_dispatcher_
->script_context_set().GetCalling();
444 if (calling_context
) {
445 if (calling_context
->effective_context_type() ==
446 extensions::Feature::BLESSED_EXTENSION_CONTEXT
) {
449 allowed
|= calling_context
->HasAPIPermission(
450 extensions::APIPermission::kClipboardWrite
);
457 bool ContentSettingsObserver::allowMutationEvents(bool default_value
) {
458 return IsPlatformApp() ? false : default_value
;
461 static void SendInsecureContentSignal(int signal
) {
462 UMA_HISTOGRAM_ENUMERATION("SSL.InsecureContent", signal
,
463 INSECURE_CONTENT_NUM_EVENTS
);
466 bool ContentSettingsObserver::allowDisplayingInsecureContent(
467 bool allowed_per_settings
,
468 const blink::WebSecurityOrigin
& origin
,
469 const blink::WebURL
& resource_url
) {
470 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY
);
472 std::string
origin_host(origin
.host().utf8());
473 WebFrame
* frame
= render_frame()->GetWebFrame();
474 GURL
frame_gurl(frame
->document().url());
475 if (IsHostInDomain(origin_host
, kGoogleDotCom
)) {
476 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE
);
477 if (base::StartsWith(frame_gurl
.path(), kGoogleSupportPathPrefix
,
478 base::CompareCase::INSENSITIVE_ASCII
)) {
479 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT
);
480 } else if (base::StartsWith(frame_gurl
.path(), kGoogleIntlPathPrefix
,
481 base::CompareCase::INSENSITIVE_ASCII
)) {
482 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL
);
486 if (origin_host
== kWWWDotGoogleDotCom
) {
487 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE
);
488 if (base::StartsWith(frame_gurl
.path(), kGoogleReaderPathPrefix
,
489 base::CompareCase::INSENSITIVE_ASCII
))
490 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER
);
491 } else if (origin_host
== kMailDotGoogleDotCom
) {
492 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE
);
493 } else if (origin_host
== kPlusDotGoogleDotCom
) {
494 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE
);
495 } else if (origin_host
== kDocsDotGoogleDotCom
) {
496 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE
);
497 } else if (origin_host
== kSitesDotGoogleDotCom
) {
498 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE
);
499 } else if (origin_host
== kPicasawebDotGoogleDotCom
) {
500 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE
);
501 } else if (origin_host
== kCodeDotGoogleDotCom
) {
502 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE
);
503 } else if (origin_host
== kGroupsDotGoogleDotCom
) {
504 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE
);
505 } else if (origin_host
== kMapsDotGoogleDotCom
) {
506 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE
);
507 } else if (origin_host
== kWWWDotYoutubeDotCom
) {
508 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE
);
511 GURL
resource_gurl(resource_url
);
512 if (base::EndsWith(resource_gurl
.path(), kDotHTML
,
513 base::CompareCase::INSENSITIVE_ASCII
))
514 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HTML
);
516 if (allowed_per_settings
|| allow_displaying_insecure_content_
)
519 Send(new ChromeViewHostMsg_DidBlockDisplayingInsecureContent(routing_id()));
524 bool ContentSettingsObserver::allowRunningInsecureContent(
525 bool allowed_per_settings
,
526 const blink::WebSecurityOrigin
& origin
,
527 const blink::WebURL
& resource_url
) {
528 std::string
origin_host(origin
.host().utf8());
529 WebFrame
* frame
= render_frame()->GetWebFrame();
530 GURL
frame_gurl(frame
->document().url());
531 DCHECK_EQ(frame_gurl
.host(), origin_host
);
533 bool is_google
= IsHostInDomain(origin_host
, kGoogleDotCom
);
535 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE
);
536 if (base::StartsWith(frame_gurl
.path(), kGoogleSupportPathPrefix
,
537 base::CompareCase::INSENSITIVE_ASCII
)) {
538 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT
);
539 } else if (base::StartsWith(frame_gurl
.path(), kGoogleIntlPathPrefix
,
540 base::CompareCase::INSENSITIVE_ASCII
)) {
541 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL
);
545 if (origin_host
== kWWWDotGoogleDotCom
) {
546 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE
);
547 if (base::StartsWith(frame_gurl
.path(), kGoogleReaderPathPrefix
,
548 base::CompareCase::INSENSITIVE_ASCII
))
549 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_READER
);
550 } else if (origin_host
== kMailDotGoogleDotCom
) {
551 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE
);
552 } else if (origin_host
== kPlusDotGoogleDotCom
) {
553 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE
);
554 } else if (origin_host
== kDocsDotGoogleDotCom
) {
555 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE
);
556 } else if (origin_host
== kSitesDotGoogleDotCom
) {
557 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE
);
558 } else if (origin_host
== kPicasawebDotGoogleDotCom
) {
559 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE
);
560 } else if (origin_host
== kCodeDotGoogleDotCom
) {
561 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE
);
562 } else if (origin_host
== kGroupsDotGoogleDotCom
) {
563 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE
);
564 } else if (origin_host
== kMapsDotGoogleDotCom
) {
565 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE
);
566 } else if (origin_host
== kWWWDotYoutubeDotCom
) {
567 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_YOUTUBE
);
568 } else if (base::EndsWith(origin_host
, kDotGoogleUserContentDotCom
,
569 base::CompareCase::INSENSITIVE_ASCII
)) {
570 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT
);
573 GURL
resource_gurl(resource_url
);
574 if (resource_gurl
.host() == kWWWDotYoutubeDotCom
)
575 SendInsecureContentSignal(INSECURE_CONTENT_RUN_TARGET_YOUTUBE
);
577 if (base::EndsWith(resource_gurl
.path(), kDotJS
,
578 base::CompareCase::INSENSITIVE_ASCII
))
579 SendInsecureContentSignal(INSECURE_CONTENT_RUN_JS
);
580 else if (base::EndsWith(resource_gurl
.path(), kDotCSS
,
581 base::CompareCase::INSENSITIVE_ASCII
))
582 SendInsecureContentSignal(INSECURE_CONTENT_RUN_CSS
);
583 else if (base::EndsWith(resource_gurl
.path(), kDotSWF
,
584 base::CompareCase::INSENSITIVE_ASCII
))
585 SendInsecureContentSignal(INSECURE_CONTENT_RUN_SWF
);
587 if (!allow_running_insecure_content_
&& !allowed_per_settings
) {
588 DidBlockContentType(CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, origin
.host());
595 void ContentSettingsObserver::didNotAllowPlugins() {
596 DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS
);
599 void ContentSettingsObserver::didNotAllowScript() {
600 DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT
);
603 bool ContentSettingsObserver::AreNPAPIPluginsBlocked() const {
604 return npapi_plugins_blocked_
;
607 void ContentSettingsObserver::OnLoadBlockedPlugins(
608 const std::string
& identifier
) {
609 temporarily_allowed_plugins_
.insert(identifier
);
612 void ContentSettingsObserver::OnSetAsInterstitial() {
613 is_interstitial_page_
= true;
616 void ContentSettingsObserver::OnNPAPINotSupported() {
617 npapi_plugins_blocked_
= true;
620 void ContentSettingsObserver::OnSetAllowDisplayingInsecureContent(bool allow
) {
621 allow_displaying_insecure_content_
= allow
;
624 void ContentSettingsObserver::OnSetAllowRunningInsecureContent(bool allow
) {
625 allow_running_insecure_content_
= allow
;
626 OnSetAllowDisplayingInsecureContent(allow
);
629 void ContentSettingsObserver::OnReloadFrame() {
630 DCHECK(!render_frame()->GetWebFrame()->parent()) <<
631 "Should only be called on the main frame";
632 render_frame()->GetWebFrame()->reload();
635 void ContentSettingsObserver::OnRequestFileSystemAccessAsyncResponse(
638 PermissionRequestMap::iterator it
= permission_requests_
.find(request_id
);
639 if (it
== permission_requests_
.end())
642 WebContentSettingCallbacks callbacks
= it
->second
;
643 permission_requests_
.erase(it
);
652 void ContentSettingsObserver::ClearBlockedContentSettings() {
653 for (size_t i
= 0; i
< arraysize(content_blocked_
); ++i
)
654 content_blocked_
[i
] = false;
655 cached_storage_permissions_
.clear();
656 cached_script_permissions_
.clear();
659 bool ContentSettingsObserver::IsPlatformApp() {
660 #if defined(ENABLE_EXTENSIONS)
661 WebFrame
* frame
= render_frame()->GetWebFrame();
662 WebSecurityOrigin origin
= frame
->document().securityOrigin();
663 const extensions::Extension
* extension
= GetExtension(origin
);
664 return extension
&& extension
->is_platform_app();
670 #if defined(ENABLE_EXTENSIONS)
671 const extensions::Extension
* ContentSettingsObserver::GetExtension(
672 const WebSecurityOrigin
& origin
) const {
673 if (!base::EqualsASCII(base::StringPiece16(origin
.protocol()),
674 extensions::kExtensionScheme
))
677 const std::string extension_id
= origin
.host().utf8().data();
678 if (!extension_dispatcher_
->IsExtensionActive(extension_id
))
681 return extensions::RendererExtensionRegistry::Get()->GetByID(extension_id
);
685 bool ContentSettingsObserver::IsWhitelistedForContentSettings() const {
686 if (should_whitelist_
)
689 // Whitelist ftp directory listings, as they require JavaScript to function
691 if (render_frame()->IsFTPDirectoryListing())
694 WebFrame
* web_frame
= render_frame()->GetWebFrame();
695 return IsWhitelistedForContentSettings(web_frame
->document().securityOrigin(),
696 web_frame
->document().url());
699 bool ContentSettingsObserver::IsWhitelistedForContentSettings(
700 const WebSecurityOrigin
& origin
,
701 const GURL
& document_url
) {
702 if (document_url
== GURL(content::kUnreachableWebDataURL
))
705 if (origin
.isUnique())
706 return false; // Uninitialized document?
708 base::string16 protocol
= origin
.protocol();
709 if (base::EqualsASCII(protocol
, content::kChromeUIScheme
))
710 return true; // Browser UI elements should still work.
712 if (base::EqualsASCII(protocol
, content::kChromeDevToolsScheme
))
713 return true; // DevTools UI elements should still work.
715 #if defined(ENABLE_EXTENSIONS)
716 if (base::EqualsASCII(protocol
, extensions::kExtensionScheme
))
720 // TODO(creis, fsamuel): Remove this once the concept of swapped out
721 // RenderFrames goes away.
722 if (document_url
== GURL(content::kSwappedOutURL
))
725 // If the scheme is file:, an empty file name indicates a directory listing,
726 // which requires JavaScript to function properly.
727 if (base::EqualsASCII(protocol
, url::kFileScheme
)) {
728 return document_url
.SchemeIs(url::kFileScheme
) &&
729 document_url
.ExtractFileName().empty();