Bug 1122236 - CSP: Implement block-all-mixed-content (r=tanvi,kate,mrbkap)
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Wed, 13 Jan 2016 20:58:16 -0800
changeset 328733 8374f1f94ea541cf8a5e9c873309e61160717eea
parent 328732 3c8ea88e6916b841fc760b7b748ef7e93bb38b38
child 328734 35252bf91d921c0ccd8689f91242e606eb3c627b
push id1146
push userCallek@gmail.com
push dateMon, 25 Jul 2016 16:35:44 +0000
treeherdermozilla-release@a55778f9cd5a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstanvi, kate, mrbkap
bugs1122236
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1122236 - CSP: Implement block-all-mixed-content (r=tanvi,kate,mrbkap)
dom/base/nsDocument.cpp
dom/base/nsIDocument.h
dom/interfaces/security/nsIContentSecurityPolicy.idl
dom/locales/en-US/chrome/security/csp.properties
dom/security/nsCSPContext.cpp
dom/security/nsCSPParser.cpp
dom/security/nsCSPUtils.cpp
dom/security/nsCSPUtils.h
dom/security/nsMixedContentBlocker.cpp
dom/webidl/CSPDictionaries.webidl
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1424,16 +1424,18 @@ static already_AddRefed<mozilla::dom::No
 
 // ==================================================================
 // =
 // ==================================================================
 nsIDocument::nsIDocument()
   : nsINode(nullNodeInfo),
     mReferrerPolicySet(false),
     mReferrerPolicy(mozilla::net::RP_Default),
+    mBlockAllMixedContent(false),
+    mBlockAllMixedContentPreloads(false),
     mUpgradeInsecureRequests(false),
     mUpgradeInsecurePreloads(false),
     mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
     mNodeInfoManager(nullptr),
     mCompatMode(eCompatibility_FullStandards),
     mVisibilityState(dom::VisibilityState::Hidden),
     mIsInitialDocumentInWindow(false),
     mMayStartLayout(true),
@@ -2587,23 +2589,28 @@ nsDocument::StartDocumentLoad(const char
   // The CSP directive upgrade-insecure-requests not only applies to the
   // toplevel document, but also to nested documents. Let's propagate that
   // flag from the parent to the nested document.
   nsCOMPtr<nsIDocShellTreeItem> treeItem = this->GetDocShell();
   if (treeItem) {
     nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
     treeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
     if (sameTypeParent) {
-      mUpgradeInsecureRequests =
-        sameTypeParent->GetDocument()->GetUpgradeInsecureRequests(false);
+      nsIDocument* doc = sameTypeParent->GetDocument();
+      mBlockAllMixedContent = doc->GetBlockAllMixedContent(false);
+      // if the parent document makes use of block-all-mixed-content
+      // then subdocument preloads should always be blocked.
+      mBlockAllMixedContentPreloads =
+        mBlockAllMixedContent || doc->GetBlockAllMixedContent(true);
+
+      mUpgradeInsecureRequests = doc->GetUpgradeInsecureRequests(false);
       // if the parent document makes use of upgrade-insecure-requests
       // then subdocument preloads should always be upgraded.
       mUpgradeInsecurePreloads =
-        mUpgradeInsecureRequests ||
-        sameTypeParent->GetDocument()->GetUpgradeInsecureRequests(true);
+        mUpgradeInsecureRequests || doc->GetUpgradeInsecureRequests(true);
     }
   }
 
   // If this is not a data document, set CSP.
   if (!mLoadedAsData) {
     nsresult rv = InitCSP(aChannel);
     NS_ENSURE_SUCCESS(rv, rv);
   }
@@ -2692,37 +2699,52 @@ nsDocument::ApplySettingsFromCSP(bool aS
       bool hasReferrerPolicy = false;
       uint32_t referrerPolicy = mozilla::net::RP_Default;
       rv = csp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
       NS_ENSURE_SUCCESS_VOID(rv);
       if (hasReferrerPolicy) {
         mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
         mReferrerPolicySet = true;
       }
+ 
+      // Set up 'block-all-mixed-content' if not already inherited
+      // from the parent context or set by any other CSP.
+      if (!mBlockAllMixedContent) {
+        rv = csp->GetBlockAllMixedContent(&mBlockAllMixedContent);
+        NS_ENSURE_SUCCESS_VOID(rv);
+      }
+      if (!mBlockAllMixedContentPreloads) {
+        mBlockAllMixedContentPreloads = mBlockAllMixedContent;
+     }
 
       // Set up 'upgrade-insecure-requests' if not already inherited
       // from the parent context or set by any other CSP.
       if (!mUpgradeInsecureRequests) {
         rv = csp->GetUpgradeInsecureRequests(&mUpgradeInsecureRequests);
         NS_ENSURE_SUCCESS_VOID(rv);
       }
       if (!mUpgradeInsecurePreloads) {
         mUpgradeInsecurePreloads = mUpgradeInsecureRequests;
       }
     }
     return;
   }
 
   // 2) apply settings from speculative csp
