From 1b4c4256ee7705724b02919b4d432b2a391bcd04 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 18:51:38 +0200
Subject: moebius#223: Consider blocking top level window data: URIs (part 1/3
 without tests)

https://github.com/MoonchildProductions/moebius/pull/223
---
 docshell/base/nsDocShell.cpp                       | 16 +++-
 docshell/base/nsDocShell.h                         |  1 +
 .../en-US/chrome/security/security.properties      |  3 +
 dom/security/nsContentSecurityManager.cpp          | 84 ++++++++++++++++++++
 dom/security/nsContentSecurityManager.h            |  5 ++
 dom/security/test/general/browser.ini              |  5 ++
 .../browser_test_toplevel_data_navigations.js      | 54 +++++++++++++
 .../file_block_toplevel_data_navigation.html       | 14 ++++
 .../file_block_toplevel_data_navigation2.html      | 29 +++++++
 .../file_block_toplevel_data_navigation3.html      | 13 ++++
 .../general/file_block_toplevel_data_redirect.sjs  | 14 ++++
 .../general/file_toplevel_data_meta_redirect.html  | 10 +++
 .../general/file_toplevel_data_navigations.sjs     | 14 ++++
 dom/security/test/general/mochitest.ini            | 12 +++
 .../test/general/test_allow_opening_data_json.html | 39 ++++++++++
 .../test/general/test_allow_opening_data_pdf.html  | 41 ++++++++++
 .../test_block_toplevel_data_img_navigation.html   | 51 ++++++++++++
 .../test_block_toplevel_data_navigation.html       | 90 ++++++++++++++++++++++
 dom/security/test/moz.build                        |  1 +
 modules/libpref/init/all.js                        |  6 ++
 netwerk/base/nsIOService.cpp                       | 10 +++
 netwerk/base/nsIOService.h                         |  4 +
 22 files changed, 515 insertions(+), 1 deletion(-)
 create mode 100644 dom/security/test/general/browser.ini
 create mode 100644 dom/security/test/general/browser_test_toplevel_data_navigations.js
 create mode 100644 dom/security/test/general/file_block_toplevel_data_navigation.html
 create mode 100644 dom/security/test/general/file_block_toplevel_data_navigation2.html
 create mode 100644 dom/security/test/general/file_block_toplevel_data_navigation3.html
 create mode 100644 dom/security/test/general/file_block_toplevel_data_redirect.sjs
 create mode 100644 dom/security/test/general/file_toplevel_data_meta_redirect.html
 create mode 100644 dom/security/test/general/file_toplevel_data_navigations.sjs
 create mode 100644 dom/security/test/general/test_allow_opening_data_json.html
 create mode 100644 dom/security/test/general/test_allow_opening_data_pdf.html
 create mode 100644 dom/security/test/general/test_block_toplevel_data_img_navigation.html
 create mode 100644 dom/security/test/general/test_block_toplevel_data_navigation.html

diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 58c182cbb..ae97a7c9e 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -42,6 +42,7 @@
 
 #include "nsArray.h"
 #include "nsArrayUtils.h"
+#include "nsContentSecurityManager.h"
 #include "nsICaptivePortalService.h"
 #include "nsIDOMStorage.h"
 #include "nsIContentViewer.h"
@@ -9884,6 +9885,15 @@ nsDocShell::InternalLoad(nsIURI* aURI,
     contentType = nsIContentPolicy::TYPE_DOCUMENT;
   }
 
+  if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
+        aURI,
+        contentType,
+        aTriggeringPrincipal,
+        (aLoadType == LOAD_NORMAL_EXTERNAL))) {
+    // logging to console happens within AllowTopLevelNavigationToDataURI
+    return NS_OK;
+  }
+
   // If there's no targetDocShell, that means we are about to create a new window,
   // perform a content policy check before creating the window.
   if (!targetDocShell) {
@@ -10232,8 +10242,11 @@ nsDocShell::InternalLoad(nsIURI* aURI,
     }
   }
 
+  bool loadFromExternal = false;
+
   // Before going any further vet loads initiated by external programs.
   if (aLoadType == LOAD_NORMAL_EXTERNAL) {
+    loadFromExternal = true;
     // Disallow external chrome: loads targetted at content windows
     bool isChrome = false;
     if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome) {
@@ -10724,7 +10737,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
                         nsINetworkPredictor::PREDICT_LOAD, this, nullptr);
 
   nsCOMPtr<nsIRequest> req;
-  rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, aReferrer,
+  rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, loadFromExternal, aReferrer,
                  !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
                  aReferrerPolicy,
                  aTriggeringPrincipal, principalToInherit, aTypeHint,
@@ -10804,6 +10817,7 @@ nsresult
 nsDocShell::DoURILoad(nsIURI* aURI,
                       nsIURI* aOriginalURI,
                       bool aLoadReplace,
+                      bool aLoadFromExternal,
                       nsIURI* aReferrerURI,
                       bool aSendReferrer,
                       uint32_t aReferrerPolicy,
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index 3ca9e0b34..549d7f540 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -369,6 +369,7 @@ protected:
   nsresult DoURILoad(nsIURI* aURI,
                      nsIURI* aOriginalURI,
                      bool aLoadReplace,
+                     bool aLoadFromExternal,
                      nsIURI* aReferrer,
                      bool aSendReferrer,
                      uint32_t aReferrerPolicy,
diff --git a/dom/locales/en-US/chrome/security/security.properties b/dom/locales/en-US/chrome/security/security.properties
index 8b66cc265..c0b80996c 100644
--- a/dom/locales/en-US/chrome/security/security.properties
+++ b/dom/locales/en-US/chrome/security/security.properties
@@ -81,3 +81,6 @@ MimeTypeMismatch=The resource from “%1$S” was blocked due to MIME type misma
 XCTOHeaderValueMissing=X-Content-Type-Options header warning: value was “%1$S”; did you mean to send “nosniff”?
 
 BlockScriptWithWrongMimeType=Script from “%1$S” was blocked because of a disallowed MIME type.
+
+# LOCALIZATION NOTE: Do not translate "data: URI".
+BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”)
diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp
index c4e1ed8e1..069e7d6a7 100644
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -1,13 +1,16 @@
 #include "nsContentSecurityManager.h"
+#include "nsEscape.h"
 #include "nsIChannel.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsIStreamListener.h"
 #include "nsILoadInfo.h"
+#include "nsIOService.h"
 #include "nsContentUtils.h"
 #include "nsCORSListenerProxy.h"
 #include "nsIStreamListener.h"
 #include "nsIDocument.h"
 #include "nsMixedContentBlocker.h"
+#include "nsNullPrincipal.h"
 
 #include "mozilla/dom/Element.h"
 
@@ -15,6 +18,66 @@ NS_IMPL_ISUPPORTS(nsContentSecurityManager,
                   nsIContentSecurityManager,
                   nsIChannelEventSink)
 
+/* static */ bool
+nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
+  nsIURI* aURI,
+  nsContentPolicyType aContentPolicyType,
+  nsIPrincipal* aTriggeringPrincipal,
+  bool aLoadFromExternal)
+{
+  // Let's block all toplevel document navigations to a data: URI.
+  // In all cases where the toplevel document is navigated to a
+  // data: URI the triggeringPrincipal is a codeBasePrincipal, or
+  // a NullPrincipal. In other cases, e.g. typing a data: URL into
+  // the URL-Bar, the triggeringPrincipal is a SystemPrincipal;
+  // we don't want to block those loads. Only exception, loads coming
+  // from an external applicaton (e.g. Thunderbird) don't load
+  // using a codeBasePrincipal, but we want to block those loads.
+  if (!mozilla::net::nsIOService::BlockToplevelDataUriNavigations()) {
+    return true;
+  }
+  if (aContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT) {
+    return true;
+  }
+  bool isDataURI =
+    (NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI);
+  if (!isDataURI) {
+    return true;
+  }
+  // Whitelist data: images as long as they are not SVGs
+  nsAutoCString filePath;
+  aURI->GetFilePath(filePath);
+  if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/")) &&
+      !StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/svg+xml"))) {
+    return true;
+  }
+  // Whitelist data: PDFs and JSON
+  if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/pdf")) ||
+      StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/json"))) {
+    return true;
+  }
+  if (!aLoadFromExternal &&
+      nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal)) {
+    return true;
+  }
+  nsAutoCString dataSpec;
+  aURI->GetSpec(dataSpec);
+  if (dataSpec.Length() > 50) {
+    dataSpec.Truncate(50);
+    dataSpec.AppendLiteral("...");
+  }
+  NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec));
+  const char16_t* params[] = { specUTF16.get() };
+  nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
+                                  NS_LITERAL_CSTRING("DATA_URI_BLOCKED"),
+                                  // no doc available, log to browser console
+                                  nullptr,
+                                  nsContentUtils::eSECURITY_PROPERTIES,
+                                  "BlockTopLevelDataURINavigation",
+                                  params, ArrayLength(params));
+  return false;
+}
+
 static nsresult
 ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
 {
@@ -478,6 +541,27 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
     }
   }
 
+  // Redirecting to a toplevel data: URI is not allowed, hence we pass
+  // a NullPrincipal as the TriggeringPrincipal to
+  // AllowTopLevelNavigationToDataURI() which definitely blocks any
+  // data: URI load.
+  nsCOMPtr<nsILoadInfo> newLoadInfo = aNewChannel->GetLoadInfo();
+  if (newLoadInfo) {
+    nsCOMPtr<nsIURI> uri;
+    nsresult rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(uri));
+    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsIPrincipal> nullTriggeringPrincipal = nsNullPrincipal::Create();
+    if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
+          uri,
+          newLoadInfo->GetExternalContentPolicyType(),
+          nullTriggeringPrincipal,
+          false)) {
+        // logging to console happens within AllowTopLevelNavigationToDataURI
+      aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
+      return NS_ERROR_DOM_BAD_URI;
+    }
+  }
+
   // Also verify that the redirecting server is allowed to redirect to the
   // given URI
   nsCOMPtr<nsIPrincipal> oldPrincipal;
diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h
index 912c0e89f..09b6c86aa 100644
--- a/dom/security/nsContentSecurityManager.h
+++ b/dom/security/nsContentSecurityManager.h
@@ -32,6 +32,11 @@ public:
   static nsresult doContentSecurityCheck(nsIChannel* aChannel,
                                          nsCOMPtr<nsIStreamListener>& aInAndOutListener);
 
+  static bool AllowTopLevelNavigationToDataURI(nsIURI* aURI,
+                                               nsContentPolicyType aContentPolicyType,
+                                               nsIPrincipal* aTriggeringPrincipal,
+                                               bool aLoadFromExternal);
+
 private:
   static nsresult CheckChannel(nsIChannel* aChannel);
 
diff --git a/dom/security/test/general/browser.ini b/dom/security/test/general/browser.ini
new file mode 100644
index 000000000..97ddae3bf
--- /dev/null
+++ b/dom/security/test/general/browser.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+[browser_test_toplevel_data_navigations.js]
+support-files =
+  file_toplevel_data_navigations.sjs
+  file_toplevel_data_meta_redirect.html
diff --git a/dom/security/test/general/browser_test_toplevel_data_navigations.js b/dom/security/test/general/browser_test_toplevel_data_navigations.js
new file mode 100644
index 000000000..a13a6350e
--- /dev/null
+++ b/dom/security/test/general/browser_test_toplevel_data_navigations.js
@@ -0,0 +1,54 @@
+/* eslint-disable mozilla/no-arbitrary-setTimeout */
+
+"use strict";
+
+const kDataBody = "toplevel navigation to data: URI allowed";
+const kDataURI = "data:text/html,<body>" + kDataBody + "</body>";
+const kTestPath = getRootDirectory(gTestPath)
+                  .replace("chrome://mochitests/content", "http://example.com")
+const kRedirectURI = kTestPath + "file_toplevel_data_navigations.sjs";
+const kMetaRedirectURI = kTestPath + "file_toplevel_data_meta_redirect.html";
+
+add_task(async function test_nav_data_uri() {
+  await SpecialPowers.pushPrefEnv({
+    "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]],
+  });
+  await BrowserTestUtils.withNewTab(kDataURI, async function(browser) {
+    await ContentTask.spawn(gBrowser.selectedBrowser, {kDataBody}, async function({kDataBody}) { // eslint-disable-line
+     is(content.document.body.innerHTML, kDataBody,
+        "data: URI navigation from system should be allowed");
+    });
+  });
+});
+
+add_task(async function test_nav_data_uri_redirect() {
+  await SpecialPowers.pushPrefEnv({
+    "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]],
+  });
+  let tab = BrowserTestUtils.addTab(gBrowser, kRedirectURI);
+  registerCleanupFunction(async function() {
+    await BrowserTestUtils.removeTab(tab);
+  });
+  // wait to make sure data: URI did not load before checking that it got blocked
+  await new Promise(resolve => setTimeout(resolve, 500));
+  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
+    is(content.document.body.innerHTML, "",
+       "data: URI navigation after server redirect should be blocked");
+  });
+});
+
+add_task(async function test_nav_data_uri_meta_redirect() {
+  await SpecialPowers.pushPrefEnv({
+    "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]],
+  });
+  let tab = BrowserTestUtils.addTab(gBrowser, kMetaRedirectURI);
+  registerCleanupFunction(async function() {
+    await BrowserTestUtils.removeTab(tab);
+  });
+  // wait to make sure data: URI did not load before checking that it got blocked
+  await new Promise(resolve => setTimeout(resolve, 500));
+  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
+    is(content.document.body.innerHTML, "",
+       "data: URI navigation after meta redirect should be blocked");
+  });
+});
diff --git a/dom/security/test/general/file_block_toplevel_data_navigation.html b/dom/security/test/general/file_block_toplevel_data_navigation.html
new file mode 100644
index 000000000..5fbfdfdef
--- /dev/null
+++ b/dom/security/test/general/file_block_toplevel_data_navigation.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Toplevel data navigation</title>
+</head>
+<body>
+test1: clicking data: URI tries to navigate window<br/>
+<a id="testlink" href="data:text/html,<body>toplevel data: URI navigations should be blocked</body>">click me</a>
+<script>
+  document.getElementById('testlink').click();
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/file_block_toplevel_data_navigation2.html b/dom/security/test/general/file_block_toplevel_data_navigation2.html
new file mode 100644
index 000000000..e0308e1ae
--- /dev/null
+++ b/dom/security/test/general/file_block_toplevel_data_navigation2.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Toplevel data navigation</title>
+</head>
+<body>
+test2: data: URI in iframe tries to window.open(data:, _blank);<br/>
+<iframe id="testFrame" src=""></iframe>
+<script>
+  let DATA_URI = `data:text/html,<body><script>
+    var win = window.open("data:text/html,<body>toplevel data: URI navigations should be blocked</body>", "_blank");
+    setTimeout(function () {
+      var result = win.document.body.innerHTML === "" ? "blocked" : "navigated";
+      parent.postMessage(result, "*");
+      win.close();
+    }, 1000);
+    <\/script></body>`;
+
+  window.addEventListener("message", receiveMessage);
+  function receiveMessage(event) {
+    window.removeEventListener("message", receiveMessage);
+    // propagate the information back to the caller
+    window.opener.postMessage(event.data, "*");
+  }
+  document.getElementById('testFrame').src = DATA_URI;
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/file_block_toplevel_data_navigation3.html b/dom/security/test/general/file_block_toplevel_data_navigation3.html
new file mode 100644
index 000000000..34aeddab3
--- /dev/null
+++ b/dom/security/test/general/file_block_toplevel_data_navigation3.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Toplevel data navigation</title>
+</head>
+<body>
+test3: performing data: URI navigation through win.loc.href<br/>
+<script>
+  window.location.href = "data:text/html,<body>toplevel data: URI navigations should be blocked</body>";
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/file_block_toplevel_data_redirect.sjs b/dom/security/test/general/file_block_toplevel_data_redirect.sjs
new file mode 100644
index 000000000..64e294cab
--- /dev/null
+++ b/dom/security/test/general/file_block_toplevel_data_redirect.sjs
@@ -0,0 +1,14 @@
+// Custom *.sjs file specifically for the needs of Bug:
+// Bug 1394554 - Block toplevel data: URI navigations after redirect
+
+var DATA_URI =
+  "<body>toplevel data: URI navigations after redirect should be blocked</body>";
+
+function handleRequest(request, response)
+{
+  // avoid confusing cache behaviors
+  response.setHeader("Cache-Control", "no-cache", false);
+
+  response.setStatusLine("1.1", 302, "Found");
+  response.setHeader("Location", "data:text/html," + escape(DATA_URI), false);
+}
diff --git a/dom/security/test/general/file_toplevel_data_meta_redirect.html b/dom/security/test/general/file_toplevel_data_meta_redirect.html
new file mode 100644
index 000000000..f4f5deb52
--- /dev/null
+++ b/dom/security/test/general/file_toplevel_data_meta_redirect.html
@@ -0,0 +1,10 @@
+<html>
+<body>
+<head>
+  <meta http-equiv="refresh"
+        content="0; url='data:text/html,<body>toplevel meta redirect to data: URI should be blocked</body>'">
+</head>
+<body>
+Meta Redirect to data: URI
+</body>
+</html>
diff --git a/dom/security/test/general/file_toplevel_data_navigations.sjs b/dom/security/test/general/file_toplevel_data_navigations.sjs
new file mode 100644
index 000000000..501b833e5
--- /dev/null
+++ b/dom/security/test/general/file_toplevel_data_navigations.sjs
@@ -0,0 +1,14 @@
+// Custom *.sjs file specifically for the needs of Bug:
+// Bug 1394554 - Block toplevel data: URI navigations after redirect
+
+var DATA_URI =
+  "data:text/html,<body>toplevel data: URI navigations after redirect should be blocked</body>";
+
+function handleRequest(request, response)
+{
+  // avoid confusing cache behaviors
+  response.setHeader("Cache-Control", "no-cache", false);
+
+  response.setStatusLine("1.1", 302, "Found");
+  response.setHeader("Location", DATA_URI, false);
+}
diff --git a/dom/security/test/general/mochitest.ini b/dom/security/test/general/mochitest.ini
index 70c0c9fb6..f3bcca072 100644
--- a/dom/security/test/general/mochitest.ini
+++ b/dom/security/test/general/mochitest.ini
@@ -3,7 +3,19 @@ support-files =
   file_contentpolicytype_targeted_link_iframe.sjs
   file_nosniff_testserver.sjs
   file_block_script_wrong_mime_server.sjs
+  file_block_toplevel_data_navigation.html
+  file_block_toplevel_data_navigation2.html
+  file_block_toplevel_data_navigation3.html
+  file_block_toplevel_data_redirect.sjs
 
 [test_contentpolicytype_targeted_link_iframe.html]
 [test_nosniff.html]
 [test_block_script_wrong_mime.html]
