diff --git a/pwabuilder-sw.js b/pwabuilder-sw.js
index da8931bf..934d5541 100644
--- a/pwabuilder-sw.js
+++ b/pwabuilder-sw.js
@@ -93,117 +93,120 @@ const regexpZIMUrlWithNamespace = /(?:^|\/)([^\/]+\/)([-ABIJMUVWX])\/(.+)/;
self.addEventListener("fetch", function (event) {
console.log('[SW] Service Worker ' + (event.request.method === "GET" ? 'intercepted ' : 'noted ') + event.request.url, event.request.method);
if (event.request.method !== "GET") return;
- if (/\.zim\w{0,2}\//i.test(event.request.url) && regexpZIMUrlWithNamespace.test(event.request.url)) {
- // If the user has disabled the display of images, and the browser wants an image, respond with empty SVG
- // A URL with "?kiwix-display" query string acts as a passthrough so that the regex will not match and
- // the image will be fetched by app.js
- // DEV: If you need to hide more image types, add them to regex below and also edit equivalent regex in app.js
- if (imageDisplay !== 'all' && /(^|\/)[IJ]\/.*\.(jpe?g|png|svg|gif)($|[?#])(?!kiwix-display)/i.test(event.request.url)) {
- var svgResponse;
- if (imageDisplay === 'manual')
- svgResponse = "";
- else
- svgResponse = "";
- event.respondWith(new Response(svgResponse, {
- headers: {
- 'Content-Type': 'image/svg+xml'
- }
- }));
- return;
- }
- // Let's ask app.js for that content
- event.respondWith(new Promise(function (resolve, reject) {
- var nameSpace;
- var title;
- var titleWithNameSpace;
- var regexpResult = regexpZIMUrlWithNamespace.exec(event.request.url);
- var prefix = regexpResult[1];
- nameSpace = regexpResult[2];
- title = regexpResult[3];
+ event.respondWith(
+ fromCache(event.request).then(
+ function (response) {
+ // The response was found in the cache so we respond with it and update the entry
- // We need to remove the potential parameters in the URL
- title = removeUrlParameters(decodeURIComponent(title));
+ // This is where we call the server to get the newest version of the
+ // file to use the next time we show view
+ // event.waitUntil(
+ // fetch(event.request).then(function (response) {
+ // console.log('[SW] Refreshing CACHE from server...');
+ // return updateCache(event.request, response);
+ // })
+ // );
- titleWithNameSpace = nameSpace + '/' + title;
-
- // Let's instantiate a new messageChannel, to allow app.js to give us the content
- var messageChannel = new MessageChannel();
- messageChannel.port1.onmessage = function (event) {
- if (event.data.action === 'giveContent') {
- // Content received from app.js
- var contentLength = event.data.content ? event.data.content.byteLength : null;
- var contentType = event.data.mimetype;
- // Set the imageDisplay variable if it has been sent in the event data
- imageDisplay = typeof event.data.imageDisplay !== 'undefined' ?
- event.data.imageDisplay : imageDisplay;
- var headers = new Headers();
- if (contentLength) headers.set('Content-Length', contentLength);
- if (contentType) headers.set('Content-Type', contentType);
- // Test if the content is a video or audio file
- // 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)) {
- // In case of a video (at least), Chrome and Edge need these HTTP headers else seeking doesn't work
- // (even if we always send all the video content, not the requested range, until the backend supports it)
- headers.set('Accept-Ranges', 'bytes');
- headers.set('Content-Range', 'bytes 0-' + (contentLength - 1) + '/' + contentLength);
- }
- var responseInit = {
- status: 200,
- statusText: 'OK',
- headers: headers
- };
-
- var httpResponse = new Response(event.data.content, responseInit);
-
- // Let's send the content back from the ServiceWorker
- resolve(httpResponse);
- } else if (event.data.action === 'sendRedirect') {
- resolve(Response.redirect(prefix + event.data.redirectUrl));
- } else {
- console.error('Invalid message received from app.js for ' + titleWithNameSpace, event.data);
- reject(event.data);
- }
- };
- outgoingMessagePort.postMessage({
- 'action': 'askForContent',
- 'title': titleWithNameSpace
- }, [messageChannel.port2]);
- }));
- } else {
- event.respondWith(
- fromCache(event.request).then(
- function (response) {
- // The response was found in the cache so we responde with it and update the entry
-
- // This is where we call the server to get the newest version of the
- // file to use the next time we show view
- event.waitUntil(
- fetch(event.request).then(function (response) {
- console.log('[SW] Refreshing CACHE from server...');
- return updateCache(event.request, response);
- })
- );
- console.log('[SW] Supplying ' + event.request.url + ' from CACHE...');
- return response;
- },
- function () {
- // The response was not found in the cache so we look for it on the server
- return fetch(event.request)
- .then(function (response) {
- // If request was success, add or update it in the cache
- event.waitUntil(updateCache(event.request, response.clone()));
-
- return response;
- })
- .catch(function (error) {
- console.log("[SW] Network request failed and no cache.", error);
+ console.log('[SW] Supplying ' + event.request.url + ' from CACHE...');
+ return response;
+ },
+ function () {
+ // The response was not found in the cache so we look for it on the server
+ if (/\.zim\w{0,2}\//i.test(event.request.url) && regexpZIMUrlWithNamespace.test(event.request.url)) {
+ // If the user has disabled the display of images, and the browser wants an image, respond with empty SVG
+ // A URL with "?kiwix-display" query string acts as a passthrough so that the regex will not match and
+ // the image will be fetched by app.js
+ // DEV: If you need to hide more image types, add them to regex below and also edit equivalent regex in app.js
+ if (imageDisplay !== 'all' && /(^|\/)[IJ]\/.*\.(jpe?g|png|svg|gif)($|[?#])(?!kiwix-display)/i.test(event.request.url)) {
+ var svgResponse;
+ if (imageDisplay === 'manual')
+ svgResponse = "";
+ else
+ svgResponse = "";
+ return new Response(svgResponse, {
+ headers: {
+ 'Content-Type': 'image/svg+xml'
+ }
});
+ }
+
+ // Let's ask app.js for that content
+ return new Promise(function (resolve, reject) {
+ var nameSpace;
+ var title;
+ var titleWithNameSpace;
+ var regexpResult = regexpZIMUrlWithNamespace.exec(event.request.url);
+ var prefix = regexpResult[1];
+ nameSpace = regexpResult[2];
+ title = regexpResult[3];
+
+ // We need to remove the potential parameters in the URL
+ title = removeUrlParameters(decodeURIComponent(title));
+
+ titleWithNameSpace = nameSpace + '/' + title;
+
+ // Let's instantiate a new messageChannel, to allow app.js to give us the content
+ var messageChannel = new MessageChannel();
+ messageChannel.port1.onmessage = function (msgEvent) {
+ if (msgEvent.data.action === 'giveContent') {
+ // Content received from app.js
+ var contentLength = msgEvent.data.content ? msgEvent.data.content.byteLength : null;
+ var contentType = msgEvent.data.mimetype;
+ // Set the imageDisplay variable if it has been sent in the event data
+ imageDisplay = typeof msgEvent.data.imageDisplay !== 'undefined' ?
+ msgEvent.data.imageDisplay : imageDisplay;
+ var headers = new Headers();
+ if (contentLength) headers.set('Content-Length', contentLength);
+ if (contentType) headers.set('Content-Type', contentType);
+ // Test if the content is a video or audio file
+ // 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)) {
+ // In case of a video (at least), Chrome and Edge need these HTTP headers else seeking doesn't work
+ // (even if we always send all the video content, not the requested range, until the backend supports it)
+ headers.set('Accept-Ranges', 'bytes');
+ headers.set('Content-Range', 'bytes 0-' + (contentLength - 1) + '/' + contentLength);
+ }
+ var responseInit = {
+ status: 200,
+ statusText: 'OK',
+ headers: headers
+ };
+
+ var httpResponse = new Response(msgEvent.data.content, responseInit);
+
+ // Add or update css or javascript assets to the cache
+ if (/(text|application)\/(css|javascript)/i.test(contentType)) {
+ updateCache(event.request, httpResponse.clone());
+ }
+
+ // Let's send the content back from the ServiceWorker
+ resolve(httpResponse);
+ } else if (msgEvent.data.action === 'sendRedirect') {
+ resolve(Response.redirect(prefix + msgEvent.data.redirectUrl));
+ } else {
+ console.error('Invalid message received from app.js for ' + titleWithNameSpace, msgEvent.data);
+ reject(msgEvent.data);
+ }
+ };
+ outgoingMessagePort.postMessage({
+ 'action': 'askForContent',
+ 'title': titleWithNameSpace
+ }, [messageChannel.port2]);
+ });
+ } else {
+ return fetch(event.request).then(function (response) {
+ // If request was success, add or update it in the cache
+ event.waitUntil(updateCache(event.request, response.clone()));
+ return response;
+ }).catch(function (error) {
+ console.log("[SW] Network request failed and no cache.", error);
+ });
}
- )
- );
- }
+ }
+ )
+ );
});
function fromCache(request) {
diff --git a/www/js/app.js b/www/js/app.js
index d39ef0ca..841a3ea1 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -1221,6 +1221,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'images', 'cooki
}
var keepAliveServiceWorkerHandle;
+ var serviceWorkerRegistration = null;
/**
* Send an 'init' message to the ServiceWorker with a new MessageChannel
@@ -1351,8 +1352,6 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'images', 'cooki
setContentInjectionMode('jquery');
}
- var serviceWorkerRegistration = null;
-
/**
* Tells if the ServiceWorker API is available
* https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorker