Bug 1602483 part 2. Add a window id argument to CheckLoadURIWithPrincipal. r=ckerschb
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 12 Dec 2019 16:41:19 +0000
changeset 569125 822078e02e7af76a28b7cb3ac4f3c336c85ff0e7
parent 569124 6ed047bf1570e98e60eb39f864f85152886dd3fe
child 569126 0559b672dbd97562b7829517e91b3942eadb0bf1
push id12493
push userffxbld-merge
push dateMon, 06 Jan 2020 15:38:57 +0000
treeherdermozilla-beta@63ae456b848d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb
bugs1602483
milestone73.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 1602483 part 2. Add a window id argument to CheckLoadURIWithPrincipal. r=ckerschb Differential Revision: https://phabricator.services.mozilla.com/D56428
caps/nsIScriptSecurityManager.idl
caps/nsScriptSecurityManager.cpp
caps/nsScriptSecurityManager.h
devtools/client/webconsole/test/browser/browser.ini
devtools/client/webconsole/test/browser/browser_webconsole_checkloaduri_errors.js
devtools/client/webconsole/test/browser/test-checkloaduri-failure.html
docshell/base/nsDocShell.cpp
dom/base/LocationBase.cpp
dom/base/nsContentUtils.cpp
dom/base/nsFrameLoader.cpp
dom/base/nsTreeSanitizer.cpp
dom/html/HTMLFormElement.cpp
dom/security/nsContentSecurityManager.cpp
dom/xml/nsXMLContentSink.cpp
dom/xul/nsXULContentSink.cpp
netwerk/protocol/http/nsCORSListenerProxy.cpp
--- a/caps/nsIScriptSecurityManager.idl
+++ b/caps/nsIScriptSecurityManager.idl
@@ -103,20 +103,25 @@ interface nsIScriptSecurityManager : nsI
      * Check that content with principal aPrincipal can load "uri".
      *
      * Will return error code NS_ERROR_DOM_BAD_URI if the load request
      * should be denied.
      *
      * @param aPrincipal the principal identifying the actor causing the load
      * @param uri the URI that is being loaded
      * @param flags the permission set, see above