+[test_block_toplevel_data_navigation.html]
+skip-if = toolkit == 'android' # intermittent failure
+[test_block_toplevel_data_img_navigation.html]
+skip-if = toolkit == 'android' # intermittent failure
+[test_allow_opening_data_pdf.html]
+skip-if = toolkit == 'android'
+[test_allow_opening_data_json.html]
+skip-if = toolkit == 'android'
diff --git a/dom/security/test/general/test_allow_opening_data_json.html b/dom/security/test/general/test_allow_opening_data_json.html
new file mode 100644
index 000000000..1530a24e8
--- /dev/null
+++ b/dom/security/test/general/test_allow_opening_data_json.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Bug 1403814: Allow toplevel data URI navigation data:application/json</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function test_toplevel_data_json() {
+  const DATA_JSON = "data:application/json,{'my_json_key':'my_json_value'}";
+
+  let win = window.open(DATA_JSON);
+  let wrappedWin = SpecialPowers.wrap(win);
+
+  // Unfortunately we can't detect whether the JSON has loaded or not using some
+  // event, hence we are constantly polling location.href till we see that
+  // the data: URI appears. Test times out on failure.
+  var jsonLoaded = setInterval(function() {
+    if (wrappedWin.document.location.href.startsWith("data:application/json")) {
+      clearInterval(jsonLoaded);
+      ok(true, "navigating to data:application/json allowed");
+      wrappedWin.close();
+      SimpleTest.finish();
+    }
+  }, 200);
+}
+
+SpecialPowers.pushPrefEnv({
+  set: [["security.data_uri.block_toplevel_data_uri_navigations", true]]
+}, test_toplevel_data_json);
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/test_allow_opening_data_pdf.html b/dom/security/test/general/test_allow_opening_data_pdf.html
new file mode 100644
index 000000000..6b51fe57b
--- /dev/null
+++ b/dom/security/test/general/test_allow_opening_data_pdf.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Bug 1398692: Allow toplevel navigation to a data:application/pdf</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function test_toplevel_data_pdf() {
+  // The PDF contains one page and it is a 3/72" square, the minimum allowed by the spec
+  const DATA_PDF =
+    "data:application/pdf;base64,JVBERi0xLjANCjEgMCBvYmo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFI+PmVuZG9iaiAyIDAgb2JqPDwvVHlwZS9QYWdlcy9LaWRzWzMgMCBSXS9Db3VudCAxPj5lbmRvYmogMyAwIG9iajw8L1R5cGUvUGFnZS9NZWRpYUJveFswIDAgMyAzXT4+ZW5kb2JqDQp4cmVmDQowIDQNCjAwMDAwMDAwMDAgNjU1MzUgZg0KMDAwMDAwMDAxMCAwMDAwMCBuDQowMDAwMDAwMDUzIDAwMDAwIG4NCjAwMDAwMDAxMDIgMDAwMDAgbg0KdHJhaWxlcjw8L1NpemUgNC9Sb290IDEgMCBSPj4NCnN0YXJ0eHJlZg0KMTQ5DQolRU9G";
+
+  let win = window.open(DATA_PDF);
+  let wrappedWin = SpecialPowers.wrap(win);
+
+  // Unfortunately we can't detect whether the PDF has loaded or not using some
+  // event, hence we are constantly polling location.href till we see that
+  // the data: URI appears. Test times out on failure.
+  var pdfLoaded = setInterval(function() {
+    if (wrappedWin.document.location.href.startsWith("data:application/pdf")) {
+      clearInterval(pdfLoaded);
+      ok(true, "navigating to data:application/pdf allowed");
+      wrappedWin.close();
+      SimpleTest.finish();
+    }
+  }, 200);
+}
+
+SpecialPowers.pushPrefEnv({
+  set: [["security.data_uri.block_toplevel_data_uri_navigations", true]]
+}, test_toplevel_data_pdf);
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/test_block_toplevel_data_img_navigation.html b/dom/security/test/general/test_block_toplevel_data_img_navigation.html
new file mode 100644
index 000000000..2b8f62760
--- /dev/null
+++ b/dom/security/test/general/test_block_toplevel_data_img_navigation.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Bug 1396798: Do not block toplevel data: navigation to image (except svgs)</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+SpecialPowers.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true);
+SimpleTest.registerCleanupFunction(() => {
+  SpecialPowers.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations");
+});
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("have to test that top level data:image loading is blocked/allowed");
+
+function test_toplevel_data_image() {
+  const DATA_PNG =
+    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
+  let win1 = window.open(DATA_PNG);
+  let wrappedWin1 = SpecialPowers.wrap(win1);
+  setTimeout(function () {
+    let images = wrappedWin1.document.getElementsByTagName('img'); 
+    is(images.length, 1, "Loading data:image/png should be allowed");
+    is(images[0].src, DATA_PNG, "Sanity: img src matches");
+    wrappedWin1.close();
+    test_toplevel_data_image_svg();
+  }, 1000);
+}
+
+function test_toplevel_data_image_svg() {
+  const DATA_SVG =
+    "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==";
+  let win2 = window.open(DATA_SVG);
+  let wrappedWin2 = SpecialPowers.wrap(win2);
+  setTimeout(function () {
+    isnot(wrappedWin2.document.documentElement.localName, "svg",
+          "Loading data:image/svg+xml should be blocked");
+    wrappedWin2.close();
+    SimpleTest.finish();
+  }, 1000);
+}
+
+// fire up the tests
+test_toplevel_data_image();
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/test_block_toplevel_data_navigation.html b/dom/security/test/general/test_block_toplevel_data_navigation.html
new file mode 100644
index 000000000..fc91f2ec0
--- /dev/null
+++ b/dom/security/test/general/test_block_toplevel_data_navigation.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Bug 1331351 - Block top level window data: URI navigations</title>
+  <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+SpecialPowers.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true);
+SimpleTest.registerCleanupFunction(() => {
+  SpecialPowers.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations");
+});
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("have to test that top level data: URI navgiation is blocked");
+
+function test1() {
+  // simple data: URI click navigation should be prevented
+  let TEST_FILE = "file_block_toplevel_data_navigation.html";
+  let win1 = window.open(TEST_FILE);
+  var readyStateCheckInterval = setInterval(function() {
+    let state = win1.document.readyState;
+    if (state === "interactive" || state === "complete") {
+      clearInterval(readyStateCheckInterval);
+      ok(win1.document.body.innerHTML.indexOf("test1:") !== -1,
+         "toplevel data: URI navigation through click() should be blocked");
+      win1.close();
+      test2();
+    }
+  }, 200);
+}
+
+function test2() {
+  // data: URI in iframe which opens data: URI in _blank should be blocked 
+  let win2 = window.open("file_block_toplevel_data_navigation2.html");
+  window.addEventListener("message", receiveMessage);
+  function receiveMessage(event) {
+    window.removeEventListener("message", receiveMessage);
+    is(event.data, "blocked",
+      "data: URI navigation using _blank from data: URI should be blocked");
+    win2.close();
+    test3();
+  }
+}
+
+function test3() {
+  // navigating to a data: URI using window.location.href should be blocked
+  let win3 = window.open("file_block_toplevel_data_navigation3.html");
+  setTimeout(function () {
+    ok(win3.document.body.innerHTML.indexOf("test3:") !== -1,
+      "data: URI navigation through win.loc.href should be blocked");
+    win3.close();
+    test4();
+  }, 1000);
+}
+
+function test4() {
+  // navigating to a data: URI using window.open() should be blocked
+  let win4 = window.open("data:text/html,<body>toplevel data: URI navigations should be blocked</body>");
+  setTimeout(function () {
+    // Please note that the data: URI will be displayed in the URL-Bar but not
+    // loaded, hence we rather rely on document.body than document.location
+    is(win4.document.body.innerHTML, "",
+      "navigating to a data: URI using window.open() should be blocked");
+    test5();
+  }, 1000);
+}
+
+function test5() {
+  // navigating to a URI which redirects to a data: URI using window.open() should be blocked
+  let win5 = window.open("file_block_toplevel_data_redirect.sjs");
+  setTimeout(function () {
+    // Please note that the data: URI will be displayed in the URL-Bar but not
+    // loaded, hence we rather rely on document.body than document.location
+    is(SpecialPowers.wrap(win5).document.body.innerHTML, "",
+      "navigating to URI which redirects to a data: URI using window.open() should be blocked");
+    win5.close();
+    SimpleTest.finish();
+  }, 1000);
+}
+
+// fire up the tests
+test1();
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/moz.build b/dom/security/test/moz.build
index ddb4e9b89..946959dee 100644
--- a/dom/security/test/moz.build
+++ b/dom/security/test/moz.build
@@ -27,5 +27,6 @@ MOCHITEST_CHROME_MANIFESTS += [
 BROWSER_CHROME_MANIFESTS += [
     'contentverifier/browser.ini',
     'csp/browser.ini',
+    'general/browser.ini',
     'hsts/browser.ini',
 ]
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 182de4a11..ccc59269b 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5564,6 +5564,12 @@ pref("security.mixed_content.use_hsts", true);
 // Approximately 1 week default cache for HSTS priming failures
 pref ("security.mixed_content.hsts_priming_cache_timeout", 10080);
 
+// TODO: Bug 1380959: Block toplevel data: URI navigations
+// If true, all toplevel data: URI navigations will be blocked.
+// Please note that manually entering a data: URI in the
+// URL-Bar will not be blocked when flipping this pref.
+pref("security.data_uri.block_toplevel_data_uri_navigations", false);
+
 // Disable Storage api in release builds.
 #ifdef NIGHTLY_BUILD
 pref("dom.storageManager.enabled", true);
diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp
index 0da79c18a..8b7f31f99 100644
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -173,6 +173,8 @@ uint32_t   nsIOService::gDefaultSegmentCount = 24;
 
 bool nsIOService::sTelemetryEnabled = false;
 
+bool nsIOService::sBlockToplevelDataUriNavigations = false;
+
 ////////////////////////////////////////////////////////////////////////////////
 
 nsIOService::nsIOService()
@@ -251,6 +253,8 @@ nsIOService::Init()
         NS_WARNING("failed to get observer service");
 
     Preferences::AddBoolVarCache(&sTelemetryEnabled, "toolkit.telemetry.enabled", false);
+    Preferences::AddBoolVarCache(&sBlockToplevelDataUriNavigations,
+                                 "security.data_uri.block_toplevel_data_uri_navigations", false);
     Preferences::AddBoolVarCache(&mOfflineMirrorsConnectivity, OFFLINE_MIRRORS_CONNECTIVITY, true);
 
     gIOService = this;
@@ -1876,5 +1880,11 @@ nsIOService::SpeculativeAnonymousConnect2(nsIURI *aURI,
     return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, true);
 }
 
+/*static*/ bool
+nsIOService::BlockToplevelDataUriNavigations()
+{
+  return sBlockToplevelDataUriNavigations;
+}
+
 } // namespace net
 } // namespace mozilla
diff --git a/netwerk/base/nsIOService.h b/netwerk/base/nsIOService.h
index 7ac23b791..e592c4d1c 100644
--- a/netwerk/base/nsIOService.h
+++ b/netwerk/base/nsIOService.h
@@ -95,6 +95,8 @@ public:
 
     bool IsLinkUp();
 
+    static bool BlockToplevelDataUriNavigations();
+
     // Used to trigger a recheck of the captive portal status
     nsresult RecheckCaptivePortal();
 private:
@@ -176,6 +178,8 @@ private:
 
     static bool                          sTelemetryEnabled;
 
+    static bool                          sBlockToplevelDataUriNavigations;
+
     // These timestamps are needed for collecting telemetry on PR_Connect,
     // PR_ConnectContinue and PR_Close blocking time.  If we spend very long
     // time in any of these functions we want to know if and what network
-- 
cgit v1.2.3


From f1e5578718ea8883438cfea06d3c55d25f5c0278 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 19:03:22 +0200
Subject: moebius#226: Consider blocking top level window data: URIs (part 2/2
 without tests)

https://github.com/MoonchildProductions/moebius/pull/226
---
 docshell/base/nsDSURIContentListener.cpp           |  9 ++++
 docshell/base/nsDocShell.cpp                       | 10 +---
 dom/security/nsContentSecurityManager.cpp          | 59 +++++++++-------------
 dom/security/nsContentSecurityManager.h            |  5 +-
 dom/security/test/general/browser.ini              |  6 +++
 .../test/general/browser_test_data_download.js     | 37 ++++++++++++++
 .../test/general/browser_test_data_text_csv.js     | 37 ++++++++++++++
 dom/security/test/general/file_data_download.html  | 14 +++++
 dom/security/test/general/file_data_text_csv.html  | 14 +++++
 .../test_block_toplevel_data_img_navigation.html   | 18 ++++---
 .../test_block_toplevel_data_navigation.html       | 16 +++---
 ipc/glue/BackgroundUtils.cpp                       |  2 +
 netwerk/base/LoadInfo.cpp                          | 23 +++++++++
 netwerk/base/LoadInfo.h                            |  2 +
 netwerk/base/nsILoadInfo.idl                       |  7 +++
 netwerk/ipc/NeckoChannelParams.ipdlh               |  1 +
 16 files changed, 194 insertions(+), 66 deletions(-)
 create mode 100644 dom/security/test/general/browser_test_data_download.js
 create mode 100644 dom/security/test/general/browser_test_data_text_csv.js
 create mode 100644 dom/security/test/general/file_data_download.html
 create mode 100644 dom/security/test/general/file_data_text_csv.html

diff --git a/docshell/base/nsDSURIContentListener.cpp b/docshell/base/nsDSURIContentListener.cpp
index 93ce3cb26..ee6a4dd62 100644
--- a/docshell/base/nsDSURIContentListener.cpp
+++ b/docshell/base/nsDSURIContentListener.cpp
@@ -17,6 +17,7 @@
 #include "nsIHttpChannel.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsError.h"
+#include "nsContentSecurityManager.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
@@ -93,6 +94,14 @@ nsDSURIContentListener::DoContent(const nsACString& aContentType,
 
   if (aOpenedChannel) {
     aOpenedChannel->GetLoadFlags(&loadFlags);
+
+    // block top-level data URI navigations if triggered by the web
+    if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(aOpenedChannel)) {
+      // logging to console happens within AllowTopLevelNavigationToDataURI
+      aRequest->Cancel(NS_ERROR_DOM_BAD_URI);
+      *aAbortProcess = true;
+      return NS_OK; 
+    }
   }
 
   if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) {
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index ae97a7c9e..596bd5d84 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -9885,15 +9885,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
     contentType = nsIContentPolicy::TYPE_DOCUMENT;
   }
 
-  if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
-        aURI,
-        contentType,
-        aTriggeringPrincipal,
-        (aLoadType == LOAD_NORMAL_EXTERNAL))) {
-    // logging to console happens within AllowTopLevelNavigationToDataURI
-    return NS_OK;
-  }
-
   // If there's no targetDocShell, that means we are about to create a new window,
   // perform a content policy check before creating the window.
   if (!targetDocShell) {
@@ -10962,6 +10953,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
   if (aPrincipalToInherit) {
     loadInfo->SetPrincipalToInherit(aPrincipalToInherit);
   }
+  loadInfo->SetLoadTriggeredFromExternal(aLoadFromExternal);
 
   // We have to do this in case our OriginAttributes are different from the
   // OriginAttributes of the parent document. Or in case there isn't a
diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp
index 069e7d6a7..c987fed67 100644
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -10,20 +10,16 @@
 #include "nsIStreamListener.h"
 #include "nsIDocument.h"
 #include "nsMixedContentBlocker.h"
-#include "nsNullPrincipal.h"
 
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/TabChild.h"
 
 NS_IMPL_ISUPPORTS(nsContentSecurityManager,
                   nsIContentSecurityManager,
                   nsIChannelEventSink)
 
 /* static */ bool
-nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
-  nsIURI* aURI,
-  nsContentPolicyType aContentPolicyType,
-  nsIPrincipal* aTriggeringPrincipal,
-  bool aLoadFromExternal)
+nsContentSecurityManager::AllowTopLevelNavigationToDataURI(nsIChannel* aChannel)
 {
   // Let's block all toplevel document navigations to a data: URI.
   // In all cases where the toplevel document is navigated to a
@@ -36,17 +32,24 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
   if (!mozilla::net::nsIOService::BlockToplevelDataUriNavigations()) {
     return true;
   }
-  if (aContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT) {
+  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
+  if (!loadInfo) {
+    return true;
+  }
+  if (loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) {
     return true;
   }
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, true);
   bool isDataURI =
-    (NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI);
+    (NS_SUCCEEDED(uri->SchemeIs("data", &isDataURI)) && isDataURI);
   if (!isDataURI) {
     return true;
   }
   // Whitelist data: images as long as they are not SVGs
   nsAutoCString filePath;
-  aURI->GetFilePath(filePath);
+  uri->GetFilePath(filePath);
   if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/")) &&
       !StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/svg+xml"))) {
     return true;
@@ -56,22 +59,29 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
       StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/json"))) {
     return true;
   }
-  if (!aLoadFromExternal &&
-      nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal)) {
+  // Redirecting to a toplevel data: URI is not allowed, hence we make
+  // sure the RedirectChain is empty.
+  if (!loadInfo->GetLoadTriggeredFromExternal() &&
+      nsContentUtils::IsSystemPrincipal(loadInfo->TriggeringPrincipal()) &&
+      loadInfo->RedirectChain().IsEmpty()) {
     return true;
   }
   nsAutoCString dataSpec;
-  aURI->GetSpec(dataSpec);
+  uri->GetSpec(dataSpec);
   if (dataSpec.Length() > 50) {
     dataSpec.Truncate(50);
     dataSpec.AppendLiteral("...");
   }
+  nsCOMPtr<nsITabChild> tabChild = do_QueryInterface(loadInfo->ContextForTopLevelLoad());
+  nsCOMPtr<nsIDocument> doc;
+  if (tabChild) {
+    doc = static_cast<mozilla::dom::TabChild*>(tabChild.get())->GetDocument();
+  }
   NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec));
   const char16_t* params[] = { specUTF16.get() };
   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                   NS_LITERAL_CSTRING("DATA_URI_BLOCKED"),
-                                  // no doc available, log to browser console
-                                  nullptr,
+                                  doc,
                                   nsContentUtils::eSECURITY_PROPERTIES,
                                   "BlockTopLevelDataURINavigation",
                                   params, ArrayLength(params));
@@ -541,27 +551,6 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
     }
   }
 
-  // Redirecting to a toplevel data: URI is not allowed, hence we pass
-  // a NullPrincipal as the TriggeringPrincipal to
-  // AllowTopLevelNavigationToDataURI() which definitely blocks any
-  // data: URI load.
-  nsCOMPtr<nsILoadInfo> newLoadInfo = aNewChannel->GetLoadInfo();
-  if (newLoadInfo) {
-    nsCOMPtr<nsIURI> uri;
-    nsresult rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(uri));
-    NS_ENSURE_SUCCESS(rv, rv);
-    nsCOMPtr<nsIPrincipal> nullTriggeringPrincipal = nsNullPrincipal::Create();
-    if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
-          uri,
-          newLoadInfo->GetExternalContentPolicyType(),
-          nullTriggeringPrincipal,
-          false)) {
-        // logging to console happens within AllowTopLevelNavigationToDataURI
-      aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
-      return NS_ERROR_DOM_BAD_URI;
-    }
-  }
-
   // Also verify that the redirecting server is allowed to redirect to the
   // given URI
   nsCOMPtr<nsIPrincipal> oldPrincipal;
diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h
index 09b6c86aa..bab847743 100644
--- a/dom/security/nsContentSecurityManager.h
+++ b/dom/security/nsContentSecurityManager.h
@@ -32,10 +32,7 @@ public:
   static nsresult doContentSecurityCheck(nsIChannel* aChannel,
                                          nsCOMPtr<nsIStreamListener>& aInAndOutListener);
 
-  static bool AllowTopLevelNavigationToDataURI(nsIURI* aURI,
-                                               nsContentPolicyType aContentPolicyType,
-                                               nsIPrincipal* aTriggeringPrincipal,
-                                               bool aLoadFromExternal);
+  static bool AllowTopLevelNavigationToDataURI(nsIChannel* aChannel);
 
 private:
   static nsresult CheckChannel(nsIChannel* aChannel);
diff --git a/dom/security/test/general/browser.ini b/dom/security/test/general/browser.ini
index 97ddae3bf..73ae72ddd 100644
--- a/dom/security/test/general/browser.ini
+++ b/dom/security/test/general/browser.ini
@@ -3,3 +3,9 @@
 support-files =
   file_toplevel_data_navigations.sjs
   file_toplevel_data_meta_redirect.html
+[browser_test_data_download.js]
+support-files =
+  file_data_download.html
+[browser_test_data_text_csv.js]
+support-files =
+  file_data_text_csv.html
diff --git a/dom/security/test/general/browser_test_data_download.js b/dom/security/test/general/browser_test_data_download.js
new file mode 100644
index 000000000..1ee8d5844
--- /dev/null
+++ b/dom/security/test/general/browser_test_data_download.js
@@ -0,0 +1,37 @@
+"use strict";
+
+const kTestPath = getRootDirectory(gTestPath)
+                  .replace("chrome://mochitests/content", "http://example.com")
+const kTestURI = kTestPath + "file_data_download.html";
+
+function addWindowListener(aURL, aCallback) {
+  Services.wm.addListener({
+    onOpenWindow(aXULWindow) {
+      info("window opened, waiting for focus");
+      Services.wm.removeListener(this);
+      var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                                .getInterface(Ci.nsIDOMWindow);
+      waitForFocus(function() {
+        is(domwindow.document.location.href, aURL, "should have seen the right window open");
+        aCallback(domwindow);
+      }, domwindow);
+    },
+    onCloseWindow(aXULWindow) { },
+    onWindowTitleChange(aXULWindow, aNewTitle) { }
+  });
+}
+
+function test() {
+  waitForExplicitFinish();
+  Services.prefs.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true);
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations");
+  });
+  addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function(win) {
+    is(win.document.getElementById("location").value, "data-foo.html",
+       "file name of download should match");
+     win.close();
+     finish();
+  });
+  gBrowser.loadURI(kTestURI);
+}
diff --git a/dom/security/test/general/browser_test_data_text_csv.js b/dom/security/test/general/browser_test_data_text_csv.js
new file mode 100644
index 000000000..c45e40cc2
--- /dev/null
+++ b/dom/security/test/general/browser_test_data_text_csv.js
@@ -0,0 +1,37 @@
+"use strict";
+
+const kTestPath = getRootDirectory(gTestPath)
+                  .replace("chrome://mochitests/content", "http://example.com")
+const kTestURI = kTestPath + "file_data_text_csv.html";
+
+function addWindowListener(aURL, aCallback) {
+  Services.wm.addListener({
+    onOpenWindow(aXULWindow) {
+      info("window opened, waiting for focus");
+      Services.wm.removeListener(this);
+      var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                                .getInterface(Ci.nsIDOMWindow);
+      waitForFocus(function() {
+        is(domwindow.document.location.href, aURL, "should have seen the right window open");
+        aCallback(domwindow);
+      }, domwindow);
+    },
+    onCloseWindow(aXULWindow) { },
+    onWindowTitleChange(aXULWindow, aNewTitle) { }
+  });
+}
+
+function test() {
+  waitForExplicitFinish();
+  Services.prefs.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true);
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations");
+  });
+  addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function(win) {
+    is(win.document.getElementById("location").value, "text/csv;foo,bar,foobar",
+       "file name of download should match");
+     win.close();
+     finish();
+  });
+  gBrowser.loadURI(kTestURI);
+}
diff --git a/dom/security/test/general/file_data_download.html b/dom/security/test/general/file_data_download.html
new file mode 100644
index 000000000..4cc92fe8f
--- /dev/null
+++ b/dom/security/test/general/file_data_download.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test download attribute for data: URI</title>
+</head>
+<body>
+  <a href="data:text/html,<body>data download</body>" download="data-foo.html" id="testlink">download data</a>
+  <script>
+    // click the link to have the downoad panel appear
+    let testlink = document.getElementById("testlink");
+    testlink.click();
+  </script>
+  </body>
+</html>
diff --git a/dom/security/test/general/file_data_text_csv.html b/dom/security/test/general/file_data_text_csv.html
new file mode 100644
index 000000000..a9ac369d1
--- /dev/null
+++ b/dom/security/test/general/file_data_text_csv.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test open data:text/csv</title>
+</head>
+<body>
+  <a href="data:text/csv;foo,bar,foobar" id="testlink">test text/csv</a>
+  <script>
+    // click the link to have the downoad panel appear
+    let testlink = document.getElementById("testlink");
+    testlink.click();
+  </script>
+  </body>
+</html>
diff --git a/dom/security/test/general/test_block_toplevel_data_img_navigation.html b/dom/security/test/general/test_block_toplevel_data_img_navigation.html
index 2b8f62760..7f8dfc748 100644
--- a/dom/security/test/general/test_block_toplevel_data_img_navigation.html
+++ b/dom/security/test/general/test_block_toplevel_data_img_navigation.html
@@ -34,15 +34,17 @@ function test_toplevel_data_image_svg() {
   const DATA_SVG =
     "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==";
   let win2 = window.open(DATA_SVG);
-  let wrappedWin2 = SpecialPowers.wrap(win2);
-  setTimeout(function () {
-    isnot(wrappedWin2.document.documentElement.localName, "svg",
-          "Loading data:image/svg+xml should be blocked");
-    wrappedWin2.close();
-    SimpleTest.finish();
-  }, 1000);
+  // Unfortunately we can't detect whether the window was closed using some event,
+  // hence we are constantly polling till we see that win == null.
+  // Test times out on failure.
+  var win2Closed = setInterval(function() {
+    if (win2 == null || win2.closed) {
+      clearInterval(win2Closed);
+      ok(true, "Loading data:image/svg+xml should be blocked");
+      SimpleTest.finish();
+    }
+  }, 200);
 }
