diff options
Diffstat (limited to 'dom/serviceworkers/test/utils.js')
-rw-r--r-- | dom/serviceworkers/test/utils.js | 136 |
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"); + }; + }); +} |