-  if (!mUpgradeInsecurePreloads) {
-    nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
-    rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
-    NS_ENSURE_SUCCESS_VOID(rv);
-    if (preloadCsp) {
-      preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
+  nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
+  rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
+  NS_ENSURE_SUCCESS_VOID(rv);
+  if (preloadCsp) {
+    if (!mBlockAllMixedContentPreloads) {
+      rv = preloadCsp->GetBlockAllMixedContent(&mBlockAllMixedContentPreloads);
+      NS_ENSURE_SUCCESS_VOID(rv);
+    }
+    if (!mUpgradeInsecurePreloads) {
+      rv = preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
+      NS_ENSURE_SUCCESS_VOID(rv);
     }
   }
 }
 
 nsresult
 nsDocument::InitCSP(nsIChannel* aChannel)
 {
   nsCOMPtr<nsIContentSecurityPolicy> csp;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -312,16 +312,29 @@ public:
    * GetReferrerPolicy() for Document.webidl.
    */
   uint32_t ReferrerPolicy() const
   {
     return GetReferrerPolicy();
   }
 
   /**
+   * If true, this flag indicates that all mixed content subresource
+   * loads for this document (and also embeded browsing contexts) will
+   * be blocked.
+   */
+  bool GetBlockAllMixedContent(bool aPreload) const
+  {
+    if (aPreload) {
+      return mBlockAllMixedContentPreloads;
+    }
+    return mBlockAllMixedContent;
+  }
+
+  /**
    * If true, this flag indicates that all subresource loads for this
    * document need to be upgraded from http to https.
    * This flag becomes true if the CSP of the document itself, or any
    * of the document's ancestors up to the toplevel document makes use
    * of the CSP directive 'upgrade-insecure-requests'.
    */
   bool GetUpgradeInsecureRequests(bool aPreload) const
   {
@@ -2761,16 +2774,18 @@ protected:
   nsCOMPtr<nsIURI> mDocumentBaseURI;
   nsCOMPtr<nsIURI> mChromeXHRDocBaseURI;
 
   nsWeakPtr mDocumentLoadGroup;
 
   bool mReferrerPolicySet;
   ReferrerPolicyEnum mReferrerPolicy;
 
+  bool mBlockAllMixedContent;
+  bool mBlockAllMixedContentPreloads;
   bool mUpgradeInsecureRequests;
   bool mUpgradeInsecurePreloads;
 
   mozilla::WeakPtr<nsDocShell> mDocumentContainer;
 
   nsCString mCharacterSet;
   int32_t mCharacterSetSource;
 
--- a/dom/interfaces/security/nsIContentSecurityPolicy.idl
+++ b/dom/interfaces/security/nsIContentSecurityPolicy.idl
@@ -47,16 +47,17 @@ interface nsIContentSecurityPolicy : nsI
   const unsigned short FRAME_ANCESTORS_DIRECTIVE      = 11;
   const unsigned short REFLECTED_XSS_DIRECTIVE        = 12;
   const unsigned short BASE_URI_DIRECTIVE             = 13;
   const unsigned short FORM_ACTION_DIRECTIVE          = 14;
   const unsigned short REFERRER_DIRECTIVE             = 15;
   const unsigned short WEB_MANIFEST_SRC_DIRECTIVE     = 16;
   const unsigned short UPGRADE_IF_INSECURE_DIRECTIVE  = 17;
   const unsigned short CHILD_SRC_DIRECTIVE            = 18;
+  const unsigned short BLOCK_ALL_MIXED_CONTENT        = 19;
 
   /**
    * Accessor method for a read-only string version of the policy at a given
    * index.
    */
   AString getPolicy(in unsigned long index);
 
   /**
@@ -68,16 +69,25 @@ interface nsIContentSecurityPolicy : nsI
   /**
    * Returns whether this policy uses the directive upgrade-insecure-requests.
    * Please note that upgrade-insecure-reqeusts also applies if the parent or
    * including document (context) makes use of the directive.
    */
   readonly attribute bool upgradeInsecureRequests;
 
   /**
+   * Returns whether this policy uses the directive block-all-mixed-content.
+   * Please note that block-all-mixed-content takes presedence in case the
+   * directive upgrade-insecure-requests is defined in the same policy and
+   * will therefore block all mixed content without even trying to perform
+   * an upgrade.
+   */
+  readonly attribute bool blockAllMixedContent;
+
+  /**
    * Obtains the referrer policy (as integer) for this browsing context as
    * specified in CSP.  If there are multiple policies and...
    *  - only one sets a referrer policy: that policy is returned
    *  - more than one sets different referrer policies: no-referrer is returned
    *  - more than one set equivalent policies: that policy is returned
    * For the enumeration of policies see ReferrerPolicy.h and nsIHttpChannel.
    *
    * @param aPolicy
--- a/dom/locales/en-US/chrome/security/csp.properties
+++ b/dom/locales/en-US/chrome/security/csp.properties
@@ -63,16 +63,19 @@ upgradeInsecureRequest = Upgrading insec
 # LOCALIZATION NOTE (ignoreSrcForDirective):
 ignoreSrcForDirective = Ignoring srcs for directive '%1$S'
 # LOCALIZATION NOTE (hostNameMightBeKeyword):
 # %1$S is the hostname in question and %2$S is the keyword
 hostNameMightBeKeyword = Interpreting %1$S as a hostname, not a keyword. If you intended this to be a keyword, use '%2$S' (wrapped in single quotes).
 # LOCALIZATION NOTE (notSupportingDirective):
 # directive is not supported (e.g. 'reflected-xss')
 notSupportingDirective = Not supporting directive '%1$S'. Directive and values will be ignored.
+# LOCALIZATION NOTE (blockAllMixedContent):
+# %1$S is the URL of the blocked resource load.
+blockAllMixedContent = Blocking insecure request '%1$S'.
 
 # CSP Errors:
 # LOCALIZATION NOTE (couldntParseInvalidSource):
 # %1$S is the source that could not be parsed
 couldntParseInvalidSource = Couldn't parse invalid source %1$S
 # LOCALIZATION NOTE (couldntParseInvalidHost):
 # %1$S is the host that's invalid
 couldntParseInvalidHost = Couldn't parse invalid host %1$S
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -304,16 +304,29 @@ nsCSPContext::GetUpgradeInsecureRequests
       *outUpgradeRequest = true;
       return NS_OK;
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsCSPContext::GetBlockAllMixedContent(bool *outBlockAllMixedContent)
+{
+  *outBlockAllMixedContent = false;
+  for (uint32_t i = 0; i < mPolicies.Length(); i++) {
+    if (mPolicies[i]->hasDirective(nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT)) {
+      *outBlockAllMixedContent = true;
+      return NS_OK;
+    }
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsCSPContext::GetReferrerPolicy(uint32_t* outPolicy, bool* outIsSet)
 {
   *outIsSet = false;
   *outPolicy = mozilla::net::RP_Default;
   nsAutoString refpol;
   mozilla::net::ReferrerPolicy previousPolicy = mozilla::net::RP_Default;
   for (uint32_t i = 0; i < mPolicies.Length(); i++) {
     mPolicies[i]->getReferrerPolicy(refpol);
--- a/dom/security/nsCSPParser.cpp
+++ b/dom/security/nsCSPParser.cpp
@@ -1003,16 +1003,21 @@ nsCSPParser::directiveName()
     // log to the console to indicate that meta CSP is ignoring the directive
     const char16_t* params[] = { mCurToken.get() };
     logWarningErrorToConsole(nsIScriptError::warningFlag,
                              "ignoringSrcFromMetaCSP",
                              params, ArrayLength(params));
     return nullptr;
   }
 
+  // special case handling for block-all-mixed-content
+  if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT)) {
+    return new nsBlockAllMixedContentDirective(CSP_StringToCSPDirective(mCurToken));
+  }
+
   // special case handling for upgrade-insecure-requests
   if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
     return new nsUpgradeInsecureDirective(CSP_StringToCSPDirective(mCurToken));
   }
 
   // child-src has it's own class to handle frame-src if necessary
   if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE)) {
     mChildSrc = new nsCSPChildSrcDirective(CSP_StringToCSPDirective(mCurToken));
@@ -1054,16 +1059,30 @@ nsCSPParser::directive()
 
   // Try to create a new CSPDirective
   nsCSPDirective* cspDir = directiveName();
   if (!cspDir) {
     // if we can not create a CSPDirective, we can skip parsing the srcs for that array
     return;
   }
 
+  // special case handling for block-all-mixed-content, which is only specified
+  // by a directive name but does not include any srcs.
+  if (cspDir->equals(nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT)) {
+    if (mCurDir.Length() > 1) {
+      const char16_t* params[] = { MOZ_UTF16("block-all-mixed-content") };
+      logWarningErrorToConsole(nsIScriptError::warningFlag,
+                               "ignoreSrcForDirective",
+                               params, ArrayLength(params));
+    }
+    // add the directive and return
+    mPolicy->addDirective(cspDir);
+    return;
+  }
+
   // special case handling for upgrade-insecure-requests, which is only specified
   // by a directive name but does not include any srcs.
   if (cspDir->equals(nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
     if (mCurDir.Length() > 1) {
       const char16_t* params[] = { MOZ_UTF16("upgrade-insecure-requests") };
       logWarningErrorToConsole(nsIScriptError::warningFlag,
                                "ignoreSrcForDirective",
                                params, ArrayLength(params));
--- a/dom/security/nsCSPUtils.cpp
+++ b/dom/security/nsCSPUtils.cpp
@@ -897,16 +897,21 @@ nsCSPDirective::toDomCSPStruct(mozilla::
       outCSP.mBase_uri.Value() = mozilla::Move(srcs);
       return;
 
     case nsIContentSecurityPolicy::FORM_ACTION_DIRECTIVE:
       outCSP.mForm_action.Construct();
       outCSP.mForm_action.Value() = mozilla::Move(srcs);
       return;
 
+    case nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT:
+      outCSP.mBlock_all_mixed_content.Construct();
+      // does not have any srcs
+      return;
+
     case nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE:
       outCSP.mUpgrade_insecure_requests.Construct();
       // does not have any srcs
       return;
 
     case nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE:
       outCSP.mChild_src.Construct();
       outCSP.mChild_src.Value() = mozilla::Move(srcs);
@@ -982,16 +987,34 @@ bool nsCSPChildSrcDirective::equals(CSPD
 {
   if (aDirective == nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE) {
     return mHandleFrameSrc;
   }
 
   return (aDirective == nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE);
 }
 
+/* =============== nsBlockAllMixedContentDirective ============= */
+
+nsBlockAllMixedContentDirective::nsBlockAllMixedContentDirective(CSPDirective aDirective)
+: nsCSPDirective(aDirective)
+{
+}
+
+nsBlockAllMixedContentDirective::~nsBlockAllMixedContentDirective()
+{
+}
+
+void
+nsBlockAllMixedContentDirective::toString(nsAString& outStr) const
+{
+  outStr.AppendASCII(CSP_CSPDirectiveToString(
+    nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT));
+}
+
 /* =============== nsUpgradeInsecureDirective ============= */
 
 nsUpgradeInsecureDirective::nsUpgradeInsecureDirective(CSPDirective aDirective)
 : nsCSPDirective(aDirective)
 {
 }
 
 nsUpgradeInsecureDirective::~nsUpgradeInsecureDirective()
--- a/dom/security/nsCSPUtils.h
+++ b/dom/security/nsCSPUtils.h
@@ -83,17 +83,18 @@ static const char* CSPStrDirectives[] = 
   "report-uri",                // REPORT_URI_DIRECTIVE
   "frame-ancestors",           // FRAME_ANCESTORS_DIRECTIVE
   "reflected-xss",             // REFLECTED_XSS_DIRECTIVE
   "base-uri",                  // BASE_URI_DIRECTIVE
   "form-action",               // FORM_ACTION_DIRECTIVE
   "referrer",                  // REFERRER_DIRECTIVE
   "manifest-src",              // MANIFEST_SRC_DIRECTIVE
   "upgrade-insecure-requests", // UPGRADE_IF_INSECURE_DIRECTIVE
-  "child-src"                  // CHILD_SRC_DIRECTIVE
+  "child-src",                 // CHILD_SRC_DIRECTIVE
+  "block-all-mixed-content"    // BLOCK_ALL_MIXED_CONTENT
 };
 
 inline const char* CSP_CSPDirectiveToString(CSPDirective aDir)
 {
   return CSPStrDirectives[static_cast<uint32_t>(aDir)];
 }
 
 inline CSPDirective CSP_StringToCSPDirective(const nsAString& aDir)
@@ -338,16 +339,39 @@ class nsCSPChildSrcDirective : public ns
     virtual bool restrictsContentType(nsContentPolicyType aContentType) const;
 
     virtual bool equals(CSPDirective aDirective) const;
 
   private:
     bool mHandleFrameSrc;
 };
 
+/* =============== nsBlockAllMixedContentDirective === */
+
+class nsBlockAllMixedContentDirective : public nsCSPDirective {
+  public:
+    explicit nsBlockAllMixedContentDirective(CSPDirective aDirective);
+    ~nsBlockAllMixedContentDirective();
+
+    bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
+                 bool aReportOnly, bool aUpgradeInsecure) const
+      { return false; }
+
+    bool permits(nsIURI* aUri) const
+      { return false; }
+
+    bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const
+      { return false; }
+
+    void toString(nsAString& outStr) const;
+
+    void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs)
+      {  MOZ_ASSERT(false, "block-all-mixed-content does not hold any srcs"); }
+};
+
 /* =============== nsUpgradeInsecureDirective === */
 
 /*
  * Upgrading insecure requests includes the following actors:
  * (1) CSP:
  *     The CSP implementation whitelists the http-request
  *     in case the policy is executed in enforcement mode.
  *     The CSP implementation however does not allow http
--- a/dom/security/nsMixedContentBlocker.cpp
+++ b/dom/security/nsMixedContentBlocker.cpp
@@ -627,16 +627,45 @@ nsMixedContentBlocker::ShouldLoad(bool a
     *aDecision = REJECT_REQUEST;
     return NS_OK;
   }
   if (!parentIsHttps) {
     *aDecision = ACCEPT;
     return NS_OK;
   }
 
+  nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
+  NS_ENSURE_TRUE(docShell, NS_OK);
+
+  // The page might have set the CSP directive 'block-all-mixed-content' which
+  // should block not only active mixed content loads but in fact all mixed content
+  // loads, see https://www.w3.org/TR/mixed-content/#strict-checking
+  // Block all non secure loads in case the CSP directive is present. Please note
+  // that at this point we already know, based on |schemeSecure| that the load is
+  // not secure, so we can bail out early at this point.
+  if (docShell->GetDocument()->GetBlockAllMixedContent(isPreload)) {
+    // log a message to the console before returning.
+    nsAutoCString spec;
+    rv = aContentLocation->GetSpec(spec);
+    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ConvertUTF8toUTF16 reportSpec(spec);
+
+    const char16_t* params[] = { reportSpec.get()};
+    CSP_LogLocalizedStr(MOZ_UTF16("blockAllMixedContent"),
+                        params, ArrayLength(params),
+                        EmptyString(), // aSourceFile
+                        EmptyString(), // aScriptSample
+                        0, // aLineNumber
+                        0, // aColumnNumber
+                        nsIScriptError::errorFlag, "CSP",
+                        docShell->GetDocument()->InnerWindowID());
+    *aDecision = REJECT_REQUEST;
+    return NS_OK;
+  }
+
   // Disallow mixed content loads for workers, shared workers and service
   // workers.
   if (isWorkerType) {
     // For workers, we can assume that we're mixed content at this point, since
     // the parent is https, and the protocol associated with aContentLocation
     // doesn't map to the secure URI flags checked above.  Assert this for
     // sanity's sake
 #ifdef DEBUG
@@ -644,20 +673,16 @@ nsMixedContentBlocker::ShouldLoad(bool a
     rv = aContentLocation->SchemeIs("https", &isHttpsScheme);
     NS_ENSURE_SUCCESS(rv, rv);
     MOZ_ASSERT(!isHttpsScheme);
 #endif
     *aDecision = REJECT_REQUEST;
     return NS_OK;
   }
 
-  // Determine if the rootDoc is https and if the user decided to allow Mixed Content
-  nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
-  NS_ENSURE_TRUE(docShell, NS_OK);
-
   // The page might have set the CSP directive 'upgrade-insecure-requests'. In such
   // a case allow the http: load to succeed with the promise that the channel will
   // get upgraded to https before fetching any data from the netwerk.
   // Please see: nsHttpChannel::Connect()
   //
   // Please note that the CSP directive 'upgrade-insecure-requests' only applies to
   // http: and ws: (for websockets). Websockets are not subject to mixed content
   // blocking since insecure websockets are not allowed within secure pages. Hence,
@@ -667,16 +692,17 @@ nsMixedContentBlocker::ShouldLoad(bool a
   bool isHttpScheme = false;
   rv = aContentLocation->SchemeIs("http", &isHttpScheme);
   NS_ENSURE_SUCCESS(rv, rv);
   if (isHttpScheme && docShell->GetDocument()->GetUpgradeInsecureRequests(isPreload)) {
     *aDecision = ACCEPT;
     return NS_OK;
   }
 
+  // Determine if the rootDoc is https and if the user decided to allow Mixed Content
   bool rootHasSecureConnection = false;
   bool allowMixedContent = false;
   bool isRootDocShell = false;
   rv = docShell->GetAllowMixedContentAndConnectionData(&rootHasSecureConnection, &allowMixedContent, &isRootDocShell);
   if (NS_FAILED(rv)) {
     *aDecision = REJECT_REQUEST;
     return rv;
   }
--- a/dom/webidl/CSPDictionaries.webidl
+++ b/dom/webidl/CSPDictionaries.webidl
@@ -22,13 +22,14 @@ dictionary CSP {
   sequence<DOMString> frame-ancestors;
   // sequence<DOMString> reflected-xss; // not suppored in Firefox
   sequence<DOMString> base-uri;
   sequence<DOMString> form-action;
   sequence<DOMString> referrer;
   sequence<DOMString> manifest-src;
   sequence<DOMString> upgrade-insecure-requests;
   sequence<DOMString> child-src;
+  sequence<DOMString> block-all-mixed-content;
 };
 
 dictionary CSPPolicies {
   sequence<CSP> csp-policies;
 };