Merge pull request #406 from kiwix/workaround-serviceworker-state-loss-after-a-while

Workaround serviceworker state loss after a while
This commit is contained in:
Mossroy 2018-09-12 17:19:17 +02:00 committed by GitHub
commit f930652aa7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -35,6 +35,15 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
*/
var MAX_SEARCH_RESULT_SIZE = 50;
/**
* 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
*/
var DELAY_BETWEEN_KEEPALIVE_SERVICEWORKER = 30000;
/**
* @type ZIMArchive
*/
@ -191,7 +200,6 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
else {
setContentInjectionMode('jquery');
}
});
/**
@ -225,6 +233,29 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
}
var contentInjectionMode;
var keepAliveServiceWorkerHandle;
/**
* Send an 'init' message to the ServiceWorker with a new MessageChannel
* to initialize it, or to keep it alive.
* This MessageChannel allows a 2-way communication between the ServiceWorker
* and the application
*/
function initOrKeepAliveServiceWorker() {
if (contentInjectionMode === 'serviceworker') {
// Create a new messageChannel
var tmpMessageChannel = new MessageChannel();
tmpMessageChannel.port1.onmessage = handleMessageChannelMessage;
// Send the init message to the ServiceWorker, with this MessageChannel as a parameter
navigator.serviceWorker.controller.postMessage({'action': 'init'}, [tmpMessageChannel.port2]);
messageChannel = tmpMessageChannel;
console.log("init message sent to ServiceWorker");
// Schedule to do it again regularly to keep the 2-way communication alive.
// See https://github.com/kiwix/kiwix-js/issues/145 to understand why
clearTimeout(keepAliveServiceWorkerHandle);
keepAliveServiceWorkerHandle = setTimeout(initOrKeepAliveServiceWorker, DELAY_BETWEEN_KEEPALIVE_SERVICEWORKER, false);
}
}
/**
* Sets the given injection mode.
@ -256,13 +287,6 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
return;
}
if (!messageChannel) {
// Let's create the messageChannel for the 2-way communication
// with the Service Worker
messageChannel = new MessageChannel();
messageChannel.port1.onmessage = handleMessageChannelMessage;
}
if (!isServiceWorkerReady()) {
$('#serviceWorkerStatus').html("ServiceWorker API available : trying to register it...");
navigator.serviceWorker.register('../service-worker.js').then(function (reg) {
@ -275,19 +299,24 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
var serviceWorker = reg.installing || reg.waiting || reg.active;
serviceWorker.addEventListener('statechange', function(statechangeevent) {
if (statechangeevent.target.state === 'activated') {
console.log("try to post an init message to ServiceWorker");
navigator.serviceWorker.controller.postMessage({'action': 'init'}, [messageChannel.port2]);
console.log("init message sent to ServiceWorker");
// Create the MessageChannel
// and send the 'init' message to the ServiceWorker
initOrKeepAliveServiceWorker();
}
});
if (serviceWorker.state === 'activated') {
// Even if the ServiceWorker is already activated,
// We need to re-create the MessageChannel
// and send the 'init' message to the ServiceWorker
// in case it has been stopped and lost its context
initOrKeepAliveServiceWorker();
}
}, function (err) {
console.error('error while registering serviceWorker', err);
refreshAPIStatus();
});
} else {
console.log("try to re-post an init message to ServiceWorker, to re-enable it in case it was disabled");
navigator.serviceWorker.controller.postMessage({'action': 'init'}, [messageChannel.port2]);
console.log("init message sent to ServiceWorker");
initOrKeepAliveServiceWorker();
}
}
$('input:radio[name=contentInjectionMode]').prop('checked', false);