Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsMixedContentBlocker.h"
8 #include "nsContentPolicyUtils.h"
9 #include "nsThreadUtils.h"
10 #include "nsINode.h"
11 #include "nsCOMPtr.h"
12 #include "nsIDocShell.h"
13 #include "nsISecurityEventSink.h"
14 #include "nsIWebProgressListener.h"
15 #include "nsContentUtils.h"
16 #include "nsNetUtil.h"
17 #include "nsIRequest.h"
18 #include "nsIDocument.h"
19 #include "nsIContentViewer.h"
20 #include "nsIChannel.h"
21 #include "nsIHttpChannel.h"
22 #include "mozilla/Preferences.h"
23 #include "nsIScriptObjectPrincipal.h"
24 #include "nsISecureBrowserUI.h"
25 #include "nsIDocumentLoader.h"
26 #include "nsIWebNavigation.h"
27 #include "nsLoadGroup.h"
28 #include "nsIScriptError.h"
30 #include "prlog.h"
32 using namespace mozilla;
34 enum nsMixedContentBlockerMessageType {
35 eBlocked = 0x00,
36 eUserOverride = 0x01
37 };
39 // Is mixed script blocking (fonts, plugin content, scripts, stylesheets,
40 // iframes, websockets, XHR) enabled?
41 bool nsMixedContentBlocker::sBlockMixedScript = false;
43 // Is mixed display content blocking (images, audio, video, <a ping>) enabled?
44 bool nsMixedContentBlocker::sBlockMixedDisplay = false;
46 // Fired at the document that attempted to load mixed content. The UI could
47 // handle this event, for example, by displaying an info bar that offers the
48 // choice to reload the page with mixed content permitted.
49 class nsMixedContentEvent : public nsRunnable
50 {
51 public:
52 nsMixedContentEvent(nsISupports *aContext, MixedContentTypes aType)
53 : mContext(aContext), mType(aType)
54 {}
56 NS_IMETHOD Run()
57 {
58 NS_ASSERTION(mContext,
59 "You can't call this runnable without a requesting context");
61 // To update the security UI in the tab with the blocked mixed content, call
62 // nsISecurityEventSink::OnSecurityChange. You can get to the event sink by
63 // calling NS_CP_GetDocShellFromContext on the context, and QI'ing to
64 // nsISecurityEventSink.
67 // Mixed content was allowed and is about to load; get the document and
68 // set the approriate flag to true if we are about to load Mixed Active
69 // Content.
70 nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(mContext);
71 if (!docShell) {
72 return NS_OK;
73 }
74 nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
75 docShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
76 NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
78 // now get the document from sameTypeRoot
79 nsCOMPtr<nsIDocument> rootDoc = do_GetInterface(sameTypeRoot);
80 NS_ASSERTION(rootDoc, "No root document from document shell root tree item.");
83 if (mType == eMixedScript) {
84 // See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI.
85 if (rootDoc->GetHasMixedActiveContentLoaded()) {
86 return NS_OK;
87 }
88 rootDoc->SetHasMixedActiveContentLoaded(true);
90 // Update the security UI in the tab with the allowed mixed active content
91 nsCOMPtr<nsISecurityEventSink> eventSink = do_QueryInterface(docShell);
92 if (eventSink) {
93 // If mixed display content is loaded, make sure to include that in the state.
94 if (rootDoc->GetHasMixedDisplayContentLoaded()) {
95 eventSink->OnSecurityChange(mContext, (nsIWebProgressListener::STATE_IS_BROKEN |
96 nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT |
97 nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT));
98 } else {
99 eventSink->OnSecurityChange(mContext, (nsIWebProgressListener::STATE_IS_BROKEN |
100 nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT));
101 }
102 }
104 } else if (mType == eMixedDisplay) {
105 // See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI.
106 if (rootDoc->GetHasMixedDisplayContentLoaded()) {
107 return NS_OK;
108 }
109 rootDoc->SetHasMixedDisplayContentLoaded(true);
111 // Update the security UI in the tab with the allowed mixed display content.
112 nsCOMPtr<nsISecurityEventSink> eventSink = do_QueryInterface(docShell);
113 if (eventSink) {
114 // If mixed active content is loaded, make sure to include that in the state.
115 if (rootDoc->GetHasMixedActiveContentLoaded()) {
116 eventSink->OnSecurityChange(mContext, (nsIWebProgressListener::STATE_IS_BROKEN |
117 nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT |
118 nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT));
119 } else {
120 eventSink->OnSecurityChange(mContext, (nsIWebProgressListener::STATE_IS_BROKEN |
121 nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT));
122 }
123 }
124 }
126 return NS_OK;
127 }
128 private:
129 // The requesting context for the content load. Generally, a DOM node from
130 // the document that caused the load.
131 nsCOMPtr<nsISupports> mContext;
133 // The type of mixed content detected, e.g. active or display
134 const MixedContentTypes mType;
135 };
138 nsMixedContentBlocker::nsMixedContentBlocker()
139 {
140 // Cache the pref for mixed script blocking
141 Preferences::AddBoolVarCache(&sBlockMixedScript,
142 "security.mixed_content.block_active_content");
144 // Cache the pref for mixed display blocking
145 Preferences::AddBoolVarCache(&sBlockMixedDisplay,
146 "security.mixed_content.block_display_content");
147 }
149 nsMixedContentBlocker::~nsMixedContentBlocker()
150 {
151 }
153 NS_IMPL_ISUPPORTS(nsMixedContentBlocker, nsIContentPolicy)
155 static void
156 LogMixedContentMessage(MixedContentTypes aClassification,
157 nsIURI* aContentLocation,
158 nsIDocument* aRootDoc,
159 nsMixedContentBlockerMessageType aMessageType)
160 {
161 nsAutoCString messageCategory;
162 uint32_t severityFlag;
163 nsAutoCString messageLookupKey;
165 if (aMessageType == eBlocked) {
166 severityFlag = nsIScriptError::errorFlag;
167 messageCategory.AssignLiteral("Mixed Content Blocker");
168 if (aClassification == eMixedDisplay) {
169 messageLookupKey.AssignLiteral("BlockMixedDisplayContent");
170 } else {
171 messageLookupKey.AssignLiteral("BlockMixedActiveContent");
172 }
173 } else {
174 severityFlag = nsIScriptError::warningFlag;
175 messageCategory.AssignLiteral("Mixed Content Message");
176 if (aClassification == eMixedDisplay) {
177 messageLookupKey.AssignLiteral("LoadingMixedDisplayContent");
178 } else {
179 messageLookupKey.AssignLiteral("LoadingMixedActiveContent");
180 }
181 }
183 nsAutoCString locationSpec;
184 aContentLocation->GetSpec(locationSpec);
185 NS_ConvertUTF8toUTF16 locationSpecUTF16(locationSpec);
187 const char16_t* strings[] = { locationSpecUTF16.get() };
188 nsContentUtils::ReportToConsole(severityFlag, messageCategory, aRootDoc,
189 nsContentUtils::eSECURITY_PROPERTIES,
190 messageLookupKey.get(), strings, ArrayLength(strings));
191 }
193 NS_IMETHODIMP
194 nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
195 nsIURI* aContentLocation,
196 nsIURI* aRequestingLocation,
197 nsISupports* aRequestingContext,
198 const nsACString& aMimeGuess,
199 nsISupports* aExtra,
200 nsIPrincipal* aRequestPrincipal,
201 int16_t* aDecision)
202 {
203 // Asserting that we are on the main thread here and hence do not have to lock
204 // and unlock sBlockMixedScript and sBlockMixedDisplay before reading/writing
205 // to them.
206 MOZ_ASSERT(NS_IsMainThread());
208 // Assume active (high risk) content and blocked by default
209 MixedContentTypes classification = eMixedScript;
212 // Notes on non-obvious decisions:
213 //
214 // TYPE_DTD: A DTD can contain entity definitions that expand to scripts.
215 //
216 // TYPE_FONT: The TrueType hinting mechanism is basically a scripting
217 // language that gets interpreted by the operating system's font rasterizer.
218 // Mixed content web fonts are relatively uncommon, and we can can fall back
219 // to built-in fonts with minimal disruption in almost all cases.
220 //
221 // TYPE_OBJECT_SUBREQUEST could actually be either active content (e.g. a
222 // script that a plugin will execute) or display content (e.g. Flash video
223 // content). Until we have a way to determine active vs passive content
224 // from plugin requests (bug 836352), we will treat this as passive content.
225 // This is to prevent false positives from causing users to become
226 // desensitized to the mixed content blocker.
227 //
228 // TYPE_CSP_REPORT: High-risk because they directly leak information about
229 // the content of the page, and because blocking them does not have any
230 // negative effect on the page loading.
231 //
232 // TYPE_PING: Ping requests are POSTS, not GETs like images and media.
233 // Also, PING requests have no bearing on the rendering or operation of
234 // the page when used as designed, so even though they are lower risk than
235 // scripts, blocking them is basically risk-free as far as compatibility is
236 // concerned. Ping is turned off by default in Firefox, so unless a user
237 // opts into ping, no request will be made. Categorizing this as Mixed
238 // Display Content for now, but this is subject to change.
239 //
240 // TYPE_STYLESHEET: XSLT stylesheets can insert scripts. CSS positioning
241 // and other advanced CSS features can possibly be exploited to cause
242 // spoofing attacks (e.g. make a "grant permission" button look like a
243 // "refuse permission" button).
244 //
245 // TYPE_BEACON: Beacon requests are similar to TYPE_PING, but are default on.
246 //
247 // TYPE_WEBSOCKET: The Websockets API requires browsers to
248 // reject mixed-content websockets: "If secure is false but the origin of
249 // the entry script has a scheme component that is itself a secure protocol,
250 // e.g. HTTPS, then throw a SecurityError exception." We already block mixed
251 // content websockets within the websockets implementation, so we don't need
252 // to do any blocking here, nor do we need to provide a way to undo or
253 // override the blocking. Websockets without TLS are very flaky anyway in the
254 // face of many HTTP-aware proxies. Compared to psasive content, there is
255 // additional risk that the script using WebSockets will disclose sensitive
256 // information from the HTTPS page and/or eval (directly or indirectly)
257 // received data.
258 //
259 // TYPE_XMLHTTPREQUEST: XHR requires either same origin or CORS, so most
260 // mixed-content XHR will already be blocked by that check. This will also
261 // block HTTPS-to-HTTP XHR with CORS. The same security concerns mentioned
262 // above for WebSockets apply to XHR, and XHR should have the same security
263 // properties as WebSockets w.r.t. mixed content. XHR's handling of redirects
264 // amplifies these concerns.
267 static_assert(TYPE_DATAREQUEST == TYPE_XMLHTTPREQUEST,
268 "TYPE_DATAREQUEST is not a synonym for "
269 "TYPE_XMLHTTPREQUEST");
271 switch (aContentType) {
272 // The top-level document cannot be mixed content by definition
273 case TYPE_DOCUMENT:
274 *aDecision = ACCEPT;
275 return NS_OK;
276 // Creating insecure websocket connections in a secure page is blocked already
277 // in the websocket constructor. We don't need to check the blocking here
278 // and we don't want to un-block
279 case TYPE_WEBSOCKET:
280 *aDecision = ACCEPT;
281 return NS_OK;
284 // Static display content is considered moderate risk for mixed content so
285 // these will be blocked according to the mixed display preference
286 case TYPE_IMAGE:
287 case TYPE_MEDIA:
288 case TYPE_OBJECT_SUBREQUEST:
289 case TYPE_PING:
290 case TYPE_BEACON:
291 classification = eMixedDisplay;
292 break;
294 // Active content (or content with a low value/risk-of-blocking ratio)
295 // that has been explicitly evaluated; listed here for documentation
296 // purposes and to avoid the assertion and warning for the default case.
297 case TYPE_CSP_REPORT:
298 case TYPE_DTD:
299 case TYPE_FONT:
300 case TYPE_OBJECT:
301 case TYPE_SCRIPT:
302 case TYPE_STYLESHEET:
303 case TYPE_SUBDOCUMENT:
304 case TYPE_XBL:
305 case TYPE_XMLHTTPREQUEST:
306 case TYPE_XSLT:
307 case TYPE_OTHER:
308 break;
311 // This content policy works as a whitelist.
312 default:
313 MOZ_ASSERT(false, "Mixed content of unknown type");
314 break;
315 }
317 /* Get the scheme of the sub-document resource to be requested. If it is
318 * a safe to load in an https context then mixed content doesn't apply.
319 *
320 * Check Protocol Flags to determine if scheme is safe to load:
321 * URI_DOES_NOT_RETURN_DATA - e.g.
322 * "mailto"
323 * URI_IS_LOCAL_RESOURCE - e.g.
324 * "data",
325 * "resource",
326 * "moz-icon"
327 * URI_INHERITS_SECURITY_CONTEXT - e.g.
328 * "javascript"
329 * URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT - e.g.
330 * "https",
331 * "moz-safe-about"
332 *
333 */
334 bool schemeLocal = false;
335 bool schemeNoReturnData = false;
336 bool schemeInherits = false;
337 bool schemeSecure = false;
338 if (NS_FAILED(NS_URIChainHasFlags(aContentLocation, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE , &schemeLocal)) ||
339 NS_FAILED(NS_URIChainHasFlags(aContentLocation, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &schemeNoReturnData)) ||
340 NS_FAILED(NS_URIChainHasFlags(aContentLocation, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, &schemeInherits)) ||
341 NS_FAILED(NS_URIChainHasFlags(aContentLocation, nsIProtocolHandler::URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT, &schemeSecure))) {
342 return NS_ERROR_FAILURE;
343 }
345 if (schemeLocal || schemeNoReturnData || schemeInherits || schemeSecure) {
346 return NS_OK;
347 }
349 // Since there are cases where aRequestingLocation and aRequestPrincipal are
350 // definitely not the owning document, we try to ignore them by extracting the
351 // requestingLocation in the following order:
352 // 1) from the aRequestingContext, either extracting
353 // a) the node's principal, or the
354 // b) script object's principal.
355 // 2) if aRequestingContext yields a principal but no location, we check
356 // if its the system principal. If it is, allow the load.
357 // 3) Special case handling for:
358 // a) speculative loads, where shouldLoad is called twice (bug 839235)
359 // and the first speculative load does not include a context.
360 // In this case we use aRequestingLocation to set requestingLocation.
361 // b) TYPE_CSP_REPORT which does not provide a context. In this case we
362 // use aRequestingLocation to set requestingLocation.
363 // c) content scripts from addon code that do not provide aRequestingContext
364 // or aRequestingLocation, but do provide aRequestPrincipal.
365 // If aRequestPrincipal is an expanded principal, we allow the load.
366 // 4) If we still end up not having a requestingLocation, we reject the load.
368 nsCOMPtr<nsIPrincipal> principal;
369 // 1a) Try to get the principal if aRequestingContext is a node.
370 nsCOMPtr<nsINode> node = do_QueryInterface(aRequestingContext);
371 if (node) {
372 principal = node->NodePrincipal();
373 }
375 // 1b) Try using the window's script object principal if it's not a node.
376 if (!principal) {
377 nsCOMPtr<nsIScriptObjectPrincipal> scriptObjPrin = do_QueryInterface(aRequestingContext);
378 if (scriptObjPrin) {
379 principal = scriptObjPrin->GetPrincipal();
380 }
381 }
383 nsCOMPtr<nsIURI> requestingLocation;
384 if (principal) {
385 principal->GetURI(getter_AddRefs(requestingLocation));
386 }
388 // 2) if aRequestingContext yields a principal but no location, we check if its a system principal.
389 if (principal && !requestingLocation) {
390 if (nsContentUtils::IsSystemPrincipal(principal)) {
391 *aDecision = ACCEPT;
392 return NS_OK;
393 }
394 }
396 // 3a,b) Special case handling for speculative loads and TYPE_CSP_REPORT. In
397 // such cases, aRequestingContext doesn't exist, so we use aRequestingLocation.
398 // Unfortunately we can not distinguish between speculative and normal loads here,
399 // otherwise we could special case this assignment.
400 if (!requestingLocation) {
401 requestingLocation = aRequestingLocation;
402 }
404 // 3c) Special case handling for content scripts from addons code, which only
405 // provide a aRequestPrincipal; aRequestingContext and aRequestingLocation are
406 // both null; if the aRequestPrincipal is an expandedPrincipal, we allow the load.
407 if (!principal && !requestingLocation && aRequestPrincipal) {
408 nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aRequestPrincipal);
409 if (expanded) {
410 *aDecision = ACCEPT;
411 return NS_OK;
412 }
413 }
415 // 4) Giving up. We still don't have a requesting location, therefore we can't tell
416 // if this is a mixed content load. Deny to be safe.
417 if (!requestingLocation) {
418 *aDecision = REJECT_REQUEST;
419 return NS_OK;
420 }
422 // Check the parent scheme. If it is not an HTTPS page then mixed content
423 // restrictions do not apply.
424 bool parentIsHttps;
425 nsresult rv = requestingLocation->SchemeIs("https", &parentIsHttps);
426 if (NS_FAILED(rv)) {
427 NS_ERROR("requestingLocation->SchemeIs failed");
428 *aDecision = REJECT_REQUEST;
429 return NS_OK;
430 }
431 if (!parentIsHttps) {
432 *aDecision = ACCEPT;
433 return NS_OK;
434 }
436 // Determine if the rootDoc is https and if the user decided to allow Mixed Content
437 nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
438 NS_ENSURE_TRUE(docShell, NS_OK);
439 bool rootHasSecureConnection = false;
440 bool allowMixedContent = false;
441 bool isRootDocShell = false;
442 rv = docShell->GetAllowMixedContentAndConnectionData(&rootHasSecureConnection, &allowMixedContent, &isRootDocShell);
443 if (NS_FAILED(rv)) {
444 return rv;
445 }
448 // Get the sameTypeRoot tree item from the docshell
449 nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
450 docShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
451 NS_ASSERTION(sameTypeRoot, "No root tree item from docshell!");
453 // When navigating an iframe, the iframe may be https
454 // but its parents may not be. Check the parents to see if any of them are https.
455 // If none of the parents are https, allow the load.
456 if (aContentType == TYPE_SUBDOCUMENT && !rootHasSecureConnection) {
458 bool httpsParentExists = false;
460 nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
461 parentTreeItem = docShell;
463 while(!httpsParentExists && parentTreeItem) {
464 nsCOMPtr<nsIWebNavigation> parentAsNav(do_QueryInterface(parentTreeItem));
465 NS_ASSERTION(parentAsNav, "No web navigation object from parent's docshell tree item");
466 nsCOMPtr<nsIURI> parentURI;
468 parentAsNav->GetCurrentURI(getter_AddRefs(parentURI));
469 if (!parentURI || NS_FAILED(parentURI->SchemeIs("https", &httpsParentExists))) {
470 // if getting the URI or the scheme fails, assume there is a https parent and break.
471 httpsParentExists = true;
472 break;
473 }
475 // When the parent and the root are the same, we have traversed all the way up
476 // the same type docshell tree. Break out of the while loop.
477 if(sameTypeRoot == parentTreeItem) {
478 break;
479 }
481 // update the parent to the grandparent.
482 nsCOMPtr<nsIDocShellTreeItem> newParentTreeItem;
483 parentTreeItem->GetSameTypeParent(getter_AddRefs(newParentTreeItem));
484 parentTreeItem = newParentTreeItem;
485 } // end while loop.
487 if (!httpsParentExists) {
488 *aDecision = nsIContentPolicy::ACCEPT;
489 return NS_OK;
490 }
491 }
493 // Get the root document from the sameTypeRoot
494 nsCOMPtr<nsIDocument> rootDoc = do_GetInterface(sameTypeRoot);
495 NS_ASSERTION(rootDoc, "No root document from document shell root tree item.");
497 // Get eventSink and the current security state from the docShell
498 nsCOMPtr<nsISecurityEventSink> eventSink = do_QueryInterface(docShell);
499 NS_ASSERTION(eventSink, "No eventSink from docShell.");
500 nsCOMPtr<nsIDocShell> rootShell = do_GetInterface(sameTypeRoot);
501 NS_ASSERTION(rootShell, "No root docshell from document shell root tree item.");
502 uint32_t State = nsIWebProgressListener::STATE_IS_BROKEN;
503 nsCOMPtr<nsISecureBrowserUI> securityUI;
504 rootShell->GetSecurityUI(getter_AddRefs(securityUI));
505 // If there is no securityUI, document doesn't have a security state.
506 // Allow load and return early.
507 if (!securityUI) {
508 *aDecision = nsIContentPolicy::ACCEPT;
509 return NS_OK;
510 }
511 nsresult stateRV = securityUI->GetState(&State);
513 // If the content is display content, and the pref says display content should be blocked, block it.
514 if (sBlockMixedDisplay && classification == eMixedDisplay) {
515 if (allowMixedContent) {
516 LogMixedContentMessage(classification, aContentLocation, rootDoc, eUserOverride);
517 *aDecision = nsIContentPolicy::ACCEPT;
518 rootDoc->SetHasMixedActiveContentLoaded(true);
519 if (!rootDoc->GetHasMixedDisplayContentLoaded() && NS_SUCCEEDED(stateRV)) {
520 rootDoc->SetHasMixedDisplayContentLoaded(true);
521 eventSink->OnSecurityChange(aRequestingContext, (State | nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT));
522 }
523 } else {
524 *aDecision = nsIContentPolicy::REJECT_REQUEST;
525 LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
526 if (!rootDoc->GetHasMixedDisplayContentBlocked() && NS_SUCCEEDED(stateRV)) {
527 rootDoc->SetHasMixedDisplayContentBlocked(true);
528 eventSink->OnSecurityChange(aRequestingContext, (State | nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT));
529 }
530 }
531 return NS_OK;
533 } else if (sBlockMixedScript && classification == eMixedScript) {
534 // If the content is active content, and the pref says active content should be blocked, block it
535 // unless the user has choosen to override the pref
536 if (allowMixedContent) {
537 LogMixedContentMessage(classification, aContentLocation, rootDoc, eUserOverride);
538 *aDecision = nsIContentPolicy::ACCEPT;
539 // See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI.
540 if (rootDoc->GetHasMixedActiveContentLoaded()) {
541 return NS_OK;
542 }
543 rootDoc->SetHasMixedActiveContentLoaded(true);
545 if (rootHasSecureConnection) {
546 // User has decided to override the pref and the root is https, so change the Security State.
547 if (rootDoc->GetHasMixedDisplayContentLoaded()) {
548 // If mixed display content is loaded, make sure to include that in the state.
549 eventSink->OnSecurityChange(aRequestingContext, (nsIWebProgressListener::STATE_IS_BROKEN |
550 nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT |
551 nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT));
552 } else {
553 eventSink->OnSecurityChange(aRequestingContext, (nsIWebProgressListener::STATE_IS_BROKEN |
554 nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT));
555 }
556 return NS_OK;
557 } else {
558 // User has already overriden the pref and the root is not https;
559 // mixed content was allowed on an https subframe.
560 if (NS_SUCCEEDED(stateRV)) {
561 eventSink->OnSecurityChange(aRequestingContext, (State | nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT));
562 }
563 return NS_OK;
564 }
565 } else {
566 //User has not overriden the pref by Disabling protection. Reject the request and update the security state.
567 *aDecision = nsIContentPolicy::REJECT_REQUEST;
568 LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
569 // See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI.
570 if (rootDoc->GetHasMixedActiveContentBlocked()) {
571 return NS_OK;
572 }
573 rootDoc->SetHasMixedActiveContentBlocked(true);
575 // The user has not overriden the pref, so make sure they still have an option by calling eventSink
576 // which will invoke the doorhanger
577 if (NS_SUCCEEDED(stateRV)) {
578 eventSink->OnSecurityChange(aRequestingContext, (State | nsIWebProgressListener::STATE_BLOCKED_MIXED_ACTIVE_CONTENT));
579 }
580 return NS_OK;
581 }
583 } else {
584 // The content is not blocked by the mixed content prefs.
586 // Log a message that we are loading mixed content.
587 LogMixedContentMessage(classification, aContentLocation, rootDoc, eUserOverride);
589 // Fire the event from a script runner as it is unsafe to run script
590 // from within ShouldLoad
591 nsContentUtils::AddScriptRunner(
592 new nsMixedContentEvent(aRequestingContext, classification));
593 return NS_OK;
594 }
596 *aDecision = REJECT_REQUEST;
597 return NS_OK;
598 }
600 NS_IMETHODIMP
601 nsMixedContentBlocker::ShouldProcess(uint32_t aContentType,
602 nsIURI* aContentLocation,
603 nsIURI* aRequestingLocation,
604 nsISupports* aRequestingContext,
605 const nsACString& aMimeGuess,
606 nsISupports* aExtra,
607 nsIPrincipal* aRequestPrincipal,
608 int16_t* aDecision)
609 {
610 if (!aContentLocation) {
611 // aContentLocation may be null when a plugin is loading without an associated URI resource
612 if (aContentType == TYPE_OBJECT) {
613 return NS_OK;
614 } else {
615 return NS_ERROR_FAILURE;
616 }
617 }
619 return ShouldLoad(aContentType, aContentLocation, aRequestingLocation,
620 aRequestingContext, aMimeGuess, aExtra, aRequestPrincipal,
621 aDecision);
622 }