+     * @param innerWindowID the window ID for error reporting.  If this is 0
+     *        (which happens automatically if it's not passed from JS), errors
+     *        will only appear in the browser console, not window-associated
+     *        consoles like the web console.
      */
     void checkLoadURIWithPrincipal(in nsIPrincipal aPrincipal,
                                    in nsIURI uri,
-                                   in unsigned long flags);
+                                   in unsigned long flags,
+                                   [optional] in unsigned long long innerWindowID);
 
     /**
      * Similar to checkLoadURIWithPrincipal but there are two differences:
      *
      * 1) The URI is a string, not a URI object.
      * 2) This function assumes that the URI may still be subject to fixup (and
      * hence will check whether fixed-up versions of the URI are allowed to
      * load as well); if any of the versions of this URI is not allowed, this
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -513,18 +513,20 @@ nsScriptSecurityManager::CheckSameOrigin
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::CheckLoadURIFromScript(JSContext* cx, nsIURI* aURI) {
   // Get principal of currently executing script.
   MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
   nsIPrincipal* principal = nsContentUtils::SubjectPrincipal();
-  nsresult rv = CheckLoadURIWithPrincipal(principal, aURI,
-                                          nsIScriptSecurityManager::STANDARD);
+  nsresult rv = CheckLoadURIWithPrincipal(
+      // Passing 0 for the window ID here is OK, because we will report a
+      // script-visible exception anyway.
+      principal, aURI, nsIScriptSecurityManager::STANDARD, 0);
   if (NS_SUCCEEDED(rv)) {
     // OK to load
     return NS_OK;
   }
 
   // Report error.
   nsAutoCString spec;
   if (NS_FAILED(aURI->GetAsciiSpec(spec))) return NS_ERROR_FAILURE;
@@ -579,17 +581,18 @@ static bool EqualOrSubdomain(nsIURI* aPr
     rv = NS_MutateURI(probe).SetHost(newHost).Finalize(probe);
     NS_ENSURE_SUCCESS(rv, false);
   }
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
                                                    nsIURI* aTargetURI,
-                                                   uint32_t aFlags) {
+                                                   uint32_t aFlags,
+                                                   uint64_t aInnerWindowID) {
   MOZ_ASSERT(aPrincipal, "CheckLoadURIWithPrincipal must have a principal");
 
   // If someone passes a flag that we don't understand, we should
   // fail, because they may need a security check that we don't
   // provide.
   NS_ENSURE_FALSE(
       aFlags &
           ~(nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
@@ -617,17 +620,18 @@ nsScriptSecurityManager::CheckLoadURIWit
 
   nsCOMPtr<nsIURI> sourceURI;
   aPrincipal->GetURI(getter_AddRefs(sourceURI));
   if (!sourceURI) {
     auto* basePrin = BasePrincipal::Cast(aPrincipal);
     if (basePrin->Is<ExpandedPrincipal>()) {
       auto expanded = basePrin->As<ExpandedPrincipal>();
       for (auto& prin : expanded->AllowList()) {
-        nsresult rv = CheckLoadURIWithPrincipal(prin, aTargetURI, aFlags);
+        nsresult rv =
+            CheckLoadURIWithPrincipal(prin, aTargetURI, aFlags, aInnerWindowID);
         if (NS_SUCCEEDED(rv)) {
           // Allow access if it succeeded with one of the allowlisted principals
           return NS_OK;
         }
       }
       // None of our allowlisted principals worked.
       return NS_ERROR_DOM_BAD_URI;
     }
@@ -668,21 +672,25 @@ nsScriptSecurityManager::CheckLoadURIWit
       targetBaseURI, nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS, &hasFlags);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (hasFlags) {
     // check nothing else in the URI chain has flags that prevent
     // access:
     rv = CheckLoadURIFlags(
         sourceURI, aTargetURI, sourceBaseURI, targetBaseURI, aFlags,
-        aPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0);
+        aPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0,
+        aInnerWindowID);
     NS_ENSURE_SUCCESS(rv, rv);
     // Check the principal is allowed to load the target.
-    // Unfortunately we don't have a window id to work with here...
-    return aPrincipal->CheckMayLoadWithReporting(targetBaseURI, false, 0);
+    if (aFlags & nsIScriptSecurityManager::DONT_REPORT_ERRORS) {
+      return aPrincipal->CheckMayLoad(targetBaseURI, false);
+    }
+    return aPrincipal->CheckMayLoadWithReporting(targetBaseURI, false,
+                                                 aInnerWindowID);
   }
 
   //-- get the source scheme
   nsAutoCString sourceScheme;
   rv = sourceBaseURI->GetScheme(sourceScheme);
   if (NS_FAILED(rv)) return rv;
 
   if (sourceScheme.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME)) {
@@ -789,17 +797,18 @@ nsScriptSecurityManager::CheckLoadURIWit
     // If schemes are not equal, or they're equal but the target URI
     // is different from the source URI and doesn't always allow linking
     // from the same scheme, check if the URI flags of the current target
     // URI allow the current source URI to link to it.
     // The policy is specified by the protocol flags on both URIs.
     if (!schemesMatch || (denySameSchemeLinks && !isSamePage)) {
       return CheckLoadURIFlags(
           currentURI, currentOtherURI, sourceBaseURI, targetBaseURI, aFlags,
-          aPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0);
+          aPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0,
+          aInnerWindowID);
     }
     // Otherwise... check if we can nest another level:
     nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(currentURI);
     nsCOMPtr<nsINestedURI> nestedOtherURI = do_QueryInterface(currentOtherURI);
 
     // If schemes match and neither URI is nested further, we're OK.
     if (!nestedURI && !nestedOtherURI) {
       return NS_OK;
@@ -823,45 +832,48 @@ nsScriptSecurityManager::CheckLoadURIWit
  * (and/or the source URI's innermost ("base") URI), taking into account any
  * nsIScriptSecurityManager flags originally passed to
  * CheckLoadURIWithPrincipal and friends.
  *
  * @return if success, access is allowed. Otherwise, deny access
  */
 nsresult nsScriptSecurityManager::CheckLoadURIFlags(
     nsIURI* aSourceURI, nsIURI* aTargetURI, nsIURI* aSourceBaseURI,
-    nsIURI* aTargetBaseURI, uint32_t aFlags, bool aFromPrivateWindow) {
+    nsIURI* aTargetBaseURI, uint32_t aFlags, bool aFromPrivateWindow,
+    uint64_t aInnerWindowID) {
   // Note that the order of policy checks here is very important!
   // We start from most restrictive and work our way down.
   bool reportErrors = !(aFlags & nsIScriptSecurityManager::DONT_REPORT_ERRORS);
   const char* errorTag = "CheckLoadURIError";
 
   nsAutoCString targetScheme;
   nsresult rv = aTargetBaseURI->GetScheme(targetScheme);
   if (NS_FAILED(rv)) return rv;
 
   // Check for system target URI
   rv = DenyAccessIfURIHasFlags(aTargetURI,
                                nsIProtocolHandler::URI_DANGEROUS_TO_LOAD);
   if (NS_FAILED(rv)) {
     // Deny access, since the origin principal is not system
     if (reportErrors) {
-      ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow);
+      ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow,
+                  aInnerWindowID);
     }
     return rv;
   }
 
   // Used by ExtensionProtocolHandler to prevent loading extension resources
   // in private contexts if the extension does not have permission.
   if (aFromPrivateWindow) {
     rv = DenyAccessIfURIHasFlags(
         aTargetURI, nsIProtocolHandler::URI_DISALLOW_IN_PRIVATE_CONTEXT);
     if (NS_FAILED(rv)) {
       if (reportErrors) {
-        ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow);
+        ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow,
+                    aInnerWindowID);
       }
       return rv;
     }
   }
 
   // Check for chrome target URI
   bool hasFlags = false;
   rv = NS_URIChainHasFlags(aTargetURI, nsIProtocolHandler::URI_IS_UI_RESOURCE,
@@ -918,17 +930,18 @@ nsresult nsScriptSecurityManager::CheckL
           if (accessAllowed) {
             return NS_OK;
           }
         }
       }
     }
 
     if (reportErrors) {
-      ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow);
+      ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow,
+                  aInnerWindowID);
     }
     return NS_ERROR_DOM_BAD_URI;
   }
 
   // Check for target URI pointing to a file
   rv = NS_URIChainHasFlags(aTargetURI, nsIProtocolHandler::URI_IS_LOCAL_FILE,
                            &hasFlags);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -943,17 +956,18 @@ nsresult nsScriptSecurityManager::CheckL
 
     // Allow chrome://
     if (aSourceBaseURI->SchemeIs("chrome")) {
       return NS_OK;
     }
 
     // Nothing else.
     if (reportErrors) {
-      ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow);
+      ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow,
+                  aInnerWindowID);
     }
     return NS_ERROR_DOM_BAD_URI;
   }
 
   // OK, everyone is allowed to load this, since unflagged handlers are
   // deprecated but treated as URI_LOADABLE_BY_ANYONE.  But check whether we
   // need to warn.  At some point we'll want to make this warning into an
   // error and treat unflagged handlers as URI_DANGEROUS_TO_LOAD.
