summaryrefslogtreecommitdiffstats
path: root/dom/serviceworkers/test/utils.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/serviceworkers/test/utils.js')
-rw-r--r--dom/serviceworkers/test/utils.js136
1 files changed, 136 insertions, 0 deletions
diff --git a/dom/serviceworkers/test/utils.js b/dom/serviceworkers/test/utils.js
new file mode 100644
index 0000000000..28be239593
--- /dev/null
+++ b/dom/serviceworkers/test/utils.js
@@ -0,0 +1,136 @@
+function waitForState(worker, state, context) {
+ return new Promise(resolve => {
+ function onStateChange() {
+ if (worker.state === state) {
+ worker.removeEventListener("statechange", onStateChange);
+ resolve(context);
+ }
+ }
+
+ // First add an event listener, so we won't miss any change that happens
+ // before we check the current state.
+ worker.addEventListener("statechange", onStateChange);
+
+ // Now check if the worker is already in the desired state.
+ onStateChange();
+ });
+}
+
+/**
+ * Helper for browser tests to issue register calls from the content global and
+ * wait for the SW to progress to the active state, as most tests desire.
+ * From the ContentTask.spawn, use via
+ * `content.wrappedJSObject.registerAndWaitForActive`.
+ */
+async function registerAndWaitForActive(script, maybeScope) {
+ console.log("...calling register");
+ let opts = undefined;
+ if (maybeScope) {
+ opts = { scope: maybeScope };
+ }
+ const reg = await navigator.serviceWorker.register(script, opts);
+ // Unless registration resurrection happens, the SW should be in the
+ // installing slot.
+ console.log("...waiting for activation");
+ await waitForState(reg.installing, "activated", reg);
+ console.log("...activated!");
+ return reg;
+}
+
+/**
+ * Helper to create an iframe with the given URL and return the first
+ * postMessage payload received. This is intended to be used when creating
+ * cross-origin iframes.
+ *
+ * A promise will be returned that resolves with the payload of the postMessage
+ * call.
+ */
+function createIframeAndWaitForMessage(url) {
+ const iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ return new Promise(resolve => {
+ window.addEventListener(
+ "message",
+ event => {
+ resolve(event.data);
+ },
+ { once: true }
+ );
+ iframe.src = url;
+ });
+}
+
+/**
+ * Helper to create a nested iframe into the iframe created by
+ * createIframeAndWaitForMessage().
+ *
+ * A promise will be returned that resolves with the payload of the postMessage
+ * call.
+ */
+function createNestedIframeAndWaitForMessage(url) {
+ const iframe = document.getElementsByTagName("iframe")[0];
+ iframe.contentWindow.postMessage("create nested iframe", "*");
+ return new Promise(resolve => {
+ window.addEventListener(
+ "message",
+ event => {
+ resolve(event.data);
+ },
+ { once: true }
+ );
+ });
+}
+
+async function unregisterAll() {
+ const registrations = await navigator.serviceWorker.getRegistrations();
+ for (const reg of registrations) {
+ await reg.unregister();
+ }
+}
+
+/**
+ * Make a blob that contains random data and therefore shouldn't compress all
+ * that well.
+ */
+function makeRandomBlob(size) {
+ const arr = new Uint8Array(size);
+ let offset = 0;
+ /**
+ * getRandomValues will only provide a maximum of 64k of data at a time and
+ * will error if we ask for more, so using a while loop for get a random value
+ * which much larger than 64k.
+ * https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#exceptions
+ */
+ while (offset < size) {
+ const nextSize = Math.min(size - offset, 65536);
+ window.crypto.getRandomValues(new Uint8Array(arr.buffer, offset, nextSize));
+ offset += nextSize;
+ }
+ return new Blob([arr], { type: "application/octet-stream" });
+}
+
+async function fillStorage(cacheBytes, idbBytes) {
+ // ## Fill Cache API Storage
+ const cache = await caches.open("filler");
+ await cache.put("fill", new Response(makeRandomBlob(cacheBytes)));
+
+ // ## Fill IDB
+ const storeName = "filler";
+ let db = await new Promise((resolve, reject) => {
+ let openReq = indexedDB.open("filler", 1);
+ openReq.onerror = event => {
+ reject(event.target.error);
+ };
+ openReq.onsuccess = event => {
+ resolve(event.target.result);
+ };
+ openReq.onupgradeneeded = event => {
+ const useDB = event.target.result;
+ useDB.onerror = error => {
+ reject(error);
+ };
+ const store = useDB.createObjectStore(storeName);
+ store.put({ blob: makeRandomBlob(idbBytes) }, "filler-blob");
+ };
+ });
+}