diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.js | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.js')
-rw-r--r-- | testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.js | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.js b/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.js new file mode 100644 index 0000000000..661595c4d9 --- /dev/null +++ b/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.js @@ -0,0 +1,299 @@ + +/** + * This test checks the Secure Context state of documents for various + * permutations of document URI types and loading methods. + * + * The hierarchy that is tested is: + * + * creator-doc > createe-doc + * + * The creator-doc is one of: + * + * http: + * https: + * + * The createe-doc is loaded as either a: + * + * popup + * iframe + * sandboxed-iframe + * + * into which we load and test: + * + * http: + * https: + * blob: + * javascript: + * about:blank + * initial about:blank + * srcdoc + * + * TODO once web-platform-tests supports it: + * - test http://localhost + * - test file: + */ + + +setup({explicit_done:true}); + + +const host_and_dirname = location.host + + location.pathname.substr(0, location.pathname.lastIndexOf("/") + 1); + + +// Flags to indicate where document types should be loaded for testing: +const eLoadInPopup = (1 << 0); +const eLoadInUnsandboxedIframe = (1 << 1); +const eLoadInSandboxedIframe = (1 << 2); +const eLoadInEverything = eLoadInPopup | eLoadInUnsandboxedIframe | eLoadInSandboxedIframe; + +// Flags indicating if a document type is expected to be a Secure Context: +const eSecureNo = 1; +const eSecureIfNewWindow = 2; +const eSecureIfCreatorSecure = 3; + +// Flags indicating how the result of a test is obtained: +const eResultFromPostMessage = 1; +const eResultFromExaminationOnLoad = 2; +const eResultFromExaminationSync = 3; + + +const loadTypes = [ + new LoadType("an http: URI", + eLoadInEverything, + http_dir + "postMessage-helper.html", + eSecureNo, + eResultFromPostMessage), + new LoadType("an https: URI", + eLoadInEverything, + https_dir + "postMessage-helper.https.html", + eSecureIfNewWindow, + eResultFromPostMessage), + new LoadType("a blob: URI", + eLoadInEverything, + URL.createObjectURL(new Blob(["<script>(opener||parent).postMessage(isSecureContext, '*')</script>"], {type: "text/html"})), + eSecureIfCreatorSecure, + eResultFromPostMessage), + new LoadType("a srcdoc", + // popup not relevant: + eLoadInUnsandboxedIframe | eLoadInSandboxedIframe, + "<script>(opener||parent).postMessage(isSecureContext, '*')</script>", + eSecureIfNewWindow, + eResultFromPostMessage), + new LoadType("a javascript: URI", + // can't load in sandbox: + eLoadInUnsandboxedIframe | eLoadInPopup, + "javascript:(opener||parent).postMessage(isSecureContext, '*')", + eSecureIfCreatorSecure, + eResultFromPostMessage), + new LoadType("about:blank", + // can't obtain state if sandboxed: + eLoadInUnsandboxedIframe | eLoadInPopup, + "about:blank", + eSecureIfCreatorSecure, + eResultFromExaminationOnLoad), + new LoadType("initial about:blank", + // can't obtain state if sandboxed: + eLoadInUnsandboxedIframe | eLoadInPopup, + "about:blank", // we don't wait for this to load, so whatever + eSecureIfCreatorSecure, + eResultFromExaminationSync), + new LoadType("a data: URL", + // can't load in a top-level browsing context + eLoadInUnsandboxedIframe | eLoadInSandboxedIframe, + "data:text/html,<script>parent.postMessage(isSecureContext, '*')</script>", + eSecureIfCreatorSecure, + eResultFromPostMessage), +]; + +const loadTargets = [ + new LoadTarget("an iframe", eLoadInUnsandboxedIframe), + new LoadTarget("a sandboxed iframe", eLoadInSandboxedIframe), + new LoadTarget("a popup", eLoadInPopup), +]; + + +function LoadType(description, loadInFlags, uri, expectedSecureFlag, resultFrom) { + this.desc = description; + this.loadInFlags = loadInFlags; + this.uri = uri; + this.expectedSecureFlag = expectedSecureFlag; + this.resultFrom = resultFrom; +} + + +function LoadTarget(description, loadInFlag) { + this.desc = description; + this.loadInFlag = loadInFlag; +} + +LoadTarget.prototype.open = function(loadType) { + let loadTarget = this; + this.currentTest.step(function() { + assert_true((loadTarget.loadInFlag & loadType.loadInFlags) != 0, + loadType.desc + " cannot be tested in " + loadTarget.desc); + }); + if (this.loadInFlag == eLoadInUnsandboxedIframe) { + let iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + iframe[loadType.desc == "a srcdoc" ? "srcdoc" : "src"] = loadType.uri; + return iframe; + } + if (this.loadInFlag == eLoadInSandboxedIframe) { + let iframe = document.body.appendChild(document.createElement("iframe")); + iframe.setAttribute("sandbox", "allow-scripts"); + iframe[loadType.desc == "a srcdoc" ? "srcdoc" : "src"] = loadType.uri; + return iframe; + } + if (this.loadInFlag == eLoadInPopup) { + return window.open(loadType.uri); + } + this.currentTest.step(function() { + assert_unreached("Unknown load type flag: " + loadInFlags); + }); + return null; +} + +LoadTarget.prototype.close = function(domTarget) { + if (this.loadInFlag == eLoadInUnsandboxedIframe || + this.loadInFlag == eLoadInSandboxedIframe) { + domTarget.remove(); + return; + } + if (this.loadInFlag == eLoadInPopup) { + domTarget.close(); + return; + } + this.currentTest.step(function() { + assert_unreached("Unknown load type flag: " + loadInFlags); + }); +} + +LoadTarget.prototype.load_and_get_result_for = function(loadType) { + if (!(loadType.loadInFlags & this.loadInFlag)) { + return Promise.reject("not applicable"); + } + if (!(this.loadInFlag & eLoadInPopup) && + location.protocol == "https:" && + loadType.uri.substr(0,5) == "http:") { + // Mixed content blocker will prevent this load + return Promise.reject("not applicable"); + } + this.currentTest = async_test("Test Window.isSecureContext in " + this.desc + + " loading " + loadType.desc) + if (loadType.resultFrom == eResultFromExaminationSync) { + let domTarget = this.open(loadType); + let isFrame = domTarget instanceof HTMLIFrameElement; + let result = !isFrame ? + domTarget.isSecureContext : domTarget.contentWindow.isSecureContext; + this.close(domTarget); + return Promise.resolve({ result: result, isFrame: isFrame}); + } + let target = this; + if (loadType.resultFrom == eResultFromExaminationOnLoad) { + return new Promise(function(resolve, reject) { + function handleLoad(event) { + clearTimeout(timer); + let isFrame = domTarget instanceof HTMLIFrameElement; + let result = !isFrame ? + domTarget.isSecureContext : domTarget.contentWindow.isSecureContext; + domTarget.removeEventListener("load", handleLoad); + target.close(domTarget); + resolve({ result: result, isFrame: isFrame}); + } + let domTarget = target.open(loadType); + domTarget.addEventListener("load", handleLoad, false); + + // Some browsers don't fire `load` events for `about:blank`. That's weird, but it also + // isn't what we're testing here. + let timer = setTimeout(handleLoad, 500); + }); + } + if (loadType.resultFrom == eResultFromPostMessage) { + return new Promise(function(resolve, reject) { + function handleMessage(event) { + let isFrame = domTarget instanceof HTMLIFrameElement; + window.removeEventListener("message", handleMessage); + target.close(domTarget); + resolve({ result: event.data, isFrame: isFrame}); + } + window.addEventListener("message", handleMessage, false); + let domTarget = target.open(loadType); + }); + } + return Promise.reject("unexpected 'result from' type"); +} + + +let current_type_index = -1; +let current_target_index = 0; + +function run_next_test() { + current_type_index++; + if (current_type_index >= loadTypes.length) { + current_type_index = 0; + current_target_index++; + if (current_target_index >= loadTargets.length) { + done(); + return; // all test permutations complete + } + } + let loadTarget = loadTargets[current_target_index]; + let loadType = loadTypes[current_type_index]; + loadTarget.load_and_get_result_for(loadType).then( + function(value) { + run_next_test_soon(); + loadTarget.currentTest.step(function() { + // If the new context is always non-secure, the assertion is straightforward. + if (loadType.expectedSecureFlag == eSecureNo) { + assert_false(value.result, loadType.desc + " in " + loadTarget.desc + " should not create a Secure Context"); + // If the new context is always secure if opened in a new window, and it's + // been opened in a new window, the assertion is likewise straightforward. + } else if (loadType.expectedSecureFlag == eSecureIfNewWindow && !value.isFrame) { + assert_true(value.result, loadType.desc + " in " + loadTarget.desc + " should create a secure context regardless of its creator's state."); + // Otherwise, we're either dealing with a context that's secure if and only + // if its creator context (e.g. this window) is secure. + } else if ((loadType.expectedSecureFlag == eSecureIfNewWindow && value.isFrame) || + (loadType.expectedSecureFlag == eSecureIfCreatorSecure)) { + if (!window.isSecureContext) { + assert_false(value.result, loadType.desc + " in " + loadTarget.desc + " should not create a Secure Context when its creator is not a Secure Context."); + } else { + assert_true(value.result, loadType.desc + " in " + loadTarget.desc + " should create a Secure Context when its creator is a Secure Context"); + } + } else { + assert_unreached(loadType.desc + " - unknown expected secure flag: " + expectedSecureFlag); + } + loadTarget.currentTest.done(); + }); + }, + function(failReason) { + run_next_test_soon(); + if (failReason == "not applicable") { + return; + } + loadTarget.currentTest.step(function() { + assert_unreached(loadType.desc + " - got unexpected rejected promise"); + }); + } + ); +} + +function run_next_test_soon() { + setTimeout(run_next_test, 0); +} + +function begin() { + test(function() { + if (location.protocol == "http:") { + assert_false(isSecureContext, + "http: creator should not be a Secure Context"); + } else if (location.protocol == "https:") { + assert_true(isSecureContext, + "https: creator should be a Secure Context"); + } else { + assert_unreached("Unknown location.protocol"); + } + }); + run_next_test(); +} + |