@@ -1045,17 +1059,17 @@ NS_IMETHODIMP
 nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(
     nsIPrincipal* aPrincipal, const nsACString& aTargetURIStr,
     uint32_t aFlags) {
   nsresult rv;
   nsCOMPtr<nsIURI> target;
   rv = NS_NewURI(getter_AddRefs(target), aTargetURIStr);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags);
+  rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags, 0);
   if (rv == NS_ERROR_DOM_BAD_URI) {
     // Don't warn because NS_ERROR_DOM_BAD_URI is one of the expected
     // return values.
     return rv;
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Now start testing fixup -- since aTargetURIStr is a string, not
@@ -1077,17 +1091,17 @@ nsScriptSecurityManager::CheckLoadURIStr
     uint32_t fixupFlags = flags[i];
     if (aPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0) {
       fixupFlags |= nsIURIFixup::FIXUP_FLAG_PRIVATE_CONTEXT;
     }
     rv = fixup->CreateFixupURI(aTargetURIStr, fixupFlags, nullptr,
                                getter_AddRefs(target));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags);
+    rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags, 0);
     if (rv == NS_ERROR_DOM_BAD_URI) {
       // Don't warn because NS_ERROR_DOM_BAD_URI is one of the expected
       // return values.
       return rv;
     }
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -97,17 +97,18 @@ class nsScriptSecurityManager final : pu
   inline void AddSitesToFileURIAllowlist(const nsCString& aSiteList);
 
   nsresult GetChannelResultPrincipal(nsIChannel* aChannel,
                                      nsIPrincipal** aPrincipal,
                                      bool aIgnoreSandboxing);
 
   nsresult CheckLoadURIFlags(nsIURI* aSourceURI, nsIURI* aTargetURI,
                              nsIURI* aSourceBaseURI, nsIURI* aTargetBaseURI,
-                             uint32_t aFlags, bool aFromPrivateWindow);
+                             uint32_t aFlags, bool aFromPrivateWindow,
+                             uint64_t aInnerWindowID);
 
   // Returns the file URI allowlist, initializing it if it has not been
   // initialized.
   const nsTArray<nsCOMPtr<nsIURI>>& EnsureFileURIAllowlist();
 
   nsCOMPtr<nsIPrincipal> mSystemPrincipal;
   bool mPrefInitialized;
   bool mIsJavaScriptEnabled;
