Seditio Source
Root |
./othercms/xenForo 2.2.8/service_worker.js
"use strict";

// ################################## CONSTANTS #################################

var CACHE_NAME = 'xf-offline';
var CACHE_ROUTE = 'index.php?sw/cache.json';
var OFFLINE_ROUTE = 'index.php?sw/offline';

var supportPreloading = false;

// ############################### EVENT LISTENERS ##############################

self.addEventListener('install', function(event)
{
self.skipWaiting();

event.waitUntil(createCache());
});

self.addEventListener('activate', function(event)
{
self.clients.claim();

event.waitUntil(
new Promise(function(resolve)
{
if (self.registration.navigationPreload)
{
self.registration.navigationPreload[supportPreloading ? 'enable' : 'disable']();
}

resolve();
})
);
});

self.addEventListener('message', function(event)
{
var clientId = event.source.id;
var message = event.data;
if (typeof message !== 'object' || message === null)
{
console.error('Invalid message:', message);
return;
}

recieveMessage(clientId, message.type, message.payload);
});

self.addEventListener('fetch', function(event)
{
var request = event.request,
accept = request.headers.get('accept')

if (
request.mode !== 'navigate' ||
request.method !== 'GET' ||
(accept && !accept.includes('text/html'))
)
{
return;
}

// bypasses for: HTTP basic auth issues, file download issues (iOS), common ad blocker issues
if (request.url.match(/\/admin\.php|\/install\/|\/download($|&|\?)|[\/?]attachments\/|google-ad|adsense/))
{
if (supportPreloading && event.preloadResponse)
{
event.respondWith(event.preloadResponse);
}

return;
}

var response = Promise.resolve(event.preloadResponse)
.then(function(r)
{
return r || fetch(request)
});

event.respondWith(
response
.catch(function(error)
{
return caches.open(getCacheName())
.then(function(cache)
{
return cache.match(OFFLINE_ROUTE);
});
})
);
});

self.addEventListener('push', function(event)
{
if (!(self.Notification && self.Notification.permission === 'granted'))
{
return;
}

try
{
var data = event.data.json();
}
catch (e)
{
console.warn('Received push notification but payload not in the expected format.', e);
console.warn('Received data:', event.data.text());
return;
}

if (!data || !data.title || !data.body)
{
console.warn('Received push notification but no payload data or required fields missing.', data);
return;
}

data.last_count = 0;

var options = {
body: data.body,
dir: data.dir || 'ltr',
data: data
};
if (data.badge)
{
options.badge = data.badge;
}
if (data.icon)
{
options.icon = data.icon;
}

var notificationPromise;

if (data.tag && data.tag_phrase)
{
options.tag = data.tag;
options.renotify = true;

notificationPromise = self.registration.getNotifications({ tag: data.tag })
.then(function(notifications)
{
var lastKey = (notifications.length - 1),
notification = notifications[lastKey],
count = 0;

if (notification)
{
count = parseInt(notification.data.last_count, 10) + 1;
options.data.last_count = count;

options.body = options.body +  ' ' + data.tag_phrase.replace('{count}', count.toString());
}

return self.registration.showNotification(data.title, options);
});
}
else
{
notificationPromise = self.registration.showNotification(data.title, options);
}

event.waitUntil(notificationPromise);
});

self.addEventListener('notificationclick', function(event)
{
var notification = event.notification;

notification.close();

if (notification.data.url)
{
event.waitUntil(clients.openWindow(notification.data.url));
}
});

// ################################## MESSAGING #################################

function sendMessage(clientId, type, payload)
{
if (typeof type !== 'string' || type === '')
{
console.error('Invalid message type:', type);
return;
}

if (typeof payload === 'undefined')
{
payload = {};
}
else if (typeof payload !== 'object' || payload === null)
{
console.error('Invalid message payload:', payload);
return;
}

clients.get(clientId)
.then(function (client)
{
client.postMessage({
type: type,
payload: payload
});
})
.catch(function(error)
{
console.error('An error occurred while sending a message:', error);
});
}

var messageHandlers = {};

function recieveMessage(clientId, type, payload)
{
if (typeof type !== 'string' || type === '')
{
console.error('Invalid message type:', type);
return;
}

if (typeof payload !== 'object' || payload === null)
{
console.error('Invalid message payload:', payload);
return;
}

var handler = messageHandlers[type];
if (typeof handler === 'undefined')
{
console.error('No handler available for message type:', type);
return;
}

handler(clientId, payload);
}

// ################################### CACHING ##################################

function getCacheName()
{
var match = self.location.pathname.match(/^\/(.*)\/[^\/]+$/);
if (match && match[1].length)
{
var cacheModifier = match[1].replace(/[^a-zA-Z0-9_-]/g, '');
}
else
{
cacheModifier = '';
}

return CACHE_NAME + (cacheModifier.length ? '-' : '') + cacheModifier;
}

function createCache()
{
var cacheName = getCacheName();

return caches.delete(cacheName)
.then(function()
{
return caches.open(cacheName);
})
.then(function(cache)
{
return fetch(CACHE_ROUTE)
.then(function(response)
{
return response.json();
})
.then(function(response)
{
var key = response.key || null;
var files = response.files || [];
files.push(OFFLINE_ROUTE);

return cache.addAll(files)
.then(function()
{
return key;
});
});
})
.catch(function(error)
{
console.error('There was an error setting up the cache:', error);
});
}

function updateCacheKey(clientId, key)
{
sendMessage(clientId, 'updateCacheKey', { 'key': key });
}

messageHandlers.updateCache = function(clientId, payload)
{
createCache();
};