Add long running gmail memory benchmark for background tab.
[chromium-blink-merge.git] / chrome / renderer / content_settings_observer.cc
blobff5dc98c80315f6d8d736c80e1075326c63524fa
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 #endif
32 using blink::WebContentSettingCallbacks;
33 using blink::WebDataSource;
34 using blink::WebDocument;
35 using blink::WebFrame;
36 using blink::WebSecurityOrigin;
37 using blink::WebString;
38 using blink::WebURL;
39 using blink::WebView;
40 using content::DocumentState;
41 using content::NavigationState;
43 namespace {
45 enum {
46 INSECURE_CONTENT_DISPLAY = 0,
47 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE,
48 INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE,
49 INSECURE_CONTENT_DISPLAY_HTML,
50 INSECURE_CONTENT_RUN,
51 INSECURE_CONTENT_RUN_HOST_GOOGLE,
52 INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE,
53 INSECURE_CONTENT_RUN_TARGET_YOUTUBE,
54 INSECURE_CONTENT_RUN_JS,
55 INSECURE_CONTENT_RUN_CSS,
56 INSECURE_CONTENT_RUN_SWF,
57 INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE,
58 INSECURE_CONTENT_RUN_HOST_YOUTUBE,
59 INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT,
60 INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE,
61 INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE,
62 INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE,
63 INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE,
64 INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE,
65 INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE,
66 INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE,
67 INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE,
68 INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE,
69 INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE,
70 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER,
71 INSECURE_CONTENT_RUN_HOST_GOOGLE_READER,
72 INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE,
73 INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE,
74 INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE,
75 INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE,
76 INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE,
77 INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE,
78 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT,
79 INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT,
80 INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL,
81 INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL,
82 INSECURE_CONTENT_NUM_EVENTS
85 // Constants for UMA statistic collection.
86 static const char kWWWDotGoogleDotCom[] = "www.google.com";
87 static const char kMailDotGoogleDotCom[] = "mail.google.com";
88 static const char kPlusDotGoogleDotCom[] = "plus.google.com";
89 static const char kDocsDotGoogleDotCom[] = "docs.google.com";
90 static const char kSitesDotGoogleDotCom[] = "sites.google.com";
91 static const char kPicasawebDotGoogleDotCom[] = "picasaweb.google.com";
92 static const char kCodeDotGoogleDotCom[] = "code.google.com";
93 static const char kGroupsDotGoogleDotCom[] = "groups.google.com";
94 static const char kMapsDotGoogleDotCom[] = "maps.google.com";
95 static const char kWWWDotYoutubeDotCom[] = "www.youtube.com";
96 static const char kDotGoogleUserContentDotCom[] = ".googleusercontent.com";
97 static const char kGoogleReaderPathPrefix[] = "/reader/";
98 static const char kGoogleSupportPathPrefix[] = "/support/";
99 static const char kGoogleIntlPathPrefix[] = "/intl/";
100 static const char kDotJS[] = ".js";
101 static const char kDotCSS[] = ".css";
102 static const char kDotSWF[] = ".swf";
103 static const char kDotHTML[] = ".html";
105 // Constants for mixed-content blocking.
106 static const char kGoogleDotCom[] = "google.com";
108 static bool IsHostInDomain(const std::string& host, const std::string& domain) {
109 return (base::EndsWith(host, domain, base::CompareCase::INSENSITIVE_ASCII) &&
110 (host.length() == domain.length() ||
111 (host.length() > domain.length() &&
112 host[host.length() - domain.length() - 1] == '.')));
115 GURL GetOriginOrURL(const WebFrame* frame) {
116 WebString top_origin = frame->top()->securityOrigin().toString();
117 // The |top_origin| is unique ("null") e.g., for file:// URLs. Use the
118 // document URL as the primary URL in those cases.
119 // TODO(alexmos): This is broken for --site-per-process, since top() can be a
120 // WebRemoteFrame which does not have a document(), and the WebRemoteFrame's
121 // URL is not replicated.
122 if (top_origin == "null")
123 return frame->top()->document().url();
124 return GURL(top_origin);
127 ContentSetting GetContentSettingFromRules(
128 const ContentSettingsForOneType& rules,
129 const WebFrame* frame,
130 const GURL& secondary_url) {
131 ContentSettingsForOneType::const_iterator it;
132 // If there is only one rule, it's the default rule and we don't need to match
133 // the patterns.
134 if (rules.size() == 1) {
135 DCHECK(rules[0].primary_pattern == ContentSettingsPattern::Wildcard());
136 DCHECK(rules[0].secondary_pattern == ContentSettingsPattern::Wildcard());
137 return rules[0].setting;
139 const GURL& primary_url = GetOriginOrURL(frame);
140 for (it = rules.begin(); it != rules.end(); ++it) {
141 if (it->primary_pattern.Matches(primary_url) &&
142 it->secondary_pattern.Matches(secondary_url)) {
143 return it->setting;
146 NOTREACHED();
147 return CONTENT_SETTING_DEFAULT;
150 } // namespace
152 ContentSettingsObserver::ContentSettingsObserver(
153 content::RenderFrame* render_frame,
154 extensions::Dispatcher* extension_dispatcher,
155 bool should_whitelist)
156 : content::RenderFrameObserver(render_frame),
157 content::RenderFrameObserverTracker<ContentSettingsObserver>(
158 render_frame),
159 #if defined(ENABLE_EXTENSIONS)
160 extension_dispatcher_(extension_dispatcher),
161 #endif
162 allow_displaying_insecure_content_(false),
163 allow_running_insecure_content_(false),
164 content_setting_rules_(NULL),
165 is_interstitial_page_(false),
166 npapi_plugins_blocked_(false),
167 current_request_id_(0),
168 should_whitelist_(should_whitelist) {
169 ClearBlockedContentSettings();
170 render_frame->GetWebFrame()->setContentSettingsClient(this);
172 content::RenderFrame* main_frame =
173 render_frame->GetRenderView()->GetMainRenderFrame();
174 // TODO(nasko): The main frame is not guaranteed to be in the same process
175 // with this frame with --site-per-process. This code needs to be updated
176 // to handle this case. See https://crbug.com/496670.
177 if (main_frame && main_frame != render_frame) {
178 // Copy all the settings from the main render frame to avoid race conditions
179 // when initializing this data. See https://crbug.com/333308.
180 ContentSettingsObserver* parent = ContentSettingsObserver::Get(main_frame);
181 allow_displaying_insecure_content_ =
182 parent->allow_displaying_insecure_content_;
183 allow_running_insecure_content_ = parent->allow_running_insecure_content_;
184 temporarily_allowed_plugins_ = parent->temporarily_allowed_plugins_;
185 is_interstitial_page_ = parent->is_interstitial_page_;
186 npapi_plugins_blocked_ = parent->npapi_plugins_blocked_;
190 ContentSettingsObserver::~ContentSettingsObserver() {
193 void ContentSettingsObserver::SetContentSettingRules(
194 const RendererContentSettingRules* content_setting_rules) {
195 content_setting_rules_ = content_setting_rules;
198 bool ContentSettingsObserver::IsPluginTemporarilyAllowed(
199 const std::string& identifier) {
200 // If the empty string is in here, it means all plugins are allowed.
201 // TODO(bauerb): Remove this once we only pass in explicit identifiers.
202 return (temporarily_allowed_plugins_.find(identifier) !=
203 temporarily_allowed_plugins_.end()) ||
204 (temporarily_allowed_plugins_.find(std::string()) !=
205 temporarily_allowed_plugins_.end());
208 void ContentSettingsObserver::DidBlockContentType(
209 ContentSettingsType settings_type) {
210 DidBlockContentType(settings_type, base::string16());
213 void ContentSettingsObserver::DidBlockContentType(
214 ContentSettingsType settings_type,
215 const base::string16& details) {
216 // Send multiple ContentBlocked messages if details are provided.
217 if (!content_blocked_[settings_type] || !details.empty()) {
218 content_blocked_[settings_type] = true;
219 Send(new ChromeViewHostMsg_ContentBlocked(routing_id(), settings_type,
220 details));
224 bool ContentSettingsObserver::OnMessageReceived(const IPC::Message& message) {
225 bool handled = true;
226 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message)
227 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAsInterstitial, OnSetAsInterstitial)
228 IPC_MESSAGE_HANDLER(ChromeViewMsg_NPAPINotSupported, OnNPAPINotSupported)
229 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowDisplayingInsecureContent,
230 OnSetAllowDisplayingInsecureContent)
231 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowRunningInsecureContent,
232 OnSetAllowRunningInsecureContent)
233 IPC_MESSAGE_HANDLER(ChromeViewMsg_ReloadFrame, OnReloadFrame);
234 IPC_MESSAGE_HANDLER(ChromeViewMsg_RequestFileSystemAccessAsyncResponse,
235 OnRequestFileSystemAccessAsyncResponse)
236 IPC_MESSAGE_UNHANDLED(handled = false)
237 IPC_END_MESSAGE_MAP()
238 if (handled)
239 return true;
241 // Don't swallow LoadBlockedPlugins messages, as they're sent to every
242 // blocked plugin.
243 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message)
244 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins)
245 IPC_END_MESSAGE_MAP()
247 return false;
250 void ContentSettingsObserver::DidCommitProvisionalLoad(
251 bool is_new_navigation,
252 bool is_same_page_navigation) {
253 WebFrame* frame = render_frame()->GetWebFrame();
254 if (frame->parent())
255 return; // Not a top-level navigation.
257 if (!is_same_page_navigation) {
258 // Clear "block" flags for the new page. This needs to happen before any of
259 // |allowScript()|, |allowScriptFromSource()|, |allowImage()|, or
260 // |allowPlugins()| is called for the new page so that these functions can
261 // correctly detect that a piece of content flipped from "not blocked" to
262 // "blocked".
263 ClearBlockedContentSettings();
264 temporarily_allowed_plugins_.clear();
267 GURL url = frame->document().url();
268 // If we start failing this DCHECK, please makes sure we don't regress
269 // this bug: http://code.google.com/p/chromium/issues/detail?id=79304
270 DCHECK(frame->document().securityOrigin().toString() == "null" ||
271 !url.SchemeIs(url::kDataScheme));
274 bool ContentSettingsObserver::allowDatabase(const WebString& name,
275 const WebString& display_name,
276 unsigned long estimated_size) {
277 WebFrame* frame = render_frame()->GetWebFrame();
278 if (frame->securityOrigin().isUnique() ||
279 frame->top()->securityOrigin().isUnique())
280 return false;
282 bool result = false;
283 Send(new ChromeViewHostMsg_AllowDatabase(
284 routing_id(), GURL(frame->securityOrigin().toString()),
285 GURL(frame->top()->securityOrigin().toString()), name, display_name,
286 &result));
287 return result;
290 void ContentSettingsObserver::requestFileSystemAccessAsync(
291 const WebContentSettingCallbacks& callbacks) {
292 WebFrame* frame = render_frame()->GetWebFrame();
293 if (frame->securityOrigin().isUnique() ||
294 frame->top()->securityOrigin().isUnique()) {
295 WebContentSettingCallbacks permissionCallbacks(callbacks);
296 permissionCallbacks.doDeny();
297 return;
299 ++current_request_id_;
300 std::pair<PermissionRequestMap::iterator, bool> insert_result =
301 permission_requests_.insert(
302 std::make_pair(current_request_id_, callbacks));
304 // Verify there are no duplicate insertions.
305 DCHECK(insert_result.second);
307 Send(new ChromeViewHostMsg_RequestFileSystemAccessAsync(
308 routing_id(), current_request_id_,
309 GURL(frame->securityOrigin().toString()),
310 GURL(frame->top()->securityOrigin().toString())));
313 bool ContentSettingsObserver::allowImage(bool enabled_per_settings,
314 const WebURL& image_url) {
315 bool allow = enabled_per_settings;
316 if (enabled_per_settings) {
317 if (is_interstitial_page_)
318 return true;
320 if (IsWhitelistedForContentSettings())
321 return true;
323 if (content_setting_rules_) {
324 GURL secondary_url(image_url);
325 allow =
326 GetContentSettingFromRules(content_setting_rules_->image_rules,
327 render_frame()->GetWebFrame(),
328 secondary_url) != CONTENT_SETTING_BLOCK;
331 if (!allow)
332 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES);
333 return allow;
336 bool ContentSettingsObserver::allowIndexedDB(const WebString& name,
337 const WebSecurityOrigin& origin) {
338 WebFrame* frame = render_frame()->GetWebFrame();
339 if (frame->securityOrigin().isUnique() ||
340 frame->top()->securityOrigin().isUnique())
341 return false;
343 bool result = false;
344 Send(new ChromeViewHostMsg_AllowIndexedDB(
345 routing_id(), GURL(frame->securityOrigin().toString()),
346 GURL(frame->top()->securityOrigin().toString()), name, &result));
347 return result;
350 bool ContentSettingsObserver::allowPlugins(bool enabled_per_settings) {
351 return enabled_per_settings;
354 bool ContentSettingsObserver::allowScript(bool enabled_per_settings) {
355 if (!enabled_per_settings)
356 return false;
357 if (is_interstitial_page_)
358 return true;
360 WebFrame* frame = render_frame()->GetWebFrame();
361 std::map<WebFrame*, bool>::const_iterator it =
362 cached_script_permissions_.find(frame);
363 if (it != cached_script_permissions_.end())
364 return it->second;
366 // Evaluate the content setting rules before
367 // |IsWhitelistedForContentSettings|; if there is only the default rule
368 // allowing all scripts, it's quicker this way.
369 bool allow = true;
370 if (content_setting_rules_) {
371 ContentSetting setting = GetContentSettingFromRules(
372 content_setting_rules_->script_rules,
373 frame,
374 GURL(frame->document().securityOrigin().toString()));
375 allow = setting != CONTENT_SETTING_BLOCK;
377 allow = allow || IsWhitelistedForContentSettings();
379 cached_script_permissions_[frame] = allow;
380 return allow;
383 bool ContentSettingsObserver::allowScriptFromSource(
384 bool enabled_per_settings,
385 const blink::WebURL& script_url) {
386 if (!enabled_per_settings)
387 return false;
388 if (is_interstitial_page_)
389 return true;
391 bool allow = true;
392 if (content_setting_rules_) {
393 ContentSetting setting =
394 GetContentSettingFromRules(content_setting_rules_->script_rules,
395 render_frame()->GetWebFrame(),
396 GURL(script_url));
397 allow = setting != CONTENT_SETTING_BLOCK;
399 return allow || IsWhitelistedForContentSettings();
402 bool ContentSettingsObserver::allowStorage(bool local) {
403 WebFrame* frame = render_frame()->GetWebFrame();
404 if (frame->securityOrigin().isUnique() ||
405 frame->top()->securityOrigin().isUnique())
406 return false;
407 bool result = false;
409 StoragePermissionsKey key(
410 GURL(frame->document().securityOrigin().toString()), local);
411 std::map<StoragePermissionsKey, bool>::const_iterator permissions =
412 cached_storage_permissions_.find(key);
413 if (permissions != cached_storage_permissions_.end())
414 return permissions->second;
416 Send(new ChromeViewHostMsg_AllowDOMStorage(
417 routing_id(), GURL(frame->securityOrigin().toString()),
418 GURL(frame->top()->securityOrigin().toString()), local, &result));
419 cached_storage_permissions_[key] = result;
420 return result;
423 bool ContentSettingsObserver::allowReadFromClipboard(bool default_value) {
424 bool allowed = default_value;
425 #if defined(ENABLE_EXTENSIONS)
426 extensions::ScriptContext* calling_context =
427 extension_dispatcher_->script_context_set().GetCalling();
428 if (calling_context) {
429 allowed |= calling_context->HasAPIPermission(
430 extensions::APIPermission::kClipboardRead);
432 #endif
433 return allowed;
436 bool ContentSettingsObserver::allowWriteToClipboard(bool default_value) {
437 bool allowed = default_value;
438 #if defined(ENABLE_EXTENSIONS)
439 // All blessed extension pages could historically write to the clipboard, so
440 // preserve that for compatibility.
441 extensions::ScriptContext* calling_context =
442 extension_dispatcher_->script_context_set().GetCalling();
443 if (calling_context) {
444 if (calling_context->effective_context_type() ==
445 extensions::Feature::BLESSED_EXTENSION_CONTEXT) {
446 allowed = true;
447 } else {
448 allowed |= calling_context->HasAPIPermission(
449 extensions::APIPermission::kClipboardWrite);
452 #endif
453 return allowed;
456 bool ContentSettingsObserver::allowMutationEvents(bool default_value) {
457 return IsPlatformApp() ? false : default_value;
460 static void SendInsecureContentSignal(int signal) {
461 UMA_HISTOGRAM_ENUMERATION("SSL.InsecureContent", signal,
462 INSECURE_CONTENT_NUM_EVENTS);
465 bool ContentSettingsObserver::allowDisplayingInsecureContent(
466 bool allowed_per_settings,
467 const blink::WebSecurityOrigin& origin,
468 const blink::WebURL& resource_url) {
469 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY);
471 std::string origin_host(origin.host().utf8());
472 WebFrame* frame = render_frame()->GetWebFrame();
473 GURL frame_gurl(frame->document().url());
474 if (IsHostInDomain(origin_host, kGoogleDotCom)) {
475 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE);
476 if (base::StartsWith(frame_gurl.path(), kGoogleSupportPathPrefix,
477 base::CompareCase::INSENSITIVE_ASCII)) {
478 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT);
479 } else if (base::StartsWith(frame_gurl.path(), kGoogleIntlPathPrefix,
480 base::CompareCase::INSENSITIVE_ASCII)) {
481 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL);
485 if (origin_host == kWWWDotGoogleDotCom) {
486 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE);
487 if (base::StartsWith(frame_gurl.path(), kGoogleReaderPathPrefix,
488 base::CompareCase::INSENSITIVE_ASCII))
489 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER);
490 } else if (origin_host == kMailDotGoogleDotCom) {
491 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE);
492 } else if (origin_host == kPlusDotGoogleDotCom) {
493 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE);
494 } else if (origin_host == kDocsDotGoogleDotCom) {
495 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE);
496 } else if (origin_host == kSitesDotGoogleDotCom) {
497 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE);
498 } else if (origin_host == kPicasawebDotGoogleDotCom) {
499 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE);
500 } else if (origin_host == kCodeDotGoogleDotCom) {
501 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE);
502 } else if (origin_host == kGroupsDotGoogleDotCom) {
503 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE);
504 } else if (origin_host == kMapsDotGoogleDotCom) {
505 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE);
506 } else if (origin_host == kWWWDotYoutubeDotCom) {
507 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE);
510 GURL resource_gurl(resource_url);
511 if (base::EndsWith(resource_gurl.path(), kDotHTML,
512 base::CompareCase::INSENSITIVE_ASCII))
513 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HTML);
515 if (allowed_per_settings || allow_displaying_insecure_content_)
516 return true;
518 Send(new ChromeViewHostMsg_DidBlockDisplayingInsecureContent(routing_id()));
520 return false;
523 bool ContentSettingsObserver::allowRunningInsecureContent(
524 bool allowed_per_settings,
525 const blink::WebSecurityOrigin& origin,
526 const blink::WebURL& resource_url) {
527 std::string origin_host(origin.host().utf8());
528 WebFrame* frame = render_frame()->GetWebFrame();
529 GURL frame_gurl(frame->document().url());
530 DCHECK_EQ(frame_gurl.host(), origin_host);
532 bool is_google = IsHostInDomain(origin_host, kGoogleDotCom);
533 if (is_google) {
534 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE);
535 if (base::StartsWith(frame_gurl.path(), kGoogleSupportPathPrefix,
536 base::CompareCase::INSENSITIVE_ASCII)) {
537 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT);
538 } else if (base::StartsWith(frame_gurl.path(), kGoogleIntlPathPrefix,
539 base::CompareCase::INSENSITIVE_ASCII)) {
540 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL);
544 if (origin_host == kWWWDotGoogleDotCom) {
545 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE);
546 if (base::StartsWith(frame_gurl.path(), kGoogleReaderPathPrefix,
547 base::CompareCase::INSENSITIVE_ASCII))
548 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_READER);
549 } else if (origin_host == kMailDotGoogleDotCom) {
550 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE);
551 } else if (origin_host == kPlusDotGoogleDotCom) {
552 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE);
553 } else if (origin_host == kDocsDotGoogleDotCom) {
554 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE);
555 } else if (origin_host == kSitesDotGoogleDotCom) {
556 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE);
557 } else if (origin_host == kPicasawebDotGoogleDotCom) {
558 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE);
559 } else if (origin_host == kCodeDotGoogleDotCom) {
560 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE);
561 } else if (origin_host == kGroupsDotGoogleDotCom) {
562 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE);
563 } else if (origin_host == kMapsDotGoogleDotCom) {
564 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE);
565 } else if (origin_host == kWWWDotYoutubeDotCom) {
566 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_YOUTUBE);
567 } else if (base::EndsWith(origin_host, kDotGoogleUserContentDotCom,
568 base::CompareCase::INSENSITIVE_ASCII)) {
569 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT);
572 GURL resource_gurl(resource_url);
573 if (resource_gurl.host() == kWWWDotYoutubeDotCom)
574 SendInsecureContentSignal(INSECURE_CONTENT_RUN_TARGET_YOUTUBE);
576 if (base::EndsWith(resource_gurl.path(), kDotJS,
577 base::CompareCase::INSENSITIVE_ASCII))
578 SendInsecureContentSignal(INSECURE_CONTENT_RUN_JS);
579 else if (base::EndsWith(resource_gurl.path(), kDotCSS,
580 base::CompareCase::INSENSITIVE_ASCII))
581 SendInsecureContentSignal(INSECURE_CONTENT_RUN_CSS);
582 else if (base::EndsWith(resource_gurl.path(), kDotSWF,
583 base::CompareCase::INSENSITIVE_ASCII))
584 SendInsecureContentSignal(INSECURE_CONTENT_RUN_SWF);
586 if (!allow_running_insecure_content_ && !allowed_per_settings) {
587 DidBlockContentType(CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, origin.host());
588 return false;
591 return true;
594 void ContentSettingsObserver::didNotAllowPlugins() {
595 DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS);
598 void ContentSettingsObserver::didNotAllowScript() {
599 DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
602 bool ContentSettingsObserver::AreNPAPIPluginsBlocked() const {
603 return npapi_plugins_blocked_;
606 void ContentSettingsObserver::OnLoadBlockedPlugins(
607 const std::string& identifier) {
608 temporarily_allowed_plugins_.insert(identifier);
611 void ContentSettingsObserver::OnSetAsInterstitial() {
612 is_interstitial_page_ = true;
615 void ContentSettingsObserver::OnNPAPINotSupported() {
616 npapi_plugins_blocked_ = true;
619 void ContentSettingsObserver::OnSetAllowDisplayingInsecureContent(bool allow) {
620 allow_displaying_insecure_content_ = allow;
623 void ContentSettingsObserver::OnSetAllowRunningInsecureContent(bool allow) {
624 allow_running_insecure_content_ = allow;
625 OnSetAllowDisplayingInsecureContent(allow);
628 void ContentSettingsObserver::OnReloadFrame() {
629 DCHECK(!render_frame()->GetWebFrame()->parent()) <<
630 "Should only be called on the main frame";
631 render_frame()->GetWebFrame()->reload();
634 void ContentSettingsObserver::OnRequestFileSystemAccessAsyncResponse(
635 int request_id,
636 bool allowed) {
637 PermissionRequestMap::iterator it = permission_requests_.find(request_id);
638 if (it == permission_requests_.end())
639 return;
641 WebContentSettingCallbacks callbacks = it->second;
642 permission_requests_.erase(it);
644 if (allowed) {
645 callbacks.doAllow();
646 return;
648 callbacks.doDeny();
651 void ContentSettingsObserver::ClearBlockedContentSettings() {
652 for (size_t i = 0; i < arraysize(content_blocked_); ++i)
653 content_blocked_[i] = false;
654 cached_storage_permissions_.clear();
655 cached_script_permissions_.clear();
658 bool ContentSettingsObserver::IsPlatformApp() {
659 #if defined(ENABLE_EXTENSIONS)
660 WebFrame* frame = render_frame()->GetWebFrame();
661 WebSecurityOrigin origin = frame->document().securityOrigin();
662 const extensions::Extension* extension = GetExtension(origin);
663 return extension && extension->is_platform_app();
664 #else
665 return false;
666 #endif
669 #if defined(ENABLE_EXTENSIONS)
670 const extensions::Extension* ContentSettingsObserver::GetExtension(
671 const WebSecurityOrigin& origin) const {
672 if (!base::EqualsASCII(base::StringPiece16(origin.protocol()),
673 extensions::kExtensionScheme))
674 return NULL;
676 const std::string extension_id = origin.host().utf8().data();
677 if (!extension_dispatcher_->IsExtensionActive(extension_id))
678 return NULL;
680 return extension_dispatcher_->extensions()->GetByID(extension_id);
682 #endif
684 bool ContentSettingsObserver::IsWhitelistedForContentSettings() const {
685 if (should_whitelist_)
686 return true;
688 // Whitelist ftp directory listings, as they require JavaScript to function
689 // properly.
690 if (render_frame()->IsFTPDirectoryListing())
691 return true;
693 WebFrame* web_frame = render_frame()->GetWebFrame();
694 return IsWhitelistedForContentSettings(web_frame->document().securityOrigin(),
695 web_frame->document().url());
698 bool ContentSettingsObserver::IsWhitelistedForContentSettings(
699 const WebSecurityOrigin& origin,
700 const GURL& document_url) {
701 if (document_url == GURL(content::kUnreachableWebDataURL))
702 return true;
704 if (origin.isUnique())
705 return false; // Uninitialized document?
707 base::string16 protocol = origin.protocol();
708 if (base::EqualsASCII(protocol, content::kChromeUIScheme))
709 return true; // Browser UI elements should still work.
711 if (base::EqualsASCII(protocol, content::kChromeDevToolsScheme))
712 return true; // DevTools UI elements should still work.
714 #if defined(ENABLE_EXTENSIONS)
715 if (base::EqualsASCII(protocol, extensions::kExtensionScheme))
716 return true;
717 #endif
719 // TODO(creis, fsamuel): Remove this once the concept of swapped out
720 // RenderFrames goes away.
721 if (document_url == GURL(content::kSwappedOutURL))
722 return true;
724 // If the scheme is file:, an empty file name indicates a directory listing,
725 // which requires JavaScript to function properly.
726 if (base::EqualsASCII(protocol, url::kFileScheme)) {
727 return document_url.SchemeIs(url::kFileScheme) &&
728 document_url.ExtractFileName().empty();
731 return false;