"use strict"; /** * Helper script for mixed content testing. It opens a new top-level window * from a secure origin and '?runtest' query. That tells us to run the test * body, function runTest(). Then we wait for call of finish(). On its first * call it loads helper page 'backward.html' that immediately navigates * back to the test secure test. This checks the bfcache. We got second call * to onload and this time we call afterNavigationTest() function to let the * test check security state after re-navigation back. Then we again wait for * finish() call, that this time finishes completelly the test. */ // Tells the framework if to load the test in an insecure page (http://) var loadAsInsecure = false; // Set true to bypass the navigation forward/back test var bypassNavigationTest = false; // Set true to do forward/back navigation over an http:// page, test state leaks var navigateToInsecure = false; // Open the test in two separate windows, test requests sharing among windows var openTwoWindows = false; // Override the name of the test page to load, useful e.g. to prevent load // of images or other content before the test starts; this is actually // a 'redirect' to a different test page. var testPage = ""; // Assign a function to this variable to have a clean up at the end var testCleanUp = null; // Contains mixed active content that needs to load to run the test var hasMixedActiveContent = false; // Internal variables var _windowCount = 0; window.onload = async function onLoad() { if (location.search == "?runtest") { try { if (history.length == 1) { // Each test that includes this helper file is supposed to define // runTest(). See the top level comment. await runTest(); // eslint-disable-line no-undef } else { // Each test that includes this helper file is supposed to define // afterNavigationTest(). See the top level comment. await afterNavigationTest(); // eslint-disable-line no-undef } } catch (ex) { ok(false, "Exception thrown during test: " + ex); finish(); } } else { window.addEventListener("message", onMessageReceived); let secureTestLocation = loadAsInsecure ? "http://example.com" : "https://example.com"; secureTestLocation += location.pathname; if (testPage != "") { let array = secureTestLocation.split("/"); array.pop(); array.push(testPage); secureTestLocation = array.join("/"); } secureTestLocation += "?runtest"; if (hasMixedActiveContent) { SpecialPowers.pushPrefEnv( { set: [["security.mixed_content.block_active_content", false]] }, null ); } if (openTwoWindows) { _windowCount = 2; window.open(secureTestLocation, "_new1", ""); window.open(secureTestLocation, "_new2", ""); } else { _windowCount = 1; window.open(secureTestLocation); } } }; function onMessageReceived(event) { switch (event.data) { // Indication of all test parts finish (from any of the frames) case "done": if (--_windowCount == 0) { if (testCleanUp) { testCleanUp(); } if (hasMixedActiveContent) { SpecialPowers.popPrefEnv(null); } SimpleTest.finish(); } break; // Any other message is an error or success message of a test. default: SimpleTest.ok(!event.data.match(/^FAILURE/), event.data); break; } } function postMsg(message) { opener.postMessage(message, "http://mochi.test:8888"); } function finish() { if (history.length == 1 && !bypassNavigationTest) { window.setTimeout(() => { window.location.assign( navigateToInsecure ? "http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/backward.html" : "https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/backward.html" ); }, 0); } else { postMsg("done"); window.close(); } } function ok(a, message) { if (!a) { postMsg("FAILURE: " + message); } else { postMsg(message); } } function is(a, b, message) { if (a != b) { postMsg(`FAILURE: ${message}, expected ${b} got ${a}`); } else { postMsg(`${message}, expected ${b} got ${a}`); } } async function isSecurityState(expectedState, message, test) { if (!test) { test = ok; } let state = await SpecialPowers.getSecurityState(window); let isInsecure = state & SpecialPowers.Ci.nsIWebProgressListener.STATE_IS_INSECURE; let isBroken = state & SpecialPowers.Ci.nsIWebProgressListener.STATE_IS_BROKEN; let isEV = state & SpecialPowers.Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL; let gotState = "secure"; if (isInsecure) { gotState = "insecure"; } else if (isBroken) { gotState = "broken"; } else if (isEV) { gotState = "EV"; } test( gotState == expectedState, (message || "") + ", expected " + expectedState + " got " + gotState ); switch (expectedState) { case "insecure": test( isInsecure && !isBroken && !isEV, "for 'insecure' excpected flags [1,0,0], " + (message || "") ); break; case "broken": test( !isInsecure && isBroken && !isEV, "for 'broken' expected flags [0,1,0], " + (message || "") ); break; case "secure": test( !isInsecure && !isBroken && !isEV, "for 'secure' expected flags [0,0,0], " + (message || "") ); break; case "EV": test( !isInsecure && !isBroken && isEV, "for 'EV' expected flags [0,0,1], " + (message || "") ); break; default: throw new Error("Invalid isSecurityState state"); } } function waitForSecurityState(expectedState, callback) { let roundsLeft = 200; // Wait for 20 seconds (=200*100ms) let interval = window.setInterval(async () => { await isSecurityState(expectedState, "", isok => { if (isok) { roundsLeft = 0; } }); if (!roundsLeft--) { window.clearInterval(interval); callback(); } }, 100); }