From fc61729cb3cb2db72153f3efafa6c6edc3b68506 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 16 Oct 2020 12:50:19 +0200 Subject: [PATCH] support closing session in other clients in service worker --- src/service-worker.template.js | 61 +++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/src/service-worker.template.js b/src/service-worker.template.js index af8eae88..2a246737 100644 --- a/src/service-worker.template.js +++ b/src/service-worker.template.js @@ -68,18 +68,6 @@ self.addEventListener('fetch', (event) => { event.respondWith(handleRequest(event.request)); }); -self.addEventListener('message', (event) => { - const reply = content => event.source.postMessage({replyTo: event.data?.id, content}); - switch (event.data?.type) { - case "version": - reply({version: VERSION, buildHash: GLOBAL_HASH}); - break; - case "skipWaiting": - self.skipWaiting(); - break; - } -}); - async function handleRequest(request) { const baseURL = self.registration.scope; if (request.url === baseURL) { @@ -131,3 +119,52 @@ async function readCache(request) { } return response; } + +self.addEventListener('message', (event) => { + const reply = payload => event.source.postMessage({replyTo: event.data.id, payload}); + const {replyTo} = event.data; + if (replyTo) { + const resolve = pendingReplies.get(replyTo); + if (resolve) { + pendingReplies.delete(replyTo); + resolve(event.data.payload); + } + } else { + switch (event.data?.type) { + case "version": + reply({version: VERSION, buildHash: GLOBAL_HASH}); + break; + case "skipWaiting": + self.skipWaiting(); + break; + case "closeSession": + event.waitUntil( + closeSession(event.data.payload.sessionId, event.source.id) + .then(() => reply()) + ); + break; + } + } +}); + + +async function closeSession(sessionId, requestingClientId) { + const clients = await self.clients.matchAll(); + await Promise.all(clients.map(async client => { + if (client.id !== requestingClientId) { + await sendAndWaitForReply(client, "closeSession", {sessionId}); + } + })); +} + +const pendingReplies = new Map(); +let messageIdCounter = 0; +function sendAndWaitForReply(client, type, payload) { + messageIdCounter += 1; + const id = messageIdCounter; + const promise = new Promise(resolve => { + pendingReplies.set(id, resolve); + }); + client.postMessage({type, id, payload}); + return promise; +}