From 95721705e472bfbcf0adae4c992bb5745d285f04 Mon Sep 17 00:00:00 2001 From: Jaifroid Date: Thu, 16 Nov 2023 13:37:59 +0000 Subject: [PATCH] Simplify messaging logic and add acknowledgement --- service-worker.js | 6 ++++++ www/js/app.js | 46 ++++++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/service-worker.js b/service-worker.js index 8409bb519..14439c0a8 100644 --- a/service-worker.js +++ b/service-worker.js @@ -290,6 +290,12 @@ self.addEventListener('message', function (event) { if (event.data.action === 'init') { // On 'init' message, we enable the fetchEventListener fetchCaptureEnabled = true; + // Acdknowledge the init message to all clients + self.clients.matchAll().then(function (clientList) { + clientList.forEach(function (client) { + client.postMessage({ action: 'acknowledge' }); + }); + }); } else if (event.data.action === 'disable') { // On 'disable' message, we disable the fetchEventListener // Note that this code doesn't currently run because the app currently never sends a 'disable' message diff --git a/www/js/app.js b/www/js/app.js index 652073773..ec2074100 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -795,39 +795,47 @@ function initServiceWorkerMessaging () { if (params.contentInjectionMode === 'serviceworker') { // Create a message listener navigator.serviceWorker.onmessage = function (event) { - if (!selectedArchive) { - console.warn('Message from SW received, but no archive is selected!'); - return; - } if (event.data.error) { console.error('Error in MessageChannel', event.data.error); throw event.data.error; - } - if (event.data.action === 'askForContent') { + } else if (event.data.action === 'acknowledge') { + // The Service Worker is acknowledging receipt of init message + console.log('SW acknowledged init message'); + initServiceWorkerHandle = true; + } else if (event.data.action === 'askForContent') { + // The Service Worker is asking for content. Check we have a loaded ZIM in this instance. + // DEV: This can happen if there are various instances of the app open in different tabs or windows, and no archive has been selected in this instance. + if (!selectedArchive) { + console.warn('Message from SW received, but no archive is selected!'); + return; + } + // See below for explanation of this exception + const videoException = selectedArchive.zimType === 'zimit' && /\/\/youtubei.*player/.test(event.data.title); // Check that the zimFileId in the messageChannel event data is the same as the one in the currently open archive // Because the SW broadcasts its request to all open tabs or windows, we need to check that the request is for this instance - if (event.data.zimFileName !== selectedArchive.file.name) { - console.warn('SW request does not match this insstance', '[zimFileName:' + event.data.zimFileName + ' !== ' + selectedArchive.file.name + ']'); - if (selectedArchive.zimType === 'zimit' && /\/\/youtubei.*player/.test(event.data.title)) { + if (event.data.zimFileName !== selectedArchive.file.name && !videoException) { + // Do nothing if the request is not for this instance + // console.debug('SW request does not match this instance', '[zimFileName:' + event.data.zimFileName + ' !== ' + selectedArchive.file.name + ']'); + } else { + if (videoException) { // DEV: This is a hack to allow YouTube videos to play in Zimit archives: // Because links are embedded in a nested iframe, the SW cannot identify the top-level window from which to request the ZIM content - // Until we find a way to tell where it is coming from, we allow the request through and try to load the content - console.warn('>>> Allowing passthrough to process YouTube video <<<'); - } else { - return; + // Until we find a way to tell where it is coming from, we allow the request through on all controlled clients and try to load the content + console.warn('>>> Allowing passthrough of SW request to process Zimit video <<<'); } + handleMessageChannelMessage(event); } - handleMessageChannelMessage(event) } else { console.error('Invalid message received', event.data); } }; // Send the init message to the ServiceWorker if (navigator.serviceWorker.controller) { + console.log('Initializing SW messaging...'); navigator.serviceWorker.controller.postMessage({ action: 'init' }); - } else if (initServiceWorkerHandle) { + } else if (!initServiceWorkerHandle) { console.error('The Service Worker is active but is not controlling the current page! We have to reload.'); // Turn off failsafe, as this is a controlled reboot settingsStore.setItem('lastPageLoad', 'rebooting', Infinity); @@ -835,7 +843,7 @@ function initServiceWorkerMessaging () { } else { // If this is the first time we are initiating the SW, allow Promises to complete by delaying potential reload till next tick console.debug('The Service Worker needs more time to load...'); - initServiceWorkerHandle = setTimeout(initServiceWorkerMessaging, 0); + setTimeout(initServiceWorkerMessaging, 0); } } } @@ -1293,10 +1301,8 @@ function setLocalArchiveFromArchiveList () { * Resets the CSS Cache (used only in jQuery mode) */ function resetCssCache () { - // Reset the cssCache. Must be done when archive changes. - if (selectedArchive.cssCache) { - selectedArchive.cssCache = new Map(); - } + // Reset the cssCache if an archive is loaded + if (selectedArchive) selectedArchive.cssCache = new Map(); } let webKitFileList = null