-
 // fire up the tests
 test_toplevel_data_image();
 
diff --git a/dom/security/test/general/test_block_toplevel_data_navigation.html b/dom/security/test/general/test_block_toplevel_data_navigation.html
index fc91f2ec0..cef232b65 100644
--- a/dom/security/test/general/test_block_toplevel_data_navigation.html
+++ b/dom/security/test/general/test_block_toplevel_data_navigation.html
@@ -21,16 +21,12 @@ function test1() {
   // simple data: URI click navigation should be prevented
   let TEST_FILE = "file_block_toplevel_data_navigation.html";
   let win1 = window.open(TEST_FILE);
-  var readyStateCheckInterval = setInterval(function() {
-    let state = win1.document.readyState;
-    if (state === "interactive" || state === "complete") {
-      clearInterval(readyStateCheckInterval);
-      ok(win1.document.body.innerHTML.indexOf("test1:") !== -1,
-         "toplevel data: URI navigation through click() should be blocked");
-      win1.close();
-      test2();
-    }
-  }, 200);
+  setTimeout(function () {
+    ok(SpecialPowers.wrap(win1).document.body.innerHTML.indexOf("test1:") !== -1,
+      "toplevel data: URI navigation through click() should be blocked");
+    win1.close();
+    test2();
+  }, 1000);
 }
 
 function test2() {
diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp
index b335f5c23..4cfbe8758 100644
--- a/ipc/glue/BackgroundUtils.cpp
+++ b/ipc/glue/BackgroundUtils.cpp
@@ -294,6 +294,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
       aLoadInfo->CorsUnsafeHeaders(),
       aLoadInfo->GetForcePreflight(),
       aLoadInfo->GetIsPreflight(),
+      aLoadInfo->GetLoadTriggeredFromExternal(),
       aLoadInfo->GetForceHSTSPriming(),
       aLoadInfo->GetMixedContentWouldBlock());
 
@@ -370,6 +371,7 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
                           loadInfoArgs.corsUnsafeHeaders(),
                           loadInfoArgs.forcePreflight(),
                           loadInfoArgs.isPreflight(),
+                          loadInfoArgs.loadTriggeredFromExternal(),
                           loadInfoArgs.forceHSTSPriming(),
                           loadInfoArgs.mixedContentWouldBlock()
                           );
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
index 42fdea4a1..2f10261cb 100644
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -7,6 +7,7 @@
 #include "mozilla/LoadInfo.h"
 
 #include "mozilla/Assertions.h"
+#include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozIThirdPartyUtil.h"
 #include "nsFrameLoader.h"
@@ -63,6 +64,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
   , mIsThirdPartyContext(false)
   , mForcePreflight(false)
   , mIsPreflight(false)
