// OpenPWA device-test lab, T7 permission retest: service worker // (scope /lab/device-tests/t7/perm/). // // A separate, minimal worker for the "Perm Test" Home Screen app. Its scope is // more specific than the main lab worker's (/lab/device-tests/), so once it is // registered it, not the lab worker, controls pages under /t7/perm/. It records // push, notificationclick and notificationclose to IndexedDB (database // "openpwa-lab-t7-perm", separate from the lab's) and posts each record to the // open windows. No fetch handler and no caching; nothing is sent anywhere. const SW_VERSION = "t7-perm-sw-v1"; const DB_NAME = "openpwa-lab-t7-perm"; const STORE = "events"; const APP_URL = new URL("./", self.location.href).href; const openDb = () => new Promise((resolve, reject) => { const request = indexedDB.open(DB_NAME, 1); request.onupgradeneeded = () => { const db = request.result; if (!db.objectStoreNames.contains(STORE)) db.createObjectStore(STORE, { keyPath: "id", autoIncrement: true }); }; request.onsuccess = () => resolve(request.result); request.onerror = () => reject(request.error); }); const saveRecord = async (record) => { const db = await openDb(); await new Promise((resolve, reject) => { const tx = db.transaction(STORE, "readwrite"); tx.objectStore(STORE).add(record); tx.oncomplete = () => resolve(); tx.onerror = () => reject(tx.error); }); db.close(); }; const broadcast = async (message) => { const windows = await self.clients.matchAll({ type: "window", includeUncontrolled: true }); for (const client of windows) client.postMessage(message); }; const record = async (fields) => { const entry = { ...fields, at: new Date().toISOString(), atMs: Date.now(), swVersion: SW_VERSION }; await saveRecord(entry); await broadcast({ type: "T7_EVENT", record: entry }); }; const focusOrOpen = async () => { const windows = await self.clients.matchAll({ type: "window", includeUncontrolled: true }); const existing = windows.find((client) => client.url.startsWith(APP_URL)); try { if (existing && typeof existing.focus === "function") { await existing.focus(); return "focused existing window"; } if (typeof self.clients.openWindow !== "function") return "clients.openWindow unavailable"; const opened = await self.clients.openWindow(APP_URL); return opened ? "opened new window" : "openWindow returned null"; } catch (error) { return `failed: ${error.name}`; } }; self.addEventListener("install", () => self.skipWaiting()); self.addEventListener("activate", (event) => { event.waitUntil(self.clients.claim()); }); self.addEventListener("push", (event) => { const text = event.data ? event.data.text() : ""; event.waitUntil( record({ type: "push", text }).then(() => self.registration.showNotification("Perm Test push", { body: text || "(no payload)", tag: "t7-perm-push" }), ), ); }); self.addEventListener("notificationclick", (event) => { event.notification.close(); event.waitUntil(focusOrOpen().then((outcome) => record({ type: "notificationclick", tag: event.notification.tag, outcome }))); }); self.addEventListener("notificationclose", (event) => { event.waitUntil(record({ type: "notificationclose", tag: event.notification.tag })); }); self.addEventListener("message", (event) => { const data = event.data || {}; if (data.type !== "T7_PING") return; if (event.source && typeof event.source.postMessage === "function") { event.source.postMessage({ type: "T7_PONG", swVersion: SW_VERSION, scope: self.registration.scope }); } });