--- a/devtools/client/webconsole/test/browser/browser.ini
+++ b/devtools/client/webconsole/test/browser/browser.ini
@@ -35,16 +35,17 @@ support-files =
   test-csp-violation-frame-ancestor-child.html
   test-csp-violation-frame-ancestor-parent.html^headers^
   test-csp-violation-frame-ancestor-parent.html
   test-cspro.html
   test-cspro.html^headers^
   test-iframe-child.html
   test-iframe-parent.html
   test-certificate-messages.html
+  test-checkloaduri-failure.html
   test-click-function-to-source.html
   test-click-function-to-source.js
   test-click-function-to-mapped-source.html
   test-click-function-to-prettyprinted-source.html
   test-click-function-to-source.min.js
   test-click-function-to-source.unmapped.min.js
   test-click-function-to-source.min.js.map
   test-closure-optimized-out.html
@@ -304,16 +305,17 @@ tags = mcb
 [browser_webconsole_block_mixedcontent_securityerrors.js]
 tags = mcb
 [browser_webconsole_cached_messages_cross_domain_iframe.js]
 [browser_webconsole_cached_messages_no_duplicate.js]
 [browser_webconsole_cached_messages.js]
 [browser_webconsole_cd_iframe.js]
 [browser_webconsole_certificate_messages.js]
 skip-if = fission
+[browser_webconsole_checkloaduri_errors.js]
 [browser_webconsole_clear_cache.js]
 [browser_webconsole_click_function_to_source.js]
 [browser_webconsole_click_function_to_mapped_source.js]
 [browser_webconsole_click_function_to_prettyprinted_source.js]
 [browser_webconsole_clickable_urls.js]
 [browser_webconsole_close_unfocused_window.js]
 [browser_webconsole_closing_after_completion.js]
 [browser_webconsole_close_sidebar.js]
copy from devtools/client/webconsole/test/browser/browser_webconsole_same_origin_errors.js
copy to devtools/client/webconsole/test/browser/browser_webconsole_checkloaduri_errors.js
--- a/devtools/client/webconsole/test/browser/browser_webconsole_same_origin_errors.js
+++ b/devtools/client/webconsole/test/browser/browser_webconsole_checkloaduri_errors.js
@@ -1,25 +1,25 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Ensure that same-origin errors are logged to the console.
 
 "use strict";
 
 const TEST_URI =