+  , mLoadTriggeredFromExternal(false)
   , mForceHSTSPriming(false)
   , mMixedContentWouldBlock(false)
 {
@@ -235,6 +237,7 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
   , mIsThirdPartyContext(false) // NB: TYPE_DOCUMENT implies not third-party.
   , mForcePreflight(false)
   , mIsPreflight(false)
+  , mLoadTriggeredFromExternal(false)
   , mForceHSTSPriming(false)
   , mMixedContentWouldBlock(false)
 {
@@ -297,6 +300,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
   , mCorsUnsafeHeaders(rhs.mCorsUnsafeHeaders)
   , mForcePreflight(rhs.mForcePreflight)
   , mIsPreflight(rhs.mIsPreflight)
+  , mLoadTriggeredFromExternal(rhs.mLoadTriggeredFromExternal)
   , mForceHSTSPriming(rhs.mForceHSTSPriming)
   , mMixedContentWouldBlock(rhs.mMixedContentWouldBlock)
 {
@@ -325,6 +329,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
                    const nsTArray<nsCString>& aCorsUnsafeHeaders,
                    bool aForcePreflight,
                    bool aIsPreflight,
+                   bool aLoadTriggeredFromExternal,
                    bool aForceHSTSPriming,
                    bool aMixedContentWouldBlock)
   : mLoadingPrincipal(aLoadingPrincipal)
@@ -348,6 +353,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
   , mCorsUnsafeHeaders(aCorsUnsafeHeaders)
   , mForcePreflight(aForcePreflight)
   , mIsPreflight(aIsPreflight)
+  , mLoadTriggeredFromExternal(aLoadTriggeredFromExternal)
   , mForceHSTSPriming (aForceHSTSPriming)
   , mMixedContentWouldBlock(aMixedContentWouldBlock)
 {
@@ -872,6 +878,23 @@ LoadInfo::GetIsPreflight(bool* aIsPreflight)
   return NS_OK;
 }
 
+NS_IMETHODIMP
+LoadInfo::SetLoadTriggeredFromExternal(bool aLoadTriggeredFromExternal)
+{
+  MOZ_ASSERT(!aLoadTriggeredFromExternal ||
+             mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,
+             "can only set load triggered from external for TYPE_DOCUMENT");
+  mLoadTriggeredFromExternal = aLoadTriggeredFromExternal;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+LoadInfo::GetLoadTriggeredFromExternal(bool* aLoadTriggeredFromExternal)
+{
+  *aLoadTriggeredFromExternal = mLoadTriggeredFromExternal;
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 LoadInfo::GetForceHSTSPriming(bool* aForceHSTSPriming)
 {
diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
index 3e1b92ff4..99deae2d2 100644
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -108,6 +108,7 @@ private:
            const nsTArray<nsCString>& aUnsafeHeaders,
            bool aForcePreflight,
            bool aIsPreflight,
+           bool aLoadTriggeredFromExternal,
            bool aForceHSTSPriming,
            bool aMixedContentWouldBlock);
   LoadInfo(const LoadInfo& rhs);
@@ -152,6 +153,7 @@ private:
   nsTArray<nsCString>              mCorsUnsafeHeaders;
   bool                             mForcePreflight;
   bool                             mIsPreflight;
+  bool                             mLoadTriggeredFromExternal;
 
   bool                             mForceHSTSPriming : 1;
   bool                             mMixedContentWouldBlock : 1;
diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl
index 78433c8b8..5b5eb425a 100644
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -574,6 +574,13 @@ interface nsILoadInfo : nsISupports
    */
   [infallible] attribute boolean initialSecurityCheckDone;
 
+  /**
+   * Returns true if the load was triggered from an external application
+   * (e.g. Thunderbird). Please note that this flag will only ever be true
+   * if the load is of TYPE_DOCUMENT. 
+   */
+  [infallible] attribute boolean loadTriggeredFromExternal;
+
   /**
    * Whenever a channel gets redirected, append the principal of the
    * channel [before the channels got redirected] to the loadinfo,
diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh
index 9365397d1..e1438cacc 100644
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -53,6 +53,7 @@ struct LoadInfoArgs
   nsCString[]           corsUnsafeHeaders;
   bool                  forcePreflight;
   bool                  isPreflight;
+  bool                  loadTriggeredFromExternal;
   bool                  forceHSTSPriming;
   bool                  mixedContentWouldBlock;
 };
-- 
cgit v1.2.3


From 660d01438a6a29ebd43f592ac7d6df2dad6a6962 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 20:28:18 +0200
Subject: moebius#230: Consider blocking top level window data: URIs (part 3/3
 without tests)

https://github.com/MoonchildProductions/moebius/pull/230
---
 application/palemoon/base/content/nsContextMenu.js |  3 ++-
 .../palemoon/base/content/utilityOverlay.js        |  5 ++++
 browser/base/content/nsContextMenu.js              |  3 ++-
 browser/base/content/utilityOverlay.js             |  5 ++++
 docshell/base/nsDocShell.cpp                       | 17 +++++++++++-
 docshell/base/nsDocShell.h                         |  1 +
 docshell/base/nsDocShellLoadInfo.cpp               | 15 +++++++++++
 docshell/base/nsDocShellLoadInfo.h                 |  1 +
 docshell/base/nsIDocShell.idl                      |  3 +++
 docshell/base/nsIDocShellLoadInfo.idl              |  6 +++++
 docshell/base/nsIWebNavigation.idl                 |  6 +++++
 dom/security/nsContentSecurityManager.cpp          |  4 +++
 dom/security/test/general/browser.ini              |  3 +++
 .../browser_test_view_image_data_navigation.js     | 30 ++++++++++++++++++++++
 .../general/file_view_image_data_navigation.html   | 12 +++++++++
 ipc/glue/BackgroundUtils.cpp                       |  2 ++
 netwerk/base/LoadInfo.cpp                          | 22 ++++++++++++++++
 netwerk/base/LoadInfo.h                            |  2 ++
 netwerk/base/nsILoadInfo.idl                       |  5 ++++
 netwerk/ipc/NeckoChannelParams.ipdlh               |  1 +
 20 files changed, 143 insertions(+), 3 deletions(-)
 create mode 100644 dom/security/test/general/browser_test_view_image_data_navigation.js
 create mode 100644 dom/security/test/general/file_view_image_data_navigation.html

diff --git a/application/palemoon/base/content/nsContextMenu.js b/application/palemoon/base/content/nsContextMenu.js
index 3d5d40e4c..830c20998 100644
--- a/application/palemoon/base/content/nsContextMenu.js
+++ b/application/palemoon/base/content/nsContextMenu.js
@@ -909,7 +909,8 @@ nsContextMenu.prototype = {
                        Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
       let doc = this.target.ownerDocument;
       openUILink(viewURL, e, { disallowInheritPrincipal: true,
-                               referrerURI: doc.documentURIObject });
+                               referrerURI: doc.documentURIObject,
+                               forceAllowDataURI: true });
     }
   },
 
diff --git a/application/palemoon/base/content/utilityOverlay.js b/application/palemoon/base/content/utilityOverlay.js
index b1e78d6a9..86cc5cea5 100644
--- a/application/palemoon/base/content/utilityOverlay.js
+++ b/application/palemoon/base/content/utilityOverlay.js
@@ -205,6 +205,7 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI
   openLinkIn(url, where, params);
 }
 
+/* eslint-disable complexity */
 function openLinkIn(url, where, params) {
   if (!where || !url)
     return;
@@ -215,6 +216,7 @@ function openLinkIn(url, where, params) {
   var aCharset              = params.charset;
   var aReferrerURI          = params.referrerURI;
   var aRelatedToCurrent     = params.relatedToCurrent;
+  var aForceAllowDataURI    = params.forceAllowDataURI;
   var aInBackground         = params.inBackground;
   var aDisallowInheritPrincipal = params.disallowInheritPrincipal;
   var aInitiatingDoc        = params.initiatingDoc;
@@ -315,6 +317,9 @@ function openLinkIn(url, where, params) {
     }
     if (aDisallowInheritPrincipal)
       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
+    if (aForceAllowDataURI) {
+      flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
+    }
     w.gBrowser.loadURIWithFlags(url, flags, aReferrerURI, null, aPostData);
     break;
   case "tabshifted":
diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js
index 8eb9b034f..ddf695202 100644
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1158,7 +1158,8 @@ nsContextMenu.prototype = {
                        this.browser.contentPrincipal,
                        Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
       openUILink(this.mediaURL, e, { disallowInheritPrincipal: true,
-                                     referrerURI: referrerURI });
+                                     referrerURI: referrerURI,
+                                     forceAllowDataURI: true });
     }
   },
 
diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js
index 0b703b6f8..6ceaf773e 100644
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -197,6 +197,7 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI
   openLinkIn(url, where, params);
 }
 
+/* eslint-disable complexity */
 function openLinkIn(url, where, params) {
   if (!where || !url)
     return;
@@ -212,6 +213,7 @@ function openLinkIn(url, where, params) {
       params.referrerPolicy : Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT);
   var aRelatedToCurrent     = params.relatedToCurrent;
   var aAllowMixedContent    = params.allowMixedContent;
+  var aForceAllowDataURI    = params.forceAllowDataURI;
   var aInBackground         = params.inBackground;
   var aDisallowInheritPrincipal = params.disallowInheritPrincipal;
   var aInitiatingDoc        = params.initiatingDoc;
@@ -378,6 +380,9 @@ function openLinkIn(url, where, params) {
     if (aIndicateErrorPageLoad) {
       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ERROR_LOAD_CHANGES_RV;
     }
+    if (aForceAllowDataURI) {
+      flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
+    }
 
     let {URI_INHERITS_SECURITY_CONTEXT} = Ci.nsIProtocolHandler;
     if (aForceAboutBlankViewerInCurrent &&
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 596bd5d84..f3db4a3cb 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1273,6 +1273,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
   nsCOMPtr<nsISHEntry> shEntry;
   nsXPIDLString target;
   nsAutoString srcdoc;
+  bool forceAllowDataURI = false;
   nsCOMPtr<nsIDocShell> sourceDocShell;
   nsCOMPtr<nsIURI> baseURI;
 
@@ -1308,6 +1309,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
     aLoadInfo->GetSrcdocData(srcdoc);
     aLoadInfo->GetSourceDocShell(getter_AddRefs(sourceDocShell));
     aLoadInfo->GetBaseURI(getter_AddRefs(baseURI));
+    aLoadInfo->GetForceAllowDataURI(&forceAllowDataURI);
   }
 
 #if defined(DEBUG)
@@ -1561,6 +1563,10 @@ nsDocShell::LoadURI(nsIURI* aURI,
     flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
   }
 
+  if (forceAllowDataURI) {
+    flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
+  }
+
   return InternalLoad(aURI,
                       originalURI,
                       loadReplace,
@@ -4822,6 +4828,9 @@ nsDocShell::LoadURIWithOptions(const char16_t* aURI,
   }
   nsAutoPopupStatePusher statePusher(popupState);
 
+  bool forceAllowDataURI =
+    aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
+
   // Don't pass certain flags that aren't needed and end up confusing
   // ConvertLoadTypeToDocShellLoadInfo.  We do need to ensure that they are
   // passed to LoadURI though, since it uses them.
@@ -4851,6 +4860,7 @@ nsDocShell::LoadURIWithOptions(const char16_t* aURI,
   loadInfo->SetReferrerPolicy(aReferrerPolicy);
   loadInfo->SetHeadersStream(aHeaderStream);
   loadInfo->SetBaseURI(aBaseURI);
+  loadInfo->SetForceAllowDataURI(forceAllowDataURI);
 
   if (fixupInfo) {
     nsAutoString searchProvider, keyword;
@@ -10083,6 +10093,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
         // principal to inherit is: it should be aTriggeringPrincipal.
         loadInfo->SetPrincipalIsExplicit(true);
         loadInfo->SetLoadType(ConvertLoadTypeToDocShellLoadInfo(LOAD_LINK));
+        loadInfo->SetForceAllowDataURI(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI);
 
         rv = win->Open(NS_ConvertUTF8toUTF16(spec),
                        aWindowTarget, // window name
@@ -10728,7 +10739,9 @@ nsDocShell::InternalLoad(nsIURI* aURI,
                         nsINetworkPredictor::PREDICT_LOAD, this, nullptr);
 
   nsCOMPtr<nsIRequest> req;
-  rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, loadFromExternal, aReferrer,
+  rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, loadFromExternal,
+                 (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI),
+                 aReferrer,
                  !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
                  aReferrerPolicy,
                  aTriggeringPrincipal, principalToInherit, aTypeHint,
@@ -10809,6 +10822,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
                       nsIURI* aOriginalURI,
                       bool aLoadReplace,
                       bool aLoadFromExternal,
+                      bool aForceAllowDataURI,
                       nsIURI* aReferrerURI,
                       bool aSendReferrer,
                       uint32_t aReferrerPolicy,
@@ -10954,6 +10968,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
     loadInfo->SetPrincipalToInherit(aPrincipalToInherit);
   }
   loadInfo->SetLoadTriggeredFromExternal(aLoadFromExternal);
+  loadInfo->SetForceAllowDataURI(aForceAllowDataURI);
 
   // We have to do this in case our OriginAttributes are different from the
   // OriginAttributes of the parent document. Or in case there isn't a
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index 549d7f540..63a4e3358 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -370,6 +370,7 @@ protected:
                      nsIURI* aOriginalURI,
                      bool aLoadReplace,
                      bool aLoadFromExternal,
+                     bool aForceAllowDataURI,
                      nsIURI* aReferrer,
                      bool aSendReferrer,
                      uint32_t aReferrerPolicy,
diff --git a/docshell/base/nsDocShellLoadInfo.cpp b/docshell/base/nsDocShellLoadInfo.cpp
index 7d0034b04..b00e8e360 100644
--- a/docshell/base/nsDocShellLoadInfo.cpp
+++ b/docshell/base/nsDocShellLoadInfo.cpp
@@ -15,6 +15,7 @@ nsDocShellLoadInfo::nsDocShellLoadInfo()
   : mLoadReplace(false)
   , mInheritPrincipal(false)
   , mPrincipalIsExplicit(false)
+  , mForceAllowDataURI(false)
   , mSendReferrer(true)
   , mReferrerPolicy(mozilla::net::RP_Default)
   , mLoadType(nsIDocShellLoadInfo::loadNormal)
@@ -126,6 +127,20 @@ nsDocShellLoadInfo::SetPrincipalIsExplicit(bool aPrincipalIsExplicit)
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDocShellLoadInfo::GetForceAllowDataURI(bool* aForceAllowDataURI)
+{
+  *aForceAllowDataURI = mForceAllowDataURI;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShellLoadInfo::SetForceAllowDataURI(bool aForceAllowDataURI)
+{
+  mForceAllowDataURI = aForceAllowDataURI;
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsDocShellLoadInfo::GetLoadType(nsDocShellInfoLoadType* aLoadType)
 {
diff --git a/docshell/base/nsDocShellLoadInfo.h b/docshell/base/nsDocShellLoadInfo.h
index b7eaed832..f3ddcca1e 100644
--- a/docshell/base/nsDocShellLoadInfo.h
+++ b/docshell/base/nsDocShellLoadInfo.h
@@ -37,6 +37,7 @@ protected:
   bool mLoadReplace;
   bool mInheritPrincipal;
   bool mPrincipalIsExplicit;
+  bool mForceAllowDataURI;
   bool mSendReferrer;
   nsDocShellInfoReferrerPolicy mReferrerPolicy;
   nsDocShellInfoLoadType mLoadType;
diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
index 8261c45dc..e34e6adfd 100644
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -116,6 +116,9 @@ interface nsIDocShell : nsIDocShellTreeItem
 
   const long INTERNAL_LOAD_FLAGS_NO_OPENER               = 0x100;
 
+  // Whether a top-level data URI navigation is allowed for that load
+  const long INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI    = 0x200;
+
   // NB: 0x80 is available.
 
   /**
diff --git a/docshell/base/nsIDocShellLoadInfo.idl b/docshell/base/nsIDocShellLoadInfo.idl
index 113c0a4c1..8804f63a3 100644
--- a/docshell/base/nsIDocShellLoadInfo.idl
+++ b/docshell/base/nsIDocShellLoadInfo.idl
@@ -55,6 +55,12 @@ interface nsIDocShellLoadInfo : nsISupports
      */
     attribute boolean principalIsExplicit;
 
+    /**
+     * If this attribute is true, then a top-level navigation
+     * to a data URI will be allowed.
+     */
+    attribute boolean forceAllowDataURI;
+
     /* these are load type enums... */
     const long loadNormal = 0;                     // Normal Load
     const long loadNormalReplace = 1;              // Normal Load but replaces current history slot
diff --git a/docshell/base/nsIWebNavigation.idl b/docshell/base/nsIWebNavigation.idl
index 042b1c547..241d0731c 100644
--- a/docshell/base/nsIWebNavigation.idl
+++ b/docshell/base/nsIWebNavigation.idl
@@ -205,6 +205,12 @@ interface nsIWebNavigation : nsISupports
    */
   const unsigned long LOAD_FLAGS_FIXUP_SCHEME_TYPOS = 0x200000;
 
+  /**
+   * Allows a top-level data: navigation to occur. E.g. view-image
+   * is an explicit user action which should be allowed.
+   */
+  const unsigned long LOAD_FLAGS_FORCE_ALLOW_DATA_URI = 0x400000;
+
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp
index c987fed67..9329c558a 100644
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -39,6 +39,10 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI(nsIChannel* aChannel)
   if (loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) {
     return true;
   }
+  if (loadInfo->GetForceAllowDataURI()) {
+    // if the loadinfo explicitly allows the data URI navigation, let's allow it now
+    return true;
+  }
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, true);
diff --git a/dom/security/test/general/browser.ini b/dom/security/test/general/browser.ini
index 73ae72ddd..b00baa95d 100644
--- a/dom/security/test/general/browser.ini
+++ b/dom/security/test/general/browser.ini
@@ -9,3 +9,6 @@ support-files =
 [browser_test_data_text_csv.js]
 support-files =
   file_data_text_csv.html
+[browser_test_view_image_data_navigation.js]
+support-files =
+  file_view_image_data_navigation.html
diff --git a/dom/security/test/general/browser_test_view_image_data_navigation.js b/dom/security/test/general/browser_test_view_image_data_navigation.js
new file mode 100644
index 000000000..22de35894
--- /dev/null
+++ b/dom/security/test/general/browser_test_view_image_data_navigation.js
@@ -0,0 +1,30 @@
+"use strict";
+
+const TEST_PAGE = getRootDirectory(gTestPath) + "file_view_image_data_navigation.html";
+
+add_task(async function test_principal_right_click_open_link_in_new_tab() {
+  await SpecialPowers.pushPrefEnv({
+    "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]],
+  });
+
+  await BrowserTestUtils.withNewTab(TEST_PAGE, async function(browser) {
+    let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, true);
+
+    // simulate right-click->view-image
+    BrowserTestUtils.waitForEvent(document, "popupshown", false, event => {
+      // These are operations that must be executed synchronously with the event.
+      document.getElementById("context-viewimage").doCommand();
+      event.target.hidePopup();
+      return true;
+    });
+    BrowserTestUtils.synthesizeMouseAtCenter("#testimage",
+                                             { type: "contextmenu", button: 2 },
+                                             gBrowser.selectedBrowser);
+    await loadPromise;
+
+    await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
+      ok(content.document.location.toString().startsWith("data:image/svg+xml;"),
+         "data:image/svg navigation allowed through right-click view-image")
+    });
+  });
+});
diff --git a/dom/security/test/general/file_view_image_data_navigation.html b/dom/security/test/general/file_view_image_data_navigation.html
new file mode 100644
index 000000000..a3f9acfb4
--- /dev/null
+++ b/dom/security/test/general/file_view_image_data_navigation.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Bug 1407891: Test navigation for right-click view-image on data:image/svg</title>
+</head>
+<body>
+
+<img id="testimage" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg=="></img>
+
+</body>
+</html>
diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp
index 4cfbe8758..e115fa74c 100644
--- a/ipc/glue/BackgroundUtils.cpp
+++ b/ipc/glue/BackgroundUtils.cpp
@@ -280,6 +280,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
       aLoadInfo->GetUpgradeInsecureRequests(),
       aLoadInfo->GetVerifySignedContent(),
       aLoadInfo->GetEnforceSRI(),
+      aLoadInfo->GetForceAllowDataURI(),
       aLoadInfo->GetForceInheritPrincipalDropped(),
       aLoadInfo->GetInnerWindowID(),
       aLoadInfo->GetOuterWindowID(),
@@ -357,6 +358,7 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
                           loadInfoArgs.upgradeInsecureRequests(),
                           loadInfoArgs.verifySignedContent(),
                           loadInfoArgs.enforceSRI(),
+                          loadInfoArgs.forceAllowDataURI(),
                           loadInfoArgs.forceInheritPrincipalDropped(),
                           loadInfoArgs.innerWindowID(),
                           loadInfoArgs.outerWindowID(),
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
index 2f10261cb..9923f6d30 100644
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -54,6 +54,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
   , mUpgradeInsecureRequests(false)
   , mVerifySignedContent(false)
   , mEnforceSRI(false)
+  , mForceAllowDataURI(false)
   , mForceInheritPrincipalDropped(false)
   , mInnerWindowID(0)
   , mOuterWindowID(0)
@@ -227,6 +228,7 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
   , mUpgradeInsecureRequests(false)
   , mVerifySignedContent(false)
   , mEnforceSRI(false)
+  , mForceAllowDataURI(false)
   , mForceInheritPrincipalDropped(false)
   , mInnerWindowID(0)
   , mOuterWindowID(0)
@@ -285,6 +287,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
   , mUpgradeInsecureRequests(rhs.mUpgradeInsecureRequests)
   , mVerifySignedContent(rhs.mVerifySignedContent)
   , mEnforceSRI(rhs.mEnforceSRI)
+  , mForceAllowDataURI(rhs.mForceAllowDataURI)
   , mForceInheritPrincipalDropped(rhs.mForceInheritPrincipalDropped)
   , mInnerWindowID(rhs.mInnerWindowID)
   , mOuterWindowID(rhs.mOuterWindowID)
@@ -315,6 +318,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
                    bool aUpgradeInsecureRequests,
                    bool aVerifySignedContent,
                    bool aEnforceSRI,
+                   bool aForceAllowDataURI,
                    bool aForceInheritPrincipalDropped,
                    uint64_t aInnerWindowID,
                    uint64_t aOuterWindowID,
@@ -341,6 +345,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
   , mUpgradeInsecureRequests(aUpgradeInsecureRequests)
   , mVerifySignedContent(aVerifySignedContent)
   , mEnforceSRI(aEnforceSRI)
+  , mForceAllowDataURI(aForceAllowDataURI)
   , mForceInheritPrincipalDropped(aForceInheritPrincipalDropped)
   , mInnerWindowID(aInnerWindowID)
   , mOuterWindowID(aOuterWindowID)
@@ -653,6 +658,23 @@ LoadInfo::GetEnforceSRI(bool* aResult)
   return NS_OK;
 }
 
+NS_IMETHODIMP
+LoadInfo::SetForceAllowDataURI(bool aForceAllowDataURI)
+{
+  MOZ_ASSERT(!mForceAllowDataURI ||
+             mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,
+             "can only allow data URI navigation for TYPE_DOCUMENT");
+  mForceAllowDataURI = aForceAllowDataURI;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+LoadInfo::GetForceAllowDataURI(bool* aForceAllowDataURI)
+{
+  *aForceAllowDataURI = mForceAllowDataURI;
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 LoadInfo::GetForceInheritPrincipalDropped(bool* aResult)
 {
diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
index 99deae2d2..86cfddc68 100644
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -94,6 +94,7 @@ private:
            bool aUpgradeInsecureRequests,
            bool aVerifySignedContent,
            bool aEnforceSRI,
+           bool aForceAllowDataURI,
            bool aForceInheritPrincipalDropped,
            uint64_t aInnerWindowID,
            uint64_t aOuterWindowID,
@@ -139,6 +140,7 @@ private:
   bool                             mUpgradeInsecureRequests;
   bool                             mVerifySignedContent;
   bool                             mEnforceSRI;
+  bool                             mForceAllowDataURI;
   bool                             mForceInheritPrincipalDropped;
   uint64_t                         mInnerWindowID;
   uint64_t                         mOuterWindowID;
diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl
index 5b5eb425a..5b35736e5 100644
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -469,6 +469,11 @@ interface nsILoadInfo : nsISupports
    */
   [infallible] attribute boolean enforceSRI;
 
+  /**
+   * If true, toplevel data: URI navigation is allowed
+   */
+  [infallible] attribute boolean forceAllowDataURI;
+
   /**
    * The SEC_FORCE_INHERIT_PRINCIPAL flag may be dropped when a load info
    * object is created.  Specifically, it will be dropped if the SEC_SANDBOXED
diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh
index e1438cacc..4f4dcf6a9 100644
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -39,6 +39,7 @@ struct LoadInfoArgs
   bool                  upgradeInsecureRequests;
   bool                  verifySignedContent;
   bool                  enforceSRI;
+  bool                  forceAllowDataURI;
   bool                  forceInheritPrincipalDropped;
   uint64_t              innerWindowID;
   uint64_t              outerWindowID;
-- 
cgit v1.2.3


From a38e87d455f6ad3637deeae20d2ddc57430b498d Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 20:37:09 +0200
Subject: Bug 1329288 - Test ContentPolicy blocks opening a new window

---
 .../file_contentpolicy_block_window.html           |  5 ++
 docshell/test/navigation/mochitest.ini             |  2 +
 .../test_contentpolicy_block_window.html           | 96 ++++++++++++++++++++++
 ...est_contentpolicytype_targeted_link_iframe.html |  1 +
 4 files changed, 104 insertions(+)
 create mode 100644 docshell/test/navigation/file_contentpolicy_block_window.html
 create mode 100644 docshell/test/navigation/test_contentpolicy_block_window.html

diff --git a/docshell/test/navigation/file_contentpolicy_block_window.html b/docshell/test/navigation/file_contentpolicy_block_window.html
new file mode 100644
index 000000000..c51e574e5
--- /dev/null
+++ b/docshell/test/navigation/file_contentpolicy_block_window.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+This window should never be openend!
+</body>
+</html>
diff --git a/docshell/test/navigation/mochitest.ini b/docshell/test/navigation/mochitest.ini
index 0c35cf352..764e400a8 100644
--- a/docshell/test/navigation/mochitest.ini
+++ b/docshell/test/navigation/mochitest.ini
@@ -36,6 +36,7 @@ support-files =
   file_bug1300461_redirect.html
   file_bug1300461_redirect.html^headers^
   file_bug1300461_back.html
+  file_contentpolicy_block_window.html
 
 [test_bug13871.html]
 [test_bug270414.html]
@@ -62,3 +63,4 @@ skip-if = toolkit == 'android' #RANDOM
 [test_triggeringprincipal_window_open.html]
 [test_triggeringprincipal_parent_iframe_window_open.html]
 [test_triggeringprincipal_iframe_iframe_window_open.html]
+[test_contentpolicy_block_window.html]
diff --git a/docshell/test/navigation/test_contentpolicy_block_window.html b/docshell/test/navigation/test_contentpolicy_block_window.html
new file mode 100644
index 000000000..651be825c
--- /dev/null
+++ b/docshell/test/navigation/test_contentpolicy_block_window.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1329288
+-->
+<head>
+  <title>Test for Bug 1329288</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1329288">Mozilla Bug 1329288</a>
+
+
+<!-- have a testlink which we can use for the test to open a new window -->
+<a href="http://test1.example.org/tests/docshell/test/navigation/file_contentpolicy_block_window.html"
+   target="_blank"
+   id="testlink">This is a link</a>
+
+<script class="testbody" type="text/javascript">
+/*
+ * Description of the test:
+ * The test tries to open a new window and makes sure that a registered contentPolicy
+ * gets called with the right (a non null) 'context' for the TYPE_DOCUMENT load.
+ */
+
+const Cc = SpecialPowers.Cc;
+const Ci = SpecialPowers.Ci;
+
+var categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
+var componentManager = SpecialPowers.wrap(SpecialPowers.Components).manager
+                                    .QueryInterface(Ci.nsIComponentRegistrar);
+
+// Content policy / factory implementation for the test
+var policyID = SpecialPowers.wrap(SpecialPowers.Components).ID("{b80e19d0-878f-d41b-2654-194714a4115c}");
+var policyName = "@mozilla.org/testpolicy;1";
+var policy = {
+  // nsISupports implementation
+  QueryInterface: function(iid) {
+    iid = SpecialPowers.wrap(iid);
+    if (iid.equals(Ci.nsISupports) ||
+        iid.equals(Ci.nsIFactory) ||
+        iid.equals(Ci.nsIContentPolicy))
+      return this;
+    throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
+  },
+
+  // nsIFactory implementation
+  createInstance: function(outer, iid) {
+    return this.QueryInterface(iid);
+  },
+
+  // nsIContentPolicy implementation
+  shouldLoad: function(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra) {
+
+    if (SpecialPowers.wrap(contentLocation).spec !== document.getElementById("testlink").href) {
+      // not the URI we are looking for, allow the load
+      return Ci.nsIContentPolicy.ACCEPT;
+    }
+
+    is(contentType, Ci.nsIContentPolicy.TYPE_DOCUMENT,
+       "needs to be type document load");
+    ok(context, "context is not allowed to be null");
+    ok(context.name.endsWith("test_contentpolicy_block_window.html"),
+       "context should be the current window");
+
+    // remove the policy and finish test.
+    categoryManager.deleteCategoryEntry("content-policy", policyName, false);
+
+    setTimeout(function() {
+      // Component must be unregistered delayed, otherwise other content
+      // policy will not be removed from the category correctly
+      componentManager.unregisterFactory(policyID, policy);
+    }, 0);
+
+    SimpleTest.finish();
+    return Ci.nsIContentPolicy.REJECT_REQUEST;
+  },
+
+  shouldProcess: function(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra) {
+    return Ci.nsIContentPolicy.ACCEPT;
+  }
+}
+
+policy = SpecialPowers.wrapCallbackObject(policy);
+componentManager.registerFactory(policyID, "Test content policy", policyName, policy);
+categoryManager.addCategoryEntry("content-policy", policyName, policyName, false, true);
+
+SimpleTest.waitForExplicitFinish();
+
+// now everything is set up, let's start the test
+document.getElementById("testlink").click()
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html b/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html
index 7b1ab72dc..3ef243824 100644
--- a/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html
+++ b/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html
@@ -61,6 +61,7 @@ var policy = {
          "content policy type should TYPESUBDOCUMENT");
       categoryManager.deleteCategoryEntry("content-policy", POLICYNAME, false);
       SimpleTest.finish();
+      return Ci.nsIContentPolicy.REJECT_REQUEST;
     }
     return Ci.nsIContentPolicy.ACCEPT;
   },
-- 
cgit v1.2.3


From 95c46082414632687e3ddd52435d476ab9dc320f Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 20:38:02 +0200
Subject: Bug 1329288: Allow content policy consumers to identify contentPolicy
 checks from docshell

---
 docshell/base/nsDocShell.cpp                | 14 +++++++++++++-
 dom/security/nsCSPContext.cpp               |  5 +++--
 toolkit/modules/addons/WebRequestContent.js | 10 ++++++++++
 3 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index f3db4a3cb..b1fcc5c23 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -139,6 +139,7 @@
 #include "nsISiteSecurityService.h"
 #include "nsStructuredCloneContainer.h"
 #include "nsIStructuredCloneContainer.h"
+#include "nsISupportsPrimitives.h"
 #ifdef MOZ_PLACES
 #include "nsIFaviconService.h"
 #include "mozIPlacesPendingOperation.h"
@@ -9931,13 +9932,24 @@ nsDocShell::InternalLoad(nsIURI* aURI,
 #endif
     }
 
+    // Since Content Policy checks are performed within docShell as well as
+    // the ContentSecurityManager we need a reliable way to let certain
+    // nsIContentPolicy consumers ignore duplicate calls. Let's use the 'extra'
+    // argument to pass a specific identifier.
+    nsCOMPtr<nsISupportsString> extraStr =
+      do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+    NS_NAMED_LITERAL_STRING(msg, "conPolCheckFromDocShell");
+    rv = extraStr->SetData(msg);
+    NS_ENSURE_SUCCESS(rv, rv);
+
     int16_t shouldLoad = nsIContentPolicy::ACCEPT;
     rv = NS_CheckContentLoadPolicy(contentType,
                                    aURI,
                                    aTriggeringPrincipal,
                                    requestingContext,
                                    EmptyCString(),  // mime guess
-                                   nullptr,  // extra
+                                   extraStr,  // extra
                                    &shouldLoad);
 
     if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp
index a7517f65e..979bd915f 100644
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -171,9 +171,10 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
     }
   }
 
-  // aExtra is only non-null if the channel got redirected.
-  bool wasRedirected = (aExtra != nullptr);
+  // aExtra holds the original URI of the channel if the
+  // channel got redirected (until we fix Bug 1332422).
   nsCOMPtr<nsIURI> originalURI = do_QueryInterface(aExtra);
+  bool wasRedirected = originalURI;
 
   bool permitted = permitsInternal(dir,
                                    aContentLocation,
diff --git a/toolkit/modules/addons/WebRequestContent.js b/toolkit/modules/addons/WebRequestContent.js
index 219675e5b..f044a1cd4 100644
--- a/toolkit/modules/addons/WebRequestContent.js
+++ b/toolkit/modules/addons/WebRequestContent.js
@@ -80,6 +80,16 @@ var ContentPolicy = {
 
   shouldLoad(policyType, contentLocation, requestOrigin,
              node, mimeTypeGuess, extra, requestPrincipal) {
+
+    // Loads of TYPE_DOCUMENT and TYPE_SUBDOCUMENT perform a ConPol check
+    // within docshell as well as within the ContentSecurityManager. To avoid
+    // duplicate evaluations we ignore ConPol checks performed within docShell.
+    if (extra instanceof Ci.nsISupportsString) {
+      if (extra.data === "conPolCheckFromDocShell") {
+        return Ci.nsIContentPolicy.ACCEPT;
+      }
+    }
+
     if (requestPrincipal &&
         Services.scriptSecurityManager.isSystemPrincipal(requestPrincipal)) {
       return Ci.nsIContentPolicy.ACCEPT;
-- 
cgit v1.2.3


From 8af1b0c22a9c449746479b8a82494e43d60af573 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 21:00:39 +0200
Subject: Bug 1329570 - Restore missing error check in
 mozilla::dom::Location::GetPathname

native in moebius
---
 dom/base/Location.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp
index e3b614931..b17e733d5 100644
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -577,9 +577,10 @@ Location::GetPathname(nsAString& aPathname)
   aPathname.Truncate();
 
   nsCOMPtr<nsIURI> uri;
-  nsresult result = NS_OK;
-
-  result = GetURI(getter_AddRefs(uri));
+  nsresult result = GetURI(getter_AddRefs(uri));
+  if (NS_FAILED(result) || !uri) {
+    return result;
+  }
 
   nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(uri));
   if (url) {
-- 
cgit v1.2.3


From dbfad99a51062e663da19266219191c0dc3521be Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 21:20:53 +0200
Subject: Bug 1323683 - Fold nsIURIWithQuery into nsIURI

native in moebius
---
 caps/nsNullPrincipalURI.cpp       | 26 +++++++++++++++++
 dom/base/Location.cpp             | 14 ++++-----
 dom/url/URL.cpp                   | 40 ++++++--------------------
 image/decoders/icon/nsIconURI.cpp | 26 +++++++++++++++++
 modules/libjar/nsJARURI.cpp       |  1 -
 modules/libjar/nsJARURI.h         |  1 -
 netwerk/base/moz.build            |  1 -
 netwerk/base/nsIURI.idl           | 60 ++++++++++++++++++++++++++-------------
 netwerk/base/nsIURIWithQuery.idl  | 30 --------------------
 netwerk/base/nsIURL.idl           |  6 ++--
 netwerk/base/nsSimpleURI.cpp      |  6 +---
 netwerk/base/nsSimpleURI.h        |  4 +--
 netwerk/base/nsStandardURL.cpp    |  1 -
 netwerk/base/nsStandardURL.h      |  1 -
 14 files changed, 110 insertions(+), 107 deletions(-)
 delete mode 100644 netwerk/base/nsIURIWithQuery.idl

diff --git a/caps/nsNullPrincipalURI.cpp b/caps/nsNullPrincipalURI.cpp
index 891a29bd8..f8b867160 100644
--- a/caps/nsNullPrincipalURI.cpp
+++ b/caps/nsNullPrincipalURI.cpp
@@ -167,6 +167,32 @@ nsNullPrincipalURI::SetPath(const nsACString &aPath)
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP
+nsNullPrincipalURI::GetFilePath(nsACString &aFilePath)
+{
+  aFilePath.Truncate();
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetFilePath(const nsACString &aFilePath)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetQuery(nsACString &aQuery)
+{
+  aQuery.Truncate();
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetQuery(const nsACString &aQuery)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 NS_IMETHODIMP
 nsNullPrincipalURI::GetRef(nsACString &_ref)
 {
diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp
index b17e733d5..b6b95aaa6 100644
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -582,15 +582,12 @@ Location::GetPathname(nsAString& aPathname)
     return result;
   }
 
-  nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(uri));
-  if (url) {
-    nsAutoCString file;
+  nsAutoCString file;
 
-    result = url->GetFilePath(file);
+  result = uri->GetFilePath(file);
 
-    if (NS_SUCCEEDED(result)) {
-      AppendUTF8toUTF16(file, aPathname);
-    }
+  if (NS_SUCCEEDED(result)) {
+    AppendUTF8toUTF16(file, aPathname);
   }
 
   return result;
@@ -605,8 +602,7 @@ Location::SetPathname(const nsAString& aPathname)
     return rv;
   }
 
-  nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(uri));
-  if (url && NS_SUCCEEDED(url->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)))) {
+  if (NS_SUCCEEDED(uri->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)))) {
     return SetURI(uri);
   }
 
diff --git a/dom/url/URL.cpp b/dom/url/URL.cpp
index 1f15e1151..c8724c359 100644
--- a/dom/url/URL.cpp
+++ b/dom/url/URL.cpp
@@ -17,7 +17,6 @@
 #include "nsEscape.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "nsIIOService.h"
-#include "nsIURIWithQuery.h"
 #include "nsIURL.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
@@ -525,21 +524,10 @@ URLMainThread::GetPathname(nsAString& aPathname, ErrorResult& aRv) const
   // Do not throw!  Not having a valid URI or URL should result in an empty
   // string.
 
-  nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(mURI));
-  if (url) {
-    nsAutoCString file;
-    nsresult rv = url->GetFilePath(file);
-    if (NS_SUCCEEDED(rv)) {
-      CopyUTF8toUTF16(file, aPathname);
-    }
-
-    return;
-  }
-
-  nsAutoCString path;
-  nsresult rv = mURI->GetPath(path);
+  nsAutoCString file;
+  nsresult rv = mURI->GetFilePath(file);
   if (NS_SUCCEEDED(rv)) {
-    CopyUTF8toUTF16(path, aPathname);
+    CopyUTF8toUTF16(file, aPathname);
   }
 }
 
@@ -548,11 +536,7 @@ URLMainThread::SetPathname(const nsAString& aPathname, ErrorResult& aRv)
 {
   // Do not throw!
 
-  nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(mURI));
-  if (url) {
-    url->SetFilePath(NS_ConvertUTF16toUTF8(aPathname));
-    return;
-  }
+  mURI->SetFilePath(NS_ConvertUTF16toUTF8(aPathname));
 }
 
 void
@@ -566,13 +550,9 @@ URLMainThread::GetSearch(nsAString& aSearch, ErrorResult& aRv) const
   nsAutoCString search;
   nsresult rv;
 
-  nsCOMPtr<nsIURIWithQuery> url(do_QueryInterface(mURI));
-  if (url) {
-    rv = url->GetQuery(search);
-    if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
-      CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch);
-    }
-    return;
+  rv = mURI->GetQuery(search);
+  if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
+    CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch);
   }
 }
 
