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/resources/sriharness.js | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.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/resources/sriharness.js')
-rw-r--r-- | testing/web-platform/tests/resources/sriharness.js | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/testing/web-platform/tests/resources/sriharness.js b/testing/web-platform/tests/resources/sriharness.js new file mode 100644 index 0000000000..943d677224 --- /dev/null +++ b/testing/web-platform/tests/resources/sriharness.js @@ -0,0 +1,226 @@ +// `integrityValue` indicates the 'integrity' attribute value at the time of +// #prepare-a-script. +// +// `integrityValueAfterPrepare` indicates how the 'integrity' attribute value +// is modified after #prepare-a-script: +// - `undefined` => not modified. +// - `null` => 'integrity' attribute is removed. +// - others => 'integrity' attribute value is set to that value. +// +// TODO: Make the arguments a dictionary for readability in the test files. +var SRIScriptTest = function(pass, name, src, integrityValue, crossoriginValue, nonce, integrityValueAfterPrepare) { + this.pass = pass; + this.name = "Script: " + name; + this.src = src; + this.integrityValue = integrityValue; + this.crossoriginValue = crossoriginValue; + this.nonce = nonce; + this.integrityValueAfterPrepare = integrityValueAfterPrepare; +} + +SRIScriptTest.prototype.execute = function() { + var test = async_test(this.name); + var e = document.createElement("script"); + e.src = this.src; + if (this.integrityValue) { + e.setAttribute("integrity", this.integrityValue); + } + if(this.crossoriginValue) { + e.setAttribute("crossorigin", this.crossoriginValue); + } + if(this.nonce) { + e.setAttribute("nonce", this.nonce); + } + if(this.pass) { + e.addEventListener("load", function() {test.done()}); + e.addEventListener("error", function() { + test.step(function(){ assert_unreached("Good load fired error handler.") }) + }); + } else { + e.addEventListener("load", function() { + test.step(function() { assert_unreached("Bad load succeeded.") }) + }); + e.addEventListener("error", function() {test.done()}); + } + document.body.appendChild(e); + + if (this.integrityValueAfterPrepare === null) { + e.removeAttribute("integrity"); + } else if (this.integrityValueAfterPrepare !== undefined) { + e.setAttribute("integrity", this.integrityValueAfterPrepare); + } +}; + +function set_extra_attributes(element, attrs) { + // Apply the rest of the attributes, if any. + for (const [attr_name, attr_val] of Object.entries(attrs)) { + element[attr_name] = attr_val; + } +} + +function buildElementFromDestination(resource_url, destination, attrs) { + // Assert: |destination| is a valid destination. + let element; + + // The below switch is responsible for: + // 1. Creating the correct subresource element + // 2. Setting said element's href, src, or fetch-instigating property + // appropriately. + switch (destination) { + case "script": + element = document.createElement(destination); + set_extra_attributes(element, attrs); + element.src = resource_url; + break; + case "style": + element = document.createElement('link'); + set_extra_attributes(element, attrs); + element.rel = 'stylesheet'; + element.href = resource_url; + break; + case "image": + element = document.createElement('img'); + set_extra_attributes(element, attrs); + element.src = resource_url; + break; + default: + assert_unreached("INVALID DESTINATION"); + } + + return element; +} + +// When using SRIPreloadTest, also include /preload/resources/preload_helper.js +// |number_of_requests| is used to ensure that preload requests are actually +// reused as expected. +const SRIPreloadTest = (preload_sri_success, subresource_sri_success, name, + number_of_requests, destination, resource_url, + link_attrs, subresource_attrs) => { + const test = async_test(name); + const link = document.createElement('link'); + + // Early-fail in UAs that do not support `preload` links. + test.step_func(() => { + assert_true(link.relList.supports('preload'), + "This test is automatically failing because the browser does not" + + "support `preload` links."); + })(); + + // Build up the link. + link.rel = 'preload'; + link.as = destination; + link.href = resource_url; + for (const [attr_name, attr_val] of Object.entries(link_attrs)) { + link[attr_name] = attr_val; // This may override `rel` to modulepreload. + } + + // Preload + subresource success and failure loading functions. + const valid_preload_failed = test.step_func(() => + { assert_unreached("Valid preload fired error handler.") }); + const invalid_preload_succeeded = test.step_func(() => + { assert_unreached("Invalid preload load succeeded.") }); + const valid_subresource_failed = test.step_func(() => + { assert_unreached("Valid subresource fired error handler.") }); + const invalid_subresource_succeeded = test.step_func(() => + { assert_unreached("Invalid subresource load succeeded.") }); + const subresource_pass = test.step_func(() => { + verifyNumberOfResourceTimingEntries(resource_url, number_of_requests); + test.done(); + }); + const preload_pass = test.step_func(() => { + const subresource_element = buildElementFromDestination( + resource_url, + destination, + subresource_attrs + ); + + if (subresource_sri_success) { + subresource_element.onload = subresource_pass; + subresource_element.onerror = valid_subresource_failed; + } else { + subresource_element.onload = invalid_subresource_succeeded; + subresource_element.onerror = subresource_pass; + } + + document.body.append(subresource_element); + }); + + if (preload_sri_success) { + link.onload = preload_pass; + link.onerror = valid_preload_failed; + } else { + link.onload = invalid_preload_succeeded; + link.onerror = preload_pass; + } + + document.head.append(link); +} + +// <link> tests +// Style tests must be done synchronously because they rely on the presence +// and absence of global style, which can affect later tests. Thus, instead +// of executing them one at a time, the style tests are implemented as a +// queue that builds up a list of tests, and then executes them one at a +// time. +var SRIStyleTest = function(queue, pass, name, attrs, customCallback, altPassValue) { + this.pass = pass; + this.name = "Style: " + name; + this.customCallback = customCallback || function () {}; + this.attrs = attrs || {}; + this.passValue = altPassValue || "rgb(255, 255, 0)"; + + this.test = async_test(this.name); + + this.queue = queue; + this.queue.push(this); +} + +SRIStyleTest.prototype.execute = function() { + var that = this; + var container = document.getElementById("container"); + while (container.hasChildNodes()) { + container.removeChild(container.firstChild); + } + + var test = this.test; + + var div = document.createElement("div"); + div.className = "testdiv"; + var e = document.createElement("link"); + + // The link relation is guaranteed to not be "preload" or "modulepreload". + this.attrs.rel = this.attrs.rel || "stylesheet"; + for (var key in this.attrs) { + if (this.attrs.hasOwnProperty(key)) { + e.setAttribute(key, this.attrs[key]); + } + } + + if(this.pass) { + e.addEventListener("load", function() { + test.step(function() { + var background = window.getComputedStyle(div, null).getPropertyValue("background-color"); + assert_equals(background, that.passValue); + test.done(); + }); + }); + e.addEventListener("error", function() { + test.step(function(){ assert_unreached("Good load fired error handler.") }) + }); + } else { + e.addEventListener("load", function() { + test.step(function() { assert_unreached("Bad load succeeded.") }) + }); + e.addEventListener("error", function() { + test.step(function() { + var background = window.getComputedStyle(div, null).getPropertyValue("background-color"); + assert_not_equals(background, that.passValue); + test.done(); + }); + }); + } + container.appendChild(div); + container.appendChild(e); + this.customCallback(e, container); +}; + |