-  "http://example.com/browser/devtools/client/webconsole/test/browser/test-same-origin-required-load.html";
+  "http://example.com/browser/devtools/client/webconsole/test/browser/test-checkloaduri-failure.html";
 
 add_task(async function() {
   const hud = await openNewTabAndConsole(TEST_URI);
 
-  const targetURL = "http://example.org";
-  const onErrorMessage = waitForMessage(hud, "may not load data");
+  const targetURL = "file:///something-weird";
+  const onErrorMessage = waitForMessage(hud, "may not load or link");
   SpecialPowers.spawn(gBrowser.selectedBrowser, [targetURL], url => {
-    XPCNativeWrapper.unwrap(content).testTrack(url);
+    XPCNativeWrapper.unwrap(content).testImage(url);
   });
   const message = await onErrorMessage;
   const node = message.node;
   ok(
     node.classList.contains("error"),
     "The message has the expected classname"
   );
   ok(
copy from devtools/client/webconsole/test/browser/test-same-origin-required-load.html
copy to devtools/client/webconsole/test/browser/test-checkloaduri-failure.html
--- a/devtools/client/webconsole/test/browser/test-same-origin-required-load.html
+++ b/devtools/client/webconsole/test/browser/test-checkloaduri-failure.html
@@ -1,26 +1,23 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <!doctype html>
 <html>
   <head>
     <meta charset="utf-8">
-    <title>Test loads that are required to be same-origin (no CORS involved)</title>
+    <title>Test loads that fail checkLoadURI</title>
     <script>
-      /* exported testTrack */
+      /* exported testImage */
       "use strict";
 
-      function testTrack(url) {
+      function testImage(url) {
         const body = document.body;
-        const video = document.createElement("video");
-        const track = document.createElement("track");
-        track.src = url;
-        track.default = true;
-        video.append(track);
-        body.append(video);
+        const image = new Image();
+        image.src = url;
+        body.append(image);
       }
     </script>
   </head>
   <body>
   </body>
 </html>
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -5671,17 +5671,18 @@ nsresult nsDocShell::SetupRefreshURIFrom
   }
 
   if (NS_SUCCEEDED(rv)) {
     nsCOMPtr<nsIScriptSecurityManager> securityManager(
         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
     if (NS_SUCCEEDED(rv)) {
       rv = securityManager->CheckLoadURIWithPrincipal(
           aPrincipal, uri,
-          nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT);
+          nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT,
+          aInnerWindowID);
 
       if (NS_SUCCEEDED(rv)) {
         bool isjs = true;
         rv = NS_URIChainHasFlags(
             uri, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
         NS_ENSURE_SUCCESS(rv, rv);
 
         if (isjs) {
--- a/dom/base/LocationBase.cpp
+++ b/dom/base/LocationBase.cpp
@@ -34,19 +34,22 @@ already_AddRefed<nsDocShellLoadState> Lo
 
   // Get security manager.
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   if (NS_WARN_IF(!ssm)) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
-  // Check to see if URI is allowed.
+  // Check to see if URI is allowed.  We're not going to worry about a
+  // window ID here because it's not 100% clear which window's id we
+  // would want, and we're throwing a content-visible exception
+  // anyway.
   nsresult rv = ssm->CheckLoadURIWithPrincipal(
-      &aSubjectPrincipal, aURI, nsIScriptSecurityManager::STANDARD);
+      &aSubjectPrincipal, aURI, nsIScriptSecurityManager::STANDARD, 0);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     nsAutoCString spec;
     aURI->GetSpec(spec);
     aRv.ThrowTypeError<MSG_URL_NOT_LOADABLE>(NS_ConvertUTF8toUTF16(spec));
     return nullptr;
   }
 
   // Make the load's referrer reflect changes to the document's URI caused by
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3155,17 +3155,18 @@ bool nsContentUtils::CanLoadImage(nsIURI
     }
   }
 
   if (appType != nsIDocShell::APP_TYPE_EDITOR) {
     // Editor apps get special treatment here, editors can load images
     // from anywhere.  This allows editor to insert images from file://
     // into documents that are being edited.
     rv = sSecurityManager->CheckLoadURIWithPrincipal(
-        aLoadingPrincipal, aURI, nsIScriptSecurityManager::ALLOW_CHROME);
+        aLoadingPrincipal, aURI, nsIScriptSecurityManager::ALLOW_CHROME,
+        aLoadingDocument->InnerWindowID());
     if (NS_FAILED(rv)) {
       return false;
     }
   }
 
   nsCOMPtr<nsILoadInfo> secCheckLoadInfo = new mozilla::net::LoadInfo(
       aLoadingPrincipal,
       aLoadingPrincipal,  // triggering principal
@@ -5095,17 +5096,18 @@ void nsContentUtils::TriggerLink(nsICont
   }
 
   // Check that this page is allowed to load this URI.
   nsresult proceed = NS_OK;
 
   if (sSecurityManager) {
     uint32_t flag = static_cast<uint32_t>(nsIScriptSecurityManager::STANDARD);
     proceed = sSecurityManager->CheckLoadURIWithPrincipal(
-        aContent->NodePrincipal(), aLinkURI, flag);
+        aContent->NodePrincipal(), aLinkURI, flag,
+        aContent->OwnerDoc()->InnerWindowID());
   }
 
   // Only pass off the click event if the script security manager says it's ok.
   // We need to rest aTargetSpec for forced downloads.
   if (NS_SUCCEEDED(proceed)) {
     // A link/area element with a download attribute is allowed to set
     // a pseudo Content-Disposition header.
     // For security reasons we only allow websites to declare same-origin
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -688,17 +688,18 @@ nsresult nsFrameLoader::CheckURILoad(nsI
 
   // Get our principal
   nsIPrincipal* principal =
       (aTriggeringPrincipal ? aTriggeringPrincipal
                             : mOwnerContent->NodePrincipal());
 
   // Check if we are allowed to load absURL
   nsresult rv = secMan->CheckLoadURIWithPrincipal(
-      principal, aURI, nsIScriptSecurityManager::STANDARD);
+      principal, aURI, nsIScriptSecurityManager::STANDARD,
+      mOwnerContent->OwnerDoc()->InnerWindowID());
   if (NS_FAILED(rv)) {
     return rv;  // We're not
   }
 
   // Bail out if this is an infinite recursion scenario
   if (IsRemoteFrame()) {
     return NS_OK;
   }
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -1246,20 +1246,21 @@ bool nsTreeSanitizer::SanitizeURL(mozill
         }
       } else if (nsGkAtoms::cdgroup_ == aLocalName ||
                  nsGkAtoms::altimg_ == aLocalName ||
                  nsGkAtoms::definitionURL_ == aLocalName) {
         // Gecko doesn't fetch these now and shouldn't in the future, but
         // in case someone goofs with these in the future, let's drop them.
         rv = NS_ERROR_FAILURE;
       } else {
-        rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
+        rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags,
+                                               0);
       }
     } else {
-      rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
+      rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags, 0);
     }
   }
   if (NS_FAILED(rv)) {
     aElement->UnsetAttr(aNamespace, aLocalName, false);
     if (mLogRemovals) {
       LogMessage("Removed unsafe URI from element attribute.",
                  aElement->OwnerDoc(), aElement, aLocalName);
     }
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -1654,17 +1654,18 @@ nsresult HTMLFormElement::GetActionURL(n
   //
   // Verify the URL should be reached
   //
   // Get security manager, check to see if access to action URI is allowed.
   //
   nsIScriptSecurityManager* securityManager =
       nsContentUtils::GetSecurityManager();
   rv = securityManager->CheckLoadURIWithPrincipal(
-      NodePrincipal(), actionURL, nsIScriptSecurityManager::STANDARD);
+      NodePrincipal(), actionURL, nsIScriptSecurityManager::STANDARD,
+      OwnerDoc()->InnerWindowID());
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Potentially the page uses the CSP directive 'upgrade-insecure-requests'. In
   // such a case we have to upgrade the action url from http:// to https://.
   // If the actionURL is not http, then there is nothing to do.
   bool isHttpScheme = actionURL->SchemeIs("http");
   if (isHttpScheme && document->GetUpgradeInsecureRequests(false)) {
     // let's use the old specification before the upgrade for logging
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -304,17 +304,18 @@ static nsresult DoCheckLoadURIChecks(nsI
   if (IsImageLoadInEditorAppType(aLoadInfo)) {
     return NS_OK;
   }
 
   // Only call CheckLoadURIWithPrincipal() using the TriggeringPrincipal and not
   // the LoadingPrincipal when SEC_ALLOW_CROSS_ORIGIN_* security flags are set,
   // to allow, e.g. user stylesheets to load chrome:// URIs.
   return nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
-      aLoadInfo->TriggeringPrincipal(), aURI, aLoadInfo->CheckLoadURIFlags());
+      aLoadInfo->TriggeringPrincipal(), aURI, aLoadInfo->CheckLoadURIFlags(),
+      aLoadInfo->GetInnerWindowID());
 }
 
 static bool URIHasFlags(nsIURI* aURI, uint32_t aURIFlags) {
   bool hasFlags;
   nsresult rv = NS_URIChainHasFlags(aURI, aURIFlags, &hasFlags);
   NS_ENSURE_SUCCESS(rv, false);
 
   return hasFlags;
@@ -950,17 +951,17 @@ nsContentSecurityManager::AsyncOnChannel
     aOldChannel->Cancel(NS_ERROR_CONTENT_BLOCKED);
     return NS_ERROR_CONTENT_BLOCKED;
   }
 
   const uint32_t flags =
       nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
       nsIScriptSecurityManager::DISALLOW_SCRIPT;
   rv = nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
