summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/fetch/private-network-access/resources/service-worker-bridge.html
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/fetch/private-network-access/resources/service-worker-bridge.html
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/fetch/private-network-access/resources/service-worker-bridge.html')
-rw-r--r--testing/web-platform/tests/fetch/private-network-access/resources/service-worker-bridge.html155
1 files changed, 155 insertions, 0 deletions
diff --git a/testing/web-platform/tests/fetch/private-network-access/resources/service-worker-bridge.html b/testing/web-platform/tests/fetch/private-network-access/resources/service-worker-bridge.html
new file mode 100644
index 0000000000..816de535fe
--- /dev/null
+++ b/testing/web-platform/tests/fetch/private-network-access/resources/service-worker-bridge.html
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>ServiceWorker Bridge</title>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script>
+ // This bridge document exists to perform service worker commands on behalf
+ // of a test page. It lives within the same scope (including origin) as the
+ // service worker script, allowing it to be controlled by the service worker.
+
+ async function register({ url, options }) {
+ await navigator.serviceWorker.register(url, options);
+ return { loaded: true };
+ }
+
+ async function unregister({ scope }) {
+ const registration = await navigator.serviceWorker.getRegistration(scope);
+ if (!registration) {
+ return { unregistered: false, error: "no registration" };
+ }
+
+ const unregistered = await registration.unregister();
+ return { unregistered };
+ }
+
+ async function update({ scope }) {
+ const registration = await navigator.serviceWorker.getRegistration(scope);
+ if (!registration) {
+ return { updated: false, error: "no registration" };
+ }
+
+ const newRegistration = await registration.update();
+ return { updated: true };
+ }
+
+ // Total number of `controllerchange` events since document creation.
+ let totalNumControllerChanges = 0;
+ navigator.serviceWorker.addEventListener("controllerchange", () => {
+ totalNumControllerChanges++;
+ });
+
+ // Using `navigator.serviceWorker.ready` does not allow noticing new
+ // controllers after an update, so we count `controllerchange` events instead.
+ // This has the added benefit of ensuring that subsequent fetches are handled
+ // by the service worker, whereas `ready` does not guarantee that.
+ async function wait({ numControllerChanges }) {
+ if (totalNumControllerChanges >= numControllerChanges) {
+ return {
+ controlled: !!navigator.serviceWorker.controller,
+ numControllerChanges: totalNumControllerChanges,
+ };
+ }
+
+ let remaining = numControllerChanges - totalNumControllerChanges;
+ await new Promise((resolve) => {
+ navigator.serviceWorker.addEventListener("controllerchange", () => {
+ remaining--;
+ if (remaining == 0) {
+ resolve();
+ }
+ });
+ });
+
+ return {
+ controlled: !!navigator.serviceWorker.controller,
+ numControllerChanges,
+ };
+ }
+
+ async function doFetch({ url, options }) {
+ const response = await fetch(url, options);
+ const body = await response.text();
+ return {
+ ok: response.ok,
+ body,
+ };
+ }
+
+ async function setPermission({ name, state }) {
+ await test_driver.set_permission({ name }, state);
+
+ // Double-check, just to be sure.
+ // See the comment in `../service-worker-background-fetch.js`.
+ const permissionStatus = await navigator.permissions.query({ name });
+ return { state: permissionStatus.state };
+ }
+
+ async function backgroundFetch({ scope, url }) {
+ const registration = await navigator.serviceWorker.getRegistration(scope);
+ if (!registration) {
+ return { error: "no registration" };
+ }
+
+ const fetchRegistration =
+ await registration.backgroundFetch.fetch("test", url);
+ const resultReady = new Promise((resolve) => {
+ fetchRegistration.addEventListener("progress", () => {
+ if (fetchRegistration.result) {
+ resolve();
+ }
+ });
+ });
+
+ let ok;
+ let body;
+ const record = await fetchRegistration.match(url);
+ if (record) {
+ const response = await record.responseReady;
+ body = await response.text();
+ ok = response.ok;
+ }
+
+ // Wait for the result after getting the response. If the steps are
+ // inverted, then sometimes the response is not found due to an
+ // `UnknownError`.
+ await resultReady;
+
+ return {
+ result: fetchRegistration.result,
+ failureReason: fetchRegistration.failureReason,
+ ok,
+ body,
+ };
+ }
+
+ function getAction(action) {
+ switch (action) {
+ case "register":
+ return register;
+ case "unregister":
+ return unregister;
+ case "wait":
+ return wait;
+ case "update":
+ return update;
+ case "fetch":
+ return doFetch;
+ case "set-permission":
+ return setPermission;
+ case "background-fetch":
+ return backgroundFetch;
+ }
+ }
+
+ window.addEventListener("message", async (evt) => {
+ let message;
+ try {
+ const action = getAction(evt.data.action);
+ message = await action(evt.data);
+ } catch(e) {
+ message = { error: e.name };
+ }
+ parent.postMessage(message, "*");
+ });
+</script>