@@ -603,11 +583,7 @@ URLMainThread::SetSearchInternal(const nsAString& aSearch, ErrorResult& aRv)
 {
   // Ignore failures to be compatible with NS4.
 
-  nsCOMPtr<nsIURIWithQuery> uriWithQuery(do_QueryInterface(mURI));
-  if (uriWithQuery) {
-    uriWithQuery->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
-    return;
-  }
+  mURI->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
 }
 
 } // anonymous namespace
diff --git a/image/decoders/icon/nsIconURI.cpp b/image/decoders/icon/nsIconURI.cpp
index 2c2788c8f..632a733fe 100644
--- a/image/decoders/icon/nsIconURI.cpp
+++ b/image/decoders/icon/nsIconURI.cpp
@@ -371,6 +371,32 @@ nsMozIconURI::SetPath(const nsACString& aPath)
   return NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+nsMozIconURI::GetFilePath(nsACString& aFilePath)
+{
+  aFilePath.Truncate();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMozIconURI::SetFilePath(const nsACString& aFilePath)
+{
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsMozIconURI::GetQuery(nsACString& aQuery)
+{
+  aQuery.Truncate();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMozIconURI::SetQuery(const nsACString& aQuery)
+{
+  return NS_ERROR_FAILURE;
+}
+
 NS_IMETHODIMP
 nsMozIconURI::GetRef(nsACString& aRef)
 {
diff --git a/modules/libjar/nsJARURI.cpp b/modules/libjar/nsJARURI.cpp
index e46e51467..d1e4b5a59 100644
--- a/modules/libjar/nsJARURI.cpp
+++ b/modules/libjar/nsJARURI.cpp
@@ -41,7 +41,6 @@ NS_IMPL_RELEASE(nsJARURI)
 NS_INTERFACE_MAP_BEGIN(nsJARURI)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJARURI)
   NS_INTERFACE_MAP_ENTRY(nsIURI)
-  NS_INTERFACE_MAP_ENTRY(nsIURIWithQuery)
   NS_INTERFACE_MAP_ENTRY(nsIURL)
   NS_INTERFACE_MAP_ENTRY(nsIJARURI)
   NS_INTERFACE_MAP_ENTRY(nsISerializable)
diff --git a/modules/libjar/nsJARURI.h b/modules/libjar/nsJARURI.h
index 31271e4ac..d2608a5c6 100644
--- a/modules/libjar/nsJARURI.h
+++ b/modules/libjar/nsJARURI.h
@@ -41,7 +41,6 @@ class nsJARURI final : public nsIJARURI,
 public:
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIURI
-    NS_DECL_NSIURIWITHQUERY
     NS_DECL_NSIURL
     NS_DECL_NSIJARURI
     NS_DECL_NSISERIALIZABLE
diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build
index 3b731db10..5de1eea81 100644
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -132,7 +132,6 @@ XPIDL_SOURCES += [
     'nsIURIClassifier.idl',
     'nsIURIWithBlobImpl.idl',
     'nsIURIWithPrincipal.idl',
-    'nsIURIWithQuery.idl',
     'nsIURL.idl',
     'nsIURLParser.idl',
     'nsPILoadGroupInternal.idl',
diff --git a/netwerk/base/nsIURI.idl b/netwerk/base/nsIURI.idl
index 2384c5fd9..ef163813a 100644
--- a/netwerk/base/nsIURI.idl
+++ b/netwerk/base/nsIURI.idl
@@ -10,18 +10,18 @@
  * provides accessors to set and query the most basic components of an URI.
  * Subclasses, including nsIURL, impose greater structure on the URI.
  *
- * This interface follows Tim Berners-Lee's URI spec (RFC2396) [1], where the
+ * This interface follows Tim Berners-Lee's URI spec (RFC3986) [1], where the
  * basic URI components are defined as such:
  * <pre>
- *      ftp://username:password@hostname:portnumber/pathname#ref
- *      \ /   \               / \      / \        /\         \ /
- *       -     ---------------   ------   --------  |         -
- *       |            |             |        |      |         |
- *       |            |             |        |      |        Ref
- *       |            |             |       Port    \        /
- *       |            |            Host      /       --------
- *       |         UserPass                 /	         |
- *     Scheme                              /	        Path
+ *      ftp://username:password@hostname:portnumber/pathname?query#ref
+ *      \ /   \               / \      / \        /\       / \   / \ /
+ *       -     ---------------   ------   --------  -------   ---   -
+ *       |            |             |        |         |       |    |
+ *       |            |             |        |      FilePath Query Ref
+ *       |            |             |       Port       \            /
+ *       |            |            Host      /          ------------
+ *       |         UserPass                 /	              |
+ *     Scheme                              /	             Path
  *       \                                /
  *        --------------------------------
  *                       |
@@ -30,13 +30,9 @@
  * The definition of the URI components has been extended to allow for
  * internationalized domain names [2] and the more generic IRI structure [3].
  *
- * Note also that the RFC defines #-separated fragment identifiers as being
- * "not part of the URI".  Despite this, we bundle them as part of the URI, for
- * convenience.
- *
- * [1] http://www.ietf.org/rfc/rfc2396.txt
- * [2] http://www.ietf.org/internet-drafts/draft-ietf-idn-idna-06.txt
- * [3] http://www.ietf.org/internet-drafts/draft-masinter-url-i18n-08.txt
+ * [1] https://tools.ietf.org/html/rfc3986
+ * [2] https://tools.ietf.org/html/rfc5890
+ * [3] https://tools.ietf.org/html/rfc3987
  */
 
 %{C++
@@ -116,7 +112,7 @@ interface nsIURI : nsISupports
 
     /**
      * The Scheme is the protocol to which this URI refers.  The scheme is
-     * restricted to the US-ASCII charset per RFC2396.  Setting this is
+     * restricted to the US-ASCII charset per RFC3986.  Setting this is
      * highly discouraged outside of a protocol handler implementation, since
      * that will generally lead to incorrect results.
      */
@@ -174,6 +170,9 @@ interface nsIURI : nsISupports
      * empty, depending on the protocol).
      *
      * Some characters may be escaped.
+     *
+     * This attribute contains query and ref parts for historical reasons.
+     * Use the 'filePath' attribute if you do not want those parts included.
      */
     attribute AUTF8String path;
 
@@ -281,10 +280,31 @@ interface nsIURI : nsISupports
     /**
      * returns a string for the current URI with the ref element cleared.
      */
-   readonly attribute AUTF8String specIgnoringRef;
+    readonly attribute AUTF8String specIgnoringRef;
 
     /**
      * Returns if there is a reference portion (the part after the "#") of the URI.
      */
-   readonly attribute boolean hasRef;
+    readonly attribute boolean hasRef;
+
+    /************************************************************************
+     * Additional attributes added for .query support:
+     */
+
+    /**
+     * Returns a path including the directory and file portions of a
+     * URL.  For example, the filePath of "http://host/foo/bar.html#baz"
+     * is "/foo/bar.html".
+     *
+     * Some characters may be escaped.
+     */
+    attribute AUTF8String filePath;
+
+    /**
+     * Returns the query portion (the part after the "?") of the URL.
+     * If there isn't one, an empty string is returned.
+     *
+     * Some characters may be escaped.
+     */
+    attribute AUTF8String query;
 };
diff --git a/netwerk/base/nsIURIWithQuery.idl b/netwerk/base/nsIURIWithQuery.idl
deleted file mode 100644
index 749b2773d..000000000
--- a/netwerk/base/nsIURIWithQuery.idl
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 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/. */
-
-#include "nsIURI.idl"
-
-/**
- * nsIURIWithQuery is implemented by URIs which have a query parameter.
- * This is useful for the URL API.
- */
-[scriptable, uuid(367510ee-8556-435a-8f99-b5fd357e08cc)]
-interface nsIURIWithQuery : nsIURI
-{
-    /**
-     * Returns a path including the directory and file portions of a
-     * URL.  For example, the filePath of "http://host/foo/bar.html#baz"
-     * is "/foo/bar.html".
-     *
-     * Some characters may be escaped.
-     */
-    attribute AUTF8String filePath;
-
-    /**
-     * Returns the query portion (the part after the "?") of the URL.
-     * If there isn't one, an empty string is returned.
-     *
-     * Some characters may be escaped.
-     */
-    attribute AUTF8String query;
-};
diff --git a/netwerk/base/nsIURL.idl b/netwerk/base/nsIURL.idl
index aeaa3f694..9ff6c3dcd 100644
--- a/netwerk/base/nsIURL.idl
+++ b/netwerk/base/nsIURL.idl
@@ -3,7 +3,7 @@
  * 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/. */
 
-#include "nsIURIWithQuery.idl"
+#include "nsIURI.idl"
 
 /**
  * The nsIURL interface provides convenience methods that further
@@ -20,7 +20,7 @@
  *                        filePath
  */
 [scriptable, uuid(86adcd89-0b70-47a2-b0fe-5bb2c5f37e31)]
-interface nsIURL : nsIURIWithQuery
+interface nsIURL : nsIURI
 {
     /*************************************************************************
      * The URL path is broken down into the following principal components:
@@ -28,7 +28,7 @@ interface nsIURL : nsIURIWithQuery
      * attribute AUTF8String filePath;
      * attribute AUTF8String query;
      *
-     * These are inherited from nsIURIWithQuery.
+     * These are inherited from nsIURI.
      */
 
     /*************************************************************************
diff --git a/netwerk/base/nsSimpleURI.cpp b/netwerk/base/nsSimpleURI.cpp
index ae5c51a1e..dbc0dc817 100644
--- a/netwerk/base/nsSimpleURI.cpp
+++ b/netwerk/base/nsSimpleURI.cpp
@@ -48,7 +48,7 @@ nsSimpleURI::~nsSimpleURI()
 NS_IMPL_ADDREF(nsSimpleURI)
 NS_IMPL_RELEASE(nsSimpleURI)
 NS_INTERFACE_TABLE_HEAD(nsSimpleURI)
-NS_INTERFACE_TABLE(nsSimpleURI, nsIURI, nsIURIWithQuery, nsISerializable,
+NS_INTERFACE_TABLE(nsSimpleURI, nsIURI, nsISerializable,
                    nsIClassInfo, nsIMutable, nsIIPCSerializableURI)
 NS_INTERFACE_TABLE_TO_MAP_SEGUE
   if (aIID.Equals(kThisSimpleURIImplementationCID))
@@ -784,10 +784,6 @@ nsSimpleURI::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
 }
 
-//----------------------------------------------------------------------------
-// nsSimpleURI::nsIURIWithQuery
-//----------------------------------------------------------------------------
-
 NS_IMETHODIMP
 nsSimpleURI::GetFilePath(nsACString& aFilePath)
 {
diff --git a/netwerk/base/nsSimpleURI.h b/netwerk/base/nsSimpleURI.h
index 29bc9b313..842136ed6 100644
--- a/netwerk/base/nsSimpleURI.h
+++ b/netwerk/base/nsSimpleURI.h
@@ -8,7 +8,6 @@
 
 #include "mozilla/MemoryReporting.h"
 #include "nsIURI.h"
-#include "nsIURIWithQuery.h"
 #include "nsISerializable.h"
 #include "nsString.h"
 #include "nsIClassInfo.h"
@@ -28,7 +27,7 @@ namespace net {
 }
 
 class nsSimpleURI
-    : public nsIURIWithQuery
+    : public nsIURI
     , public nsISerializable
     , public nsIClassInfo
     , public nsIMutable
@@ -41,7 +40,6 @@ protected:
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIURI
-    NS_DECL_NSIURIWITHQUERY
     NS_DECL_NSISERIALIZABLE
     NS_DECL_NSICLASSINFO
     NS_DECL_NSIMUTABLE
diff --git a/netwerk/base/nsStandardURL.cpp b/netwerk/base/nsStandardURL.cpp
index 0cdd2a7b5..e2a290e4d 100644
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -1182,7 +1182,6 @@ NS_IMPL_RELEASE(nsStandardURL)
 NS_INTERFACE_MAP_BEGIN(nsStandardURL)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStandardURL)
     NS_INTERFACE_MAP_ENTRY(nsIURI)
-    NS_INTERFACE_MAP_ENTRY(nsIURIWithQuery)
     NS_INTERFACE_MAP_ENTRY(nsIURL)
     NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFileURL, mSupportsFileURL)
     NS_INTERFACE_MAP_ENTRY(nsIStandardURL)
diff --git a/netwerk/base/nsStandardURL.h b/netwerk/base/nsStandardURL.h
index 90f7f7db2..0ca345572 100644
--- a/netwerk/base/nsStandardURL.h
+++ b/netwerk/base/nsStandardURL.h
@@ -54,7 +54,6 @@ protected:
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIURI
-    NS_DECL_NSIURIWITHQUERY
     NS_DECL_NSIURL
     NS_DECL_NSIFILEURL
     NS_DECL_NSISTANDARDURL
-- 
cgit v1.2.3


From 29bd11c3cd6ff41f7167530f9bbcd9d195b7c427 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 21:47:27 +0200
Subject: Bug 1182569: Use AsyncOpen2 for docshell loads

native in moebius
---
 docshell/base/nsDocShell.cpp      | 23 +++---------------
 dom/jsurl/nsJSProtocolHandler.cpp | 49 ++++++++++++++-------------------------
 uriloader/base/nsURILoader.cpp    |  2 +-
 3 files changed, 21 insertions(+), 53 deletions(-)

diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index b1fcc5c23..6810d0179 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -69,7 +69,6 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScrollableFrame.h"
-#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
 #include "nsISeekableStream.h"
 #include "nsAutoPtr.h"
 #include "nsQueryObject.h"
@@ -1644,7 +1643,7 @@ nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
                                          uri,
                                          aStream,
                                          triggeringPrincipal,
-                                         nsILoadInfo::SEC_NORMAL,
+                                         nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                                          nsIContentPolicy::TYPE_OTHER,
                                          aContentType,
                                          aContentCharset);
@@ -9943,23 +9942,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
     rv = extraStr->SetData(msg);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    int16_t shouldLoad = nsIContentPolicy::ACCEPT;
-    rv = NS_CheckContentLoadPolicy(contentType,
-                                   aURI,
-                                   aTriggeringPrincipal,
-                                   requestingContext,
-                                   EmptyCString(),  // mime guess
-                                   extraStr,  // extra
-                                   &shouldLoad);
-
-    if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
-      if (NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) {
-        return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
-      }
-
-      return NS_ERROR_CONTENT_BLOCKED;
-    }
-
     // If HSTS priming was set by nsMixedContentBlocker::ShouldLoad, and we
     // would block due to mixed content, go ahead and block here. If we try to
     // proceed with priming, we will error out later on.
@@ -10949,7 +10931,8 @@ nsDocShell::DoURILoad(nsIURI* aURI,
   }
 
   nsLoadFlags loadFlags = mDefaultLoadFlags;
-  nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL;
+  nsSecurityFlags securityFlags =
+    nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
 
   if (aFirstParty) {
     // tag first party URL loads
diff --git a/dom/jsurl/nsJSProtocolHandler.cpp b/dom/jsurl/nsJSProtocolHandler.cpp
index cdb63f890..90171db10 100644
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -36,7 +36,6 @@
 #include "nsIContentViewer.h"
 #include "nsIXPConnect.h"
 #include "nsContentUtils.h"
-#include "nsNullPrincipal.h"
 #include "nsJSUtils.h"
 #include "nsThreadUtils.h"
 #include "nsIScriptChannel.h"
@@ -336,7 +335,7 @@ public:
     NS_FORWARD_SAFE_NSIPROPERTYBAG(mPropertyBag)
     NS_FORWARD_SAFE_NSIPROPERTYBAG2(mPropertyBag)
 
-    nsresult Init(nsIURI *aURI);
+    nsresult Init(nsIURI *aURI, nsILoadInfo* aLoadInfo);
 
     // Actually evaluate the script.
     void EvaluateScript();
@@ -354,17 +353,16 @@ protected:
     nsCOMPtr<nsIChannel>    mStreamChannel;
     nsCOMPtr<nsIPropertyBag2> mPropertyBag;
     nsCOMPtr<nsIStreamListener> mListener;  // Our final listener
-    nsCOMPtr<nsISupports> mContext; // The context passed to AsyncOpen
     nsCOMPtr<nsPIDOMWindowInner> mOriginalInnerWindow;  // The inner window our load
                                                         // started against.
-    // If we blocked onload on a document in AsyncOpen, this is the document we
+    // If we blocked onload on a document in AsyncOpen2, this is the document we
     // did it on.
     nsCOMPtr<nsIDocument>   mDocumentOnloadBlockedOn;
 
     nsresult mStatus; // Our status
 
     nsLoadFlags             mLoadFlags;
-    nsLoadFlags             mActualLoadFlags; // See AsyncOpen
+    nsLoadFlags             mActualLoadFlags; // See AsyncOpen2
 
     RefPtr<nsJSThunk>     mIOThunk;
     PopupControlState       mPopupState;
@@ -404,7 +402,7 @@ nsresult nsJSChannel::StopAll()
     return rv;
 }
 
-nsresult nsJSChannel::Init(nsIURI *aURI)
+nsresult nsJSChannel::Init(nsIURI* aURI, nsILoadInfo* aLoadInfo)
 {
     RefPtr<nsJSURI> jsURI;
     nsresult rv = aURI->QueryInterface(kJSURICID,
@@ -418,21 +416,13 @@ nsresult nsJSChannel::Init(nsIURI *aURI)
     // Remember, until AsyncOpen is called, the script will not be evaluated
     // and the underlying Input Stream will not be created...
     nsCOMPtr<nsIChannel> channel;
-
-    nsCOMPtr<nsIPrincipal> nullPrincipal = nsNullPrincipal::Create();
-
-    // If the resultant script evaluation actually does return a value, we
-    // treat it as html.
-    // The following channel is never openend, so it does not matter what
-    // securityFlags we pass; let's follow the principle of least privilege.
-    rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
-                                  aURI,
-                                  mIOThunk,
-                                  nullPrincipal,
-                                  nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
-                                  nsIContentPolicy::TYPE_OTHER,
-                                  NS_LITERAL_CSTRING("text/html"));
-    if (NS_FAILED(rv)) return rv;
+    rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
+                                          aURI,
+                                          mIOThunk,
+                                          NS_LITERAL_CSTRING("text/html"),
+                                          EmptyCString(),
+                                          aLoadInfo);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     rv = mIOThunk->Init(aURI);
     if (NS_SUCCEEDED(rv)) {
@@ -563,6 +553,7 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
                "security flags in loadInfo but asyncOpen2() not called");
     }
 #endif
+    MOZ_RELEASE_ASSERT(!aContext, "please call AsyncOpen2()");
 
     NS_ENSURE_ARG(aListener);
 
@@ -584,7 +575,6 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
     }
     
     mListener = aListener;
-    mContext = aContext;
 
     mIsActive = true;
 
@@ -655,7 +645,7 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
             return mStatus;
         }
 
-        // We're returning success from asyncOpen(), but we didn't open a
+        // We're returning success from asyncOpen2(), but we didn't open a
         // stream channel.  We'll have to notify ourselves, but make sure to do
         // it asynchronously.
         method = &nsJSChannel::NotifyListener;            
@@ -772,7 +762,7 @@ nsJSChannel::EvaluateScript()
         return;
     }
     
-    mStatus = mStreamChannel->AsyncOpen(this, mContext);
+    mStatus = mStreamChannel->AsyncOpen2(this);
     if (NS_SUCCEEDED(mStatus)) {
         // mStreamChannel will call OnStartRequest and OnStopRequest on
         // us, so we'll be sure to call them on our listener.
@@ -800,8 +790,8 @@ nsJSChannel::EvaluateScript()
 void
 nsJSChannel::NotifyListener()
 {
-    mListener->OnStartRequest(this, mContext);
-    mListener->OnStopRequest(this, mContext, mStatus);
+    mListener->OnStartRequest(this, nullptr);
+    mListener->OnStopRequest(this, nullptr, mStatus);
 
     CleanupStrongRefs();
 }
@@ -810,7 +800,6 @@ void
 nsJSChannel::CleanupStrongRefs()
 {
     mListener = nullptr;
-    mContext = nullptr;
     mOriginalInnerWindow = nullptr;
     if (mDocumentOnloadBlockedOn) {
         mDocumentOnloadBlockedOn->UnblockOnload(false);
@@ -1240,11 +1229,7 @@ nsJSProtocolHandler::NewChannel2(nsIURI* uri,
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    rv = channel->Init(uri);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // set the loadInfo on the new channel
-    rv = channel->SetLoadInfo(aLoadInfo);
+    rv = channel->Init(uri, aLoadInfo);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (NS_SUCCEEDED(rv)) {
diff --git a/uriloader/base/nsURILoader.cpp b/uriloader/base/nsURILoader.cpp
index 69475d68f..ea370aa37 100644
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -834,7 +834,7 @@ NS_IMETHODIMP nsURILoader::OpenURI(nsIChannel *channel,
     // the preferred protocol handler. 
 
     // But for now, I'm going to let necko do the work for us....
-    rv = channel->AsyncOpen(loader, nullptr);
+    rv = channel->AsyncOpen2(loader);
 
     // no content from this load - that's OK.
     if (rv == NS_ERROR_NO_CONTENT) {
-- 
cgit v1.2.3


From 2e33335820b2816bee111e78588ac82e401c86ae Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 21:51:49 +0200
Subject: Bug 1182569: Update ContentSecurityManager to handle docshell loads

native in moebius
---
 dom/security/nsContentSecurityManager.cpp | 81 ++++++++++++++++++++++++-------
 netwerk/base/nsNetUtil.cpp                | 14 ++----
 2 files changed, 68 insertions(+), 27 deletions(-)

diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp
index 9329c558a..458f41144 100644
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -10,6 +10,9 @@
 #include "nsIStreamListener.h"
 #include "nsIDocument.h"
 #include "nsMixedContentBlocker.h"
+#include "nsCDefaultURIFixup.h"
+#include "nsIURIFixup.h"
+#include "nsINestedURI.h"
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/TabChild.h"
@@ -244,10 +247,6 @@ DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
 static nsresult
 DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
 {
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
-  NS_ENSURE_SUCCESS(rv, rv);
-
   nsContentPolicyType contentPolicyType =
     aLoadInfo->GetExternalContentPolicyType();
   nsContentPolicyType internalContentPolicyType =
@@ -255,12 +254,24 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
   nsCString mimeTypeGuess;
   nsCOMPtr<nsINode> requestingContext = nullptr;
 
-#ifdef DEBUG
-  // Don't enforce TYPE_DOCUMENT assertions for loads
-  // initiated by javascript tests.
-  bool skipContentTypeCheck = false;
-  skipContentTypeCheck = Preferences::GetBool("network.loadinfo.skip_type_assertion");
-#endif
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+      contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
+    // TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
+    // be wyciwyg:// channels. Let's fix up the URI so we can
+    // perform proper security checks.
+    nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
+    if (NS_SUCCEEDED(rv) && urifixup) {
+      nsCOMPtr<nsIURI> fixedURI;
+      rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
+      if (NS_SUCCEEDED(rv)) {
+        uri = fixedURI;
+      }
+    }
+  }
 
   switch(contentPolicyType) {
     case nsIContentPolicy::TYPE_OTHER: {
@@ -294,16 +305,14 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
     }
 
     case nsIContentPolicy::TYPE_DOCUMENT: {
-      MOZ_ASSERT(skipContentTypeCheck || false, "contentPolicyType not supported yet");
+      mimeTypeGuess = EmptyCString();
+      requestingContext = aLoadInfo->LoadingNode();
       break;
     }
 
     case nsIContentPolicy::TYPE_SUBDOCUMENT: {
       mimeTypeGuess = NS_LITERAL_CSTRING("text/html");
       requestingContext = aLoadInfo->LoadingNode();
-      MOZ_ASSERT(!requestingContext ||
-                 requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
-                 "type_subdocument requires requestingContext of type Document");
       break;
     }
 
@@ -447,18 +456,32 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
       MOZ_ASSERT(false, "can not perform security check without a valid contentType");
   }
 
+  // For document loads we use the triggeringPrincipal as the originPrincipal.
+  // Note the the loadingPrincipal for loads of TYPE_DOCUMENT is a nullptr.
+  nsCOMPtr<nsIPrincipal> principal =
+    (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+    contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)
+    ? aLoadInfo->TriggeringPrincipal()
+    : aLoadInfo->LoadingPrincipal();
+
   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
   rv = NS_CheckContentLoadPolicy(internalContentPolicyType,
                                  uri,
-                                 aLoadInfo->LoadingPrincipal(),
+                                 principal,
                                  requestingContext,
                                  mimeTypeGuess,
                                  nullptr,        //extra,
                                  &shouldLoad,
                                  nsContentUtils::GetContentPolicy(),
                                  nsContentUtils::GetSecurityManager());
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (NS_CP_REJECTED(shouldLoad)) {
+
+  if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
+    if ((NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) &&
+        (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+         contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)) {
+      // for docshell loads we might have to return SHOW_ALT.
+      return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
+    }
     return NS_ERROR_CONTENT_BLOCKED;
   }
 
@@ -606,6 +629,30 @@ nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  nsContentPolicyType contentPolicyType =
+    loadInfo->GetExternalContentPolicyType();
+
+  if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+      contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
+    // query the nested URI for security checks like in the case of view-source
+    nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(uri);
+    if (nestedURI) {
+      nestedURI->GetInnerURI(getter_AddRefs(uri));
+    }
+
+    // TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
+    // be wyciwyg:// channels. Let's fix up the URI so we can
+    // perform proper security checks.
+    nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
+    if (NS_SUCCEEDED(rv) && urifixup) {
+      nsCOMPtr<nsIURI> fixedURI;
+      rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
+      if (NS_SUCCEEDED(rv)) {
+        uri = fixedURI;
+      }
+    }
+  }
+
   // Handle cookie policies
   uint32_t cookiePolicy = loadInfo->GetCookiePolicy();
   if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {
diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp
index 8ff3e788f..bc9bcf88a 100644
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -1285,16 +1285,10 @@ NS_HasBeenCrossOrigin(nsIChannel* aChannel, bool aReport)
   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
   MOZ_RELEASE_ASSERT(loadInfo, "Origin tracking only works for channels created with a loadinfo");
 
-#ifdef DEBUG
-  // Don't enforce TYPE_DOCUMENT assertions for loads
-  // initiated by javascript tests.
-  bool skipContentTypeCheck = false;
-  skipContentTypeCheck = Preferences::GetBool("network.loadinfo.skip_type_assertion");
-#endif
-
-  MOZ_ASSERT(skipContentTypeCheck ||
-             loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT,
-             "calling NS_HasBeenCrossOrigin on a top level load");
+  // TYPE_DOCUMENT loads have a null LoadingPrincipal and can not be cross origin.
+  if (!loadInfo->LoadingPrincipal()) {
+    return false;
+  }
 
   // Always treat tainted channels as cross-origin.
   if (loadInfo->GetTainting() != LoadTainting::Basic) {
-- 
cgit v1.2.3


From 5b0f4649b3fee771379af60ec04d43b8a525cf80 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 21:59:46 +0200
Subject: Bug 1182569 - Skip security check for plugins using newstream
 attribute

native in moebius
---
 docshell/base/nsDocShell.cpp               | 28 ++++++++++++++++++++--------
 docshell/base/nsDocShell.h                 |  6 ++++--
 docshell/base/nsILinkHandler.h             | 10 ++++++++--
 dom/base/nsContentUtils.cpp                |  2 +-
 dom/plugins/base/nsPluginInstanceOwner.cpp | 25 ++++++++++++++-----------
 5 files changed, 47 insertions(+), 24 deletions(-)

diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 6810d0179..8167a76ec 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -13888,7 +13888,8 @@ public:
                    const nsAString& aFileName,
                    nsIInputStream* aPostDataStream,
                    nsIInputStream* aHeadersDataStream,
-                   bool aIsTrusted);
+                   bool aIsTrusted,
+                   nsIPrincipal* aTriggeringPrincipal);
 
   NS_IMETHOD Run() override
   {
@@ -13904,7 +13905,7 @@ public:
       mHandler->OnLinkClickSync(mContent, mURI,
                                 mTargetSpec.get(), mFileName,
                                 mPostDataStream, mHeadersDataStream,
-                                nullptr, nullptr);
+                                nullptr, nullptr, mTriggeringPrincipal);
     }
     return NS_OK;
   }
@@ -13919,6 +13920,7 @@ private:
   nsCOMPtr<nsIContent> mContent;
   PopupControlState mPopupState;
   bool mIsTrusted;
+  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
 };
 
 OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
@@ -13928,7 +13930,8 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
                                    const nsAString& aFileName,
                                    nsIInputStream* aPostDataStream,
                                    nsIInputStream* aHeadersDataStream,
-                                   bool aIsTrusted)
+                                   bool aIsTrusted,
+                                   nsIPrincipal* aTriggeringPrincipal)
   : mHandler(aHandler)
   , mURI(aURI)
   , mTargetSpec(aTargetSpec)
@@ -13938,6 +13941,7 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
   , mContent(aContent)
   , mPopupState(mHandler->mScriptGlobal->GetPopupControlState())
   , mIsTrusted(aIsTrusted)
+  , mTriggeringPrincipal(aTriggeringPrincipal)
 {
 }
 
@@ -13948,7 +13952,8 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
                         const nsAString& aFileName,
                         nsIInputStream* aPostDataStream,
                         nsIInputStream* aHeadersDataStream,
-                        bool aIsTrusted)
+                        bool aIsTrusted,
+                        nsIPrincipal* aTriggeringPrincipal)
 {
   NS_ASSERTION(NS_IsMainThread(), "wrong thread");
 
@@ -13987,7 +13992,8 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
 
   nsCOMPtr<nsIRunnable> ev =
     new OnLinkClickEvent(this, aContent, aURI, target.get(), aFileName,
-                         aPostDataStream, aHeadersDataStream, aIsTrusted);
+                         aPostDataStream, aHeadersDataStream,
+                         aIsTrusted, aTriggeringPrincipal);
   return NS_DispatchToCurrentThread(ev);
 }
 
@@ -13999,7 +14005,8 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
                             nsIInputStream* aPostDataStream,
                             nsIInputStream* aHeadersDataStream,
                             nsIDocShell** aDocShell,
-                            nsIRequest** aRequest)
+                            nsIRequest** aRequest,
+                            nsIPrincipal* aTriggeringPrincipal)
 {
   // Initialize the DocShell / Request
   if (aDocShell) {
@@ -14122,13 +14129,18 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
+  // if the triggeringPrincipal is not passed explicitly, then we
+  // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
+  nsCOMPtr<nsIPrincipal> triggeringPrincipal =
+    aTriggeringPrincipal ? aTriggeringPrincipal
+                         : aContent->NodePrincipal();
+
   nsresult rv = InternalLoad(clonedURI,                 // New URI
                              nullptr,                   // Original URI
                              false,                     // LoadReplace
                              referer,                   // Referer URI
                              refererPolicy,             // Referer policy
-                             aContent->NodePrincipal(), // Triggering is our node's
-                                                        // principal
+                             triggeringPrincipal,
                              aContent->NodePrincipal(),
                              flags,
                              target,                    // Window target
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index 63a4e3358..f510a15b0 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -201,7 +201,8 @@ public:
                          const nsAString& aFileName,
                          nsIInputStream* aPostDataStream,
                          nsIInputStream* aHeadersDataStream,
-                         bool aIsTrusted) override;
+                         bool aIsTrusted,
+                         nsIPrincipal* aTriggeringPrincipal) override;
   NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
                              nsIURI* aURI,
                              const char16_t* aTargetSpec,
@@ -209,7 +210,8 @@ public:
                              nsIInputStream* aPostDataStream = 0,
                              nsIInputStream* aHeadersDataStream = 0,
                              nsIDocShell** aDocShell = 0,
-                             nsIRequest** aRequest = 0) override;
+                             nsIRequest** aRequest = 0,
+                             nsIPrincipal* aTriggeringPrincipal = nullptr) override;
   NS_IMETHOD OnOverLink(nsIContent* aContent,
                         nsIURI* aURI,
                         const char16_t* aTargetSpec) override;
diff --git a/docshell/base/nsILinkHandler.h b/docshell/base/nsILinkHandler.h
index 7cdcd566d..7069f1f1d 100644
--- a/docshell/base/nsILinkHandler.h
+++ b/docshell/base/nsILinkHandler.h
@@ -37,6 +37,8 @@ public:
    * @param aFileName non-null when the link should be downloaded as the given file
    * @param aHeadersDataStream ???
    * @param aIsTrusted false if the triggerer is an untrusted DOM event.
+   * @param aTriggeringPrincipal, if not passed explicitly we fall back to
+   *        the document's principal.
    */
   NS_IMETHOD OnLinkClick(nsIContent* aContent,
                          nsIURI* aURI,
@@ -44,7 +46,8 @@ public:
                          const nsAString& aFileName,
                          nsIInputStream* aPostDataStream,
                          nsIInputStream* aHeadersDataStream,
-                         bool aIsTrusted) = 0;
+                         bool aIsTrusted,
+                         nsIPrincipal* aTriggeringPrincipal) = 0;
 
   /**
    * Process a click on a link.
@@ -61,6 +64,8 @@ public:
    * @param aHeadersDataStream ???
    * @param aDocShell (out-param) the DocShell that the request was opened on
    * @param aRequest the request that was opened
+   * @param aTriggeringPrincipal, if not passed explicitly we fall back to
+   *        the document's principal.
    */
   NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
                              nsIURI* aURI,
@@ -69,7 +74,8 @@ public:
                              nsIInputStream* aPostDataStream = 0,
                              nsIInputStream* aHeadersDataStream = 0,
                              nsIDocShell** aDocShell = 0,
-                             nsIRequest** aRequest = 0) = 0;
+                             nsIRequest** aRequest = 0,
+                             nsIPrincipal* aTriggeringPrincipal = nullptr) = 0;
 
   /**
    * Process a mouse-over a link.
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index ef87a250e..c3ff2b4d8 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -5100,7 +5100,7 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
 
     handler->OnLinkClick(aContent, aLinkURI,
                          fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
-                         fileName, nullptr, nullptr, aIsTrusted);
+                         fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal());
   }
 }
 
diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp
index b7651be1a..7de6c2b73 100644
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -535,16 +535,6 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
   nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, baseURI);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
-  if (aDoCheckLoadURIChecks) {
-    nsCOMPtr<nsIScriptSecurityManager> secMan(
-      do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
-    NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
-
-    rv = secMan->CheckLoadURIWithPrincipal(content->NodePrincipal(), uri,
-                                           nsIScriptSecurityManager::STANDARD);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
   nsCOMPtr<nsIInputStream> headersDataStream;
   if (aPostStream && aHeadersData) {
     if (!aHeadersDataLen)
@@ -563,8 +553,21 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
     Preferences::GetInt("privacy.popups.disable_from_plugins");
   nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups);
 
+
+  // if security checks (in particular CheckLoadURIWithPrincipal) needs
+  // to be skipped we are creating a codebasePrincipal to make sure
+  // that security check succeeds. Please note that we do not want to
+  // fall back to using the systemPrincipal, because that would also
+  // bypass ContentPolicy checks which should still be enforced.
+  nsCOMPtr<nsIPrincipal> triggeringPrincipal;
+  if (!aDoCheckLoadURIChecks) {
+    mozilla::PrincipalOriginAttributes attrs =
+      BasePrincipal::Cast(content->NodePrincipal())->OriginAttributesRef();
+    triggeringPrincipal = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
+  }
+
   rv = lh->OnLinkClick(content, uri, unitarget.get(), NullString(),
-                       aPostStream, headersDataStream, true);
+                       aPostStream, headersDataStream, true, triggeringPrincipal);
 
   return rv;
 }
-- 
cgit v1.2.3


From b73225e886f84182384a2b5b09f83e51501bdc38 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 22:02:20 +0200
Subject: Bug 1182569: Update tests when converting docshell loads to use
 AynscOpen2

native in moebius
---
 dom/base/test/file_simplecontentpolicy.js      |  1 -
 dom/plugins/test/mochitest/test_bug813906.html | 22 ++++++++++++++++++----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/dom/base/test/file_simplecontentpolicy.js b/dom/base/test/file_simplecontentpolicy.js
index 1f9606c49..2727b9530 100644
--- a/dom/base/test/file_simplecontentpolicy.js
+++ b/dom/base/test/file_simplecontentpolicy.js
@@ -39,7 +39,6 @@ var policy = {
   {
     // Remember last content type seen for the test url
     if (contentLocation.spec.endsWith(urlSuffix)) {
-      assert.ok(frame === browserElement, "correct <browser> element");
       sendAsyncMessage("shouldLoad", {contentType: contentType, isTopLevel: isTopLevel});
       return Ci.nsIContentPolicy.REJECT_REQUEST;
     }
diff --git a/dom/plugins/test/mochitest/test_bug813906.html b/dom/plugins/test/mochitest/test_bug813906.html
index 04c34daaf..d18dbbff2 100644
--- a/dom/plugins/test/mochitest/test_bug813906.html
+++ b/dom/plugins/test/mochitest/test_bug813906.html
@@ -18,21 +18,35 @@ function f() {
 </script>
 
 <script type="application/javascript">
+SimpleTest.requestFlakyTimeout(
+  "Blocking an iframe does not cause the onerror event to be fired");
+
 SimpleTest.waitForExplicitFinish();
 setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
 
 var frameLoadCount = 0;
+
+function frameNavBlocked() {
+  isnot(SpecialPowers.wrap(window.frame1).location.href.indexOf('chrome://'),
+        0, 'plugin shouldnt be able to cause navigation to chrome URLs');
+  SimpleTest.finish();
+}
+
 function frameLoaded() {
   frameLoadCount++;
   if (frameLoadCount == 1) {
     document.getElementsByTagName("object")[0].type = "application/x-test";
     document.getElementsByTagName("use")[0].setAttributeNS("http://www.w3.org/1999/xlink", "href", location.href + "#a");
-  } else if (frameLoadCount == 2) {
-    isnot(SpecialPowers.wrap(window.frame1).location.href.indexOf('chrome://'),
-          0, 'plugin shouldnt be able to cause navigation to chrome URLs');
-    SimpleTest.finish();
+
+    // wait two seconds and verify that frame navigation did not succeed
+    setTimeout(frameNavBlocked, 2000);
+    return;
   }
+  // we should never get here, but just in case, make sure the test fails in that case.
+  ok(false, "onload() event should not fire for blocked navigation");
+  SimpleTest.finish();
 }
+
 </script>
 
 <!-- Note that <svg:use> ends up creating an anonymous subtree, which means that the plugin
-- 
cgit v1.2.3


From 5d9ae788d5fe66da0f687e941d5ef90880641fd5 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 22:09:32 +0200
Subject: Bug 1182569: Disable hsts priming for loads of type subdocument for
 wpt tests

native in moebius
---
 .../top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini     | 3 +++
 .../iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini   | 3 +++
 .../top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini     | 3 +++
 .../top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini     | 3 +++
 .../iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini   | 3 +++
 .../top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini     | 3 +++
 6 files changed, 18 insertions(+)
 create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
 create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
 create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
 create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
 create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
 create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini

diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
new file mode 100644
index 000000000..c65b27a08
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,3 @@
+[no-opt-in-blocks.https.html]
+  type: testharness
+  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
new file mode 100644
index 000000000..c65b27a08
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,3 @@
+[no-opt-in-blocks.https.html]
+  type: testharness
+  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
new file mode 100644
index 000000000..c65b27a08
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,3 @@
+[no-opt-in-blocks.https.html]
+  type: testharness
+  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
new file mode 100644
index 000000000..c65b27a08
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,3 @@
+[no-opt-in-blocks.https.html]
+  type: testharness
+  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
new file mode 100644
index 000000000..c65b27a08
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,3 @@
+[no-opt-in-blocks.https.html]
+  type: testharness
+  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
new file mode 100644
index 000000000..c65b27a08
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,3 @@
+[no-opt-in-blocks.https.html]
+  type: testharness
+  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
-- 
cgit v1.2.3


From d3575bfb5b62b0c0f566233faae55e4f5f525e99 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 22:11:33 +0200
Subject: Bug 1182569: Add credentials mode for fetch-frame-resource.https.html
 wpt test

native in moebius
---
 .../service-workers/service-worker/fetch-frame-resource.https.html  | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/testing/web-platform/tests/service-workers/service-worker/fetch-frame-resource.https.html b/testing/web-platform/tests/service-workers/service-worker/fetch-frame-resource.https.html
index cc1dac472..fd7419832 100644
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-frame-resource.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-frame-resource.https.html
@@ -110,7 +110,8 @@ async_test(function(t) {
           frame.src =
             scope + '?mode=cors&url=' +
             encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path +
-                               '?ACAOrigin=' + host_info['HTTPS_ORIGIN']);
+                               '?ACAOrigin=' + host_info['HTTPS_ORIGIN'] +
+                               '&ACACredentials=true');
           document.body.appendChild(frame);
           return getLoadedFrameAsObject(frame);
         })
@@ -183,7 +184,8 @@ async_test(function(t) {
           var win = window.open(
             scope + '?mode=cors&url=' +
             encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path +
-                               '?ACAOrigin=' + host_info['HTTPS_ORIGIN']));
+                               '?ACAOrigin=' + host_info['HTTPS_ORIGIN'] +
+                               '&ACACredentials=true'));
           return getLoadedWindowAsObject(win);
         })
       .then(function(result) {
-- 
cgit v1.2.3


From 49989d0f01e7be293cfb3f2d3c996f9c63c7118c Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 22:16:11 +0200
Subject: Revert "Bug 1182569: Add credentials mode for
 fetch-frame-resource.https.html wpt test"

This reverts commit d3575bfb5b62b0c0f566233faae55e4f5f525e99.
---
 .../service-workers/service-worker/fetch-frame-resource.https.html  | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/testing/web-platform/tests/service-workers/service-worker/fetch-frame-resource.https.html b/testing/web-platform/tests/service-workers/service-worker/fetch-frame-resource.https.html
index fd7419832..cc1dac472 100644
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-frame-resource.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-frame-resource.https.html
@@ -110,8 +110,7 @@ async_test(function(t) {
           frame.src =
             scope + '?mode=cors&url=' +
             encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path +
-                               '?ACAOrigin=' + host_info['HTTPS_ORIGIN'] +
-                               '&ACACredentials=true');
+                               '?ACAOrigin=' + host_info['HTTPS_ORIGIN']);
           document.body.appendChild(frame);
           return getLoadedFrameAsObject(frame);
         })
@@ -184,8 +183,7 @@ async_test(function(t) {
           var win = window.open(
             scope + '?mode=cors&url=' +
             encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path +
-                               '?ACAOrigin=' + host_info['HTTPS_ORIGIN'] +
-                               '&ACACredentials=true'));
+                               '?ACAOrigin=' + host_info['HTTPS_ORIGIN']));
           return getLoadedWindowAsObject(win);
         })
       .then(function(result) {
-- 
cgit v1.2.3


From f5545f8af22ce7199b0b82cc10989b31ecfdec01 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 22:16:22 +0200
Subject: Revert "Bug 1182569: Disable hsts priming for loads of type
 subdocument for wpt tests"

This reverts commit 5d9ae788d5fe66da0f687e941d5ef90880641fd5.
---
 .../top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini     | 3 ---
 .../iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini   | 3 ---
 .../top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini     | 3 ---
 .../top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini     | 3 ---
 .../iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini   | 3 ---
 .../top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini     | 3 ---
 6 files changed, 18 deletions(-)
 delete mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
 delete mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
 delete mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
 delete mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
 delete mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
 delete mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini

diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
deleted file mode 100644
index c65b27a08..000000000
--- a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[no-opt-in-blocks.https.html]
-  type: testharness
-  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
deleted file mode 100644
index c65b27a08..000000000
--- a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[no-opt-in-blocks.https.html]
-  type: testharness
-  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
deleted file mode 100644
index c65b27a08..000000000
--- a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[no-opt-in-blocks.https.html]
-  type: testharness
-  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
deleted file mode 100644
index c65b27a08..000000000
--- a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[no-opt-in-blocks.https.html]
-  type: testharness
-  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
deleted file mode 100644
index c65b27a08..000000000
--- a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[no-opt-in-blocks.https.html]
-  type: testharness
-  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
diff --git a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini b/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
deleted file mode 100644
index c65b27a08..000000000
--- a/testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[no-opt-in-blocks.https.html]
-  type: testharness
-  prefs: [security.mixed_content.send_hsts_priming:false, security.mixed_content.use_hsts:false]
-- 
cgit v1.2.3


From ee4f7c4aa17068cfda347fb6ce51ca0b1958fbb6 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 22:16:35 +0200
Subject: Revert "Bug 1182569: Update tests when converting docshell loads to
 use AynscOpen2"

This reverts commit b73225e886f84182384a2b5b09f83e51501bdc38.
---
 dom/base/test/file_simplecontentpolicy.js      |  1 +
 dom/plugins/test/mochitest/test_bug813906.html | 22 ++++------------------
 2 files changed, 5 insertions(+), 18 deletions(-)

diff --git a/dom/base/test/file_simplecontentpolicy.js b/dom/base/test/file_simplecontentpolicy.js
index 2727b9530..1f9606c49 100644
--- a/dom/base/test/file_simplecontentpolicy.js
+++ b/dom/base/test/file_simplecontentpolicy.js
@@ -39,6 +39,7 @@ var policy = {
   {
     // Remember last content type seen for the test url
     if (contentLocation.spec.endsWith(urlSuffix)) {
+      assert.ok(frame === browserElement, "correct <browser> element");
       sendAsyncMessage("shouldLoad", {contentType: contentType, isTopLevel: isTopLevel});
       return Ci.nsIContentPolicy.REJECT_REQUEST;
     }
diff --git a/dom/plugins/test/mochitest/test_bug813906.html b/dom/plugins/test/mochitest/test_bug813906.html
index d18dbbff2..04c34daaf 100644
--- a/dom/plugins/test/mochitest/test_bug813906.html
+++ b/dom/plugins/test/mochitest/test_bug813906.html
@@ -18,35 +18,21 @@ function f() {
 </script>
 
 <script type="application/javascript">
-SimpleTest.requestFlakyTimeout(
-  "Blocking an iframe does not cause the onerror event to be fired");
-
 SimpleTest.waitForExplicitFinish();
 setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
 
 var frameLoadCount = 0;
-
-function frameNavBlocked() {
-  isnot(SpecialPowers.wrap(window.frame1).location.href.indexOf('chrome://'),
-        0, 'plugin shouldnt be able to cause navigation to chrome URLs');
-  SimpleTest.finish();
-}
-
 function frameLoaded() {
   frameLoadCount++;
   if (frameLoadCount == 1) {
     document.getElementsByTagName("object")[0].type = "application/x-test";
     document.getElementsByTagName("use")[0].setAttributeNS("http://www.w3.org/1999/xlink", "href", location.href + "#a");
-
-    // wait two seconds and verify that frame navigation did not succeed
-    setTimeout(frameNavBlocked, 2000);
-    return;
+  } else if (frameLoadCount == 2) {
+    isnot(SpecialPowers.wrap(window.frame1).location.href.indexOf('chrome://'),
+          0, 'plugin shouldnt be able to cause navigation to chrome URLs');
+    SimpleTest.finish();
   }
-  // we should never get here, but just in case, make sure the test fails in that case.
-  ok(false, "onload() event should not fire for blocked navigation");
-  SimpleTest.finish();
 }
-
 </script>
 
 <!-- Note that <svg:use> ends up creating an anonymous subtree, which means that the plugin
-- 
cgit v1.2.3


From 13f3978a14cb90eb01fc7f185f62b2ee2ac9f466 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 22:16:58 +0200
Subject: Revert "Bug 1182569 - Skip security check for plugins using newstream
 attribute"

This reverts commit 5b0f4649b3fee771379af60ec04d43b8a525cf80.
---
 docshell/base/nsDocShell.cpp               | 28 ++++++++--------------------
 docshell/base/nsDocShell.h                 |  6 ++----
 docshell/base/nsILinkHandler.h             | 10 ++--------
 dom/base/nsContentUtils.cpp                |  2 +-
 dom/plugins/base/nsPluginInstanceOwner.cpp | 25 +++++++++++--------------
 5 files changed, 24 insertions(+), 47 deletions(-)

diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 8167a76ec..6810d0179 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -13888,8 +13888,7 @@ public:
                    const nsAString& aFileName,
                    nsIInputStream* aPostDataStream,
                    nsIInputStream* aHeadersDataStream,
-                   bool aIsTrusted,
-                   nsIPrincipal* aTriggeringPrincipal);
+                   bool aIsTrusted);
 
   NS_IMETHOD Run() override
   {
@@ -13905,7 +13904,7 @@ public:
       mHandler->OnLinkClickSync(mContent, mURI,
                                 mTargetSpec.get(), mFileName,
                                 mPostDataStream, mHeadersDataStream,
-                                nullptr, nullptr, mTriggeringPrincipal);
+                                nullptr, nullptr);
     }
     return NS_OK;
   }
@@ -13920,7 +13919,6 @@ private:
   nsCOMPtr<nsIContent> mContent;
   PopupControlState mPopupState;
   bool mIsTrusted;
-  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
 };
 
 OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
@@ -13930,8 +13928,7 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
                                    const nsAString& aFileName,
                                    nsIInputStream* aPostDataStream,
                                    nsIInputStream* aHeadersDataStream,
-                                   bool aIsTrusted,
-                                   nsIPrincipal* aTriggeringPrincipal)
+                                   bool aIsTrusted)
   : mHandler(aHandler)
   , mURI(aURI)
   , mTargetSpec(aTargetSpec)
@@ -13941,7 +13938,6 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
   , mContent(aContent)
   , mPopupState(mHandler->mScriptGlobal->GetPopupControlState())
   , mIsTrusted(aIsTrusted)
-  , mTriggeringPrincipal(aTriggeringPrincipal)
 {
 }
 
@@ -13952,8 +13948,7 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
                         const nsAString& aFileName,
                         nsIInputStream* aPostDataStream,
                         nsIInputStream* aHeadersDataStream,
-                        bool aIsTrusted,
-                        nsIPrincipal* aTriggeringPrincipal)
+                        bool aIsTrusted)
 {
   NS_ASSERTION(NS_IsMainThread(), "wrong thread");
 
@@ -13992,8 +13987,7 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
 
   nsCOMPtr<nsIRunnable> ev =
     new OnLinkClickEvent(this, aContent, aURI, target.get(), aFileName,
-                         aPostDataStream, aHeadersDataStream,
-                         aIsTrusted, aTriggeringPrincipal);
+                         aPostDataStream, aHeadersDataStream, aIsTrusted);
   return NS_DispatchToCurrentThread(ev);
 }
 
@@ -14005,8 +13999,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
                             nsIInputStream* aPostDataStream,
                             nsIInputStream* aHeadersDataStream,
                             nsIDocShell** aDocShell,
-                            nsIRequest** aRequest,
-                            nsIPrincipal* aTriggeringPrincipal)
+                            nsIRequest** aRequest)
 {
   // Initialize the DocShell / Request
   if (aDocShell) {
@@ -14129,18 +14122,13 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  // if the triggeringPrincipal is not passed explicitly, then we
-  // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
-  nsCOMPtr<nsIPrincipal> triggeringPrincipal =
-    aTriggeringPrincipal ? aTriggeringPrincipal
-                         : aContent->NodePrincipal();
-
   nsresult rv = InternalLoad(clonedURI,                 // New URI
                              nullptr,                   // Original URI
                              false,                     // LoadReplace
                              referer,                   // Referer URI
                              refererPolicy,             // Referer policy
-                             triggeringPrincipal,
+                             aContent->NodePrincipal(), // Triggering is our node's
+                                                        // principal
                              aContent->NodePrincipal(),
                              flags,
                              target,                    // Window target
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index f510a15b0..63a4e3358 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -201,8 +201,7 @@ public:
                          const nsAString& aFileName,
                          nsIInputStream* aPostDataStream,
                          nsIInputStream* aHeadersDataStream,
-                         bool aIsTrusted,
-                         nsIPrincipal* aTriggeringPrincipal) override;
+                         bool aIsTrusted) override;
   NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
                              nsIURI* aURI,
                              const char16_t* aTargetSpec,
@@ -210,8 +209,7 @@ public:
                              nsIInputStream* aPostDataStream = 0,
                              nsIInputStream* aHeadersDataStream = 0,
                              nsIDocShell** aDocShell = 0,
-                             nsIRequest** aRequest = 0,
-                             nsIPrincipal* aTriggeringPrincipal = nullptr) override;
+                             nsIRequest** aRequest = 0) override;
   NS_IMETHOD OnOverLink(nsIContent* aContent,
                         nsIURI* aURI,
                         const char16_t* aTargetSpec) override;
diff --git a/docshell/base/nsILinkHandler.h b/docshell/base/nsILinkHandler.h
index 7069f1f1d..7cdcd566d 100644
--- a/docshell/base/nsILinkHandler.h
+++ b/docshell/base/nsILinkHandler.h
@@ -37,8 +37,6 @@ public:
    * @param aFileName non-null when the link should be downloaded as the given file
    * @param aHeadersDataStream ???
    * @param aIsTrusted false if the triggerer is an untrusted DOM event.
-   * @param aTriggeringPrincipal, if not passed explicitly we fall back to
-   *        the document's principal.
    */
   NS_IMETHOD OnLinkClick(nsIContent* aContent,
                          nsIURI* aURI,
@@ -46,8 +44,7 @@ public:
                          const nsAString& aFileName,
                          nsIInputStream* aPostDataStream,
                          nsIInputStream* aHeadersDataStream,
-                         bool aIsTrusted,
-                         nsIPrincipal* aTriggeringPrincipal) = 0;
+                         bool aIsTrusted) = 0;
 
   /**
    * Process a click on a link.
@@ -64,8 +61,6 @@ public:
    * @param aHeadersDataStream ???
    * @param aDocShell (out-param) the DocShell that the request was opened on
    * @param aRequest the request that was opened
-   * @param aTriggeringPrincipal, if not passed explicitly we fall back to
-   *        the document's principal.
    */
   NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
                              nsIURI* aURI,