-      oldPrincipal, newURI, flags);
+      oldPrincipal, newURI, flags, loadInfo->GetInnerWindowID());
   NS_ENSURE_SUCCESS(rv, rv);
 
   aCb->OnRedirectVerifyCallback(NS_OK);
   return NS_OK;
 }
 
 static void AddLoadFlags(nsIRequest* aRequest, nsLoadFlags aNewFlags) {
   nsLoadFlags flags;
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -680,18 +680,19 @@ nsresult nsXMLContentSink::MaybeProcessX
 
   nsCOMPtr<nsIURI> url;
   nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nullptr,
                           mDocument->GetDocBaseURI());
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Do security check
   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
-  rv = secMan->CheckLoadURIWithPrincipal(
-      mDocument->NodePrincipal(), url, nsIScriptSecurityManager::ALLOW_CHROME);
+  rv = secMan->CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), url,
+                                         nsIScriptSecurityManager::ALLOW_CHROME,
+                                         mDocument->InnerWindowID());
   NS_ENSURE_SUCCESS(rv, NS_OK);
 
   nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
       new net::LoadInfo(mDocument->NodePrincipal(),  // loading principal
                         mDocument->NodePrincipal(),  // triggering principal
                         aProcessingInstruction,
                         nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
                         nsIContentPolicy::TYPE_XSLT);
