UNPKG

@mstange/offline-plugin

Version:
246 lines (205 loc) 6.89 kB
var appCacheIframe; function hasSW() { <% if (typeof ServiceWorker === 'object' && ServiceWorker.force) { %> // Forced install return 'serviceWorker' in navigator; <% } else { %> return 'serviceWorker' in navigator && ( window.location.protocol === 'https:' || window.location.hostname === 'localhost' || window.location.hostname.indexOf('127.') === 0 ); <% } %> } function install(options) { options || (options = {}); <% if (typeof ServiceWorker !== 'undefined') { %> if (hasSW()) { var registration = navigator.serviceWorker .register( <%- JSON.stringify(ServiceWorker.location) %>, { <% if (ServiceWorker.scope) { %> scope: <%- JSON.stringify(ServiceWorker.scope) %>, <% } %> <% if ( ServiceWorker.updateViaCache && ServiceWorker.updateViaCache !== 'imports' ) { %> updateViaCache: <%- JSON.stringify(ServiceWorker.updateViaCache) %>, <% } %> } ); <% if (ServiceWorker.events) { %> var handleUpdating = function(registration) { var sw = registration.installing || registration.waiting; var ignoreInstalling; var ignoreWaiting; // No SW or already handled if (!sw || sw.onstatechange) return; var stateChangeHandler; // Already has SW if (registration.active) { onUpdateStateChange(); stateChangeHandler = onUpdateStateChange; } else { onInstallStateChange(); stateChangeHandler = onInstallStateChange; } ignoreInstalling = true; if (registration.waiting) { ignoreWaiting = true; } sw.onstatechange = stateChangeHandler; function onUpdateStateChange() { switch (sw.state) { case 'redundant': { sendEvent('onUpdateFailed'); sw.onstatechange = null; } break; case 'installing': { if (!ignoreInstalling) { sendEvent('onUpdating'); } } break; case 'installed': { if (!ignoreWaiting) { sendEvent('onUpdateReady'); } } break; case 'activated': { sendEvent('onUpdated'); sw.onstatechange = null; } break; } } function onInstallStateChange() { switch (sw.state) { case 'redundant': { // Failed to install, ignore sw.onstatechange = null; } break; case 'installing': { // Installing, ignore } break; case 'installed': { // Installed, wait activation } break; case 'activated': { sendEvent('onInstalled'); sw.onstatechange = null; } break; } } }; var sendEvent = function(event) { if (typeof options[event] === 'function') { options[event]({ source: 'ServiceWorker' }); } }; registration.then(function(reg) { // WTF no reg? if (!reg) return; // Installed but Shift-Reloaded (page is not controller by SW), // update might be ready at this point (more than one tab opened). // Anyway, if page is hard-reloaded, then it probably already have latest version // but it's not controlled by SW yet. Applying update will claim this page // to be controlled by SW. Maybe set flag to not reload it? // if (!navigator.serviceWorker.controller) return; handleUpdating(reg); reg.onupdatefound = function() { handleUpdating(reg); }; }).catch(function(err) { sendEvent('onError'); return Promise.reject(err); }); <% } %> return; } <% } %> <% if (typeof AppCache !== 'undefined' && AppCache.disableInstall !== true) { %> if (window.applicationCache) { var directory = <%- JSON.stringify(AppCache.location) %>; var name = <%- JSON.stringify(AppCache.name) %>; var doLoad = function() { var page = directory + name + '.html'; var iframe = document.createElement('iframe'); <% if (AppCache.events) { %> window.addEventListener('message', function(e) { if (e.source !== iframe.contentWindow) return; var match = (e.data + '').match(/__offline-plugin_AppCacheEvent:(\w+)/); if (!match) return; var event = match[1]; if (typeof options[event] === 'function') { options[event]({ source: 'AppCache' }); } }); <% } %> iframe.src = page; iframe.style.display = 'none'; appCacheIframe = iframe; document.body.appendChild(iframe); }; if (document.readyState === 'complete') { setTimeout(doLoad); } else { window.addEventListener('load', doLoad); } return; } <% } %> } function applyUpdate(callback, errback) { <% if (typeof ServiceWorker !== 'undefined' && ServiceWorker.events) { %> if (hasSW()) { navigator.serviceWorker.getRegistration().then(function(registration) { if (!registration || !registration.waiting) { errback && errback(); return; } registration.waiting.postMessage({ action: 'skipWaiting' }); callback && callback(); }); return; } <% } %> <% if (typeof AppCache !== 'undefined' && AppCache.events && AppCache.disableInstall !== true) { %> if (appCacheIframe) { try { appCacheIframe.contentWindow.__applyUpdate(); callback && setTimeout(callback); } catch (e) { errback && setTimeout(errback); } } <% } %> } function update() { <% if (typeof ServiceWorker !== 'undefined') { %> if (hasSW()) { navigator.serviceWorker.getRegistration().then(function(registration) { if (!registration) return; return registration.update(); }); } <% } %> <% if (typeof AppCache !== 'undefined' && AppCache.disableInstall !== true) { %> if (appCacheIframe) { try { appCacheIframe.contentWindow.applicationCache.update(); } catch (e) {} } <% } %> } <% if (typeof autoUpdate !== 'undefined') { %> setInterval(update, <%- autoUpdate %>); <% } %> exports.install = install; exports.applyUpdate = applyUpdate; exports.update = update;