Files.app: Start to use DeviceEventRouter.
[chromium-blink-merge.git] / chrome / renderer / content_settings_observer.cc
blob57de0757f4b3e8869a2f264e1855cbefe7a370b1
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 "content/public/renderer/document_state.h"
13 #include "content/public/renderer/navigation_state.h"
14 #include "content/public/renderer/render_frame.h"
15 #include "content/public/renderer/render_view.h"
16 #include "third_party/WebKit/public/platform/WebPermissionCallbacks.h"
17 #include "third_party/WebKit/public/platform/WebURL.h"
18 #include "third_party/WebKit/public/web/WebDataSource.h"
19 #include "third_party/WebKit/public/web/WebDocument.h"
20 #include "third_party/WebKit/public/web/WebFrame.h"
21 #include "third_party/WebKit/public/web/WebFrameClient.h"
22 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
23 #include "third_party/WebKit/public/web/WebView.h"
25 #if defined(ENABLE_EXTENSIONS)
26 #include "chrome/common/extensions/chrome_extension_messages.h"
27 #include "extensions/common/constants.h"
28 #include "extensions/common/extension.h"
29 #include "extensions/renderer/dispatcher.h"
30 #endif
32 using blink::WebDataSource;
33 using blink::WebDocument;
34 using blink::WebFrame;
35 using blink::WebPermissionCallbacks;
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 (EndsWith(host, domain, false) &&
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()->document().securityOrigin().toString();
117 // The the |top_origin| is unique ("null") e.g., for file:// URLs. Use the
118 // document URL as the primary URL in those cases.
119 if (top_origin == "null")
120 return frame->top()->document().url();
121 return GURL(top_origin);
124 ContentSetting GetContentSettingFromRules(
125 const ContentSettingsForOneType& rules,
126 const WebFrame* frame,
127 const GURL& secondary_url) {
128 ContentSettingsForOneType::const_iterator it;
129 // If there is only one rule, it's the default rule and we don't need to match
130 // the patterns.
131 if (rules.size() == 1) {
132 DCHECK(rules[0].primary_pattern == ContentSettingsPattern::Wildcard());
133 DCHECK(rules[0].secondary_pattern == ContentSettingsPattern::Wildcard());
134 return rules[0].setting;
136 const GURL& primary_url = GetOriginOrURL(frame);
137 for (it = rules.begin(); it != rules.end(); ++it) {
138 if (it->primary_pattern.Matches(primary_url) &&
139 it->secondary_pattern.Matches(secondary_url)) {
140 return it->setting;
143 NOTREACHED();
144 return CONTENT_SETTING_DEFAULT;
147 } // namespace
149 ContentSettingsObserver::ContentSettingsObserver(
150 content::RenderFrame* render_frame,
151 extensions::Dispatcher* extension_dispatcher)
152 : content::RenderFrameObserver(render_frame),
153 content::RenderFrameObserverTracker<ContentSettingsObserver>(
154 render_frame),
155 #if defined(ENABLE_EXTENSIONS)
156 extension_dispatcher_(extension_dispatcher),
157 #endif
158 allow_displaying_insecure_content_(false),
159 allow_running_insecure_content_(false),
160 content_setting_rules_(NULL),
161 is_interstitial_page_(false),
162 npapi_plugins_blocked_(false),
163 current_request_id_(0) {
164 ClearBlockedContentSettings();
165 render_frame->GetWebFrame()->setPermissionClient(this);
167 if (render_frame->GetRenderView()->GetMainRenderFrame() != render_frame) {
168 // Copy all the settings from the main render frame to avoid race conditions
169 // when initializing this data. See http://crbug.com/333308.
170 ContentSettingsObserver* parent = ContentSettingsObserver::Get(
171 render_frame->GetRenderView()->GetMainRenderFrame());
172 allow_displaying_insecure_content_ =
173 parent->allow_displaying_insecure_content_;
174 allow_running_insecure_content_ = parent->allow_running_insecure_content_;
175 temporarily_allowed_plugins_ = parent->temporarily_allowed_plugins_;
176 is_interstitial_page_ = parent->is_interstitial_page_;
177 npapi_plugins_blocked_ = parent->npapi_plugins_blocked_;
181 ContentSettingsObserver::~ContentSettingsObserver() {
184 void ContentSettingsObserver::SetContentSettingRules(
185 const RendererContentSettingRules* content_setting_rules) {
186 content_setting_rules_ = content_setting_rules;
189 bool ContentSettingsObserver::IsPluginTemporarilyAllowed(
190 const std::string& identifier) {
191 // If the empty string is in here, it means all plug-ins are allowed.
192 // TODO(bauerb): Remove this once we only pass in explicit identifiers.
193 return (temporarily_allowed_plugins_.find(identifier) !=
194 temporarily_allowed_plugins_.end()) ||
195 (temporarily_allowed_plugins_.find(std::string()) !=
196 temporarily_allowed_plugins_.end());
199 void ContentSettingsObserver::DidBlockContentType(
200 ContentSettingsType settings_type) {
201 if (!content_blocked_[settings_type]) {
202 content_blocked_[settings_type] = true;
203 Send(new ChromeViewHostMsg_ContentBlocked(routing_id(), settings_type));
207 bool ContentSettingsObserver::OnMessageReceived(const IPC::Message& message) {
208 bool handled = true;
209 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message)
210 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAsInterstitial, OnSetAsInterstitial)
211 IPC_MESSAGE_HANDLER(ChromeViewMsg_NPAPINotSupported, OnNPAPINotSupported)
212 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowDisplayingInsecureContent,
213 OnSetAllowDisplayingInsecureContent)
214 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowRunningInsecureContent,
215 OnSetAllowRunningInsecureContent)
216 IPC_MESSAGE_HANDLER(ChromeViewMsg_ReloadFrame, OnReloadFrame);
217 IPC_MESSAGE_HANDLER(ChromeViewMsg_RequestFileSystemAccessAsyncResponse,
218 OnRequestFileSystemAccessAsyncResponse)
219 IPC_MESSAGE_UNHANDLED(handled = false)
220 IPC_END_MESSAGE_MAP()
221 if (handled)
222 return true;
224 // Don't swallow LoadBlockedPlugins messages, as they're sent to every
225 // blocked plugin.
226 IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message)
227 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins)
228 IPC_END_MESSAGE_MAP()
230 return false;
233 void ContentSettingsObserver::DidCommitProvisionalLoad(bool is_new_navigation) {
234 WebFrame* frame = render_frame()->GetWebFrame();
235 if (frame->parent())
236 return; // Not a top-level navigation.
238 DocumentState* document_state = DocumentState::FromDataSource(
239 frame->dataSource());
240 NavigationState* navigation_state = document_state->navigation_state();
241 if (!navigation_state->was_within_same_page()) {
242 // Clear "block" flags for the new page. This needs to happen before any of
243 // |allowScript()|, |allowScriptFromSource()|, |allowImage()|, or
244 // |allowPlugins()| is called for the new page so that these functions can
245 // correctly detect that a piece of content flipped from "not blocked" to
246 // "blocked".
247 ClearBlockedContentSettings();
248 temporarily_allowed_plugins_.clear();
251 GURL url = frame->document().url();
252 // If we start failing this DCHECK, please makes sure we don't regress
253 // this bug: http://code.google.com/p/chromium/issues/detail?id=79304
254 DCHECK(frame->document().securityOrigin().toString() == "null" ||
255 !url.SchemeIs(url::kDataScheme));
258 bool ContentSettingsObserver::allowDatabase(const WebString& name,
259 const WebString& display_name,
260 unsigned long estimated_size) {
261 WebFrame* frame = render_frame()->GetWebFrame();
262 if (frame->document().securityOrigin().isUnique() ||
263 frame->top()->document().securityOrigin().isUnique())
264 return false;
266 bool result = false;
267 Send(new ChromeViewHostMsg_AllowDatabase(
268 routing_id(), GURL(frame->document().securityOrigin().toString()),
269 GURL(frame->top()->document().securityOrigin().toString()),
270 name, display_name, &result));
271 return result;
274 void ContentSettingsObserver::requestFileSystemAccessAsync(
275 const WebPermissionCallbacks& callbacks) {
276 WebFrame* frame = render_frame()->GetWebFrame();
277 if (frame->document().securityOrigin().isUnique() ||
278 frame->top()->document().securityOrigin().isUnique()) {
279 WebPermissionCallbacks permissionCallbacks(callbacks);
280 permissionCallbacks.doDeny();
281 return;
283 ++current_request_id_;
284 std::pair<PermissionRequestMap::iterator, bool> insert_result =
285 permission_requests_.insert(
286 std::make_pair(current_request_id_, callbacks));
288 // Verify there are no duplicate insertions.
289 DCHECK(insert_result.second);
291 Send(new ChromeViewHostMsg_RequestFileSystemAccessAsync(
292 routing_id(),
293 current_request_id_,
294 GURL(frame->document().securityOrigin().toString()),
295 GURL(frame->top()->document().securityOrigin().toString())));
298 bool ContentSettingsObserver::allowImage(bool enabled_per_settings,
299 const WebURL& image_url) {
300 bool allow = enabled_per_settings;
301 if (enabled_per_settings) {
302 if (is_interstitial_page_)
303 return true;
305 if (IsWhitelistedForContentSettings(render_frame()))
306 return true;
308 if (content_setting_rules_) {
309 GURL secondary_url(image_url);
310 allow =
311 GetContentSettingFromRules(content_setting_rules_->image_rules,
312 render_frame()->GetWebFrame(),
313 secondary_url) != CONTENT_SETTING_BLOCK;
316 if (!allow)
317 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES);
318 return allow;
321 bool ContentSettingsObserver::allowIndexedDB(const WebString& name,
322 const WebSecurityOrigin& origin) {
323 WebFrame* frame = render_frame()->GetWebFrame();
324 if (frame->document().securityOrigin().isUnique() ||
325 frame->top()->document().securityOrigin().isUnique())
326 return false;
328 bool result = false;
329 Send(new ChromeViewHostMsg_AllowIndexedDB(
330 routing_id(), GURL(frame->document().securityOrigin().toString()),
331 GURL(frame->top()->document().securityOrigin().toString()),
332 name, &result));
333 return result;
336 bool ContentSettingsObserver::allowPlugins(bool enabled_per_settings) {
337 return enabled_per_settings;
340 bool ContentSettingsObserver::allowScript(bool enabled_per_settings) {
341 if (!enabled_per_settings)
342 return false;
343 if (is_interstitial_page_)
344 return true;
346 WebFrame* frame = render_frame()->GetWebFrame();
347 std::map<WebFrame*, bool>::const_iterator it =
348 cached_script_permissions_.find(frame);
349 if (it != cached_script_permissions_.end())
350 return it->second;
352 // Evaluate the content setting rules before
353 // |IsWhitelistedForContentSettings|; if there is only the default rule
354 // allowing all scripts, it's quicker this way.
355 bool allow = true;
356 if (content_setting_rules_) {
357 ContentSetting setting = GetContentSettingFromRules(
358 content_setting_rules_->script_rules,
359 frame,
360 GURL(frame->document().securityOrigin().toString()));
361 allow = setting != CONTENT_SETTING_BLOCK;
363 allow = allow || IsWhitelistedForContentSettings(render_frame());
365 cached_script_permissions_[frame] = allow;
366 return allow;
369 bool ContentSettingsObserver::allowScriptFromSource(
370 bool enabled_per_settings,
371 const blink::WebURL& script_url) {
372 if (!enabled_per_settings)
373 return false;
374 if (is_interstitial_page_)
375 return true;
377 bool allow = true;
378 if (content_setting_rules_) {
379 ContentSetting setting =
380 GetContentSettingFromRules(content_setting_rules_->script_rules,
381 render_frame()->GetWebFrame(),
382 GURL(script_url));
383 allow = setting != CONTENT_SETTING_BLOCK;
385 return allow || IsWhitelistedForContentSettings(render_frame());
388 bool ContentSettingsObserver::allowStorage(bool local) {
389 WebFrame* frame = render_frame()->GetWebFrame();
390 if (frame->document().securityOrigin().isUnique() ||
391 frame->top()->document().securityOrigin().isUnique())
392 return false;
393 bool result = false;
395 StoragePermissionsKey key(
396 GURL(frame->document().securityOrigin().toString()), local);
397 std::map<StoragePermissionsKey, bool>::const_iterator permissions =
398 cached_storage_permissions_.find(key);
399 if (permissions != cached_storage_permissions_.end())
400 return permissions->second;
402 Send(new ChromeViewHostMsg_AllowDOMStorage(
403 routing_id(), GURL(frame->document().securityOrigin().toString()),
404 GURL(frame->top()->document().securityOrigin().toString()),
405 local, &result));
406 cached_storage_permissions_[key] = result;
407 return result;
410 bool ContentSettingsObserver::allowReadFromClipboard(bool default_value) {
411 bool allowed = false;
412 #if defined(ENABLE_EXTENSIONS)
413 WebFrame* frame = render_frame()->GetWebFrame();
414 // TODO(dcheng): Should we consider a toURL() method on WebSecurityOrigin?
415 Send(new ChromeViewHostMsg_CanTriggerClipboardRead(
416 GURL(frame->document().securityOrigin().toString()), &allowed));
417 #endif
418 return allowed;
421 bool ContentSettingsObserver::allowWriteToClipboard(bool default_value) {
422 bool allowed = false;
423 #if defined(ENABLE_EXTENSIONS)
424 WebFrame* frame = render_frame()->GetWebFrame();
425 Send(new ChromeViewHostMsg_CanTriggerClipboardWrite(
426 GURL(frame->document().securityOrigin().toString()), &allowed));
427 #endif
428 return allowed;
431 bool ContentSettingsObserver::allowMutationEvents(bool default_value) {
432 return IsPlatformApp() ? false : default_value;
435 bool ContentSettingsObserver::allowPushState() {
436 return !IsPlatformApp();
439 static void SendInsecureContentSignal(int signal) {
440 UMA_HISTOGRAM_ENUMERATION("SSL.InsecureContent", signal,
441 INSECURE_CONTENT_NUM_EVENTS);
444 bool ContentSettingsObserver::allowDisplayingInsecureContent(
445 bool allowed_per_settings,
446 const blink::WebSecurityOrigin& origin,
447 const blink::WebURL& resource_url) {
448 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY);
450 std::string origin_host(origin.host().utf8());
451 WebFrame* frame = render_frame()->GetWebFrame();
452 GURL frame_gurl(frame->document().url());
453 if (IsHostInDomain(origin_host, kGoogleDotCom)) {
454 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE);
455 if (StartsWithASCII(frame_gurl.path(), kGoogleSupportPathPrefix, false)) {
456 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT);
457 } else if (StartsWithASCII(frame_gurl.path(),
458 kGoogleIntlPathPrefix,
459 false)) {
460 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL);
464 if (origin_host == kWWWDotGoogleDotCom) {
465 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE);
466 if (StartsWithASCII(frame_gurl.path(), kGoogleReaderPathPrefix, false))
467 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER);
468 } else if (origin_host == kMailDotGoogleDotCom) {
469 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE);
470 } else if (origin_host == kPlusDotGoogleDotCom) {
471 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE);
472 } else if (origin_host == kDocsDotGoogleDotCom) {
473 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE);
474 } else if (origin_host == kSitesDotGoogleDotCom) {
475 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE);
476 } else if (origin_host == kPicasawebDotGoogleDotCom) {
477 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE);
478 } else if (origin_host == kCodeDotGoogleDotCom) {
479 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE);
480 } else if (origin_host == kGroupsDotGoogleDotCom) {
481 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE);
482 } else if (origin_host == kMapsDotGoogleDotCom) {
483 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE);
484 } else if (origin_host == kWWWDotYoutubeDotCom) {
485 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE);
488 GURL resource_gurl(resource_url);
489 if (EndsWith(resource_gurl.path(), kDotHTML, false))
490 SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HTML);
492 if (allowed_per_settings || allow_displaying_insecure_content_)
493 return true;
495 Send(new ChromeViewHostMsg_DidBlockDisplayingInsecureContent(routing_id()));
497 return false;
500 bool ContentSettingsObserver::allowRunningInsecureContent(
501 bool allowed_per_settings,
502 const blink::WebSecurityOrigin& origin,
503 const blink::WebURL& resource_url) {
504 std::string origin_host(origin.host().utf8());
505 WebFrame* frame = render_frame()->GetWebFrame();
506 GURL frame_gurl(frame->document().url());
507 DCHECK_EQ(frame_gurl.host(), origin_host);
509 bool is_google = IsHostInDomain(origin_host, kGoogleDotCom);
510 if (is_google) {
511 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE);
512 if (StartsWithASCII(frame_gurl.path(), kGoogleSupportPathPrefix, false)) {
513 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT);
514 } else if (StartsWithASCII(frame_gurl.path(),
515 kGoogleIntlPathPrefix,
516 false)) {
517 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL);
521 if (origin_host == kWWWDotGoogleDotCom) {
522 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE);
523 if (StartsWithASCII(frame_gurl.path(), kGoogleReaderPathPrefix, false))
524 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_READER);
525 } else if (origin_host == kMailDotGoogleDotCom) {
526 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE);
527 } else if (origin_host == kPlusDotGoogleDotCom) {
528 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE);
529 } else if (origin_host == kDocsDotGoogleDotCom) {
530 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE);
531 } else if (origin_host == kSitesDotGoogleDotCom) {
532 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE);
533 } else if (origin_host == kPicasawebDotGoogleDotCom) {
534 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE);
535 } else if (origin_host == kCodeDotGoogleDotCom) {
536 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE);
537 } else if (origin_host == kGroupsDotGoogleDotCom) {
538 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE);
539 } else if (origin_host == kMapsDotGoogleDotCom) {
540 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE);
541 } else if (origin_host == kWWWDotYoutubeDotCom) {
542 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_YOUTUBE);
543 } else if (EndsWith(origin_host, kDotGoogleUserContentDotCom, false)) {
544 SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT);
547 GURL resource_gurl(resource_url);
548 if (resource_gurl.host() == kWWWDotYoutubeDotCom)
549 SendInsecureContentSignal(INSECURE_CONTENT_RUN_TARGET_YOUTUBE);
551 if (EndsWith(resource_gurl.path(), kDotJS, false))
552 SendInsecureContentSignal(INSECURE_CONTENT_RUN_JS);
553 else if (EndsWith(resource_gurl.path(), kDotCSS, false))
554 SendInsecureContentSignal(INSECURE_CONTENT_RUN_CSS);
555 else if (EndsWith(resource_gurl.path(), kDotSWF, false))
556 SendInsecureContentSignal(INSECURE_CONTENT_RUN_SWF);
558 if (!allow_running_insecure_content_ && !allowed_per_settings) {
559 DidBlockContentType(CONTENT_SETTINGS_TYPE_MIXEDSCRIPT);
560 return false;
563 return true;
566 void ContentSettingsObserver::didNotAllowPlugins() {
567 DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS);
570 void ContentSettingsObserver::didNotAllowScript() {
571 DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
574 bool ContentSettingsObserver::AreNPAPIPluginsBlocked() const {
575 return npapi_plugins_blocked_;
578 void ContentSettingsObserver::OnLoadBlockedPlugins(
579 const std::string& identifier) {
580 temporarily_allowed_plugins_.insert(identifier);
583 void ContentSettingsObserver::OnSetAsInterstitial() {
584 is_interstitial_page_ = true;
587 void ContentSettingsObserver::OnNPAPINotSupported() {
588 npapi_plugins_blocked_ = true;
591 void ContentSettingsObserver::OnSetAllowDisplayingInsecureContent(bool allow) {
592 allow_displaying_insecure_content_ = allow;
595 void ContentSettingsObserver::OnSetAllowRunningInsecureContent(bool allow) {
596 allow_running_insecure_content_ = allow;
597 OnSetAllowDisplayingInsecureContent(allow);
600 void ContentSettingsObserver::OnReloadFrame() {
601 DCHECK(!render_frame()->GetWebFrame()->parent()) <<
602 "Should only be called on the main frame";
603 render_frame()->GetWebFrame()->reload();
606 void ContentSettingsObserver::OnRequestFileSystemAccessAsyncResponse(
607 int request_id,
608 bool allowed) {
609 PermissionRequestMap::iterator it = permission_requests_.find(request_id);
610 if (it == permission_requests_.end())
611 return;
613 WebPermissionCallbacks callbacks = it->second;
614 permission_requests_.erase(it);
616 if (allowed) {
617 callbacks.doAllow();
618 return;
620 callbacks.doDeny();
623 void ContentSettingsObserver::ClearBlockedContentSettings() {
624 for (size_t i = 0; i < arraysize(content_blocked_); ++i)
625 content_blocked_[i] = false;
626 cached_storage_permissions_.clear();
627 cached_script_permissions_.clear();
630 bool ContentSettingsObserver::IsPlatformApp() {
631 #if defined(ENABLE_EXTENSIONS)
632 WebFrame* frame = render_frame()->GetWebFrame();
633 WebSecurityOrigin origin = frame->document().securityOrigin();
634 const extensions::Extension* extension = GetExtension(origin);
635 return extension && extension->is_platform_app();
636 #else
637 return false;
638 #endif
641 #if defined(ENABLE_EXTENSIONS)
642 const extensions::Extension* ContentSettingsObserver::GetExtension(
643 const WebSecurityOrigin& origin) const {
644 if (!EqualsASCII(origin.protocol(), extensions::kExtensionScheme))
645 return NULL;
647 const std::string extension_id = origin.host().utf8().data();
648 if (!extension_dispatcher_->IsExtensionActive(extension_id))
649 return NULL;
651 return extension_dispatcher_->extensions()->GetByID(extension_id);
653 #endif
655 bool ContentSettingsObserver::IsWhitelistedForContentSettings(
656 content::RenderFrame* frame) {
657 // Whitelist Instant processes.
658 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInstantProcess))
659 return true;
661 // Whitelist ftp directory listings, as they require JavaScript to function
662 // properly.
663 if (frame->IsFTPDirectoryListing())
664 return true;
666 WebFrame* web_frame = frame->GetWebFrame();
667 return IsWhitelistedForContentSettings(web_frame->document().securityOrigin(),
668 web_frame->document().url());
671 bool ContentSettingsObserver::IsWhitelistedForContentSettings(
672 const WebSecurityOrigin& origin,
673 const GURL& document_url) {
674 if (document_url == GURL(content::kUnreachableWebDataURL))
675 return true;
677 if (origin.isUnique())
678 return false; // Uninitialized document?
680 if (EqualsASCII(origin.protocol(), content::kChromeUIScheme))
681 return true; // Browser UI elements should still work.
683 if (EqualsASCII(origin.protocol(), content::kChromeDevToolsScheme))
684 return true; // DevTools UI elements should still work.
686 #if defined(ENABLE_EXTENSIONS)
687 if (EqualsASCII(origin.protocol(), extensions::kExtensionScheme))
688 return true;
689 #endif
691 // TODO(creis, fsamuel): Remove this once the concept of swapped out
692 // RenderFrames goes away.
693 if (document_url == GURL(content::kSwappedOutURL))
694 return true;
696 // If the scheme is file:, an empty file name indicates a directory listing,
697 // which requires JavaScript to function properly.
698 if (EqualsASCII(origin.protocol(), url::kFileScheme)) {
699 return document_url.SchemeIs(url::kFileScheme) &&
700 document_url.ExtractFileName().empty();
703 return false;