[sessions]: Componentize TabRestore code
[chromium-blink-merge.git] / chrome / renderer / content_settings_observer.cc
blob9707f3da239b05b11b95e9d85dc4484cfe02da59
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"
31 #endif
33 using blink::WebContentSettingCallbacks;
34 using blink::WebDataSource;
35 using blink::WebDocument;
36 using blink::WebFrame;
37 using blink::WebSecurityOrigin;
38 using blink::WebString;
39 using blink::WebURL;
40 using blink::WebView;
41 using content::DocumentState;
42 using content::NavigationState;
44 namespace {
46 enum {
47 INSECURE_CONTENT_DISPLAY = 0,
48 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE,
49 INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE,
50 INSECURE_CONTENT_DISPLAY_HTML,
51 INSECURE_CONTENT_RUN,
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
134 // the patterns.
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)) {
144 return it->setting;
147 NOTREACHED();
148 return CONTENT_SETTING_DEFAULT;
151 } // namespace
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>(
159 render_frame),
160 #if defined(ENABLE_EXTENSIONS)
161 extension_dispatcher_(extension_dispatcher),
162 #endif
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 bool& blocked = content_blocked_[settings_type];
219 if (!blocked || !details.empty()) {
220 blocked = true;
221 Send(new ChromeViewHostMsg_ContentBlocked(routing_id(), settings_type,
222 details));
226 bool ContentSettingsObserver::OnMessageReceived(const IPC::Message& message) {
227 bool handled = true;
228 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message)
229 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAsInterstitial, OnSetAsInterstitial)
230 IPC_MESSAGE_HANDLER(ChromeViewMsg_NPAPINotSupported, OnNPAPINotSupported)
231 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowDisplayingInsecureContent,
232 OnSetAllowDisplayingInsecureContent)
233 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowRunningInsecureContent,
234 OnSetAllowRunningInsecureContent)
235 IPC_MESSAGE_HANDLER(ChromeViewMsg_ReloadFrame, OnReloadFrame);
236 IPC_MESSAGE_HANDLER(ChromeViewMsg_RequestFileSystemAccessAsyncResponse,
237 OnRequestFileSystemAccessAsyncResponse)
238 IPC_MESSAGE_UNHANDLED(handled = false)
239 IPC_END_MESSAGE_MAP()
240 if (handled)
241 return true;
243 // Don't swallow LoadBlockedPlugins messages, as they're sent to every
244 // blocked plugin.
245 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message)
246 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins)
247 IPC_END_MESSAGE_MAP()
249 return false;
252 void ContentSettingsObserver::DidCommitProvisionalLoad(
253 bool is_new_navigation,
254 bool is_same_page_navigation) {
255 WebFrame* frame = render_frame()->GetWebFrame();
256 if (frame->parent())
257 return; // Not a top-level navigation.
259 if (!is_same_page_navigation) {
260 // Clear "block" flags for the new page. This needs to happen before any of
261 // |allowScript()|, |allowScriptFromSource()|, |allowImage()|, or
262 // |allowPlugins()| is called for the new page so that these functions can
263 // correctly detect that a piece of content flipped from "not blocked" to
264 // "blocked".
265 ClearBlockedContentSettings();
266 temporarily_allowed_plugins_.clear();
269 GURL url = frame->document().url();
270 // If we start failing this DCHECK, please makes sure we don't regress
271 // this bug: http://code.google.com/p/chromium/issues/detail?id=79304
272 DCHECK(frame->document().securityOrigin().toString() == "null" ||
273 !url.SchemeIs(url::kDataScheme));
276 bool ContentSettingsObserver::allowDatabase(const WebString& name,
277 const WebString& display_name,
278 unsigned long estimated_size) {
279 WebFrame* frame = render_frame()->GetWebFrame();
280 if (frame->securityOrigin().isUnique() ||
281 frame->top()->securityOrigin().isUnique())
282 return false;
284 bool result = false;
285 Send(new ChromeViewHostMsg_AllowDatabase(
286 routing_id(), GURL(frame->securityOrigin().toString()),
287 GURL(frame->top()->securityOrigin().toString()), name, display_name,
288 &result));
289 return result;
292 void ContentSettingsObserver::requestFileSystemAccessAsync(
293 const WebContentSettingCallbacks& callbacks) {
294 WebFrame* frame = render_frame()->GetWebFrame();
295 if (frame->securityOrigin().isUnique() ||
296 frame->top()->securityOrigin().isUnique()) {
297 WebContentSettingCallbacks permissionCallbacks(callbacks);
298 permissionCallbacks.doDeny();
299 return;
301 ++current_request_id_;
302 std::pair<PermissionRequestMap::iterator, bool> insert_result =
303 permission_requests_.insert(
304 std::make_pair(current_request_id_, callbacks));
306 // Verify there are no duplicate insertions.
307 DCHECK(insert_result.second);
309 Send(new ChromeViewHostMsg_RequestFileSystemAccessAsync(
310 routing_id(), current_request_id_,
311 GURL(frame->securityOrigin().toString()),
312 GURL(frame->top()->securityOrigin().toString())));
315 bool ContentSettingsObserver::allowImage(bool enabled_per_settings,
316 const WebURL& image_url) {
317 bool allow = enabled_per_settings;
318 if (enabled_per_settings) {
319 if (is_interstitial_page_)
320 return true;
322 if (IsWhitelistedForContentSettings())
323 return true;
325 if (content_setting_rules_) {
326 GURL secondary_url(image_url);
327 allow =
328 GetContentSettingFromRules(content_setting_rules_->image_rules,
329 render_frame()->GetWebFrame(),
330 secondary_url) != CONTENT_SETTING_BLOCK;
333 if (!allow)
334 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES);
335 return allow;
338 bool ContentSettingsObserver::allowIndexedDB(const WebString& name,
339 const WebSecurityOrigin& origin) {
340 WebFrame* frame = render_frame()->GetWebFrame();
341 if (frame->securityOrigin().isUnique() ||
342 frame->top()->securityOrigin().isUnique())
343 return false;
345 bool result = false;
346 Send(new ChromeViewHostMsg_AllowIndexedDB(
347 routing_id(), GURL(frame->securityOrigin().toString()),
348 GURL(frame->top()->securityOrigin().toString()), name, &result));
349 return result;
352 bool ContentSettingsObserver::allowPlugins(bool enabled_per_settings) {
353 return enabled_per_settings;
356 bool ContentSettingsObserver::allowScript(bool enabled_per_settings) {
357 if (!enabled_per_settings)
358 return false;
359 if (is_interstitial_page_)
360 return true;
362 WebFrame* frame = render_frame()->GetWebFrame();
363 std::map<WebFrame*, bool>::const_iterator it =
364 cached_script_permissions_.find(frame);
365 if (it != cached_script_permissions_.end())
366 return it->second;
368 // Evaluate the content setting rules before
369 // |IsWhitelistedForContentSettings|; if there is only the default rule
370 // allowing all scripts, it's quicker this way.
371 bool allow = true;
372 if (content_setting_rules_) {
373 ContentSetting setting = GetContentSettingFromRules(
374 content_setting_rules_->script_rules,
375 frame,
376 GURL(frame->document().securityOrigin().toString()));
377 allow = setting != CONTENT_SETTING_BLOCK;
379 allow = allow || IsWhitelistedForContentSettings();
381 cached_script_permissions_[frame] = allow;
382 return allow;
385 bool ContentSettingsObserver::allowScriptFromSource(
386 bool enabled_per_settings,
387 const blink::WebURL& script_url) {
388 if (!enabled_per_settings)
389 return false;
390 if (is_interstitial_page_)
391 return true;
393 bool allow = true;
394 if (content_setting_rules_) {
395 ContentSetting setting =
396 GetContentSettingFromRules(content_setting_rules_->script_rules,
397 render_frame()->GetWebFrame(),
398 GURL(script_url));
399 allow = setting != CONTENT_SETTING_BLOCK;
401 return allow || IsWhitelistedForContentSettings();
404 bool ContentSettingsObserver::allowStorage(bool local) {
405 WebFrame* frame = render_frame()->GetWebFrame();
406 if (frame->securityOrigin().isUnique() ||
407 frame->top()->securityOrigin().isUnique())
408 return false;
409 bool result = false;
411 StoragePermissionsKey key(
412 GURL(frame->document().securityOrigin().toString()), local);
413 std::map<StoragePermissionsKey, bool>::const_iterator permissions =
414 cached_storage_permissions_.find(key);
415 if (permissions != cached_storage_permissions_.end())
416 return permissions->second;
418 Send(new ChromeViewHostMsg_AllowDOMStorage(
419 routing_id(), GURL(frame->securityOrigin().toString()),
420 GURL(frame->top()->securityOrigin().toString()), local, &result));
421 cached_storage_permissions_[key] = result;
422 return result;
425 bool ContentSettingsObserver::allowReadFromClipboard(bool default_value) {
426 bool allowed = default_value;
427 #if defined(ENABLE_EXTENSIONS)
428 extensions::ScriptContext* calling_context =
429 extension_dispatcher_->script_context_set().GetCalling();
430 if (calling_context) {
431 allowed |= calling_context->HasAPIPermission(
432 extensions::APIPermission::kClipboardRead);
434 #endif
435 return allowed;
438 bool ContentSettingsObserver::allowWriteToClipboard(bool default_value) {
439 bool allowed = default_value;
440 #if defined(ENABLE_EXTENSIONS)
441 // All blessed extension pages could historically write to the clipboard, so
442 // preserve that for compatibility.
443 extensions::ScriptContext* calling_context =
444 extension_dispatcher_->script_context_set().GetCalling();
445 if (calling_context) {
446 if (calling_context->effective_context_type() ==
447 extensions::Feature::BLESSED_EXTENSION_CONTEXT) {
448 allowed = true;
449 } else {
450 allowed |= calling_context->HasAPIPermission(
451 extensions::APIPermission::kClipboardWrite);
454 #endif
455 return allowed;
458 bool ContentSettingsObserver::allowMutationEvents(bool default_value) {
459 return IsPlatformApp() ? false : default_value;
462 static void SendInsecureContentSignal(int signal) {
463 UMA_HISTOGRAM_ENUMERATION("SSL.InsecureContent", signal,
464 INSECURE_CONTENT_NUM_EVENTS);
467 bool ContentSettingsObserver::allowDisplayingInsecureContent(
468 bool allowed_per_settings,
469 const blink::WebSecurityOrigin& origin,
470 const blink::WebURL& resource_url) {
471 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY);
473 std::string origin_host(origin.host().utf8());
474 WebFrame* frame = render_frame()->GetWebFrame();
475 GURL frame_gurl(frame->document().url());
476 if (IsHostInDomain(origin_host, kGoogleDotCom)) {
477 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE);
478 if (base::StartsWith(frame_gurl.path(), kGoogleSupportPathPrefix,
479 base::CompareCase::INSENSITIVE_ASCII)) {
480 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT);
481 } else if (base::StartsWith(frame_gurl.path(), kGoogleIntlPathPrefix,
482 base::CompareCase::INSENSITIVE_ASCII)) {
483 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL);
487 if (origin_host == kWWWDotGoogleDotCom) {
488 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE);
489 if (base::StartsWith(frame_gurl.path(), kGoogleReaderPathPrefix,
490 base::CompareCase::INSENSITIVE_ASCII))
491 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER);
492 } else if (origin_host == kMailDotGoogleDotCom) {
493 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE);
494 } else if (origin_host == kPlusDotGoogleDotCom) {
495 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE);
496 } else if (origin_host == kDocsDotGoogleDotCom) {
497 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE);
498 } else if (origin_host == kSitesDotGoogleDotCom) {
499 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE);
500 } else if (origin_host == kPicasawebDotGoogleDotCom) {
501 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE);
502 } else if (origin_host == kCodeDotGoogleDotCom) {
503 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE);
504 } else if (origin_host == kGroupsDotGoogleDotCom) {
505 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE);
506 } else if (origin_host == kMapsDotGoogleDotCom) {
507 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE);
508 } else if (origin_host == kWWWDotYoutubeDotCom) {
509 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE);
512 GURL resource_gurl(resource_url);
513 if (base::EndsWith(resource_gurl.path(), kDotHTML,
514 base::CompareCase::INSENSITIVE_ASCII))
515 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HTML);
517 if (allowed_per_settings || allow_displaying_insecure_content_)
518 return true;
520 Send(new ChromeViewHostMsg_DidBlockDisplayingInsecureContent(routing_id()));
522 return false;
525 bool ContentSettingsObserver::allowRunningInsecureContent(
526 bool allowed_per_settings,
527 const blink::WebSecurityOrigin& origin,
528 const blink::WebURL& resource_url) {
529 std::string origin_host(origin.host().utf8());
530 WebFrame* frame = render_frame()->GetWebFrame();
531 GURL frame_gurl(frame->document().url());
532 DCHECK_EQ(frame_gurl.host(), origin_host);
534 bool is_google = IsHostInDomain(origin_host, kGoogleDotCom);
535 if (is_google) {
536 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE);
537 if (base::StartsWith(frame_gurl.path(), kGoogleSupportPathPrefix,
538 base::CompareCase::INSENSITIVE_ASCII)) {
539 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT);
540 } else if (base::StartsWith(frame_gurl.path(), kGoogleIntlPathPrefix,
541 base::CompareCase::INSENSITIVE_ASCII)) {
542 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL);
546 if (origin_host == kWWWDotGoogleDotCom) {
547 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE);
548 if (base::StartsWith(frame_gurl.path(), kGoogleReaderPathPrefix,
549 base::CompareCase::INSENSITIVE_ASCII))
550 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_READER);
551 } else if (origin_host == kMailDotGoogleDotCom) {
552 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE);
553 } else if (origin_host == kPlusDotGoogleDotCom) {
554 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE);
555 } else if (origin_host == kDocsDotGoogleDotCom) {
556 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE);
557 } else if (origin_host == kSitesDotGoogleDotCom) {
558 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE);
559 } else if (origin_host == kPicasawebDotGoogleDotCom) {
560 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE);
561 } else if (origin_host == kCodeDotGoogleDotCom) {
562 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE);
563 } else if (origin_host == kGroupsDotGoogleDotCom) {
564 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE);
565 } else if (origin_host == kMapsDotGoogleDotCom) {
566 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE);
567 } else if (origin_host == kWWWDotYoutubeDotCom) {
568 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_YOUTUBE);
569 } else if (base::EndsWith(origin_host, kDotGoogleUserContentDotCom,
570 base::CompareCase::INSENSITIVE_ASCII)) {
571 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT);
574 GURL resource_gurl(resource_url);
575 if (resource_gurl.host() == kWWWDotYoutubeDotCom)
576 SendInsecureContentSignal(INSECURE_CONTENT_RUN_TARGET_YOUTUBE);
578 if (base::EndsWith(resource_gurl.path(), kDotJS,
579 base::CompareCase::INSENSITIVE_ASCII))
580 SendInsecureContentSignal(INSECURE_CONTENT_RUN_JS);
581 else if (base::EndsWith(resource_gurl.path(), kDotCSS,
582 base::CompareCase::INSENSITIVE_ASCII))
583 SendInsecureContentSignal(INSECURE_CONTENT_RUN_CSS);
584 else if (base::EndsWith(resource_gurl.path(), kDotSWF,
585 base::CompareCase::INSENSITIVE_ASCII))
586 SendInsecureContentSignal(INSECURE_CONTENT_RUN_SWF);
588 if (!allow_running_insecure_content_ && !allowed_per_settings) {
589 DidBlockContentType(CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, origin.host());
590 return false;
593 return true;
596 void ContentSettingsObserver::didNotAllowPlugins() {
597 DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS);
600 void ContentSettingsObserver::didNotAllowScript() {
601 DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
604 bool ContentSettingsObserver::AreNPAPIPluginsBlocked() const {
605 return npapi_plugins_blocked_;
608 void ContentSettingsObserver::OnLoadBlockedPlugins(
609 const std::string& identifier) {
610 temporarily_allowed_plugins_.insert(identifier);
613 void ContentSettingsObserver::OnSetAsInterstitial() {
614 is_interstitial_page_ = true;
617 void ContentSettingsObserver::OnNPAPINotSupported() {
618 npapi_plugins_blocked_ = true;
621 void ContentSettingsObserver::OnSetAllowDisplayingInsecureContent(bool allow) {
622 allow_displaying_insecure_content_ = allow;
625 void ContentSettingsObserver::OnSetAllowRunningInsecureContent(bool allow) {
626 allow_running_insecure_content_ = allow;
627 OnSetAllowDisplayingInsecureContent(allow);
630 void ContentSettingsObserver::OnReloadFrame() {
631 DCHECK(!render_frame()->GetWebFrame()->parent()) <<
632 "Should only be called on the main frame";
633 render_frame()->GetWebFrame()->reload();
636 void ContentSettingsObserver::OnRequestFileSystemAccessAsyncResponse(
637 int request_id,
638 bool allowed) {
639 PermissionRequestMap::iterator it = permission_requests_.find(request_id);
640 if (it == permission_requests_.end())
641 return;
643 WebContentSettingCallbacks callbacks = it->second;
644 permission_requests_.erase(it);
646 if (allowed) {
647 callbacks.doAllow();
648 return;
650 callbacks.doDeny();
653 void ContentSettingsObserver::ClearBlockedContentSettings() {
654 content_blocked_.clear();
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();
665 #else
666 return false;
667 #endif
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))
675 return NULL;
677 const std::string extension_id = origin.host().utf8().data();
678 if (!extension_dispatcher_->IsExtensionActive(extension_id))
679 return NULL;
681 return extensions::RendererExtensionRegistry::Get()->GetByID(extension_id);
683 #endif
685 bool ContentSettingsObserver::IsWhitelistedForContentSettings() const {
686 if (should_whitelist_)
687 return true;
689 // Whitelist ftp directory listings, as they require JavaScript to function
690 // properly.
691 if (render_frame()->IsFTPDirectoryListing())
692 return true;
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))
703 return true;
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))
717 return true;
718 #endif
720 // TODO(creis, fsamuel): Remove this once the concept of swapped out
721 // RenderFrames goes away.
722 if (document_url == GURL(content::kSwappedOutURL))
723 return true;
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();
732 return false;