@@ -74,8 +69,7 @@ public:
                              nsIInputStream* aPostDataStream = 0,
                              nsIInputStream* aHeadersDataStream = 0,
                              nsIDocShell** aDocShell = 0,
-                             nsIRequest** aRequest = 0,
-                             nsIPrincipal* aTriggeringPrincipal = nullptr) = 0;
+                             nsIRequest** aRequest = 0) = 0;
 
   /**
    * Process a mouse-over a link.
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index c3ff2b4d8..ef87a250e 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -5100,7 +5100,7 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
 
     handler->OnLinkClick(aContent, aLinkURI,
                          fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
-                         fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal());
+                         fileName, nullptr, nullptr, aIsTrusted);
   }
 }
 
diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp
index 7de6c2b73..b7651be1a 100644
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -535,6 +535,16 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
   nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, baseURI);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
+  if (aDoCheckLoadURIChecks) {
+    nsCOMPtr<nsIScriptSecurityManager> secMan(
+      do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
+    NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
+
+    rv = secMan->CheckLoadURIWithPrincipal(content->NodePrincipal(), uri,
+                                           nsIScriptSecurityManager::STANDARD);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
   nsCOMPtr<nsIInputStream> headersDataStream;
   if (aPostStream && aHeadersData) {
     if (!aHeadersDataLen)
@@ -553,21 +563,8 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
     Preferences::GetInt("privacy.popups.disable_from_plugins");
   nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups);
 
-
-  // if security checks (in particular CheckLoadURIWithPrincipal) needs
-  // to be skipped we are creating a codebasePrincipal to make sure
-  // that security check succeeds. Please note that we do not want to
-  // fall back to using the systemPrincipal, because that would also
-  // bypass ContentPolicy checks which should still be enforced.
-  nsCOMPtr<nsIPrincipal> triggeringPrincipal;
-  if (!aDoCheckLoadURIChecks) {
-    mozilla::PrincipalOriginAttributes attrs =
-      BasePrincipal::Cast(content->NodePrincipal())->OriginAttributesRef();
-    triggeringPrincipal = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
-  }
-
   rv = lh->OnLinkClick(content, uri, unitarget.get(), NullString(),
-                       aPostStream, headersDataStream, true, triggeringPrincipal);
+                       aPostStream, headersDataStream, true);
 
   return rv;
 }
-- 
cgit v1.2.3


From 115cf1e322bdabaee001781e1d5a8ee4928992af Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 22:17:09 +0200
Subject: Revert "Bug 1182569: Update ContentSecurityManager to handle docshell
 loads"

This reverts commit 2e33335820b2816bee111e78588ac82e401c86ae.
---
 dom/security/nsContentSecurityManager.cpp | 81 +++++++------------------------
 netwerk/base/nsNetUtil.cpp                | 14 ++++--
 2 files changed, 27 insertions(+), 68 deletions(-)

diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp
index 458f41144..9329c558a 100644
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -10,9 +10,6 @@
 #include "nsIStreamListener.h"
 #include "nsIDocument.h"
 #include "nsMixedContentBlocker.h"
-#include "nsCDefaultURIFixup.h"
-#include "nsIURIFixup.h"
-#include "nsINestedURI.h"
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/TabChild.h"
@@ -247,6 +244,10 @@ DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
 static nsresult
 DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
 {
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, rv);
+
   nsContentPolicyType contentPolicyType =
     aLoadInfo->GetExternalContentPolicyType();
   nsContentPolicyType internalContentPolicyType =
@@ -254,24 +255,12 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
   nsCString mimeTypeGuess;
   nsCOMPtr<nsINode> requestingContext = nullptr;
 
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
-      contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
-    // TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
-    // be wyciwyg:// channels. Let's fix up the URI so we can
-    // perform proper security checks.
-    nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
-    if (NS_SUCCEEDED(rv) && urifixup) {
-      nsCOMPtr<nsIURI> fixedURI;
-      rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
-      if (NS_SUCCEEDED(rv)) {
-        uri = fixedURI;
-      }
-    }
-  }
+#ifdef DEBUG
+  // Don't enforce TYPE_DOCUMENT assertions for loads
+  // initiated by javascript tests.
+  bool skipContentTypeCheck = false;
+  skipContentTypeCheck = Preferences::GetBool("network.loadinfo.skip_type_assertion");
+#endif
 
   switch(contentPolicyType) {
     case nsIContentPolicy::TYPE_OTHER: {
@@ -305,14 +294,16 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
     }
 
     case nsIContentPolicy::TYPE_DOCUMENT: {
-      mimeTypeGuess = EmptyCString();
-      requestingContext = aLoadInfo->LoadingNode();
+      MOZ_ASSERT(skipContentTypeCheck || false, "contentPolicyType not supported yet");
       break;
     }
 
     case nsIContentPolicy::TYPE_SUBDOCUMENT: {
       mimeTypeGuess = NS_LITERAL_CSTRING("text/html");
       requestingContext = aLoadInfo->LoadingNode();
+      MOZ_ASSERT(!requestingContext ||
+                 requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+                 "type_subdocument requires requestingContext of type Document");
       break;
     }
 
@@ -456,32 +447,18 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
       MOZ_ASSERT(false, "can not perform security check without a valid contentType");
   }
 
-  // For document loads we use the triggeringPrincipal as the originPrincipal.
-  // Note the the loadingPrincipal for loads of TYPE_DOCUMENT is a nullptr.
-  nsCOMPtr<nsIPrincipal> principal =
-    (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
-    contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)
-    ? aLoadInfo->TriggeringPrincipal()
-    : aLoadInfo->LoadingPrincipal();
-
   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
   rv = NS_CheckContentLoadPolicy(internalContentPolicyType,
                                  uri,
-                                 principal,
+                                 aLoadInfo->LoadingPrincipal(),
                                  requestingContext,
                                  mimeTypeGuess,
                                  nullptr,        //extra,
                                  &shouldLoad,
                                  nsContentUtils::GetContentPolicy(),
                                  nsContentUtils::GetSecurityManager());
-
-  if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
-    if ((NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) &&
-        (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
-         contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)) {
-      // for docshell loads we might have to return SHOW_ALT.
-      return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
-    }
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_CP_REJECTED(shouldLoad)) {
     return NS_ERROR_CONTENT_BLOCKED;
   }
 
@@ -629,30 +606,6 @@ nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsContentPolicyType contentPolicyType =
-    loadInfo->GetExternalContentPolicyType();
-
-  if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
-      contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
-    // query the nested URI for security checks like in the case of view-source
-    nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(uri);
-    if (nestedURI) {
-      nestedURI->GetInnerURI(getter_AddRefs(uri));
-    }
-
-    // TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
-    // be wyciwyg:// channels. Let's fix up the URI so we can
-    // perform proper security checks.
-    nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
-    if (NS_SUCCEEDED(rv) && urifixup) {
-      nsCOMPtr<nsIURI> fixedURI;
-      rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
-      if (NS_SUCCEEDED(rv)) {
-        uri = fixedURI;
-      }
-    }
-  }
-
   // Handle cookie policies
   uint32_t cookiePolicy = loadInfo->GetCookiePolicy();
   if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {
diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp
index bc9bcf88a..8ff3e788f 100644
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -1285,10 +1285,16 @@ NS_HasBeenCrossOrigin(nsIChannel* aChannel, bool aReport)
   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
   MOZ_RELEASE_ASSERT(loadInfo, "Origin tracking only works for channels created with a loadinfo");
 
-  // TYPE_DOCUMENT loads have a null LoadingPrincipal and can not be cross origin.
-  if (!loadInfo->LoadingPrincipal()) {
-    return false;
-  }
+#ifdef DEBUG
+  // Don't enforce TYPE_DOCUMENT assertions for loads
+  // initiated by javascript tests.
+  bool skipContentTypeCheck = false;
+  skipContentTypeCheck = Preferences::GetBool("network.loadinfo.skip_type_assertion");
+#endif
+
+  MOZ_ASSERT(skipContentTypeCheck ||
+             loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT,
+             "calling NS_HasBeenCrossOrigin on a top level load");
 
   // Always treat tainted channels as cross-origin.
   if (loadInfo->GetTainting() != LoadTainting::Basic) {
-- 
cgit v1.2.3


From 30621a6307171f009948001b3730c5b61b894048 Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Sun, 22 Apr 2018 22:17:18 +0200
Subject: Revert "Bug 1182569: Use AsyncOpen2 for docshell loads"

This reverts commit 29bd11c3cd6ff41f7167530f9bbcd9d195b7c427.
---
 docshell/base/nsDocShell.cpp      | 23 +++++++++++++++---
 dom/jsurl/nsJSProtocolHandler.cpp | 49 +++++++++++++++++++++++++--------------
 uriloader/base/nsURILoader.cpp    |  2 +-
 3 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 6810d0179..b1fcc5c23 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -69,6 +69,7 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScrollableFrame.h"
+#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
 #include "nsISeekableStream.h"
 #include "nsAutoPtr.h"
 #include "nsQueryObject.h"
@@ -1643,7 +1644,7 @@ nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
                                          uri,
                                          aStream,
                                          triggeringPrincipal,
-                                         nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
+                                         nsILoadInfo::SEC_NORMAL,
                                          nsIContentPolicy::TYPE_OTHER,
                                          aContentType,
                                          aContentCharset);
@@ -9942,6 +9943,23 @@ nsDocShell::InternalLoad(nsIURI* aURI,
     rv = extraStr->SetData(msg);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    int16_t shouldLoad = nsIContentPolicy::ACCEPT;
+    rv = NS_CheckContentLoadPolicy(contentType,
+                                   aURI,
+                                   aTriggeringPrincipal,
+                                   requestingContext,
+                                   EmptyCString(),  // mime guess
+                                   extraStr,  // extra
+                                   &shouldLoad);
+
+    if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
+      if (NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) {
+        return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
+      }
+
+      return NS_ERROR_CONTENT_BLOCKED;
+    }
+
     // If HSTS priming was set by nsMixedContentBlocker::ShouldLoad, and we
     // would block due to mixed content, go ahead and block here. If we try to
     // proceed with priming, we will error out later on.
@@ -10931,8 +10949,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
   }
 
   nsLoadFlags loadFlags = mDefaultLoadFlags;
-  nsSecurityFlags securityFlags =
-    nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
+  nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL;
 
   if (aFirstParty) {
     // tag first party URL loads
diff --git a/dom/jsurl/nsJSProtocolHandler.cpp b/dom/jsurl/nsJSProtocolHandler.cpp
index 90171db10..cdb63f890 100644
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -36,6 +36,7 @@
 #include "nsIContentViewer.h"
 #include "nsIXPConnect.h"
 #include "nsContentUtils.h"
+#include "nsNullPrincipal.h"
 #include "nsJSUtils.h"
 #include "nsThreadUtils.h"
 #include "nsIScriptChannel.h"
@@ -335,7 +336,7 @@ public:
     NS_FORWARD_SAFE_NSIPROPERTYBAG(mPropertyBag)
     NS_FORWARD_SAFE_NSIPROPERTYBAG2(mPropertyBag)
 
-    nsresult Init(nsIURI *aURI, nsILoadInfo* aLoadInfo);
+    nsresult Init(nsIURI *aURI);
 
     // Actually evaluate the script.
     void EvaluateScript();
@@ -353,16 +354,17 @@ protected:
     nsCOMPtr<nsIChannel>    mStreamChannel;
     nsCOMPtr<nsIPropertyBag2> mPropertyBag;
     nsCOMPtr<nsIStreamListener> mListener;  // Our final listener
+    nsCOMPtr<nsISupports> mContext; // The context passed to AsyncOpen
     nsCOMPtr<nsPIDOMWindowInner> mOriginalInnerWindow;  // The inner window our load
                                                         // started against.
-    // If we blocked onload on a document in AsyncOpen2, this is the document we
+    // If we blocked onload on a document in AsyncOpen, this is the document we
     // did it on.
     nsCOMPtr<nsIDocument>   mDocumentOnloadBlockedOn;
 
     nsresult mStatus; // Our status
 
     nsLoadFlags             mLoadFlags;
-    nsLoadFlags             mActualLoadFlags; // See AsyncOpen2
+    nsLoadFlags             mActualLoadFlags; // See AsyncOpen
 
     RefPtr<nsJSThunk>     mIOThunk;
     PopupControlState       mPopupState;
@@ -402,7 +404,7 @@ nsresult nsJSChannel::StopAll()
     return rv;
 }
 
-nsresult nsJSChannel::Init(nsIURI* aURI, nsILoadInfo* aLoadInfo)
+nsresult nsJSChannel::Init(nsIURI *aURI)
 {
     RefPtr<nsJSURI> jsURI;
     nsresult rv = aURI->QueryInterface(kJSURICID,
@@ -416,13 +418,21 @@ nsresult nsJSChannel::Init(nsIURI* aURI, nsILoadInfo* aLoadInfo)
     // Remember, until AsyncOpen is called, the script will not be evaluated
     // and the underlying Input Stream will not be created...
     nsCOMPtr<nsIChannel> channel;
-    rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
-                                          aURI,
-                                          mIOThunk,
-                                          NS_LITERAL_CSTRING("text/html"),
-                                          EmptyCString(),
-                                          aLoadInfo);
-    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIPrincipal> nullPrincipal = nsNullPrincipal::Create();
+
+    // If the resultant script evaluation actually does return a value, we
+    // treat it as html.
+    // The following channel is never openend, so it does not matter what
+    // securityFlags we pass; let's follow the principle of least privilege.
+    rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
+                                  aURI,
+                                  mIOThunk,
+                                  nullPrincipal,
+                                  nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
+                                  nsIContentPolicy::TYPE_OTHER,
+                                  NS_LITERAL_CSTRING("text/html"));
+    if (NS_FAILED(rv)) return rv;
 
     rv = mIOThunk->Init(aURI);
     if (NS_SUCCEEDED(rv)) {
@@ -553,7 +563,6 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
                "security flags in loadInfo but asyncOpen2() not called");
     }
 #endif
-    MOZ_RELEASE_ASSERT(!aContext, "please call AsyncOpen2()");
 
     NS_ENSURE_ARG(aListener);
 
@@ -575,6 +584,7 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
     }
     
     mListener = aListener;
+    mContext = aContext;
 
     mIsActive = true;
 
@@ -645,7 +655,7 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
             return mStatus;
         }
 
-        // We're returning success from asyncOpen2(), but we didn't open a
+        // We're returning success from asyncOpen(), but we didn't open a
         // stream channel.  We'll have to notify ourselves, but make sure to do
         // it asynchronously.
         method = &nsJSChannel::NotifyListener;            
@@ -762,7 +772,7 @@ nsJSChannel::EvaluateScript()
         return;
     }
     
-    mStatus = mStreamChannel->AsyncOpen2(this);
+    mStatus = mStreamChannel->AsyncOpen(this, mContext);
     if (NS_SUCCEEDED(mStatus)) {
         // mStreamChannel will call OnStartRequest and OnStopRequest on
         // us, so we'll be sure to call them on our listener.
@@ -790,8 +800,8 @@ nsJSChannel::EvaluateScript()
 void
 nsJSChannel::NotifyListener()
 {
-    mListener->OnStartRequest(this, nullptr);
-    mListener->OnStopRequest(this, nullptr, mStatus);
+    mListener->OnStartRequest(this, mContext);
+    mListener->OnStopRequest(this, mContext, mStatus);
 
     CleanupStrongRefs();
 }
@@ -800,6 +810,7 @@ void
 nsJSChannel::CleanupStrongRefs()
 {
     mListener = nullptr;
+    mContext = nullptr;
     mOriginalInnerWindow = nullptr;
     if (mDocumentOnloadBlockedOn) {
         mDocumentOnloadBlockedOn->UnblockOnload(false);
@@ -1229,7 +1240,11 @@ nsJSProtocolHandler::NewChannel2(nsIURI* uri,
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    rv = channel->Init(uri, aLoadInfo);
+    rv = channel->Init(uri);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // set the loadInfo on the new channel
+    rv = channel->SetLoadInfo(aLoadInfo);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (NS_SUCCEEDED(rv)) {
diff --git a/uriloader/base/nsURILoader.cpp b/uriloader/base/nsURILoader.cpp
index ea370aa37..69475d68f 100644
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -834,7 +834,7 @@ NS_IMETHODIMP nsURILoader::OpenURI(nsIChannel *channel,
     // the preferred protocol handler. 
 
     // But for now, I'm going to let necko do the work for us....
-    rv = channel->AsyncOpen2(loader);
+    rv = channel->AsyncOpen(loader, nullptr);
 
     // no content from this load - that's OK.
     if (rv == NS_ERROR_NO_CONTENT) {
-- 
cgit v1.2.3


From ccbd5ecf57fcd53ac8b28ddf7466b6c930f764df Mon Sep 17 00:00:00 2001
From: janekptacijarabaci <janekptacijarabaci@seznam.cz>
Date: Mon, 23 Apr 2018 00:13:56 +0200
Subject: moebius#187: DOM - nsIContentPolicy - context (document)

https://github.com/MoonchildProductions/moebius/pull/187
---
 docshell/base/nsDocShell.cpp              | 74 ++++++++++++++++++-------------
 dom/base/nsContentPolicy.cpp              |  6 ++-
 dom/security/nsContentSecurityManager.cpp | 63 +++++++++++++++++---------
 netwerk/base/LoadInfo.cpp                 | 15 +++++++
 netwerk/base/LoadInfo.h                   |  7 ++-
 netwerk/base/nsILoadInfo.idl              | 10 +++++
 6 files changed, 120 insertions(+), 55 deletions(-)

diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index b1fcc5c23..bd2a8a433 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -9896,40 +9896,29 @@ nsDocShell::InternalLoad(nsIURI* aURI,
     contentType = nsIContentPolicy::TYPE_DOCUMENT;
   }
 
-  // If there's no targetDocShell, that means we are about to create a new window,
-  // perform a content policy check before creating the window.
-  if (!targetDocShell) {
-    nsCOMPtr<Element> requestingElement;
+  // If there's no targetDocShell, that means we are about to create a new
+  // window (or aWindowTarget is empty). Perform a content policy check before
+  // creating the window. Please note for all other docshell loads
+  // content policy checks are performed within the contentSecurityManager
+  // when the channel is about to be openend.
+  if (!targetDocShell && !aWindowTarget.IsEmpty()) {
+    MOZ_ASSERT(contentType == nsIContentPolicy::TYPE_DOCUMENT,
+               "opening a new window requires type to be TYPE_DOCUMENT");
+
     nsISupports* requestingContext = nullptr;
 
-    if (contentType == nsIContentPolicy::TYPE_DOCUMENT) {
-      if (XRE_IsContentProcess()) {
-        // In e10s the child process doesn't have access to the element that
-        // contains the browsing context (because that element is in the chrome
-        // process). So we just pass mScriptGlobal.
-        requestingContext = ToSupports(mScriptGlobal);
-      } else {
-        // This is for loading non-e10s tabs and toplevel windows of various
-        // sorts.
-        // For the toplevel window cases, requestingElement will be null.
-        requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal();
-        requestingContext = requestingElement;
-      }
+    if (XRE_IsContentProcess()) {
+      // In e10s the child process doesn't have access to the element that
+      // contains the browsing context (because that element is in the chrome
+      // process). So we just pass mScriptGlobal.
+      requestingContext = ToSupports(mScriptGlobal);
     } else {
-      requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal();
+      // This is for loading non-e10s tabs and toplevel windows of various
+      // sorts.
+      // For the toplevel window cases, requestingElement will be null.
+      nsCOMPtr<Element> requestingElement =
+        mScriptGlobal->AsOuter()->GetFrameElementInternal();
       requestingContext = requestingElement;
-
-#ifdef DEBUG
-      if (requestingElement) {
-        // Get the docshell type for requestingElement.
-        nsCOMPtr<nsIDocument> requestingDoc = requestingElement->OwnerDoc();
-        nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
-
-        // requestingElement docshell type = current docshell type.
-        MOZ_ASSERT(mItemType == elementDocShell->ItemType(),
-                  "subframes should have the same docshell type as their parent");
-      }
-#endif
     }
 
     // Since Content Policy checks are performed within docShell as well as
@@ -10911,17 +10900,40 @@ nsDocShell::DoURILoad(nsIURI* aURI,
   nsCOMPtr<nsINode> loadingNode;
   nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
   nsCOMPtr<nsIPrincipal> loadingPrincipal;
+  nsCOMPtr<nsISupports> topLevelLoadingContext;
 
   if (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
     loadingNode = nullptr;
     loadingPrincipal = nullptr;
     loadingWindow = mScriptGlobal->AsOuter();
+    if (XRE_IsContentProcess()) {
+      // In e10s the child process doesn't have access to the element that
+      // contains the browsing context (because that element is in the chrome
+      // process).
+      nsCOMPtr<nsITabChild> tabChild = GetTabChild();
+      topLevelLoadingContext = ToSupports(tabChild);
+    } else {
+      // This is for loading non-e10s tabs and toplevel windows of various
+      // sorts.
+      // For the toplevel window cases, requestingElement will be null.
+      nsCOMPtr<Element> requestingElement =
+        loadingWindow->GetFrameElementInternal();
+      topLevelLoadingContext = requestingElement;
+    }
   } else {
     loadingWindow = nullptr;
     loadingNode = mScriptGlobal->AsOuter()->GetFrameElementInternal();
     if (loadingNode) {
       // If we have a loading node, then use that as our loadingPrincipal.
       loadingPrincipal = loadingNode->NodePrincipal();
+#ifdef DEBUG
+      // Get the docshell type for requestingElement.
+      nsCOMPtr<nsIDocument> requestingDoc = loadingNode->OwnerDoc();
+      nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
+      // requestingElement docshell type = current docshell type.
+      MOZ_ASSERT(mItemType == elementDocShell->ItemType(),
+                "subframes should have the same docshell type as their parent");
+#endif
     } else {
       // If this isn't a top-level load and mScriptGlobal's frame element is
       // null, then the element got removed from the DOM while we were trying
@@ -10971,7 +10983,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
 
   nsCOMPtr<nsILoadInfo> loadInfo =
     (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) ?
-      new LoadInfo(loadingWindow, aTriggeringPrincipal,
+      new LoadInfo(loadingWindow, aTriggeringPrincipal, topLevelLoadingContext,
                    securityFlags) :
       new LoadInfo(loadingPrincipal, aTriggeringPrincipal, loadingNode,
                    securityFlags, aContentPolicyType);
diff --git a/dom/base/nsContentPolicy.cpp b/dom/base/nsContentPolicy.cpp
index 337debcea..5511b9086 100644
--- a/dom/base/nsContentPolicy.cpp
+++ b/dom/base/nsContentPolicy.cpp
@@ -20,6 +20,7 @@
 #include "nsIDOMElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMWindow.h"
+#include "nsITabChild.h"
 #include "nsIContent.h"
 #include "nsILoadContext.h"
 #include "nsCOMArray.h"
@@ -89,8 +90,9 @@ nsContentPolicy::CheckPolicy(CPMethod          policyMethod,
     {
         nsCOMPtr<nsIDOMNode> node(do_QueryInterface(requestingContext));
         nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(requestingContext));
-        NS_ASSERTION(!requestingContext || node || window,
-                     "Context should be a DOM node or a DOM window!");
+        nsCOMPtr<nsITabChild> tabChild(do_QueryInterface(requestingContext));
+        NS_ASSERTION(!requestingContext || node || window || tabChild,
+                     "Context should be a DOM node, DOM window or a tabChild!");
     }
 #endif
 
diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp
index 9329c558a..0cc4933fe 100644
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -253,7 +253,7 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
   nsContentPolicyType internalContentPolicyType =
     aLoadInfo->InternalContentPolicyType();
   nsCString mimeTypeGuess;
-  nsCOMPtr<nsINode> requestingContext = nullptr;
+  nsCOMPtr<nsISupports> requestingContext = nullptr;
 
 #ifdef DEBUG
   // Don't enforce TYPE_DOCUMENT assertions for loads
@@ -327,10 +327,13 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
     case nsIContentPolicy::TYPE_XMLHTTPREQUEST: {
       // alias nsIContentPolicy::TYPE_DATAREQUEST:
       requestingContext = aLoadInfo->LoadingNode();
-      MOZ_ASSERT(!requestingContext ||
-                 requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
-                 "type_xml requires requestingContext of type Document");
-
+#ifdef DEBUG
+      {
+        nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+                   "type_xml requires requestingContext of type Document");
+      }
+#endif
       // We're checking for the external TYPE_XMLHTTPREQUEST here in case
       // an addon creates a request with that type.
       if (internalContentPolicyType ==
@@ -351,18 +354,26 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
     case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: {
       mimeTypeGuess = EmptyCString();
       requestingContext = aLoadInfo->LoadingNode();
-      MOZ_ASSERT(!requestingContext ||
-                 requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE,
-                 "type_subrequest requires requestingContext of type Element");
+#ifdef DEBUG
+      {
+        nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE,
+                   "type_subrequest requires requestingContext of type Element");
+      }
+#endif
       break;
     }
 
     case nsIContentPolicy::TYPE_DTD: {
       mimeTypeGuess = EmptyCString();
       requestingContext = aLoadInfo->LoadingNode();
-      MOZ_ASSERT(!requestingContext ||
-                 requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
-                 "type_dtd requires requestingContext of type Document");
+#ifdef DEBUG
+      {
+        nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+                   "type_dtd requires requestingContext of type Document");
+      }
+#endif
       break;
     }
 
@@ -380,9 +391,13 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
         mimeTypeGuess = EmptyCString();
       }
       requestingContext = aLoadInfo->LoadingNode();
-      MOZ_ASSERT(!requestingContext ||
-                 requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE,
-                 "type_media requires requestingContext of type Element");
+#ifdef DEBUG
+      {
+        nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE,
+                   "type_media requires requestingContext of type Element");
+      }
+#endif
       break;
     }
 
@@ -409,18 +424,26 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
     case nsIContentPolicy::TYPE_XSLT: {
       mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
       requestingContext = aLoadInfo->LoadingNode();
-      MOZ_ASSERT(!requestingContext ||
-                 requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
-                 "type_xslt requires requestingContext of type Document");
+#ifdef DEBUG
+      {
+        nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+                   "type_xslt requires requestingContext of type Document");
+      }
+#endif
       break;
     }
 
     case nsIContentPolicy::TYPE_BEACON: {
       mimeTypeGuess = EmptyCString();
       requestingContext = aLoadInfo->LoadingNode();
-      MOZ_ASSERT(!requestingContext ||
-                 requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
-                 "type_beacon requires requestingContext of type Document");
+#ifdef DEBUG
+      {
+        nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
+        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+                   "type_beacon requires requestingContext of type Document");
+      }
+#endif
       break;
     }
 
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
index 9923f6d30..ede825b8f 100644
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -48,6 +48,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
                            aTriggeringPrincipal : mLoadingPrincipal.get())
   , mPrincipalToInherit(nullptr)
   , mLoadingContext(do_GetWeakReference(aLoadingContext))
+  , mContextForTopLevelLoad(nullptr)
   , mSecurityFlags(aSecurityFlags)
   , mInternalContentPolicyType(aContentPolicyType)
   , mTainting(LoadTainting::Basic)
@@ -218,10 +219,12 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
 */
 LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
                    nsIPrincipal* aTriggeringPrincipal,
