From d59384f05aed95ec353ecfeb123cd69603357823 Mon Sep 17 00:00:00 2001 From: Jaifroid Date: Fri, 18 Aug 2023 18:45:01 +0100 Subject: [PATCH] Clean up after rebase --- service-worker.js | 46 +++++------ www/js/app.js | 168 ++++++++++++++++++++------------------- www/js/lib/zimArchive.js | 2 + 3 files changed, 110 insertions(+), 106 deletions(-) diff --git a/service-worker.js b/service-worker.js index 20cd0c5cb..7c7fa5de5 100644 --- a/service-worker.js +++ b/service-worker.js @@ -2,22 +2,22 @@ * service-worker.js : Service Worker implementation, * in order to capture the HTTP requests made by an article, and respond with the * corresponding content, coming from the archive - * + * * Copyright 2022 Mossroy, Jaifroid and contributors * Licence GPL v3: - * + * * This file is part of Kiwix. - * + * * Kiwix is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public Licence as published by * the Free Software Foundation, either version 3 of the Licence, or * (at your option) any later version. - * + * * Kiwix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public Licence for more details. - * + * * You should have received a copy of the GNU General Public Licence * along with Kiwix (file LICENSE-GPLv3.txt). If not, see */ @@ -62,9 +62,9 @@ var useAssetsCache = true; * This is an expert setting in Configuration * @type {Boolean} */ - var useAppCache = true; +var useAppCache = true; -/** +/** * A regular expression that matches the Content-Types of assets that may be stored in ASSETS_CACHE * Add any further Content-Types you wish to cache to the regexp, separated by '|' * @type {RegExp} @@ -79,7 +79,7 @@ var regexpCachedContentTypes = /text\/css|text\/javascript|application\/javascri */ var regexpExcludedURLSchema = /^(?:file|chrome-extension|example-extension):/i; -/** +/** * Pattern for ZIM file namespace: see https://wiki.openzim.org/wiki/ZIM_file_format#Namespaces * In our case, there is also the ZIM file name used as a prefix in the URL * @type {RegExp} @@ -92,7 +92,7 @@ const regexpZIMUrlWithNamespace = /(?:^|\/)([^/]+\/)([-ABCIJMUVWX])\/(.+)/; * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range * But, in our case, we send a header to tell the browser we only accept the bytes unit. * I did not see multiple ranges asked by a browser. - * + * * @type {RegExp} */ const regexpByteRangeHeader = /^\s*bytes=(\d+)-/; @@ -241,7 +241,7 @@ self.addEventListener('fetch', function (event) { event.respondWith( // First see if the content is in the cache fromCache(cache, rqUrl).then(function (response) { - // The response was found in the cache so we respond with it + // The response was found in the cache so we respond with it return response; }, function () { // The response was not found in the cache so we look for it in the ZIM @@ -278,7 +278,7 @@ self.addEventListener('fetch', function (event) { /** * Handle custom commands sent from app.js */ - self.addEventListener('message', function (event) { +self.addEventListener('message', function (event) { if (event.data.action) { if (event.data.action === 'init') { // On 'init' message, we initialize the outgoingMessagePort and enable the fetchEventListener @@ -316,12 +316,12 @@ self.addEventListener('fetch', function (event) { /** * Handles URLs that need to be extracted from the ZIM archive - * + * * @param {URL} urlObject The URL object to be processed for extraction from the ZIM * @param {String} range Optional byte range string * @returns {Promise} A Promise for the Response, or rejects with the invalid message port data */ -function fetchUrlFromZIM(urlObject, range) { +function fetchUrlFromZIM (urlObject, range) { return new Promise(function (resolve, reject) { // Note that titles may contain bare question marks or hashes, so we must use only the pathname without any URL parameters. // Be sure that you haven't encoded any querystring along with the URL. @@ -346,14 +346,14 @@ function fetchUrlFromZIM(urlObject, range) { headers.set('Content-Security-Policy', "default-src 'self' data: blob: about: chrome-extension: moz-extension: https://browser-extension.kiwix.org https://kiwix.github.io 'unsafe-inline' 'unsafe-eval'; sandbox allow-scripts allow-same-origin allow-modals allow-popups allow-forms allow-downloads;"); headers.set('Referrer-Policy', 'no-referrer'); if (contentType) headers.set('Content-Type', contentType); - + // Test if the content is a video or audio file. In this case, Chrome & Edge need us to support ranges. // See kiwix-js #519 and openzim/zimwriterfs #113 for why we test for invalid types like "mp4" or "webm" (without "video/") // The full list of types produced by zimwriterfs is in https://github.com/openzim/zimwriterfs/blob/master/src/tools.cpp if (contentLength >= 1 && /^(video|audio)|(^|\/)(mp4|webm|og[gmv]|mpeg)$/i.test(contentType)) { headers.set('Accept-Ranges', 'bytes'); } - + var slicedData = msgPortEvent.data.content; if (range) { // The browser asks for a range of bytes (usually for a video or audio stream) @@ -367,18 +367,18 @@ function fetchUrlFromZIM(urlObject, range) { const begin = partsOfRangeHeader[1]; const end = contentLength - 1; slicedData = slicedData.slice(begin); - + headers.set('Content-Range', 'bytes ' + begin + '-' + end + '/' + contentLength); headers.set('Content-Length', end - begin + 1); } - + var responseInit = { // HTTP status is usually 200, but has to bee 206 when partial content (range) is sent status: range ? 206 : 200, statusText: 'OK', headers }; - + var httpResponse = new Response(slicedData, responseInit); // Let's send the content back from the ServiceWorker @@ -402,7 +402,7 @@ function fetchUrlFromZIM(urlObject, range) { * @param {String} requestUrl The Request URL to fulfill from cache * @returns {Promise} A Promise for the cached Response, or rejects with strings 'disabled' or 'no-match' */ -function fromCache(cache, requestUrl) { +function fromCache (cache, requestUrl) { // Prevents use of Cache API if user has disabled it if (!(useAppCache && cache === APP_CACHE || useAssetsCache && cache === ASSETS_CACHE)) { return Promise.reject(new Error('disabled')); @@ -425,7 +425,7 @@ function fromCache(cache, requestUrl) { * @param {Response} response The Response received from the server/ZIM * @returns {Promise} A Promise for the update action */ -function updateCache(cache, request, response) { +function updateCache (cache, request, response) { // Prevents use of Cache API if user has disabled it if (!response.ok || !(useAppCache && cache === APP_CACHE || useAssetsCache && cache === ASSETS_CACHE)) { return Promise.resolve(); @@ -442,16 +442,16 @@ function updateCache(cache, request, response) { * @param {String} url A URL to test against excludedURLSchema * @returns {Promise} A Promise for an array of format [cacheType, cacheDescription, assetCount] */ -function testCacheAndCountAssets(url) { +function testCacheAndCountAssets (url) { if (regexpExcludedURLSchema.test(url)) return Promise.resolve(['custom', 'custom', 'Custom', '-']); if (!useAssetsCache) return Promise.resolve(['none', 'none', 'None', 0]); return caches.open(ASSETS_CACHE).then(function (cache) { return cache.keys().then(function (keys) { return ['cacheAPI', ASSETS_CACHE, 'Cache API', keys.length]; - }).catch(function(err) { + }).catch(function (err) { return err; }); - }).catch(function(err) { + }).catch(function (err) { return err; }); } diff --git a/www/js/app.js b/www/js/app.js index 09eb28cbb..4e806f3aa 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -41,67 +41,67 @@ if (params.abort) { throw new Error('Managed error: exiting local extension code.') } - /** - * The delay (in milliseconds) between two "keepalive" messages sent to the ServiceWorker (so that it is not stopped - * by the browser, and keeps the MessageChannel to communicate with the application) - * @type Integer - */ - const DELAY_BETWEEN_KEEPALIVE_SERVICEWORKER = 30000; - - /** - * The name of the Cache API cache to use for caching Service Worker requests and responses for certain asset types - * We need access to the cache name in app.js in order to complete utility actions when Service Worker is not initialized, - * so we have to duplicate it here - * @type {String} - */ - // DEV: Ensure this matches the name defined in service-worker.js (a check is provided in refreshCacheStatus() below) - const ASSETS_CACHE = 'kiwixjs-assetsCache'; +/** + * The delay (in milliseconds) between two "keepalive" messages sent to the ServiceWorker (so that it is not stopped + * by the browser, and keeps the MessageChannel to communicate with the application) + * @type Integer + */ +const DELAY_BETWEEN_KEEPALIVE_SERVICEWORKER = 30000; - /** - * Memory cache for CSS styles contained in ZIM: it significantly speeds up subsequent page display - * This cache is used by default in jQuery mode, but can be turned off in Configuration for low-memory devices - * In Service Worker mode, the Cache API will be used instead - * @type {Map} - */ - var cssCache = new Map(); +/** + * The name of the Cache API cache to use for caching Service Worker requests and responses for certain asset types + * We need access to the cache name in app.js in order to complete utility actions when Service Worker is not initialized, + * so we have to duplicate it here + * @type {String} + */ +// DEV: Ensure this matches the name defined in service-worker.js (a check is provided in refreshCacheStatus() below) +const ASSETS_CACHE = 'kiwixjs-assetsCache'; + +/** + * Memory cache for CSS styles contained in ZIM: it significantly speeds up subsequent page display + * This cache is used by default in jQuery mode, but can be turned off in Configuration for low-memory devices + * In Service Worker mode, the Cache API will be used instead + * @type {Map} + */ +var cssCache = new Map(); - /** - * A global object for storing app state - * - * @type Object - */ - var appstate = {}; +/** + * A global object for storing app state + * + * @type Object + */ +var appstate = {}; - /** - * @type ZIMArchive - */ - var selectedArchive = null; +/** + * @type ZIMArchive + */ +var selectedArchive = null; - // An object to hold the current search and its state (allows cancellation of search across modules) - appstate['search'] = { +// An object to hold the current search and its state (allows cancellation of search across modules) +appstate['search'] = { prefix: '', // A field to hold the original search string status: '', // The status of the search: ''|'init'|'interim'|'cancelled'|'complete' type: '' // The type of the search: 'basic'|'full' (set automatically in search algorithm) - }; +}; - // A Boolean to store the update status of the PWA version (currently only used with Firefox Extension) - appstate['pwaUpdateNeeded'] = false; // This will be set to true if the Service Worker has an update waiting +// A Boolean to store the update status of the PWA version (currently only used with Firefox Extension) +appstate['pwaUpdateNeeded'] = false; // This will be set to true if the Service Worker has an update waiting switchHomeKeyToFocusSearchBar(); - // We check here if we have to warn the user that we switched to ServiceWorkerMode +// We check here if we have to warn the user that we switched to ServiceWorkerMode // This is only needed if the ServiceWorker mode is available, or we are in an Extension that supports Service Workers - // outside of the extension environment, AND the user's settings are stuck on jQuery mode, AND the user has not already been - // alerted about the switch to ServiceWorker mode by default +// outside of the extension environment, AND the user's settings are stuck on jQuery mode, AND the user has not already been +// alerted about the switch to ServiceWorker mode by default if ((isServiceWorkerAvailable() || isMessageChannelAvailable() && /^(moz|chrome)-extension:/i.test(window.location.protocol)) && params.contentInjectionMode === 'jquery' && !params.defaultModeChangeAlertDisplayed) { - // Attempt to upgrade user to ServiceWorker mode - params.contentInjectionMode = 'serviceworker'; - } else if (params.contentInjectionMode === 'serviceworker') { - // User is already in SW mode, so we will never need to display the upgrade alert - params.defaultModeChangeAlertDisplayed = true; - settingsStore.setItem('defaultModeChangeAlertDisplayed', true, Infinity); - } + // Attempt to upgrade user to ServiceWorker mode + params.contentInjectionMode = 'serviceworker'; +} else if (params.contentInjectionMode === 'serviceworker') { + // User is already in SW mode, so we will never need to display the upgrade alert + params.defaultModeChangeAlertDisplayed = true; + settingsStore.setItem('defaultModeChangeAlertDisplayed', true, Infinity); +} if (!/^chrome-extension:/i.test(window.location.protocol)) { document.getElementById('serviceWorkerLocal').style.display = 'none'; document.getElementById('serviceWorkerLocalDescription').style.display = 'none'; @@ -151,7 +151,7 @@ var expectedArticleURLToBeDisplayed = ''; nestedFrame.style.height = window.innerHeight - 110 + 'px'; } else { // IE cannot retrieve computed headerStyles till the next paint, so we wait a few ticks - setTimeout(function () { + setTimeout(function() { // Get header height *including* its bottom margin const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom); iframe.style.height = window.innerHeight - headerHeight + 'px'; @@ -1342,12 +1342,14 @@ document.getElementById('libraryBtn').addEventListener('click', function (e) { selectedArchive = null; selectedArchive = zimArchiveLoader.loadArchiveFromFiles(files, function () { document.getElementById('downloadInstruction').style.display = 'none'; - var tmpMessageChannel = new MessageChannel(); - tmpMessageChannel.port1.onmessage = function () { - // The archive is set : go back to home page to start searching - $("#btnHome").click(); - } - libzimWebWorker.postMessage({action: "init", files: selectedArchive._file._files}, [tmpMessageChannel.port2]); + // var tmpMessageChannel = new MessageChannel(); + // tmpMessageChannel.port1.onmessage = function () { + // // The archive is set : go back to home page to start searching + // $("#btnHome").click(); + // } + // selectedArchive.callLibzimWorker({ action: "init", files: selectedArchive._file._files }).then(function (worker) { + // $("#btnHome").click(); + // }); }, function (message, label) { // callbackError which is called in case of an error uiUtil.systemAlert(message, label); @@ -1672,34 +1674,34 @@ document.getElementById('libraryBtn').addEventListener('click', function (e) { } } - var libzimWebWorker = new Worker("a.out.js"); + // var libzimWebWorker = new Worker("a.out.js"); - /** - * Calls the libzim WebWorker with the given parameters, and returns a Promise with its response - * - * @param {Object} parameters - * @returns {Promise} - */ - function callLibzimWebWorker(parameters) { - return new Promise(function (resolve, reject) { - console.debug("Calling libzim WebWorker with parameters", parameters); - var tmpMessageChannel = new MessageChannel(); - var t0 = performance.now(); - tmpMessageChannel.port1.onmessage = function (event) { - var t1 = performance.now(); - var readTime = Math.round(t1 - t0); - console.debug("Response given by the WebWorker in " + readTime + " ms", event.data); - resolve(event.data); - }; - tmpMessageChannel.port1.onerror = function (event) { - var t1 = performance.now(); - var readTime = Math.round(t1 - t0); - console.error("Error sent by the WebWorker in " + readTime + " ms", event.data); - reject(event.data); - }; - libzimWebWorker.postMessage(parameters, [tmpMessageChannel.port2]); - }); - } + // /** + // * Calls the libzim WebWorker with the given parameters, and returns a Promise with its response + // * + // * @param {Object} parameters + // * @returns {Promise} + // */ + // function callLibzimWebWorker(parameters) { + // return new Promise(function (resolve, reject) { + // console.debug("Calling libzim WebWorker with parameters", parameters); + // var tmpMessageChannel = new MessageChannel(); + // var t0 = performance.now(); + // tmpMessageChannel.port1.onmessage = function (event) { + // var t1 = performance.now(); + // var readTime = Math.round(t1 - t0); + // console.debug("Response given by the WebWorker in " + readTime + " ms", event.data); + // resolve(event.data); + // }; + // tmpMessageChannel.port1.onerror = function (event) { + // var t1 = performance.now(); + // var readTime = Math.round(t1 - t0); + // console.error("Error sent by the WebWorker in " + readTime + " ms", event.data); + // reject(event.data); + // }; + // libzimWebWorker.postMessage(parameters, [tmpMessageChannel.port2]); + // }); + // } /** * Function that handles a message of the messageChannel. @@ -1733,8 +1735,8 @@ document.getElementById('libraryBtn').addEventListener('click', function (e) { messagePort.postMessage(message); } }; - callLibzimWebWorker({action: "getEntryByPath", path: title, follow: false}).then(readFile).catch(function () { - messagePort.postMessage({ action: 'giveContent', title: title, content: new Uint8Array() }); + selectedArchive.callLibzimWorker({action: "getEntryByPath", path: title, follow: false}).then(readFile).catch(function () { + messagePort.postMessage({ action: 'giveContent', title: title, content: new Uint8Array() }); }); } else { console.error('Invalid message received', event.data); diff --git a/www/js/lib/zimArchive.js b/www/js/lib/zimArchive.js index 47a03d681..07fb16cfd 100644 --- a/www/js/lib/zimArchive.js +++ b/www/js/lib/zimArchive.js @@ -111,6 +111,8 @@ function ZIMArchive (storage, path, callbackReady, callbackError) { params.searchProvider = 'fulltext: ' + libzimReaderType; // Update the API panel uiUtil.reportSearchProviderToAPIStatusPanel(params.searchProvider); + // Archive is set, go home + document.getElementById('btnHome').click(); }).catch(function (err) { uiUtil.reportSearchProviderToAPIStatusPanel(params.searchProvider + ': ERROR'); console.error('The libzim worker could not be instantiated!', err);