summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/resources/sriharness.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/resources/sriharness.js
parentInitial commit. (diff)
downloadfirefox-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.js226
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);
+};
+