+                   nsISupports* aContextForTopLevelLoad,
                    nsSecurityFlags aSecurityFlags)
   : mLoadingPrincipal(nullptr)
   , mTriggeringPrincipal(aTriggeringPrincipal)
   , mPrincipalToInherit(nullptr)
+  , mContextForTopLevelLoad(do_GetWeakReference(aContextForTopLevelLoad))
   , mSecurityFlags(aSecurityFlags)
   , mInternalContentPolicyType(nsIContentPolicy::TYPE_DOCUMENT)
   , mTainting(LoadTainting::Basic)
@@ -281,6 +284,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
   , mTriggeringPrincipal(rhs.mTriggeringPrincipal)
   , mPrincipalToInherit(rhs.mPrincipalToInherit)
   , mLoadingContext(rhs.mLoadingContext)
+  , mContextForTopLevelLoad(rhs.mContextForTopLevelLoad)
   , mSecurityFlags(rhs.mSecurityFlags)
   , mInternalContentPolicyType(rhs.mInternalContentPolicyType)
   , mTainting(rhs.mTainting)
@@ -488,6 +492,17 @@ LoadInfo::LoadingNode()
   return node;
 }
 
+nsISupports*
+LoadInfo::ContextForTopLevelLoad()
+{
+  // Most likely you want to query LoadingNode() instead of
+  // ContextForTopLevelLoad() if this assertion fires.
+  MOZ_ASSERT(mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,
+            "should only query this context for top level document loads");
+  nsCOMPtr<nsISupports> context = do_QueryReferent(mContextForTopLevelLoad);
+  return context;
+}
+
 NS_IMETHODIMP
 LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult)
 {
diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
index 86cfddc68..0ae6061b3 100644
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -59,10 +59,12 @@ public:
            nsSecurityFlags aSecurityFlags,
            nsContentPolicyType aContentPolicyType);
 
