summaryrefslogtreecommitdiffstats
path: root/dom/security/test/mixedcontentblocker
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /dom/security/test/mixedcontentblocker
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--dom/security/test/mixedcontentblocker/auto_upgrading_identity.html11
-rw-r--r--dom/security/test/mixedcontentblocker/auto_upgrading_identity.pngbin0 -> 70 bytes
-rw-r--r--dom/security/test/mixedcontentblocker/browser.ini12
-rw-r--r--dom/security/test/mixedcontentblocker/browser_auto_upgrading_identity.js49
-rw-r--r--dom/security/test/mixedcontentblocker/browser_mixed_content_auto_upgrade_display_console.js51
-rw-r--r--dom/security/test/mixedcontentblocker/browser_test_mixed_content_download.js215
-rw-r--r--dom/security/test/mixedcontentblocker/download_page.html35
-rw-r--r--dom/security/test/mixedcontentblocker/download_server.sjs9
-rw-r--r--dom/security/test/mixedcontentblocker/file_bug803225_test_mailto.html13
-rw-r--r--dom/security/test/mixedcontentblocker/file_frameNavigation.html74
-rw-r--r--dom/security/test/mixedcontentblocker/file_frameNavigation_blankTarget.html31
-rw-r--r--dom/security/test/mixedcontentblocker/file_frameNavigation_grandchild.html57
-rw-r--r--dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html74
-rw-r--r--dom/security/test/mixedcontentblocker/file_frameNavigation_secure.html73
-rw-r--r--dom/security/test/mixedcontentblocker/file_frameNavigation_secure_grandchild.html58
-rw-r--r--dom/security/test/mixedcontentblocker/file_main.html338
-rw-r--r--dom/security/test/mixedcontentblocker/file_main_bug803225.html172
-rw-r--r--dom/security/test/mixedcontentblocker/file_main_bug803225_websocket_wsh.py6
-rw-r--r--dom/security/test/mixedcontentblocker/file_mixed_content_auto_upgrade_display_console.html10
-rw-r--r--dom/security/test/mixedcontentblocker/file_redirect.html31
-rw-r--r--dom/security/test/mixedcontentblocker/file_redirect_handler.sjs29
-rw-r--r--dom/security/test/mixedcontentblocker/file_server.sjs123
-rw-r--r--dom/security/test/mixedcontentblocker/mochitest.ini36
-rw-r--r--dom/security/test/mixedcontentblocker/test_bug803225.html155
-rw-r--r--dom/security/test/mixedcontentblocker/test_frameNavigation.html127
-rw-r--r--dom/security/test/mixedcontentblocker/test_main.html231
-rw-r--r--dom/security/test/mixedcontentblocker/test_redirect.html45
27 files changed, 2065 insertions, 0 deletions
diff --git a/dom/security/test/mixedcontentblocker/auto_upgrading_identity.html b/dom/security/test/mixedcontentblocker/auto_upgrading_identity.html
new file mode 100644
index 0000000000..d843b7fae1
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/auto_upgrading_identity.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>Bug 1674341: Test SiteIdentity when auto-upgrading mixed content</title>
+</head>
+<body>
+ <!-- needs to be http: image for mixed content and auto-upgrading -->
+ <img type="image/png" id="testimage" src="http://example.com/browser/dom/security/test/mixedcontentblocker/auto_upgrading_identity.png" />
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/auto_upgrading_identity.png b/dom/security/test/mixedcontentblocker/auto_upgrading_identity.png
new file mode 100644
index 0000000000..52c591798e
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/auto_upgrading_identity.png
Binary files differ
diff --git a/dom/security/test/mixedcontentblocker/browser.ini b/dom/security/test/mixedcontentblocker/browser.ini
new file mode 100644
index 0000000000..91e984e799
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/browser.ini
@@ -0,0 +1,12 @@
+[DEFAULT]
+support-files =
+ download_page.html
+ download_server.sjs
+
+[browser_test_mixed_content_download.js]
+[browser_mixed_content_auto_upgrade_display_console.js]
+support-files = file_mixed_content_auto_upgrade_display_console.html
+[browser_auto_upgrading_identity.js]
+support-files =
+ auto_upgrading_identity.html
+ auto_upgrading_identity.png
diff --git a/dom/security/test/mixedcontentblocker/browser_auto_upgrading_identity.js b/dom/security/test/mixedcontentblocker/browser_auto_upgrading_identity.js
new file mode 100644
index 0000000000..3ae924a4dc
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/browser_auto_upgrading_identity.js
@@ -0,0 +1,49 @@
+"use strict";
+
+const TEST_PATH = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "https://example.com"
+);
+const TEST_TOPLEVEL_URI = TEST_PATH + "auto_upgrading_identity.html";
+
+// auto upgrading mixed content should not indicate passive mixed content loaded
+add_task(async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [["security.mixed_content.upgrade_display_content", true]],
+ });
+ await BrowserTestUtils.withNewTab(TEST_TOPLEVEL_URI, async function(browser) {
+ await ContentTask.spawn(browser, {}, async function() {
+ let testImg = content.document.getElementById("testimage");
+ ok(
+ testImg.src.includes("auto_upgrading_identity.png"),
+ "sanity: correct image is loaded"
+ );
+ });
+ // Ensure the identiy handler does not show mixed content!
+ ok(
+ !gIdentityHandler._isMixedPassiveContentLoaded,
+ "Auto-Upgrading Mixed Content: Identity should note indicate mixed content"
+ );
+ });
+});
+
+// regular mixed content test should indicate passive mixed content loaded
+add_task(async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [["security.mixed_content.upgrade_display_content", false]],
+ });
+ await BrowserTestUtils.withNewTab(TEST_TOPLEVEL_URI, async function(browser) {
+ await ContentTask.spawn(browser, {}, async function() {
+ let testImg = content.document.getElementById("testimage");
+ ok(
+ testImg.src.includes("auto_upgrading_identity.png"),
+ "sanity: correct image is loaded"
+ );
+ });
+ // Ensure the identiy handler does show mixed content!
+ ok(
+ gIdentityHandler._isMixedPassiveContentLoaded,
+ "Regular Mixed Content: Identity should indicate mixed content"
+ );
+ });
+});
diff --git a/dom/security/test/mixedcontentblocker/browser_mixed_content_auto_upgrade_display_console.js b/dom/security/test/mixedcontentblocker/browser_mixed_content_auto_upgrade_display_console.js
new file mode 100644
index 0000000000..1da3e770a3
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/browser_mixed_content_auto_upgrade_display_console.js
@@ -0,0 +1,51 @@
+// Bug 1673574 - Improve Console logging for mixed content auto upgrading
+"use strict";
+
+const testPath = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "https://example.com"
+);
+
+let seenAutoUpgradeMessage = false;
+
+const kTestURI =
+ testPath + "file_mixed_content_auto_upgrade_display_console.html";
+
+add_task(async function() {
+ // A longer timeout is necessary for this test than the plain mochitests
+ // due to opening a new tab with the web console.
+ requestLongerTimeout(4);
+
+ // Enable HTTPS-Only Mode and register console-listener
+ await SpecialPowers.pushPrefEnv({
+ set: [["security.mixed_content.upgrade_display_content", true]],
+ });
+ Services.console.registerListener(on_auto_upgrade_message);
+
+ BrowserTestUtils.loadURI(gBrowser.selectedBrowser, kTestURI);
+
+ await BrowserTestUtils.waitForCondition(() => seenAutoUpgradeMessage);
+
+ Services.console.unregisterListener(on_auto_upgrade_message);
+});
+
+function on_auto_upgrade_message(msgObj) {
+ const message = msgObj.message;
+
+ // The console message is:
+ // "Mixed Content: Upgrading insecure display request
+ // ‘http://example.com/file_mixed_content_auto_upgrade_display_console.jpg’ to use ‘https’"
+
+ if (!message.includes("Mixed Content:")) {
+ return;
+ }
+ ok(
+ message.includes("Upgrading insecure display request"),
+ "msg includes info"
+ );
+ ok(
+ message.includes("file_mixed_content_auto_upgrade_display_console.jpg"),
+ "msg includes file"
+ );
+ seenAutoUpgradeMessage = true;
+}
diff --git a/dom/security/test/mixedcontentblocker/browser_test_mixed_content_download.js b/dom/security/test/mixedcontentblocker/browser_test_mixed_content_download.js
new file mode 100644
index 0000000000..3df280b0ec
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/browser_test_mixed_content_download.js
@@ -0,0 +1,215 @@
+ChromeUtils.defineModuleGetter(
+ this,
+ "Downloads",
+ "resource://gre/modules/Downloads.jsm"
+);
+ChromeUtils.defineModuleGetter(
+ this,
+ "DownloadsCommon",
+ "resource:///modules/DownloadsCommon.jsm"
+);
+
+let INSECURE_BASE_URL =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content/",
+ "http://example.com/"
+ ) + "download_page.html";
+let SECURE_BASE_URL =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content/",
+ "https://example.com/"
+ ) + "download_page.html";
+
+function promiseFocus() {
+ return new Promise(resolve => {
+ waitForFocus(resolve);
+ });
+}
+
+function promisePanelOpened() {
+ if (DownloadsPanel.panel && DownloadsPanel.panel.state == "open") {
+ return Promise.resolve();
+ }
+ return BrowserTestUtils.waitForEvent(DownloadsPanel.panel, "popupshown");
+}
+
+async function task_openPanel() {
+ await promiseFocus();
+
+ let promise = promisePanelOpened();
+ DownloadsPanel.showPanel();
+ await promise;
+}
+
+function shouldPromptDownload() {
+ // Waits until the download Prompt is shown
+ return new Promise((resolve, reject) => {
+ Services.wm.addListener({
+ onOpenWindow(xulWin) {
+ Services.wm.removeListener(this);
+ let win = xulWin.docShell.domWindow;
+ waitForFocus(() => {
+ if (
+ win.location ==
+ "chrome://mozapps/content/downloads/unknownContentType.xhtml"
+ ) {
+ let dialog = win.document.getElementById("unknownContentType");
+ let button = dialog.getButton("accept");
+ let saveRadio = win.document.getElementById("save");
+ saveRadio.click();
+ button.disabled = false;
+ dialog.acceptDialog();
+ resolve();
+ } else {
+ reject();
+ }
+ }, win);
+ },
+ });
+ });
+}
+
+const CONSOLE_ERROR_MESSAGE = "Blocked downloading insecure content";
+
+function shouldConsoleError() {
+ // Waits until CONSOLE_ERROR_MESSAGE was logged
+ return new Promise((resolve, reject) => {
+ function listener(msgObj) {
+ let text = msgObj.message;
+ if (text.includes(CONSOLE_ERROR_MESSAGE)) {
+ Services.console.unregisterListener(listener);
+ resolve();
+ }
+ }
+ Services.console.registerListener(listener);
+ });
+}
+
+async function resetDownloads() {
+ // Removes all downloads from the download List
+ let publicList = await Downloads.getList(Downloads.PUBLIC);
+ let downloads = await publicList.getAll();
+ for (let download of downloads) {
+ publicList.remove(download);
+ await download.finalize(true);
+ }
+}
+
+async function shouldNotifyDownloadUI() {
+ // Waits until a Blocked download was added to the Download List
+ // -> returns the blocked Download
+ let list = await Downloads.getList(Downloads.ALL);
+ return new Promise(res => {
+ const view = {
+ onDownloadAdded: aDownload => {
+ let { error } = aDownload;
+ if (
+ error.becauseBlockedByReputationCheck &&
+ error.reputationCheckVerdict == Downloads.Error.BLOCK_VERDICT_INSECURE
+ ) {
+ res(aDownload);
+ list.removeView(view);
+ }
+ },
+ };
+ list.addView(view);
+ });
+}
+
+async function runTest(url, link, checkFunction, decscription) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.block_download_insecure", true]],
+ });
+ await resetDownloads();
+
+ let tab = BrowserTestUtils.addTab(gBrowser, url);
+ gBrowser.selectedTab = tab;
+
+ let browser = gBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+
+ info("Checking: " + decscription);
+
+ let checkPromise = checkFunction();
+ // Click the Link to trigger the download
+ SpecialPowers.spawn(gBrowser.selectedBrowser, [link], contentLink => {
+ content.document.getElementById(contentLink).click();
+ });
+
+ await checkPromise;
+
+ ok(true, decscription);
+ BrowserTestUtils.removeTab(tab);
+
+ await SpecialPowers.popPrefEnv();
+}
+
+// Test Blocking
+add_task(async function() {
+ await runTest(
+ INSECURE_BASE_URL,
+ "insecure",
+ shouldPromptDownload,
+ "Insecure -> Insecure should download"
+ );
+ await runTest(
+ INSECURE_BASE_URL,
+ "secure",
+ shouldPromptDownload,
+ "Insecure -> Secure should download"
+ );
+ await runTest(
+ SECURE_BASE_URL,
+ "insecure",
+ () =>
+ Promise.all([
+ shouldPromptDownload(),
+ shouldNotifyDownloadUI(),
+ shouldConsoleError(),
+ ]),
+ "Secure -> Insecure should Error"
+ );
+ await runTest(
+ SECURE_BASE_URL,
+ "secure",
+ shouldPromptDownload,
+ "Secure -> Secure should Download"
+ );
+});
+// Test Manual Unblocking
+add_task(async function() {
+ await runTest(
+ SECURE_BASE_URL,
+ "insecure",
+ async () => {
+ await shouldPromptDownload();
+ let download = await shouldNotifyDownloadUI();
+ await download.unblock();
+ ok(download.error == null, "There should be no error after unblocking");
+ },
+ "A Blocked Download Should succeeded to Download after a Manual unblock"
+ );
+});
+
+// Test Unblock Download Visible
+add_task(async function() {
+ // Focus, open and close the panel once
+ // to make sure the panel is loaded and ready
+ await promiseFocus();
+ await runTest(
+ SECURE_BASE_URL,
+ "insecure",
+ async () => {
+ let panelHasOpened = promisePanelOpened();
+ info("awaiting that the Download Prompt is shown");
+ await shouldPromptDownload();
+ info("awaiting that the Download list adds the new download");
+ await shouldNotifyDownloadUI();
+ info("awaiting that the Download list shows itself");
+ await panelHasOpened;
+ DownloadsPanel.hidePanel();
+ ok(true, "The Download Panel should have opened on blocked download");
+ },
+ "A Blocked Download Should open the Download Panel"
+ );
+});
diff --git a/dom/security/test/mixedcontentblocker/download_page.html b/dom/security/test/mixedcontentblocker/download_page.html
new file mode 100644
index 0000000000..a9f7b731fe
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/download_page.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=676619
+-->
+ <head>
+
+ <title>Test for the download attribute</title>
+
+ </head>
+ <body>
+ hi
+
+ <script>
+ const host = window.location.host;
+ const path = location.pathname.replace("download_page.html","download_server.sjs");
+
+ const secureLink = document.createElement("a");
+ secureLink.href=`https://${host}/${path}`;
+ secureLink.download="true";
+ secureLink.textContent="Secure Link";
+
+ secureLink.id="secure";
+
+ const insecureLink = document.createElement("a");
+ insecureLink.href=`http://${host}/${path}`;
+ insecureLink.download="true";
+ insecureLink.id="insecure";
+ insecureLink.textContent="Not secure Link";
+
+ document.body.append(secureLink);
+ document.body.append(insecureLink);
+ </script>
+ </body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/download_server.sjs b/dom/security/test/mixedcontentblocker/download_server.sjs
new file mode 100644
index 0000000000..09d041f4c0
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/download_server.sjs
@@ -0,0 +1,9 @@
+// force the Browser to Show a Download Prompt
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Disposition", "attachment");
+ response.setHeader("Content-Type", "image/png");
+ response.write('🙈🙊🐵🙊');
+}
diff --git a/dom/security/test/mixedcontentblocker/file_bug803225_test_mailto.html b/dom/security/test/mixedcontentblocker/file_bug803225_test_mailto.html
new file mode 100644
index 0000000000..f1459d3667
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_bug803225_test_mailto.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker - Mailto Protocol Compose Page
+https://bugzilla.mozilla.org/show_bug.cgi?id=803225
+-->
+<head> <meta charset="utf-8">
+</head>
+<body>
+Hello
+<script>window.close();</script>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_frameNavigation.html b/dom/security/test/mixedcontentblocker/file_frameNavigation.html
new file mode 100644
index 0000000000..fd9ea23178
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_frameNavigation.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker related to navigating children, grandchildren, etc
+https://bugzilla.mozilla.org/show_bug.cgi?id=840388
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Mixed Content Frame Navigation</title>
+</head>
+<body>
+<div id="testContent"></div>
+
+<script>
+ var baseUrlHttps = "https://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html";
+
+ // For tests that require setTimeout, set the maximum polling time to 50 x 100ms = 5 seconds.
+ var MAX_COUNT = 50;
+ var TIMEOUT_INTERVAL = 100;
+
+ var testContent = document.getElementById("testContent");
+
+ // Test 1: Navigate secure iframe to insecure iframe on an insecure page
+ var iframe_test1 = document.createElement("iframe");
+ var counter_test1 = 0;
+ iframe_test1.src = baseUrlHttps + "?insecurePage_navigate_child";
+ iframe_test1.setAttribute("id", "test1");
+ iframe_test1.onerror = function() {
+ parent.postMessage({"test": "insecurePage_navigate_child", "msg": "got an onerror alert when loading or navigating testing iframe"}, "http://mochi.test:8888");
+ };
+ testContent.appendChild(iframe_test1);
+
+ function navigationStatus(iframe_test1)
+ {
+ // When the page is navigating, it goes through about:blank and we will get a permission denied for loc.
+ // Catch that specific exception and return
+ try {
+ var loc = document.getElementById("test1").contentDocument.location;
+ } catch(e) {
+ if (e.name === "SecurityError") {
+ // We received an exception we didn't expect.
+ throw e;
+ }
+ counter_test1++;
+ return;
+ }
+ if (loc == "http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?insecurePage_navigate_child_response") {
+ return;
+ }
+ else {
+ if(counter_test1 < MAX_COUNT) {
+ counter_test1++;
+ setTimeout(navigationStatus, TIMEOUT_INTERVAL, iframe_test1);
+ }
+ else {
+ // After we have called setTimeout the maximum number of times, assume navigating the iframe is blocked
+ parent.postMessage({"test": "insecurePage_navigate_child", "msg": "navigating to insecure iframe blocked on insecure page"}, "http://mochi.test:8888");
+ }
+ }
+ }
+
+ setTimeout(navigationStatus, TIMEOUT_INTERVAL, iframe_test1);
+
+ // Test 2: Navigate secure grandchild iframe to insecure grandchild iframe on a page that has no secure parents
+ var iframe_test2 = document.createElement("iframe");
+ iframe_test2.src = "http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_grandchild.html"
+ iframe_test2.onerror = function() {
+ parent.postMessage({"test": "insecurePage_navigate_grandchild", "msg": "got an on error alert when loading or navigating testing iframe"}, "http://mochi.test:8888");
+ };
+ testContent.appendChild(iframe_test2);
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_frameNavigation_blankTarget.html b/dom/security/test/mixedcontentblocker/file_frameNavigation_blankTarget.html
new file mode 100644
index 0000000000..a3fccf21f0
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_frameNavigation_blankTarget.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker - Opening link with _blank target in an https iframe.
+https://bugzilla.mozilla.org/show_bug.cgi?id=841850
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Mixed Content Frame Navigation</title>
+</head>
+<body>
+<a href="http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?blankTarget" id="blankTarget" target="_blank" rel="opener">Go to http site</a>
+
+<script>
+ var blankTarget = document.getElementById("blankTarget");
+ blankTarget.click();
+
+ var observer = {
+ observe(subject, topic, data) {
+ //Subject location check added for Bug 1391823 to avoid removeAsyncObserver from being called multiple times
+ if(topic == "content-document-global-created" && data =="http://example.com" && subject.location.href == "http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?blankTarget") {
+ parent.parent.postMessage({"test": "blankTarget", "msg": "opened an http link with target=_blank from a secure page"}, "http://mochi.test:8888");
+ SpecialPowers.removeAsyncObserver(observer, "content-document-global-created");
+ }
+ }
+ }
+ SpecialPowers.addAsyncObserver(observer, "content-document-global-created");
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_frameNavigation_grandchild.html b/dom/security/test/mixedcontentblocker/file_frameNavigation_grandchild.html
new file mode 100644
index 0000000000..10cf1e4d90
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_frameNavigation_grandchild.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker - Navigating Grandchild frames when a secure parent doesn't exist
+https://bugzilla.mozilla.org/show_bug.cgi?id=840388
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Mixed Content Frame Navigation</title>
+</head>
+<body>
+<iframe src="https://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?insecurePage_navigate_grandchild" id="child"></iframe>
+
+<script>
+ // For tests that require setTimeout, set the maximum polling time to 100 x 100ms = 10 seconds.
+ var MAX_COUNT = 50;
+ var TIMEOUT_INTERVAL = 100;
+ var counter = 0;
+
+ var child = document.getElementById("child");
+ function navigationStatus(child)
+ {
+ // When the page is navigating, it goes through about:blank and we will get a permission denied for loc.
+ // Catch that specific exception and return
+ try {
+ var loc;
+ if (child.contentDocument) {
+ loc = child.contentDocument.location;
+ }
+ } catch(e) {
+ if (e.message && !e.message.includes("Permission denied to access property")) {
+ // We received an exception we didn't expect.
+ throw e;
+ }
+ counter++;
+ return;
+ }
+ if (loc == "http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?insecurePage_navigate_grandchild_response") {
+ return;
+ }
+ else {
+ if(counter < MAX_COUNT) {
+ counter++;
+ setTimeout(navigationStatus, TIMEOUT_INTERVAL, child);
+ }
+ else {
+ // After we have called setTimeout the maximum number of times, assume navigating the iframe is blocked
+ parent.parent.postMessage({"test": "insecurePage_navigate_grandchild", "msg": "navigating to insecure grandchild iframe blocked on insecure page"}, "http://mochi.test:8888");
+ }
+ }
+ }
+
+ setTimeout(navigationStatus, TIMEOUT_INTERVAL, child);
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html b/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html
new file mode 100644
index 0000000000..251bb73e33
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<div id="content"></div>
+<script>
+ // get the case from the query string
+ var type = location.search.substring(1);
+
+ function clickLink() {
+ // If we don't reflow before clicking the link, the test will fail intermittently. The reason is still unknown. We'll track this issue in bug 1259715.
+ requestAnimationFrame(function() {
+ setTimeout(function() {
+ document.getElementById("link").click();
+ }, 0);
+ });
+ }
+
+ switch (type) {
+ case "insecurePage_navigate_child":
+ document.getElementById("content").innerHTML =
+ '<a href="http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?insecurePage_navigate_child_response" id="link">Testing\<\/a>';
+ clickLink();
+ break;
+
+ case "insecurePage_navigate_child_response":
+ parent.parent.postMessage({"test": "insecurePage_navigate_child", "msg": "navigated to insecure iframe on insecure page"}, "http://mochi.test:8888");
+ document.getElementById("content").innerHTML = "Navigated from secure to insecure frame on an insecure page";
+ break;
+
+ case "insecurePage_navigate_grandchild":
+ document.getElementById("content").innerHTML =
+ '<a href="http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?insecurePage_navigate_grandchild_response" id="link">Testing\<\/a>';
+ clickLink();
+ break;
+
+ case "insecurePage_navigate_grandchild_response":
+ parent.parent.parent.postMessage({"test": "insecurePage_navigate_grandchild", "msg": "navigated to insecure grandchild iframe on insecure page"}, "http://mochi.test:8888");
+ document.getElementById("content").innerHTML = "Navigated from secure to insecure grandchild frame on an insecure page";
+ break;
+
+ case "securePage_navigate_child":
+ document.getElementById("content").innerHTML =
+ '<a href="http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?securePage_navigate_child_response" id="link">Testing\<\/a>';
+ clickLink();
+ break;
+
+ case "securePage_navigate_child_response":
+ document.getElementById("content").innerHTML = "<p>Navigated from secure to insecure frame on a secure page</p>";
+ parent.parent.postMessage({"test": "securePage_navigate_child", "msg": "navigated to insecure iframe on secure page"}, "http://mochi.test:8888");
+ break;
+
+ case "securePage_navigate_grandchild":
+ document.getElementById("content").innerHTML=
+ '<a href="http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?securePage_navigate_grandchild_response" id="link">Testing\<\/a>';
+ clickLink();
+ break;
+
+ case "securePage_navigate_grandchild_response":
+ parent.parent.parent.postMessage({"test": "securePage_navigate_grandchild", "msg": "navigated to insecure grandchild iframe on secure page"}, "http://mochi.test:8888");
+ document.getElementById("content").innerHTML = "<p>Navigated from secure to insecure grandchild frame on a secure page</p>";
+ break;
+
+ case "blankTarget":
+ window.close();
+ break;
+
+ default:
+ document.getElementById("content").innerHTML = "Hello";
+ break;
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_frameNavigation_secure.html b/dom/security/test/mixedcontentblocker/file_frameNavigation_secure.html
new file mode 100644
index 0000000000..692d542067
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_frameNavigation_secure.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker related to navigating children, grandchildren, etc
+https://bugzilla.mozilla.org/show_bug.cgi?id=840388
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Mixed Content Frame Navigation</title>
+</head>
+<body>
+<div id="testContent"></div>
+
+<script>
+ var baseUrl = "https://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html";
+
+ // For tests that require setTimeout, set the maximum polling time to 50 x 100ms = 5 seconds.
+ var MAX_COUNT = 50;
+ var TIMEOUT_INTERVAL = 100;
+
+ var testContent = document.getElementById("testContent");
+
+ // Test 1: Navigate secure iframe to insecure iframe on a secure page
+ var iframe_test1 = document.createElement("iframe");
+ var counter_test1 = 0;
+ iframe_test1.setAttribute("id", "test1");
+ iframe_test1.src = baseUrl + "?securePage_navigate_child";
+ iframe_test1.onerror = function() {
+ parent.postMessage({"test": "securePage_navigate_child", "msg": "navigating to insecure iframe blocked on secure page"}, "http://mochi.test:8888");
+ };
+ testContent.appendChild(iframe_test1);
+
+ function navigationStatus(iframe_test1)
+ {
+ // When the page is navigating, it goes through about:blank and we will get a permission denied for loc.
+ // Catch that specific exception and return
+ try {
+ var loc = document.getElementById("test1").contentDocument.location;
+ } catch(e) {
+ if (e.name === "SecurityError") {
+ // We received an exception we didn't expect.
+ throw e;
+ }
+ counter_test1++;
+ return;
+ }
+ if (loc == "http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?insecurePage_navigate_child_response") {
+ return;
+ } else {
+ if(counter_test1 < MAX_COUNT) {
+ counter_test1++;
+ setTimeout(navigationStatus, TIMEOUT_INTERVAL, iframe_test1);
+ }
+ else {
+ // After we have called setTimeout the maximum number of times, assume navigating the iframe is blocked
+ parent.postMessage({"test": "securePage_navigate_child", "msg": "navigating to insecure iframe blocked on secure page"}, "http://mochi.test:8888");
+ }
+ }
+ }
+
+ setTimeout(navigationStatus, TIMEOUT_INTERVAL, iframe_test1);
+
+ // Test 2: Open an http page in a new tab from a link click with target=_blank.
+ var iframe_test3 = document.createElement("iframe");
+ iframe_test3.src = "https://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_blankTarget.html";
+ iframe_test3.onerror = function() {
+ parent.postMessage({"test": "blankTarget", "msg": "got an onerror event when loading or navigating testing iframe"}, "http://mochi.test:8888");
+ };
+ testContent.appendChild(iframe_test3);
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_frameNavigation_secure_grandchild.html b/dom/security/test/mixedcontentblocker/file_frameNavigation_secure_grandchild.html
new file mode 100644
index 0000000000..235ac0055e
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_frameNavigation_secure_grandchild.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker - Navigating Grandchild Frames when a secure parent exists
+https://bugzilla.mozilla.org/show_bug.cgi?id=840388
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Mixed Content Frame Navigation</title>
+</head>
+<body>
+
+<iframe src="https://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?securePage_navigate_grandchild" id="child"></iframe>
+<script>
+ // For tests that require setTimeout, set the maximum polling time to 50 x 100ms = 5 seconds.
+ var MAX_COUNT = 50;
+ var TIMEOUT_INTERVAL = 100;
+ var counter = 0;
+
+ var child = document.getElementById("child");
+ function navigationStatus(child)
+ {
+ var loc;
+ // When the page is navigating, it goes through about:blank and we will get a permission denied for loc.
+ // Catch that specific exception and return
+ try {
+ loc = document.getElementById("child").contentDocument.location;
+ } catch(e) {
+ if (e.message && !e.message.includes("Permission denied to access property")) {
+ // We received an exception we didn't expect.
+ throw e;
+ }
+ counter++;
+ return;
+ }
+ if (loc == "http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?securePage_navigate_grandchild_response") {
+ return;
+ }
+ else {
+ if(counter < MAX_COUNT) {
+ counter++;
+ setTimeout(navigationStatus, TIMEOUT_INTERVAL, child);
+ }
+ else {
+ // After we have called setTimeout the maximum number of times, assume navigating the iframe is blocked
+ dump("\nThe current location of the grandchild iframe is: "+loc+".\n");
+ dump("\nWe have past the maximum timeout. Navigating a grandchild iframe from an https location to an http location on a secure page failed. We are about to post message to the top level page\n");
+ parent.parent.postMessage({"test": "securePage_navigate_grandchild", "msg": "navigating to insecure grandchild iframe blocked on secure page"}, "http://mochi.test:8888");
+ dump("\nAttempted postMessage\n");
+ }
+ }
+ }
+
+ setTimeout(navigationStatus, TIMEOUT_INTERVAL, child);
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_main.html b/dom/security/test/mixedcontentblocker/file_main.html
new file mode 100644
index 0000000000..e4a2d8d08b
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_main.html
@@ -0,0 +1,338 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker
+https://bugzilla.mozilla.org/show_bug.cgi?id=62178
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 62178</title>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="testContent"></div>
+
+<!-- types the Mixed Content Blocker can block
+ /*
+ switch (aContentType) {
+ case nsIContentPolicy::TYPE_OBJECT:
+ case nsIContentPolicy::TYPE_SCRIPT:
+ case nsIContentPolicy::TYPE_STYLESHEET:
+ case nsIContentPolicy::TYPE_SUBDOCUMENT:
+ case nsIContentPolicy::TYPE_XMLHTTPREQUEST:
+
+ case nsIContentPolicy::TYPE_FONT: - NO TEST:
+ Load events for external fonts are not detectable by javascript.
+ case nsIContentPolicy::TYPE_WEBSOCKET: - NO TEST:
+ websocket connections over https require an encrypted websocket protocol (wss:)
+
+ case nsIContentPolicy::TYPE_IMAGE:
+ case nsIContentPolicy::TYPE_IMAGESET:
+ case nsIContentPolicy::TYPE_MEDIA:
+ case nsIContentPolicy::TYPE_PING:
+ our ping implementation is off by default and does not comply with the current spec (bug 786347)
+ case nsIContentPolicy::TYPE_BEACON:
+
+ }
+ */
+-->
+
+<script>
+ function ok(a, msg) {
+ parent.postMessage({msg, check: true, status: !!a}, "http://mochi.test:8888");
+ }
+
+ function is(a, b, msg) {
+ ok(a == b, msg);
+ }
+
+ function report(type, msg) {
+ parent.postMessage({test: type, msg}, "http://mochi.test:8888");
+ }
+
+ function uniqueID() {
+ return Math.floor(Math.random() * 100000)
+ }
+ function uniqueIDParam(id) {
+ return "&uniqueID=" + id;
+ }
+
+ async function init() {
+ var baseUrl = "http://example.com/tests/dom/security/test/mixedcontentblocker/file_server.sjs";
+ var checkLastRequestUrl = "https://example.com/tests/dom/security/test/mixedcontentblocker/file_server.sjs?lastRequest=true";
+
+ //For tests that require setTimeout, set the maximum polling time to 100 x 100ms = 10 seconds.
+ var MAX_COUNT = 100;
+ var TIMEOUT_INTERVAL = 100;
+
+ var testContent = document.getElementById("testContent");
+
+ async function checkLastRequest() {
+ const response = await fetch(checkLastRequestUrl);
+ return response.json();
+ }
+
+ /* Part 1: Mixed Script tests */
+
+ // Test 1a: insecure object
+ var object = document.createElement("object");
+ var objectId = uniqueID();
+ object.data = baseUrl + "?type=object" + uniqueIDParam(objectId);
+ object.type = "image/png";
+ object.width = "200";
+ object.height = "200";
+
+ testContent.appendChild(object);
+
+ var objectCount = 0;
+
+ function objectStatus(object) {
+ // Expose our privileged bits on the object. We will match the MIME type to the one
+ // provided by file_server.sjs
+ object = SpecialPowers.wrap(object);
+ var typeIsSet = object.actualType && (object.actualType !== '');
+ var isLoaded = typeIsSet && object.actualType === 'application/x-test-match';
+ if (isLoaded) {
+ //object loaded
+ report("object", "insecure object loaded");
+ }
+ else {
+ if(!typeIsSet && objectCount < MAX_COUNT) {
+ objectCount++;
+ setTimeout(objectStatus, TIMEOUT_INTERVAL, object);
+ }
+ else {
+ //After we have called setTimeout the maximum number of times, assume object is blocked
+ report("object", "insecure object blocked");
+ }
+ }
+ }
+
+ // object does not have onload and onerror events. Hence we need a setTimeout to check the object's status
+ setTimeout(objectStatus, TIMEOUT_INTERVAL, object);
+
+ // Test 1b: insecure script
+ var script = document.createElement("script");
+ var scriptId = uniqueID();
+ var scriptLoad = false;
+ var scriptCount = 0;
+ script.src = baseUrl + "?type=script" + uniqueIDParam(scriptId);
+ script.onload = function(e) {
+ report("script", "insecure script loaded");
+ scriptLoad = true;
+ }
+ testContent.appendChild(script);
+
+ function scriptStatus(script)
+ {
+ if(scriptLoad) {
+ return;
+ }
+ else {
+ if(scriptCount < MAX_COUNT) {
+ scriptCount++;
+ setTimeout(scriptStatus, TIMEOUT_INTERVAL, script);
+ }
+ else {
+ //After we have called setTimeout the maximum number of times, assume script is blocked
+ report("script", "insecure script blocked");
+ }
+ }
+ }
+
+ // scripts blocked by Content Policy's do not have onerror events (see bug 789856). Hence we need a setTimeout to check the script's status
+ setTimeout(scriptStatus, TIMEOUT_INTERVAL, script);
+
+
+ // Test 1c: insecure stylesheet
+ var cssStyleSheet = document.createElement("link");
+ var cssStyleSheetId = uniqueID();
+ cssStyleSheet.rel = "stylesheet";
+ cssStyleSheet.href = baseUrl + "?type=stylesheet" + uniqueIDParam(cssStyleSheetId);
+ cssStyleSheet.type = "text/css";
+ testContent.appendChild(cssStyleSheet);
+
+ var styleCount = 0;
+
+ function styleStatus(cssStyleSheet) {
+ if( cssStyleSheet.sheet || cssStyleSheet.styleSheet || cssStyleSheet.innerHTML ) {
+ report("stylesheet", "insecure stylesheet loaded");
+ }
+ else {
+ if(styleCount < MAX_COUNT) {
+ styleCount++;
+ setTimeout(styleStatus, TIMEOUT_INTERVAL, cssStyleSheet);
+ }
+ else {
+ //After we have called setTimeout the maximum number of times, assume stylesheet is blocked
+ report("stylesheet", "insecure stylesheet blocked");
+ }
+ }
+ }
+
+ // link does not have onload and onerror events. Hence we need a setTimeout to check the link's status
+ window.setTimeout(styleStatus, TIMEOUT_INTERVAL, cssStyleSheet);
+
+ // Test 1d: insecure iframe
+ var iframe = document.createElement("iframe");
+ var iframeId = uniqueID();
+ iframe.src = baseUrl + "?type=iframe" + uniqueIDParam(iframeId);
+ iframe.onload = function() {
+ report("iframe", "insecure iframe loaded");
+ }
+ iframe.onerror = function() {
+ report("iframe", "insecure iframe blocked");
+ };
+ testContent.appendChild(iframe);
+
+
+ // Test 1e: insecure xhr
+ await new Promise((resolve) => {
+ var xhr = new XMLHttpRequest;
+ var xhrId = uniqueID();
+ try {
+ xhr.open("GET", baseUrl + "?type=xhr" + uniqueIDParam(xhrId), true);
+ xhr.send();
+ xhr.onloadend = function (oEvent) {
+ if (xhr.status == 200) {
+ report("xhr", "insecure xhr loaded");
+ resolve();
+ }
+ else {
+ report("xhr", "insecure xhr blocked");
+ resolve();
+ }
+ }
+ } catch(ex) {
+ report("xhr", "insecure xhr blocked");
+ resolve();
+ }
+ });
+
+ /* Part 2: Mixed Display tests */
+
+ // Shorthand for all image test variants
+ async function imgHandlers(img, test, uniqueID) {
+ await new Promise((resolve) => {
+ img.onload = async () => {
+ const lastRequest = await checkLastRequest();
+ is(lastRequest.uniqueID, uniqueID, "UniqueID for the last request matches");
+ let message = "insecure image loaded";
+ if (lastRequest.scheme == "https") {
+ message = "secure image loaded after upgrade";
+ }
+ report(test, message);
+ resolve();
+ }
+ img.onerror = async () => {
+ let message = "insecure image blocked";
+ report(test, message);
+ resolve();
+ }
+ });
+ }
+
+ // Test 2a: insecure image
+ var img = document.createElement("img");
+ var imgId = uniqueID();
+ img.src = baseUrl + "?type=img" + uniqueIDParam(imgId);
+ await imgHandlers(img, "image", imgId);
+ // We don't need to append the image to the document. Doing so causes the image test to run twice.
+
+ // Test 2b: insecure media
+ var media = document.createElement("video");
+ var mediaId = uniqueID();
+ media.src = baseUrl + "?type=media" + uniqueIDParam(mediaId);
+ media.width = "320";
+ media.height = "200";
+ media.type = "video/ogg";
+ await new Promise(res => {
+ media.onloadeddata = async () => {
+ const lastRequest = await checkLastRequest();
+ is(lastRequest.uniqueID, mediaId, "UniqueID for the last request matches");
+ let message = "insecure media loaded";
+ if (lastRequest.scheme == "https") {
+ message = "secure media loaded after upgrade";
+ }
+ report("media", message);
+ res();
+ }
+ media.onerror = function() {
+ report("media", "insecure media blocked");
+ res();
+ }
+ });
+ // We don't need to append the video to the document. Doing so causes the image test to run twice.
+
+ /* Part 3: Mixed Active Tests for Image srcset */
+
+ // Test 3a: image with srcset
+ var imgA = document.createElement("img");
+ var imgAId = uniqueID();
+ imgA.srcset = baseUrl + "?type=img&subtype=imageSrcset" + uniqueIDParam(imgAId);
+ await imgHandlers(imgA, "imageSrcset", imgAId);
+
+ // Test 3b: image with srcset, using fallback from src, should still use imageset policy
+ var imgB = document.createElement("img");
+ var imgBId = uniqueID();
+ imgB.srcset = " ";
+ imgB.src = baseUrl + "?type=img&subtype=imageSrcSetFallback" + uniqueIDParam(imgBId);
+ await imgHandlers(imgB, "imageSrcsetFallback", imgBId);
+
+ // Test 3c: image in <picture>
+ var imgC = document.createElement("img");
+ var pictureC = document.createElement("picture");
+ var sourceC = document.createElement("source");
+ var sourceCId = uniqueID();
+ sourceC.srcset = baseUrl + "?type=img&subtype=imagePicture" + uniqueIDParam(sourceCId);
+ pictureC.appendChild(sourceC);
+ pictureC.appendChild(imgC);
+ await imgHandlers(imgC, "imagePicture", sourceCId);
+
+ // Test 3d: Loaded basic image switching to a <picture>, loading
+ // same source, should still redo the request with new
+ // policy.
+ var imgD = document.createElement("img");
+ var imgDId = uniqueID();
+ var sourceDId = uniqueID();
+ imgD.src = baseUrl + "?type=img&subtype=imageJoinPicture" + uniqueIDParam(imgDId);
+ await new Promise(res => {
+ imgD.onload = imgD.onerror = function() {
+ // Whether or not it loads, we want to now append it to a picture and observe
+ var pictureD = document.createElement("picture");
+ var sourceD = document.createElement("source");
+ sourceD.srcset = baseUrl + "?type=img&subtype=imageJoinPicture2" + uniqueIDParam(sourceDId);
+ pictureD.appendChild(sourceD);
+ pictureD.appendChild(imgD);
+ res();
+ }
+ });
+ await imgHandlers(imgD, "imageJoinPicture", sourceDId);
+
+ // Test 3e: img load from <picture> source reverts to img.src as it
+ // is removed -- the new request should revert to mixed
+ // display policy
+ var imgE = document.createElement("img");
+ var pictureE = document.createElement("picture");
+ var pictureEId = uniqueID();
+ var sourceE = document.createElement("source");
+ var sourceEId = uniqueID();
+ sourceE.srcset = baseUrl + "?type=img&subtype=imageLeavePicture" + uniqueIDParam(sourceEId);
+ pictureE.appendChild(sourceE);
+ pictureE.appendChild(imgE);
+ imgE.src = baseUrl + "?type=img&subtype=imageLeavePicture2" + uniqueIDParam(pictureEId);
+ await new Promise(res => {
+ imgE.onload = imgE.onerror = function() {
+ // Whether or not it loads, remove it from the picture and observe
+ pictureE.removeChild(imgE)
+ res();
+ }
+ });
+ await imgHandlers(imgE, "imageLeavePicture", pictureEId);
+ }
+
+ init();
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_main_bug803225.html b/dom/security/test/mixedcontentblocker/file_main_bug803225.html
new file mode 100644
index 0000000000..793c40768a
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_main_bug803225.html
@@ -0,0 +1,172 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker - Allowed Protocols
+https://bugzilla.mozilla.org/show_bug.cgi?id=803225
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 62178</title>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="testContent"></div>
+
+<!-- Test additional schemes the Mixed Content Blocker should not block
+ "about" protocol URIs that are URI_SAFE_FOR_UNTRUSTED_CONTENT (moz-safe-about; see nsAboutProtocolHandler::NewURI
+ "data",
+ "javascript",
+ "mailto",
+ "resource",
+ "wss"
+-->
+
+<script>
+ const {AppConstants} = SpecialPowers.Cu.import("resource://gre/modules/AppConstants.jsm", {});
+
+ //For tests that require setTimeout, set the timeout interval
+ var TIMEOUT_INTERVAL = 100;
+
+ var testContent = document.getElementById("testContent");
+
+ // Test 1 & 2: about and javascript protcols within an iframe
+ var data = Array(2,2);
+ var protocols = [
+ ["about", ""], //When no source is specified, the frame gets a source of about:blank
+ ["javascript", "javascript:document.open();document.write='<h1>SUCCESS</h1>';document.close();"],
+ ];
+ for(var i=0; i < protocols.length; i++)
+ {
+ var generic_frame = document.createElement("iframe");
+ generic_frame.src = protocols[i][1];
+ generic_frame.name="generic_protocol";
+
+ generic_frame.onload = function(i) {
+ data = {"test": protocols[i][0], "msg": "resource with " + protocols[i][0] + " protocol loaded"};
+ parent.postMessage(data, "http://mochi.test:8888");
+ }.bind(generic_frame, i)
+
+ generic_frame.onerror = function(i) {
+ data = {"test": protocols[i][0], "msg": "resource with " + protocols[i][0] + " protocol did not load"};
+ parent.postMessage(data, "http://mochi.test:8888");
+ }.bind(generic_frame, i);
+
+ testContent.appendChild(generic_frame, i);
+ }
+
+ // Test 3: for resource within a script tag
+ // Note: the script we load throws an exception, but the script element's
+ // onload listener is called after we successfully fetch the script,
+ // independently of whether it throws an exception.
+ var resource_script=document.createElement("script");
+ resource_script.src = "resource://gre/modules/XPCOMUtils.jsm";
+ resource_script.name = "resource_protocol";
+ resource_script.onload = function() {
+ parent.postMessage({"test": "resource", "msg": "resource with resource protocol loaded"}, "http://mochi.test:8888");
+ }
+ resource_script.onerror = function() {
+ parent.postMessage({"test": "resource", "msg": "resource with resource protocol did not load"}, "http://mochi.test:8888");
+ }
+
+ testContent.appendChild(resource_script);
+
+ // Test 4: about unsafe protocol within an iframe
+ var unsafe_about_frame = document.createElement("iframe");
+ unsafe_about_frame.src = "about:config";
+ unsafe_about_frame.name = "unsafe_about_protocol";
+ unsafe_about_frame.onload = function() {
+ parent.postMessage({"test": "unsafe_about", "msg": "resource with unsafe about protocol loaded"}, "http://mochi.test:8888");
+ }
+ unsafe_about_frame.onerror = function() {
+ parent.postMessage({"test": "unsafe_about", "msg": "resource with unsafe about protocol did not load"}, "http://mochi.test:8888");
+ }
+ testContent.appendChild(unsafe_about_frame);
+
+ // Test 5: data protocol within a script tag
+ var x = 2;
+ var newscript = document.createElement("script");
+ newscript.src= "data:text/javascript,var x = 4;";
+ newscript.onload = function() {
+ parent.postMessage({"test": "data_protocol", "msg": "resource with data protocol loaded"}, "http://mochi.test:8888");
+ }
+ newscript.onerror = function() {
+ parent.postMessage({"test": "data_protocol", "msg": "resource with data protocol did not load"}, "http://mochi.test:8888");
+ }
+ testContent.appendChild(newscript);
+
+ // Test 6: mailto protocol
+ let mm = SpecialPowers.loadChromeScript(function launchHandler() {
+ var ioService = Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+
+ var webHandler = Cc["@mozilla.org/uriloader/web-handler-app;1"].
+ createInstance(Ci.nsIWebHandlerApp);
+ webHandler.name = "Web Handler";
+ webHandler.uriTemplate = "http://example.com/tests/dom/security/test/mixedcontentblocker/file_bug803225_test_mailto.html?s=%";
+
+ const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+ Services.ppmm.addMessageListener("Test:content-ready", function contentReadyListener() {
+ Services.ppmm.removeMessageListener("Test:content-ready", contentReadyListener);
+ sendAsyncMessage("Test:content-ready-forward");
+ Services.ppmm.removeDelayedProcessScript(pScript);
+ })
+
+ var pScript = "data:,new " + function () {
+ var os = Cc["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+ var observer = {
+ observe(subject, topic, data) {
+ if (topic == "content-document-global-created" && data == "http://example.com") {
+ sendAsyncMessage("Test:content-ready");
+ os.removeObserver(observer, "content-document-global-created");
+ }
+ }
+ };
+ os.addObserver(observer, "content-document-global-created");
+ }
+
+ Services.ppmm.loadProcessScript(pScript, true);
+
+ var uri = ioService.newURI("mailto:foo@bar.com");
+ webHandler.launchWithURI(uri);
+ });
+
+ var mailto = false;
+
+ mm.addMessageListener("Test:content-ready-forward", function contentReadyListener() {
+ mm.removeMessageListener("Test:content-ready-forward", contentReadyListener);
+ mailto = true;
+ parent.postMessage({"test": "mailto", "msg": "resource with mailto protocol loaded"}, "http://mochi.test:8888");
+ });
+
+ function mailtoProtocolStatus() {
+ if(!mailto) {
+ //There is no onerror event associated with the WebHandler, and hence we need a setTimeout to check the status
+ setTimeout(mailtoProtocolStatus, TIMEOUT_INTERVAL);
+ }
+ }
+
+ mailtoProtocolStatus();
+
+ // Test 7: wss protocol
+ // WebSocket tests are not supported on Android Yet. Bug 1566168.
+ if (AppConstants.platform !== "android") {
+ var wss;
+ wss = new WebSocket("wss://example.com/tests/dom/security/test/mixedcontentblocker/file_main_bug803225_websocket");
+
+ var status_wss = "started";
+ wss.onopen = function(e) {
+ status_wss = "opened";
+ wss.close();
+ }
+ wss.onclose = function(e) {
+ if(status_wss == "opened") {
+ parent.postMessage({"test": "wss", "msg": "resource with wss protocol loaded"}, "http://mochi.test:8888");
+ } else {
+ parent.postMessage({"test": "wss", "msg": "resource with wss protocol did not load"}, "http://mochi.test:8888");
+ }
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_main_bug803225_websocket_wsh.py b/dom/security/test/mixedcontentblocker/file_main_bug803225_websocket_wsh.py
new file mode 100644
index 0000000000..b7159c742b
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_main_bug803225_websocket_wsh.py
@@ -0,0 +1,6 @@
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ pass
diff --git a/dom/security/test/mixedcontentblocker/file_mixed_content_auto_upgrade_display_console.html b/dom/security/test/mixedcontentblocker/file_mixed_content_auto_upgrade_display_console.html
new file mode 100644
index 0000000000..b86fbc9cbc
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_mixed_content_auto_upgrade_display_console.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Bug 1673574 - Improve Console logging for mixed content auto upgrading</title>
+</head>
+<body>
+ <!-- The following file does in fact not exist because we only care if it shows up in the console -->
+ <img src="http://example.com/file_mixed_content_auto_upgrade_display_console.jpg">
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_redirect.html b/dom/security/test/mixedcontentblocker/file_redirect.html
new file mode 100644
index 0000000000..99e1873791
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_redirect.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Bug1402363: Test mixed content redirects</title>
+</head>
+<body>
+
+<script type="text/javascript">
+ const PATH = "https://example.com/tests/dom/security/test/mixedcontentblocker/";
+
+ // check a fetch redirect from https to https (should be allowed)
+ fetch(PATH + "file_redirect_handler.sjs?https-to-https-redirect", {
+ method: 'get'
+ }).then(function(response) {
+ window.parent.postMessage("https-to-https-loaded", "*");
+ }).catch(function(err) {
+ window.parent.postMessage("https-to-https-blocked", "*");
+ });
+
+ // check a fetch redirect from https to http (should be blocked)
+ fetch(PATH + "file_redirect_handler.sjs?https-to-http-redirect", {
+ method: 'get'
+ }).then(function(response) {
+ window.parent.postMessage("https-to-http-loaded", "*");
+ }).catch(function(err) {
+ window.parent.postMessage("https-to-http-blocked", "*");
+ });
+
+</script>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/file_redirect_handler.sjs b/dom/security/test/mixedcontentblocker/file_redirect_handler.sjs
new file mode 100644
index 0000000000..88dc849fe9
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_redirect_handler.sjs
@@ -0,0 +1,29 @@
+// custom *.sjs file for
+// Bug 1402363: Test Mixed Content Redirect Blocking.
+
+const URL_PATH = "example.com/tests/dom/security/test/mixedcontentblocker/";
+
+function handleRequest(request, response) {
+ response.setHeader("Cache-Control", "no-cache", false);
+ let queryStr = request.queryString;
+
+ if (queryStr === "https-to-https-redirect") {
+ response.setStatusLine("1.1", 302, "Found");
+ response.setHeader("Location",
+ "https://" + URL_PATH + "file_redirect_handler.sjs?load", false);
+ return;
+ }
+
+ if (queryStr === "https-to-http-redirect") {
+ response.setStatusLine("1.1", 302, "Found");
+ response.setHeader("Location",
+ "http://" + URL_PATH + "file_redirect_handler.sjs?load", false);
+ return;
+ }
+
+ if (queryStr === "load") {
+ response.setHeader("Content-Type", "text/html", false);
+ response.write("foo");
+ return;
+ }
+}
diff --git a/dom/security/test/mixedcontentblocker/file_server.sjs b/dom/security/test/mixedcontentblocker/file_server.sjs
new file mode 100644
index 0000000000..612ee5db9e
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_server.sjs
@@ -0,0 +1,123 @@
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+
+function ERR(response, msg) {
+ dump("ERROR: " + msg + "\n");
+ response.write("HTTP/1.1 400 Bad Request\r\n");
+ response.write("Content-Type: text/html; charset=UTF-8\r\n");
+ response.write("Content-Length: " + msg.length + "\r\n");
+ response.write("\r\n");
+ response.write(msg);
+}
+
+function loadContentFromFile(path) {
+ // Load the content to return in the response from file.
+ // Since it's relative to the cwd of the test runner, we start there and
+ // append to get to the actual path of the file.
+ var testContentFile =
+ Components.classes["@mozilla.org/file/directory_service;1"].
+ getService(Components.interfaces.nsIProperties).
+ get("CurWorkD", Components.interfaces.nsIFile);
+ var dirs = path.split("/");
+ for (var i = 0; i < dirs.length; i++) {
+ testContentFile.append(dirs[i]);
+ }
+ var testContentFileStream =
+ Components.classes["@mozilla.org/network/file-input-stream;1"].
+ createInstance(Components.interfaces.nsIFileInputStream);
+ testContentFileStream.init(testContentFile, -1, 0, 0);
+ var testContent = NetUtil.readInputStreamToString(testContentFileStream, testContentFileStream.available());
+ return testContent;
+}
+
+function handleRequest(request, response)
+{
+ const { scheme, host, path } = request;
+ // get the Content-Type to serve from the query string
+ var contentType = null;
+ var uniqueID = null;
+ var showLastRequest = false;
+ request.queryString.split('&').forEach(function (val) {
+ var [name, value] = val.split('=');
+ if (name == "type") {
+ contentType = unescape(value);
+ }
+ if (name == "uniqueID") {
+ uniqueID = unescape(value);
+ }
+ if (name == "lastRequest") {
+ showLastRequest = true;
+ }
+ });
+
+ // avoid confusing cache behaviors
+ response.setHeader("Cache-Control", "no-cache", false);
+
+ if (showLastRequest) {
+ response.setHeader("Content-Type", "text/html", false);
+
+ // We don't want to expose the same lastRequest multiple times.
+ var state = getState("lastRequest");
+ setState("lastRequest", "");
+
+ if (state == "") {
+ ERR(response, "No last request!");
+ return;
+ }
+
+ response.write(state);
+ return;
+ }
+
+ if (!uniqueID) {
+ ERR(response, "No uniqueID?!?");
+ return;
+ }
+
+ setState("lastRequest", JSON.stringify({
+ scheme,
+ host,
+ path,
+ uniqueID,
+ contentType: contentType || "other",
+ }));
+
+ switch (contentType) {
+ case "img":
+ response.setHeader("Content-Type", "image/png", false);
+ response.write(loadContentFromFile("tests/image/test/mochitest/blue.png"));
+ break;
+
+ case "media":
+ response.setHeader("Content-Type", "video/ogg", false);
+ response.write(loadContentFromFile("tests/dom/media/test/320x240.ogv"));
+ break;
+
+ case "iframe":
+ response.setHeader("Content-Type", "text/html", false);
+ response.write("frame content");
+ break;
+
+ case "script":
+ response.setHeader("Content-Type", "application/javascript", false);
+ break;
+
+ case "stylesheet":
+ response.setHeader("Content-Type", "text/css", false);
+ break;
+
+ case "object":
+ response.setHeader("Content-Type", "application/x-test-match", false);
+ break;
+
+ case "xhr":
+ response.setHeader("Content-Type", "text/xml", false);
+ response.setHeader("Access-Control-Allow-Origin", "https://example.com");
+ response.write('<?xml version="1.0" encoding="UTF-8" ?><test></test>');
+ break;
+
+ default:
+ response.setHeader("Content-Type", "text/html", false);
+ response.write("<html><body>Hello World</body></html>");
+ break;
+ }
+}
diff --git a/dom/security/test/mixedcontentblocker/mochitest.ini b/dom/security/test/mixedcontentblocker/mochitest.ini
new file mode 100644
index 0000000000..3c07133b78
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/mochitest.ini
@@ -0,0 +1,36 @@
+[DEFAULT]
+tags = mcb
+prefs =
+ plugin.load_flash_only=false
+ security.mixed_content.upgrade_display_content=false
+support-files =
+ file_bug803225_test_mailto.html
+ file_frameNavigation.html
+ file_frameNavigation_blankTarget.html
+ file_frameNavigation_grandchild.html
+ file_frameNavigation_innermost.html
+ file_frameNavigation_secure.html
+ file_frameNavigation_secure_grandchild.html
+ file_main.html
+ file_main_bug803225.html
+ file_main_bug803225_websocket_wsh.py
+ file_server.sjs
+ !/dom/media/test/320x240.ogv
+ !/image/test/mochitest/blue.png
+ file_redirect.html
+ file_redirect_handler.sjs
+
+[test_main.html]
+skip-if =
+ toolkit == 'android' || webrender || (verify && !debug && os == 'linux') # Android: TIMED_OUT; bug 1402554
+ tsan # Times out / Memory consumption, bug 1612707
+[test_bug803225.html]
+skip-if = (os=='linux' && bits==32) || headless || tsan # Linux32:bug 1324870; Headless:bug 1405870; tsan:bug 1612707
+[test_frameNavigation.html]
+fail-if = fission
+skip-if =
+ webrender # Bug 1424752
+ debug && (os == 'linux' || os == 'win') # Bug 1391823
+ os == 'win' && !debug # Bug 1353608
+ xorigin && fission # Application time out
+[test_redirect.html]
diff --git a/dom/security/test/mixedcontentblocker/test_bug803225.html b/dom/security/test/mixedcontentblocker/test_bug803225.html
new file mode 100644
index 0000000000..e15ce45ec1
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/test_bug803225.html
@@ -0,0 +1,155 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Testing Allowlist of Resource Scheme for Mixed Content Blocker
+https://bugzilla.mozilla.org/show_bug.cgi?id=803225
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 803225</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+ <script>
+ const {AppConstants} = SpecialPowers.Cu.import("resource://gre/modules/AppConstants.jsm", {});
+
+ var counter = 0;
+ var settings = [ [true, true], [true, false], [false, true], [false, false] ];
+
+ var blockActive;
+ var blockDisplay;
+
+ //Cycle through 4 different preference settings.
+ function changePrefs(callback) {
+ let newPrefs = [
+ ["security.all_resource_uri_content_accessible", true], // Temporarily allow content to access all resource:// URIs.
+ ["security.mixed_content.block_display_content", settings[counter][0]],
+ ["security.mixed_content.block_active_content", settings[counter][1]]
+ ];
+
+ SpecialPowers.pushPrefEnv({"set": newPrefs}, function () {
+ blockDisplay = SpecialPowers.getBoolPref("security.mixed_content.block_display_content");
+ blockActive = SpecialPowers.getBoolPref("security.mixed_content.block_active_content");
+ counter++;
+ callback();
+ });
+ }
+
+ var testsToRun = {
+ /* https - Tests already run as part of bug 62178. */
+ about: false,
+ resource: false,
+ unsafe_about: false,
+ data_protocol: false,
+ javascript: false,
+ };
+
+ if (AppConstants.platform !== "android") {
+ // WebSocket tests are not supported on Android Yet. Bug 1566168.
+ testsToRun.wss = false;
+ testsToRun.mailto = false;
+ }
+
+ function log(msg) {
+ document.getElementById("log").textContent += "\n" + msg;
+ }
+
+ function reloadFrame() {
+ document.getElementById('framediv').innerHTML = '<iframe id="testHarness" src="https://example.com/tests/dom/security/test/mixedcontentblocker/file_main_bug803225.html"></iframe>';
+ }
+
+ function checkTestsCompleted() {
+ for (var prop in testsToRun) {
+ // some test hasn't run yet so we're not done
+ if (!testsToRun[prop])
+ return;
+ }
+ //if the testsToRun are all completed, change the pref and run the tests again until we have cycled through all the prefs.
+ if(counter < 4) {
+ for (var prop in testsToRun) {
+ testsToRun[prop] = false;
+ }
+ //call to change the preferences
+ changePrefs(function() {
+ log("\nblockDisplay set to "+blockDisplay+", blockActive set to "+blockActive+".");
+ reloadFrame();
+ });
+ }
+ else {
+ SimpleTest.finish();
+ }
+ }
+
+ var firstTest = true;
+
+ function receiveMessage(event) {
+ if(firstTest) {
+ log("blockDisplay set to "+blockDisplay+", blockActive set to "+blockActive+".");
+ firstTest = false;
+ }
+
+ log("test: "+event.data.test+", msg: "+event.data.msg + " logging message.");
+ // test that the load type matches the pref for this type of content
+ // (i.e. active vs. display)
+
+ switch(event.data.test) {
+
+ /* Mixed Script tests */
+ case "about":
+ ok(event.data.msg == "resource with about protocol loaded", "resource with about protocol did not load");
+ testsToRun.about = true;
+ break;
+
+ case "resource":
+ ok(event.data.msg == "resource with resource protocol loaded", "resource with resource protocol did not load");
+ testsToRun.resource = true;
+ break;
+
+ case "unsafe_about":
+ // This one should not load
+ ok(event.data.msg == "resource with unsafe about protocol did not load", "resource with unsafe about protocol loaded");
+ testsToRun.unsafe_about = true;
+ break;
+
+ case "data_protocol":
+ ok(event.data.msg == "resource with data protocol loaded", "resource with data protocol did not load");
+ testsToRun.data_protocol = true;
+ break;
+
+ case "javascript":
+ ok(event.data.msg == "resource with javascript protocol loaded", "resource with javascript protocol did not load");
+ testsToRun.javascript = true;
+ break;
+
+ case "wss":
+ ok(event.data.msg == "resource with wss protocol loaded", "resource with wss protocol did not load");
+ testsToRun.wss = true;
+ break;
+
+ case "mailto":
+ ok(event.data.msg == "resource with mailto protocol loaded", "resource with mailto protocol did not load");
+ testsToRun.mailto = true;
+ break;
+ }
+ checkTestsCompleted();
+ }
+
+ function startTest() {
+ //Set the first set of settings (true, true) and increment the counter.
+ changePrefs(function() {
+ // listen for a messages from the mixed content test harness
+ window.addEventListener("message", receiveMessage);
+
+ reloadFrame();
+ });
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ </script>
+</head>
+
+<body onload='startTest()'>
+ <div id="framediv"></div>
+ <pre id="log"></pre>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/test_frameNavigation.html b/dom/security/test/mixedcontentblocker/test_frameNavigation.html
new file mode 100644
index 0000000000..82e3e715d2
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/test_frameNavigation.html
@@ -0,0 +1,127 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker
+https://bugzilla.mozilla.org/show_bug.cgi?id=840388
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 840388</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+ <script>
+ var counter = 0;
+ var origBlockActive = SpecialPowers.getBoolPref("security.mixed_content.block_active_content");
+
+ SpecialPowers.setBoolPref("security.mixed_content.block_active_content", true);
+ var blockActive = SpecialPowers.getBoolPref("security.mixed_content.block_active_content");
+
+
+ var testsToRunInsecure = {
+ insecurePage_navigate_child: false,
+ insecurePage_navigate_grandchild: false,
+ };
+
+ var testsToRunSecure = {
+ securePage_navigate_child: false,
+ blankTarget: false,
+ };
+
+ function log(msg) {
+ document.getElementById("log").textContent += "\n" + msg;
+ }
+
+ var secureTestsStarted = false;
+ async function checkTestsCompleted() {
+ for (var prop in testsToRunInsecure) {
+ // some test hasn't run yet so we're not done
+ if (!testsToRunInsecure[prop])
+ return;
+ }
+ // If we are here, all the insecure tests have run.
+ // If we haven't changed the iframe to run the secure tests, change it now.
+ if (!secureTestsStarted) {
+ document.getElementById('testing_frame').src = "https://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_secure.html";
+ secureTestsStarted = true;
+ }
+ for (var prop in testsToRunSecure) {
+ // some test hasn't run yet so we're not done
+ if (!testsToRunSecure[prop])
+ return;
+ }
+ //if the secure and insecure testsToRun are all completed, change the block mixed active content pref and run the tests again.
+ if(counter < 1) {
+ for (var prop in testsToRunSecure) {
+ testsToRunSecure[prop] = false;
+ }
+ for (var prop in testsToRunInsecure) {
+ testsToRunInsecure[prop] = false;
+ }
+ //call to change the preferences
+ counter++;
+ await SpecialPowers.setBoolPref("security.mixed_content.block_active_content", false);
+ blockActive = SpecialPowers.getBoolPref("security.mixed_content.block_active_content");
+ log("blockActive set to "+blockActive+".");
+ secureTestsStarted = false;
+ document.getElementById('framediv').innerHTML = '<iframe src="http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation.html" id="testing_frame"></iframe>';
+ }
+ else {
+ //set the prefs back to what they were set to originally
+ SpecialPowers.setBoolPref("security.mixed_content.block_active_content", origBlockActive);
+ SimpleTest.finish();
+ }
+ }
+
+ var firstTestDebugMessage = true;
+
+ // listen for a messages from the mixed content test harness
+ window.addEventListener("message", receiveMessage);
+ function receiveMessage(event) {
+ if(firstTestDebugMessage) {
+ log("blockActive set to "+blockActive);
+ firstTestDebugMessage = false;
+ }
+
+ log("test: "+event.data.test+", msg: "+event.data.msg + ".");
+ // test that the load type matches the pref for this type of content
+ // (i.e. active vs. display)
+
+ switch(event.data.test) {
+
+ case "insecurePage_navigate_child":
+ is(event.data.msg, "navigated to insecure iframe on insecure page", "navigating to insecure iframe blocked on insecure page");
+ testsToRunInsecure.insecurePage_navigate_child = true;
+ break;
+
+ case "insecurePage_navigate_grandchild":
+ is(event.data.msg, "navigated to insecure grandchild iframe on insecure page", "navigating to insecure grandchild iframe blocked on insecure page");
+ testsToRunInsecure.insecurePage_navigate_grandchild = true;
+ break;
+
+ case "securePage_navigate_child":
+ ok(blockActive == (event.data.msg == "navigating to insecure iframe blocked on secure page"), "navigated to insecure iframe on secure page");
+ testsToRunSecure.securePage_navigate_child = true;
+ break;
+
+ case "blankTarget":
+ is(event.data.msg, "opened an http link with target=_blank from a secure page", "couldn't open an http link in a new window from a secure page");
+ testsToRunSecure.blankTarget = true;
+ break;
+
+ }
+ checkTestsCompleted();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ </script>
+</head>
+
+<body>
+ <div id="framediv">
+ <iframe src="http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation.html" id="testing_frame"></iframe>
+ </div>
+
+ <pre id="log"></pre>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/test_main.html b/dom/security/test/mixedcontentblocker/test_main.html
new file mode 100644
index 0000000000..9a13a0853f
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/test_main.html
@@ -0,0 +1,231 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker
+https://bugzilla.mozilla.org/show_bug.cgi?id=62178
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 62178</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+ <script>
+ let counter = 0;
+ // blockDisplay blockActive upgradeDisplay
+ const settings = [
+ [true, true, true],
+ [true, false, true],
+ [false, true, true],
+ [false, false, true],
+ [true, true, false],
+ [true, false, false],
+ [false, true, false],
+ [false, false, false],
+ ];
+
+ let blockActive;
+ let blockDisplay;
+ let upgradeDisplay;
+
+ //Cycle through 8 different preference settings.
+ function changePrefs(otherPrefs, callback) {
+ let basePrefs = [["security.mixed_content.block_display_content", settings[counter][0]],
+ ["security.mixed_content.block_active_content", settings[counter][1]],
+ ["security.mixed_content.upgrade_display_content", settings[counter][2]]];
+ let newPrefs = basePrefs.concat(otherPrefs);
+
+ SpecialPowers.pushPrefEnv({"set": newPrefs}, function () {
+ blockDisplay = SpecialPowers.getBoolPref("security.mixed_content.block_display_content");
+ blockActive = SpecialPowers.getBoolPref("security.mixed_content.block_active_content");
+ upgradeDisplay = SpecialPowers.getBoolPref("security.mixed_content.upgrade_display_content");
+ counter++;
+ callback();
+ });
+ }
+
+ let testsToRun = {
+ iframe: false,
+ image: false,
+ imageSrcset: false,
+ imageSrcsetFallback: false,
+ imagePicture: false,
+ imageJoinPicture: false,
+ imageLeavePicture: false,
+ script: false,
+ stylesheet: false,
+ object: false,
+ media: false,
+ xhr: false,
+ };
+
+ function log(msg) {
+ document.getElementById("log").textContent += "\n" + msg;
+ }
+
+ function reloadFrame() {
+ document.getElementById('framediv').innerHTML = '<iframe id="testHarness" src="https://example.com/tests/dom/security/test/mixedcontentblocker/file_main.html"></iframe>';
+ }
+
+ function checkTestsCompleted() {
+ for (var prop in testsToRun) {
+ // some test hasn't run yet so we're not done
+ if (!testsToRun[prop])
+ return;
+ }
+ //if the testsToRun are all completed, chnage the pref and run the tests again until we have cycled through all the prefs.
+ if(counter < 8) {
+ for (var prop in testsToRun) {
+ testsToRun[prop] = false;
+ }
+ //call to change the preferences
+ changePrefs([], function() {
+ log(`\nblockDisplay set to ${blockDisplay}, blockActive set to ${blockActive}, upgradeDisplay set to ${upgradeDisplay}`);
+ reloadFrame();
+ });
+ }
+ else {
+ SimpleTest.finish();
+ }
+ }
+
+ var firstTest = true;
+
+ function receiveMessage(event) {
+ if(firstTest) {
+ log(`blockActive set to ${blockActive}, blockDisplay set to ${blockDisplay}, upgradeDisplay set to ${upgradeDisplay}.`);
+ firstTest = false;
+ }
+
+ // Simple check from the iframe.
+ if (event.data.check) {
+ ok(event.data.status, event.data.msg);
+ return;
+ }
+
+ log("test: "+event.data.test+", msg: "+event.data.msg + " logging message.");
+ // test that the load type matches the pref for this type of content
+ // (i.e. active vs. display)
+
+ switch(event.data.test) {
+
+ /* Mixed Script tests */
+ case "iframe":
+ ok(blockActive == (event.data.msg == "insecure iframe blocked"), "iframe did not follow block_active_content pref");
+ testsToRun.iframe = true;
+ break;
+
+ case "object":
+ ok(blockActive == (event.data.msg == "insecure object blocked"), "object did not follow block_active_content pref");
+ testsToRun.object = true;
+ break;
+
+ case "script":
+ ok(blockActive == (event.data.msg == "insecure script blocked"), "script did not follow block_active_content pref");
+ testsToRun.script = true;
+ break;
+
+ case "stylesheet":
+ ok(blockActive == (event.data.msg == "insecure stylesheet blocked"), "stylesheet did not follow block_active_content pref");
+ testsToRun.stylesheet = true;
+ break;
+
+ case "xhr":
+ ok(blockActive == (event.data.msg == "insecure xhr blocked"), "xhr did not follow block_active_content pref");
+ testsToRun.xhr = true;
+ break;
+
+ /* Mixed Display tests */
+ case "image":
+ //test that the image load matches the pref for display content
+ if (upgradeDisplay) {
+ ok(event.data.msg == "secure image loaded after upgrade", "image did not follow upgrade_display_content pref");
+ } else {
+ ok(blockDisplay == (event.data.msg == "insecure image blocked"), "image did not follow block_display_content pref");
+ }
+ testsToRun.image = true;
+ break;
+
+ case "media":
+ if (upgradeDisplay) {
+ ok(event.data.msg == "secure media loaded after upgrade", "media did not follow upgrade_display_content pref");
+ } else {
+ ok(blockDisplay == (event.data.msg == "insecure media blocked"), "media did not follow block_display_content pref");
+ }
+ testsToRun.media = true;
+ break;
+
+ /* Images using the "imageset" policy, from <img srcset> and <picture>, do not get the mixed display exception */
+ case "imageSrcset":
+ // When blockDisplay && blockActive && upgradeDisplay are all true the request is blocked
+ // This appears to be a side effect of blockDisplay taking precedence here.
+ if (event.data.msg == "secure image loaded after upgrade") {
+ ok(upgradeDisplay, "imageSrcset did not follow upgrade_display_content pref");
+ } else {
+ ok(blockActive == (event.data.msg == "insecure image blocked"), "imageSrcset did not follow block_active_content pref");
+ }
+ testsToRun.imageSrcset = true;
+ break;
+
+ case "imageSrcsetFallback":
+ if (event.data.msg == "secure image loaded after upgrade") {
+ ok(upgradeDisplay, "imageSrcsetFallback did not follow upgrade_display_content pref");
+ } else {
+ ok(blockActive == (event.data.msg == "insecure image blocked"), "imageSrcsetFallback did not follow block_active_content pref");
+ }
+ testsToRun.imageSrcsetFallback = true;
+ break;
+
+ case "imagePicture":
+ if (event.data.msg == "secure image loaded after upgrade") {
+ ok(upgradeDisplay, "imagePicture did not follow upgrade_display_content pref");
+ } else {
+ ok(blockActive == (event.data.msg == "insecure image blocked"), "imagePicture did not follow block_active_content pref");
+ }
+ testsToRun.imagePicture = true;
+ break;
+
+ case "imageJoinPicture":
+ if (event.data.msg == "secure image loaded after upgrade") {
+ ok(upgradeDisplay, "imageJoinPicture did not follow upgrade_display_content pref");
+ } else {
+ ok(blockActive == (event.data.msg == "insecure image blocked"), "imageJoinPicture did not follow block_active_content pref");
+ }
+ testsToRun.imageJoinPicture = true;
+ break;
+
+ // Should return to mixed display mode
+ case "imageLeavePicture":
+ if (event.data.msg == "secure image loaded after upgrade") {
+ ok(upgradeDisplay, "imageLeavePicture did not follow upgrade_display_content pref");
+ } else {
+ ok(blockDisplay == (event.data.msg == "insecure image blocked"), "imageLeavePicture did not follow block_display_content pref");
+ }
+ testsToRun.imageLeavePicture = true;
+ break;
+
+ }
+ checkTestsCompleted();
+ }
+
+ function startTest() {
+ //Set the first set of mixed content settings and increment the counter.
+ changePrefs([], function() {
+ //listen for a messages from the mixed content test harness
+ window.addEventListener("message", receiveMessage);
+
+ //Kick off test
+ reloadFrame();
+ });
+ }
+
+ SimpleTest.waitForExplicitFinish();
+
+ </script>
+</head>
+
+<body onload='startTest()'>
+ <div id="framediv"></div>
+ <pre id="log"></pre>
+</body>
+</html>
diff --git a/dom/security/test/mixedcontentblocker/test_redirect.html b/dom/security/test/mixedcontentblocker/test_redirect.html
new file mode 100644
index 0000000000..3fdd4e2e7b
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/test_redirect.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Bug1402363: Test mixed content redirects</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+
+<body onload='startTest()'>
+<iframe style="width:100%;height:300px;" id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+const PATH = "https://example.com/tests/dom/security/test/mixedcontentblocker/";
+let testcounter = 0;
+
+window.addEventListener("message", receiveMessage);
+function receiveMessage(event) {
+ if (event.data === "https-to-https-loaded") {
+ ok(true, "https to https fetch redirect should be allowed");
+ }
+ else if (event.data === "https-to-http-blocked") {
+ ok(true, "https to http fetch redirect should be blocked");
+ }
+ else {
+ ok(false, "sanity: we should never enter that branch (" + event.data + ")");
+ }
+ testcounter++;
+ if (testcounter < 2) {
+ return;
+ }
+ window.removeEventListener("message", receiveMessage);
+ SimpleTest.finish();
+}
+
+function startTest() {
+ let testframe = document.getElementById("testframe");
+ testframe.src = PATH + "file_redirect.html";
+}
+
+</script>
+</body>
+</html>