summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/mozilla/tests/workers
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/mozilla/tests/workers')
-rw-r--r--testing/web-platform/mozilla/tests/workers/2-mib-file.py7
-rw-r--r--testing/web-platform/mozilla/tests/workers/bug1674278-crash.html6
-rw-r--r--testing/web-platform/mozilla/tests/workers/bug1674278.js6
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/dedicated-worker-import-csp.html115
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/resources/dynamic-import-remote-origin-script-worker.sub.js17
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/resources/new-shared-worker-window.html19
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/resources/new-worker-window.html19
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/resources/static-import-remote-origin-script-worker.sub.js20
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/shared-worker-import-csp.html123
-rw-r--r--testing/web-platform/mozilla/tests/workers/resources/worker.js129
-rw-r--r--testing/web-platform/mozilla/tests/workers/worker_timer_nesting_level.html52
11 files changed, 513 insertions, 0 deletions
diff --git a/testing/web-platform/mozilla/tests/workers/2-mib-file.py b/testing/web-platform/mozilla/tests/workers/2-mib-file.py
new file mode 100644
index 0000000000..cfb563ff21
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/2-mib-file.py
@@ -0,0 +1,7 @@
+import random
+import string
+
+
+def main(request, response):
+ r = "".join(random.choice(string.ascii_letters) for _ in range(2 * 1024 * 1024))
+ return r
diff --git a/testing/web-platform/mozilla/tests/workers/bug1674278-crash.html b/testing/web-platform/mozilla/tests/workers/bug1674278-crash.html
new file mode 100644
index 0000000000..2b037e5b37
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/bug1674278-crash.html
@@ -0,0 +1,6 @@
+<html class='test-wait'>
+<script>
+var worker = new Worker('bug1674278.js');
+worker.postMessage('', []);
+</script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/workers/bug1674278.js b/testing/web-platform/mozilla/tests/workers/bug1674278.js
new file mode 100644
index 0000000000..56105cb76e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/bug1674278.js
@@ -0,0 +1,6 @@
+self.onmessage = async function(e) {
+ var a = await self.fetch('2-mib-file.py');
+ var b = await a.blob();
+ self.close()
+ await b.arrayBuffer();
+}
diff --git a/testing/web-platform/mozilla/tests/workers/modules/dedicated-worker-import-csp.html b/testing/web-platform/mozilla/tests/workers/modules/dedicated-worker-import-csp.html
new file mode 100644
index 0000000000..ed38ecb3e5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/dedicated-worker-import-csp.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<title>DedicatedWorker: CSP for ES Modules</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+async function openWindow(url) {
+ const win = window.open(url, '_blank');
+ add_result_callback(() => win.close());
+ const msg_event = await new Promise(resolve => window.onmessage = resolve);
+ assert_equals(msg_event.data, 'LOADED');
+ return win;
+}
+
+function import_csp_test(
+ cspHeader, importType, expectedImportedModules, description) {
+ // Append CSP header to windowURL for static import tests since static import
+ // scripts should obey Window's CSP.
+ const windowURL = `resources/new-worker-window.html`;
+ // Append CSP header to scriptURL for dynamic import tests since dynamic
+ // import scripts should obey Worker script's response's CSP.
+ const scriptURL = `${importType}-import-remote-origin-script-worker.sub.js` +
+ `?pipe=header(Content-Security-Policy, ${cspHeader})`;
+ promise_test(async () => {
+ const win = await openWindow(windowURL);
+ // Ask the window to start a dedicated worker.
+ win.postMessage(scriptURL, '*');
+ const msg_event = await new Promise(resolve => window.onmessage = resolve);
+ assert_array_equals(msg_event.data, expectedImportedModules);
+ }, description);
+}
+
+// Tests for static import.
+//
+// Static import should obey the worker-src directive and the script-src
+// directive. If the both directives are specified, the worker-src directive
+// should be prioritized.
+//
+// Step 1: "If the result of executing 6.6.1.11 Get the effective directive for
+// request on request is "worker-src", and policy contains a directive whose
+// name is "worker-src", return "Allowed"."
+// "Note: If worker-src is present, we’ll defer to it when handling worker
+// requests."
+// https://w3c.github.io/webappsec-csp/#script-src-pre-request
+
+import_csp_test(
+ "worker-src 'self' 'unsafe-inline'",
+ "static",
+ ['ERROR'],
+ "worker-src 'self' directive should disallow cross origin static import.");
+
+import_csp_test(
+ "worker-src * 'unsafe-inline'",
+ "static",
+ ["export-on-load-script.js"],
+ "worker-src * directive should allow cross origin static import.")
+
+import_csp_test(
+ "script-src 'self' 'unsafe-inline'",
+ "static",
+ ['ERROR'],
+ "script-src 'self' directive should disallow cross origin static import.");
+
+import_csp_test(
+ "script-src * 'unsafe-inline'",
+ "static",
+ ["export-on-load-script.js"],
+ "script-src * directive should allow cross origin static import.")
+
+import_csp_test(
+ "worker-src *; script-src 'self' 'unsafe-inline'",
+ "static",
+ ["export-on-load-script.js"],
+ "worker-src * directive should override script-src 'self' directive and " +
+ "allow cross origin static import.");
+
+import_csp_test(
+ "worker-src 'self'; script-src * 'unsafe-inline'",
+ "static",
+ ['ERROR'],
+ "worker-src 'self' directive should override script-src * directive and " +
+ "disallow cross origin static import.");
+
+// Tests for dynamic import.
+//
+// Dynamic import should obey the script-src directive instead of the worker-src
+// directive according to the specs:
+//
+// Dynamic import has the "script" destination.
+// Step 2.4: "Fetch a module script graph given url, ..., "script", ..."
+// https://html.spec.whatwg.org/multipage/webappapis.html#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability)
+//
+// The "script" destination should obey the script-src CSP directive.
+// Step 2: "If request's destination is script-like:"
+// https://w3c.github.io/webappsec-csp/#script-src-pre-request
+
+import_csp_test(
+ "script-src 'self' 'unsafe-inline'",
+ "dynamic",
+ ['ERROR'],
+ "script-src 'self' directive should disallow cross origin dynamic import.");
+
+import_csp_test(
+ "script-src * 'unsafe-inline'",
+ "dynamic",
+ ["export-on-load-script.js"],
+ "script-src * directive should allow cross origin dynamic import.")
+
+import_csp_test(
+ "worker-src 'self' 'unsafe-inline'",
+ "dynamic",
+ ["export-on-load-script.js"],
+ "worker-src 'self' directive should not take effect on dynamic import.");
+
+</script>
diff --git a/testing/web-platform/mozilla/tests/workers/modules/resources/dynamic-import-remote-origin-script-worker.sub.js b/testing/web-platform/mozilla/tests/workers/modules/resources/dynamic-import-remote-origin-script-worker.sub.js
new file mode 100644
index 0000000000..7ed6543890
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/resources/dynamic-import-remote-origin-script-worker.sub.js
@@ -0,0 +1,17 @@
+// Import a remote origin script.
+const importUrl =
+ 'https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/export-on-load-script.js';
+if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ import(importUrl)
+ .then(module => postMessage(module.importedModules))
+ .catch(e => postMessage(['ERROR']));
+} else if (
+ 'SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ onconnect = e => {
+ import(importUrl)
+ .then(module => e.ports[0].postMessage(module.importedModules))
+ .catch(error => e.ports[0].postMessage(['ERROR']));
+ };
+}
diff --git a/testing/web-platform/mozilla/tests/workers/modules/resources/new-shared-worker-window.html b/testing/web-platform/mozilla/tests/workers/modules/resources/new-shared-worker-window.html
new file mode 100644
index 0000000000..84564fd7b6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/resources/new-shared-worker-window.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>SharedWorker: new SharedWorker()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+let worker;
+
+// Create a new shared worker for a given script url.
+window.onmessage = e => {
+ worker = new SharedWorker(e.data.scriptURL,
+ { name: e.data.name, type: 'module' });
+ worker.port.onmessage = msg => window.opener.postMessage(msg.data, '*');
+ worker.onerror = err => {
+ window.opener.postMessage(['ERROR'], '*');
+ err.preventDefault();
+ };
+}
+window.opener.postMessage('LOADED', '*');
+</script>
diff --git a/testing/web-platform/mozilla/tests/workers/modules/resources/new-worker-window.html b/testing/web-platform/mozilla/tests/workers/modules/resources/new-worker-window.html
new file mode 100644
index 0000000000..32a89fae0e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/resources/new-worker-window.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>DedicatedWorker: new Worker()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+let worker;
+
+// Creates a new dedicated worker for a given script url.
+window.onmessage = e => {
+ worker = new Worker(e.data, { type: 'module' });
+ worker.postMessage('start');
+ worker.onmessage = msg => window.opener.postMessage(msg.data, '*');
+ worker.onerror = err => {
+ window.opener.postMessage(['ERROR'], '*');
+ err.preventDefault();
+ };
+};
+window.opener.postMessage('LOADED', '*');
+</script>
diff --git a/testing/web-platform/mozilla/tests/workers/modules/resources/static-import-remote-origin-script-worker.sub.js b/testing/web-platform/mozilla/tests/workers/modules/resources/static-import-remote-origin-script-worker.sub.js
new file mode 100644
index 0000000000..6432dd5d80
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/resources/static-import-remote-origin-script-worker.sub.js
@@ -0,0 +1,20 @@
+// Import a remote origin script.
+import * as module from 'https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/export-on-load-script.py';
+if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ self.onmessage = e => {
+ e.target.postMessage(module.importedModules);
+ };
+} else if (
+ 'SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ self.onconnect = e => {
+ e.ports[0].postMessage(module.importedModules);
+ };
+} else if (
+ 'ServiceWorkerGlobalScope' in self &&
+ self instanceof ServiceWorkerGlobalScope) {
+ self.onmessage = e => {
+ e.source.postMessage(module.importedModules);
+ };
+}
diff --git a/testing/web-platform/mozilla/tests/workers/modules/shared-worker-import-csp.html b/testing/web-platform/mozilla/tests/workers/modules/shared-worker-import-csp.html
new file mode 100644
index 0000000000..707b6fb020
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/shared-worker-import-csp.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<title>SharedWorker: CSP for ES Modules</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+// This Set is for checking a shared worker in each test is newly created.
+const existingWorkers = new Set();
+
+async function openWindow(url) {
+ const win = window.open(url, '_blank');
+ add_result_callback(() => win.close());
+ const msgEvent = await new Promise(resolve => window.onmessage = resolve);
+ assert_equals(msgEvent.data, 'LOADED');
+ return win;
+}
+
+function import_csp_test(
+ cspHeader, importType, expectedImportedModules, description) {
+ // Append CSP header to windowURL for static import tests since static import
+ // scripts should obey Window's CSP.
+ const windowURL = "resources/new-shared-worker-window.html"
+ // Append CSP header to scriptURL as scripts should obey SharedWorker
+ // script's responce's CSP.
+ const scriptURL = `${importType}-import-remote-origin-script-worker.sub.js` +
+ `?pipe=header(Content-Security-Policy, ${cspHeader})`;
+ promise_test(async () => {
+ // Open a window that has the given CSP header.
+ const win = await openWindow(windowURL);
+ // Construct a unique name for SharedWorker.
+ const name = `${cspHeader}_${importType}`;
+ const workerProperties = { scriptURL, name };
+ // Check if this shared worker is newly created.
+ assert_false(existingWorkers.has(workerProperties));
+ existingWorkers.add(workerProperties);
+
+ // Ask the window to start a shared worker with the given CSP header.
+ // The shared worker doesn't inherits the window's CSP header.
+ // https://w3c.github.io/webappsec-csp/#initialize-global-object-csp
+ win.postMessage(workerProperties, '*');
+ const msg_event = await new Promise(resolve => window.onmessage = resolve);
+ assert_array_equals(msg_event.data, expectedImportedModules);
+ }, description);
+}
+
+// Tests for static import.
+//
+// Static import should obey the worker-src directive and the script-src
+// directive. If the both directives are specified, the worker-src directive
+// should be prioritized.
+//
+// "The script-src directive acts as a default fallback for all script-like
+// destinations (including worker-specific destinations if worker-src is not
+// present)."
+// https://w3c.github.io/webappsec-csp/#directive-script-src
+
+import_csp_test(
+ "worker-src 'self' 'unsafe-inline'", "static",
+ ['ERROR'],
+ "worker-src 'self' directive should disallow cross origin static import.");
+
+import_csp_test(
+ "worker-src * 'unsafe-inline'", "static",
+ ["export-on-load-script.js"],
+ "worker-src * directive should allow cross origin static import.");
+
+import_csp_test(
+ "script-src 'self' 'unsafe-inline'", "static",
+ ['ERROR'],
+ "script-src 'self' directive should disallow cross origin static import.");
+
+import_csp_test(
+ "script-src * 'unsafe-inline'", "static",
+ ["export-on-load-script.js"],
+ "script-src * directive should allow cross origin static import.");
+
+import_csp_test(
+ "worker-src *; script-src 'self' 'unsafe-inline'", "static",
+ ["export-on-load-script.js"],
+ "worker-src * directive should override script-src 'self' directive and " +
+ "allow cross origin static import.");
+
+import_csp_test(
+ "worker-src 'self'; script-src * 'unsafe-inline'", "static",
+ ['ERROR'],
+ "worker-src 'self' directive should override script-src * directive and " +
+ "disallow cross origin static import.");
+
+// Tests for dynamic import.
+//
+// Dynamic import should obey SharedWorker script's CSP instead of parent
+// Window's CSP.
+//
+// Dynamic import should obey the script-src directive instead of the worker-src
+// directive according to the specs:
+//
+// Dynamic import has the "script" destination.
+// Step 3: "Fetch a single module script graph given url, ..., "script", ..."
+// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-an-import()-module-script-graph
+//
+// The "script" destination should obey the script-src CSP directive.
+// "The script-src directive acts as a default fallback for all script-like
+// destinations (including worker-specific destinations if worker-src is not
+// present)."
+// https://w3c.github.io/webappsec-csp/#directive-script-src
+
+import_csp_test(
+ "script-src 'self' 'unsafe-inline'", "dynamic",
+ ['ERROR'],
+ "script-src 'self' directive should disallow cross origin dynamic import.");
+
+import_csp_test(
+ "script-src * 'unsafe-inline'", "dynamic",
+ ["export-on-load-script.js"],
+ "script-src * directive should allow cross origin dynamic import.");
+
+import_csp_test(
+ "worker-src 'self' 'unsafe-inline'", "dynamic",
+ ["export-on-load-script.js"],
+ "worker-src 'self' directive should not take effect on dynamic import.");
+
+</script>
diff --git a/testing/web-platform/mozilla/tests/workers/resources/worker.js b/testing/web-platform/mozilla/tests/workers/resources/worker.js
new file mode 100644
index 0000000000..cc1692eb9c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/resources/worker.js
@@ -0,0 +1,129 @@
+const maxNestingLevel = 5;
+let expectedNestingLevel = 1;
+let timer;
+let isInterval = false;
+let testStage = "ScriptLoaded";
+let stopIncreaseExpectedLevel = false;
+let startClampedTimeStamp = 0;
+let startRepeatingClamped = false;
+let repeatCount = 0;
+let maxRepeatTimes = 10;
+
+let timerCallback = async () => {
+ let now = Date.now();
+ if (WorkerTestUtils.currentTimerNestingLevel() !== expectedNestingLevel) {
+ postMessage({
+ stage: testStage,
+ status: "FAIL",
+ msg: `current timer nesting level is ${WorkerTestUtils.currentTimerNestingLevel()}, expected ${expectedNestingLevel}`,
+ });
+ if (isInterval) {
+ clearInterval(timer);
+ }
+ return;
+ }
+
+ if (!stopIncreaseExpectedLevel) {
+ if (expectedNestingLevel === maxNestingLevel) {
+ stopIncreaseExpectedLevel = true;
+ startClampedTimeStamp = now;
+ } else {
+ expectedNestingLevel = expectedNestingLevel + 1;
+ }
+ if (!isInterval) {
+ setTimeout(timerCallback, 0);
+ }
+ return;
+ }
+
+ // This is the first time the timeout is clamped, checking if it is clamped
+ // to at least 2ms.
+ if (repeatCount === 0) {
+ await Promise.resolve(true).then(() => {
+ if (WorkerTestUtils.currentTimerNestingLevel() !== expectedNestingLevel) {
+ postMessage({
+ stage: testStage,
+ status: "FAIL",
+ msg: `Timer nesting level should be in effect for immediately resolved micro-tasks`,
+ });
+ }
+ });
+ if (now - startClampedTimeStamp < 2 ) {
+ startRepeatingClamped = true;
+ } else {
+ postMessage({ stage: testStage, status: "PASS", msg: "" });
+ }
+ }
+
+ // If the first clamped timeout is less than 2ms, start to repeat the clamped
+ // timeout for 10 times. Then checking if total clamped time should be at least
+ // 25ms.
+ if (startRepeatingClamped) {
+ if (repeatCount === 10) {
+ if (now - startClampedTimeStamp < 25) {
+ postMessage({
+ stage: testStage,
+ status: "FAIL",
+ msg: `total clamped time of repeating ten times should be at least 25ms(${now - startClampedTimeStamp})`,
+ });
+ } else {
+ postMessage({ stage: testStage, status: "PASS", msg: "" });
+ }
+ } else {
+ repeatCount = repeatCount + 1;
+ if (!isInterval) {
+ setTimeout(timerCallback, 0);
+ }
+ return;
+ }
+ }
+
+ // reset testing variables
+ repeatCount = 0;
+ startRepeatingClamped = false;
+ stopIncreaseExpectedLevel = false;
+ if (isInterval) {
+ clearInterval(timer);
+ }
+};
+
+onmessage = async e => {
+ testStage = e.data;
+ switch (e.data) {
+ case "CheckInitialValue":
+ if (WorkerTestUtils.currentTimerNestingLevel() === 0) {
+ postMessage({ stage: testStage, status: "PASS", msg: "" });
+ } else {
+ postMessage({
+ stage: testStage,
+ status: "FAIL",
+ msg: `current timer nesting level should be 0(${WorkerTestUtils.currentTimerNestingLevel()}) after top level script loaded.`,
+ });
+ }
+ break;
+ case "TestSetInterval":
+ expectedNestingLevel = 1;
+ isInterval = true;
+ timer = setInterval(timerCallback, 0);
+ break;
+ case "TestSetTimeout":
+ expectedNestingLevel = 1;
+ isInterval = false;
+ setTimeout(timerCallback, 0);
+ break;
+ case "CheckNoTimer":
+ if (WorkerTestUtils.currentTimerNestingLevel() === 0) {
+ postMessage({ stage: testStage, status: "PASS", msg: "" });
+ } else {
+ postMessage({
+ stage: testStage,
+ status: "FAIL",
+ msg: `current timer nesting level should be 0(${WorkerTestUtils.currentTimerNestingLevel()}) when there is no timer in queue.`,
+ });
+ }
+
+ break;
+ }
+};
+
+postMessage({ stage: testStage, status: "PASS" });
diff --git a/testing/web-platform/mozilla/tests/workers/worker_timer_nesting_level.html b/testing/web-platform/mozilla/tests/workers/worker_timer_nesting_level.html
new file mode 100644
index 0000000000..e39f9e1b0e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/worker_timer_nesting_level.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<title>Worker: Timer Nesting Level</title>
+<Script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict'
+
+/**
+ * This test includes following four test stages.
+ * 1. CheckInitialValue: Checking the initial value of worker's current timer
+ * nesting level after the worker's top level script is loaded. The result
+ * is expected as 0.
+ * 2. TestSetInterval: Checking the worker's current timer nesting level with
+ * setInterval with following steps
+ * 1. call setInterval(callback, 0) to create a repeating timer.
+ * 2. checking the current timer nesting level in the callback. The value
+ * should increase every time executing the callback until it reaches the
+ * maximun nesting level(5).
+ * 3. Checking the worker's current timer nesting level with immediately
+ * resolved promise.
+ * 4. Checking the the time duration between two callback launching.
+ * 3. TestSetTimeout: Checking the worker's current timer nesting level with
+ * setTimeout. This stage has similar test steps with TestSetInterval.
+ * The difference is this stage using the recursive setTimeout to accumulate
+ * the timer nesting level.
+ * 4. CheckNoTimer: Checking the situation which the worker has no pending
+ * timer. The result is expected as 0.
+ */
+
+let testStages = ["CheckInitialValue",
+ "TestSetInterval",
+ "TestSetTimeout",
+ "CheckNoTimer"];
+
+promise_test(async function(t) {
+ let result = await new Promise( (resolve, reject) => {
+ let worker = new Worker("resources/worker.js");
+ worker.onmessage = (e) => {
+ if (e.data.status === "FAIL") {
+ resolve(e.data);
+ return;
+ }
+ if (testStages.length !== 0) {
+ worker.postMessage(testStages.shift());
+ } else {
+ resolve({status: "PASS", msg: "Timer nesting level for workers"});
+ }
+ };
+ });
+ assert_true(result.status === "PASS", result.msg);
+}, 'Worker timer nesting level');
+</script>