function waitForState(worker, state, context) { return new Promise(resolve => { if (worker.state === state) { resolve(context); return; } worker.addEventListener("statechange", function onStateChange() { if (worker.state === state) { worker.removeEventListener("statechange", onStateChange); resolve(context); } }); }); } function waitForControlled(win) { return new Promise(resolve => { if (win.navigator.serviceWorker.controller) { return resolve(); } win.navigator.serviceWorker.addEventListener("controllerchange", resolve, { once: true, }); }); } /** * 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(...args) { console.log("...calling register"); const reg = await navigator.serviceWorker.register(...args); // 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(); } }