mirror of
https://github.com/kiwix/kiwix-js-pwa.git
synced 2025-09-09 04:06:27 -04:00
Add missing file
Former-commit-id: 95f77bb1cda3dfe1deb47a09951dc2db28007782 [formerly 35e0012153a44d1a720a31f8558fc6e8c4049749] Former-commit-id: 2230d51f8b8c1e898774fc75c01ea94307baf3f7
This commit is contained in:
parent
ffb8cdcbdb
commit
cf521c9f73
191
service-worker.js
Normal file
191
service-worker.js
Normal file
@ -0,0 +1,191 @@
|
||||
/**
|
||||
* 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 2015 Mossroy and contributors
|
||||
* License 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 License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, 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 License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
self.addEventListener('install', function(event) {
|
||||
event.waitUntil(self.skipWaiting());
|
||||
console.log("ServiceWorker installed");
|
||||
});
|
||||
|
||||
self.addEventListener('activate', function(event) {
|
||||
// "Claiming" the ServiceWorker is necessary to make it work right away,
|
||||
// without the need to reload the page.
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/API/Clients/claim
|
||||
event.waitUntil(self.clients.claim());
|
||||
console.log("ServiceWorker activated");
|
||||
});
|
||||
|
||||
var regexpRemoveUrlParameters = new RegExp(/([^\?]+)\?.*$/);
|
||||
|
||||
// This function is duplicated from uiUtil.js
|
||||
// because using requirejs would force to add the 'fetch' event listener
|
||||
// after the initial evaluation of this script, which is not supported any more
|
||||
// in recent versions of the browsers.
|
||||
// Cf https://bugzilla.mozilla.org/show_bug.cgi?id=1181127
|
||||
// TODO : find a way to avoid this duplication
|
||||
function removeUrlParameters(url) {
|
||||
if (regexpRemoveUrlParameters.test(url)) {
|
||||
return regexpRemoveUrlParameters.exec(url)[1];
|
||||
} else {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("ServiceWorker startup");
|
||||
|
||||
var outgoingMessagePort = null;
|
||||
var fetchCaptureEnabled = false;
|
||||
self.addEventListener('fetch', fetchEventListener);
|
||||
console.log('fetchEventListener set');
|
||||
|
||||
self.addEventListener('message', function (event) {
|
||||
if (event.data.action === 'init') {
|
||||
console.log('Init message received', event.data);
|
||||
outgoingMessagePort = event.ports[0];
|
||||
console.log('outgoingMessagePort initialized', outgoingMessagePort);
|
||||
fetchCaptureEnabled = true;
|
||||
console.log('fetchEventListener enabled');
|
||||
}
|
||||
if (event.data.action === 'disable') {
|
||||
console.log('Disable message received');
|
||||
outgoingMessagePort = null;
|
||||
console.log('outgoingMessagePort deleted');
|
||||
fetchCaptureEnabled = false;
|
||||
console.log('fetchEventListener disabled');
|
||||
}
|
||||
});
|
||||
|
||||
// TODO : this way to recognize content types is temporary
|
||||
// It must be replaced by reading the actual MIME-Type from the backend
|
||||
var regexpJPEG = new RegExp(/\.jpe?g$/i);
|
||||
var regexpPNG = new RegExp(/\.png$/i);
|
||||
var regexpJS = new RegExp(/\.js/i);
|
||||
var regexpCSS = new RegExp(/\.css$/i);
|
||||
|
||||
var regexpContentUrlWithNamespace = new RegExp(/\/(.)\/(.*[^\/]+)$/);
|
||||
var regexpContentUrlWithoutNamespace = new RegExp(/^([^\/]+)$/);
|
||||
var regexpDummyArticle = new RegExp(/dummyArticle\.html$/);
|
||||
|
||||
function fetchEventListener(event) {
|
||||
if (fetchCaptureEnabled) {
|
||||
console.log('ServiceWorker handling fetch event for : ' + event.request.url);
|
||||
|
||||
// TODO handle the dummy article more properly
|
||||
if ((regexpContentUrlWithNamespace.test(event.request.url)
|
||||
|| regexpContentUrlWithoutNamespace.test(event.request.url))
|
||||
&& !regexpDummyArticle.test(event.request.url)) {
|
||||
|
||||
console.log('Asking app.js for a content', event.request.url);
|
||||
event.respondWith(new Promise(function(resolve, reject) {
|
||||
var nameSpace;
|
||||
var title;
|
||||
var titleWithNameSpace;
|
||||
var contentType;
|
||||
if (regexpContentUrlWithoutNamespace.test(event.request.url)) {
|
||||
// When the request URL is in the same folder,
|
||||
// it means it's a link to an article (namespace A)
|
||||
var regexpResult = regexpContentUrlWithoutNamespace.exec(event.request.url);
|
||||
nameSpace = 'A';
|
||||
title = regexpResult[1];
|
||||
} else {
|
||||
var regexpResult = regexpContentUrlWithNamespace.exec(event.request.url);
|
||||
nameSpace = regexpResult[1];
|
||||
title = regexpResult[2];
|
||||
}
|
||||
|
||||
// The namespace defines the type of content. See http://www.openzim.org/wiki/ZIM_file_format#Namespaces
|
||||
// TODO : read the contentType from the ZIM file instead of hard-coding it here
|
||||
if (nameSpace === 'A') {
|
||||
console.log("It's an article : " + title);
|
||||
contentType = 'text/html';
|
||||
}
|
||||
else if (nameSpace === 'I' || nameSpace === 'J') {
|
||||
console.log("It's an image : " + title);
|
||||
if (regexpJPEG.test(title)) {
|
||||
contentType = 'image/jpeg';
|
||||
}
|
||||
else if (regexpPNG.test(title)) {
|
||||
contentType = 'image/png';
|
||||
}
|
||||
}
|
||||
else if (nameSpace === '-') {
|
||||
console.log("It's a layout dependency : " + title);
|
||||
if (regexpJS.test(title)) {
|
||||
contentType = 'text/javascript';
|
||||
var responseInit = {
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
headers: {
|
||||
'Content-Type': contentType
|
||||
}
|
||||
};
|
||||
|
||||
var httpResponse = new Response(';', responseInit);
|
||||
|
||||
// TODO : temporary before the backend actually sends a proper content
|
||||
resolve(httpResponse);
|
||||
return;
|
||||
}
|
||||
else if (regexpCSS.test(title)) {
|
||||
contentType = 'text/css';
|
||||
}
|
||||
}
|
||||
|
||||
// We need to remove the potential parameters in the URL
|
||||
title = removeUrlParameters(decodeURIComponent(title));
|
||||
|
||||
titleWithNameSpace = nameSpace + '/' + title;
|
||||
|
||||
// Let's instanciate a new messageChannel, to allow app.s to give us the content
|
||||
var messageChannel = new MessageChannel();
|
||||
messageChannel.port1.onmessage = function(event) {
|
||||
if (event.data.action === 'giveContent') {
|
||||
console.log('content message received for ' + titleWithNameSpace, event.data);
|
||||
var responseInit = {
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
headers: {
|
||||
'Content-Type': contentType
|
||||
}
|
||||
};
|
||||
|
||||
var httpResponse = new Response(event.data.content, responseInit);
|
||||
|
||||
console.log('ServiceWorker responding to the HTTP request for ' + titleWithNameSpace + ' (size=' + event.data.content.length + ' octets)' , httpResponse);
|
||||
resolve(httpResponse);
|
||||
}
|
||||
else {
|
||||
console.log('Invalid message received from app.js for ' + titleWithNameSpace, event.data);
|
||||
reject(event.data);
|
||||
}
|
||||
};
|
||||
console.log('Eventlistener added to listen for an answer to ' + titleWithNameSpace);
|
||||
outgoingMessagePort.postMessage({'action': 'askForContent', 'title': titleWithNameSpace}, [messageChannel.port2]);
|
||||
console.log('Message sent to app.js through outgoingMessagePort');
|
||||
}));
|
||||
}
|
||||
// If event.respondWith() isn't called because this wasn't a request that we want to handle,
|
||||
// then the default request/response behavior will automatically be used.
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user