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