--- a/dom/xul/nsXULContentSink.cpp
+++ b/dom/xul/nsXULContentSink.cpp
@@ -754,17 +754,17 @@ nsresult XULContentSinkImpl::OpenScript(
       if (!mSecMan)
         mSecMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
       if (NS_SUCCEEDED(rv)) {
         nsCOMPtr<Document> doc = do_QueryReferent(mDocument, &rv);
 
         if (NS_SUCCEEDED(rv)) {
           rv = mSecMan->CheckLoadURIWithPrincipal(
               doc->NodePrincipal(), script->mSrcURI,
-              nsIScriptSecurityManager::ALLOW_CHROME);
+              nsIScriptSecurityManager::ALLOW_CHROME, doc->InnerWindowID());
         }
       }
     }
 
     if (NS_FAILED(rv)) {
       return rv;
     }
 
--- a/netwerk/protocol/http/nsCORSListenerProxy.cpp
+++ b/netwerk/protocol/http/nsCORSListenerProxy.cpp
@@ -899,22 +899,22 @@ nsresult nsCORSListenerProxy::UpdateChan
   }
 
   // TODO: Bug 1353683
   // consider calling SetBlockedRequest in nsCORSListenerProxy::UpdateChannel
   //
   // Check that the uri is ok to load
   uint32_t flags = loadInfo->CheckLoadURIFlags();
   rv = nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
-      mRequestingPrincipal, uri, flags);
+      mRequestingPrincipal, uri, flags, loadInfo->GetInnerWindowID());
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (originalURI != uri) {
     rv = nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
-        mRequestingPrincipal, originalURI, flags);
+        mRequestingPrincipal, originalURI, flags, loadInfo->GetInnerWindowID());
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (!mHasBeenCrossSite &&
       NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(uri, false)) &&
       (originalURI == uri ||
        NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(originalURI, false)))) {
     return NS_OK;