-  // Constructor used for TYPE_DOCUMENT loads which have no reasonable
-  // loadingNode or loadingPrincipal
+  // Constructor used for TYPE_DOCUMENT loads which have a different
+  // loadingContext than other loads. This ContextForTopLevelLoad is
+  // only used for content policy checks.
   LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
            nsIPrincipal* aTriggeringPrincipal,
+           nsISupports* aContextForTopLevelLoad,
            nsSecurityFlags aSecurityFlags);
 
   // create an exact copy of the loadinfo
@@ -134,6 +136,7 @@ private:
   nsCOMPtr<nsIPrincipal>           mTriggeringPrincipal;
   nsCOMPtr<nsIPrincipal>           mPrincipalToInherit;
   nsWeakPtr                        mLoadingContext;
+  nsWeakPtr                        mContextForTopLevelLoad;
   nsSecurityFlags                  mSecurityFlags;
   nsContentPolicyType              mInternalContentPolicyType;
   LoadTainting                     mTainting;
diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl
index 5b35736e5..4ec29b972 100644
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -323,6 +323,16 @@ interface nsILoadInfo : nsISupports
   [noscript, notxpcom, nostdcall, binaryname(LoadingNode)]
   nsINode binaryLoadingNode();
 
+  /**
+   * A C++ friendly version of the loadingContext for toplevel loads.
+   * Most likely you want to query the ownerDocument or LoadingNode
+   * and not this context only available for TYPE_DOCUMENT loads.
+   * Please note that except for loads of TYPE_DOCUMENT, this
+   * ContextForTopLevelLoad will always return null.
+   */
+  [noscript, notxpcom, nostdcall, binaryname(ContextForTopLevelLoad)]
+  nsISupports binaryContextForTopLevelLoad();
+
   /**
    * The securityFlags of that channel.
    */
-- 
cgit v1.2.3