send/app/serviceWorker.js

93 lines
2.5 KiB
JavaScript
Raw Normal View History

2018-07-05 19:40:49 +00:00
import Keychain from './keychain';
2018-07-11 23:52:46 +00:00
import { downloadStream } from './api';
2018-07-17 18:40:01 +00:00
import { TStream as TransformStream, wrapReadable } from './streams';
2018-07-11 23:52:46 +00:00
let noSave = false;
const map = new Map();
2018-07-05 19:40:49 +00:00
2018-07-06 22:49:50 +00:00
self.addEventListener('install', event => {
2018-07-05 19:40:49 +00:00
self.skipWaiting();
});
2018-07-11 23:52:46 +00:00
self.addEventListener('activate', event => {
self.clients.claim();
});
2018-07-05 19:40:49 +00:00
async function decryptStream(request) {
2018-07-11 23:52:46 +00:00
const id = request.url.split('/')[5];
try {
const file = map.get(id);
2018-07-10 00:00:19 +00:00
2018-07-11 23:52:46 +00:00
file.download = downloadStream(id, file.keychain);
2018-07-05 19:40:49 +00:00
2018-07-11 23:52:46 +00:00
const stream = await file.download.result;
2018-07-05 19:40:49 +00:00
2018-07-11 23:52:46 +00:00
// eslint-disable-next-line no-undef
const progStream = new TransformStream({
transform: (chunk, controller) => {
file.progress += chunk.length;
controller.enqueue(chunk);
}
});
2018-07-09 22:39:06 +00:00
2018-07-17 18:40:01 +00:00
const readStream = wrapReadable(stream).pipeThrough(progStream);
2018-07-11 23:52:46 +00:00
const decrypted = file.keychain.decryptStream(readStream);
2018-07-09 22:39:06 +00:00
2018-07-11 23:52:46 +00:00
const headers = {
2018-07-12 22:32:07 +00:00
'Content-Disposition': 'attachment; filename=' + file.filename,
2018-07-13 18:13:09 +00:00
'Content-Type': file.type,
2018-07-12 22:32:07 +00:00
'Content-Length': file.size
2018-07-11 23:52:46 +00:00
};
2018-07-17 18:40:01 +00:00
const body = decrypted.isPony ? decrypted.toNative() : decrypted;
2018-07-14 00:05:19 +00:00
return new Response(body, { headers });
2018-07-11 23:52:46 +00:00
} catch (e) {
if (noSave) {
return new Response(null, { status: e.message });
2018-07-06 22:49:50 +00:00
}
2018-07-05 19:40:49 +00:00
2018-07-11 23:52:46 +00:00
const redirectRes = await fetch(`/download/${id}`);
return new Response(redirectRes.body, { status: 302 });
}
2018-07-05 19:40:49 +00:00
}
2018-07-06 22:49:50 +00:00
self.onfetch = event => {
2018-07-05 19:40:49 +00:00
const req = event.request.clone();
if (req.url.includes('/api/download')) {
event.respondWith(decryptStream(req));
}
};
2018-07-06 22:49:50 +00:00
self.onmessage = event => {
2018-07-11 23:52:46 +00:00
if (event.data.request === 'init') {
noSave = event.data.noSave;
const info = {
keychain: new Keychain(event.data.key),
filename: event.data.filename,
2018-07-13 18:13:09 +00:00
type: event.data.type,
2018-07-12 22:32:07 +00:00
size: event.data.size,
2018-07-11 23:52:46 +00:00
progress: 0,
cancelled: false
};
if (event.data.requiresPassword) {
info.keychain.setPassword(event.data.password, event.data.url);
}
map.set(event.data.id, info);
2018-07-10 00:00:19 +00:00
event.ports[0].postMessage('file info received');
2018-07-11 23:52:46 +00:00
} else if (event.data.request === 'progress') {
const file = map.get(event.data.id);
if (file.cancelled) {
2018-07-10 00:00:19 +00:00
event.ports[0].postMessage({ error: 'cancelled' });
2018-07-09 22:39:06 +00:00
} else {
2018-07-11 23:52:46 +00:00
event.ports[0].postMessage({ progress: file.progress });
2018-07-09 22:39:06 +00:00
}
2018-07-11 23:52:46 +00:00
} else if (event.data.request === 'cancel') {
const file = map.get(event.data.id);
file.cancelled = true;
if (file.download) {
file.download.cancel();
2018-07-09 22:39:06 +00:00
}
2018-07-10 00:00:19 +00:00
event.ports[0].postMessage('download cancelled');
2018-07-09 22:39:06 +00:00
}
2018-07-06 22:49:50 +00:00
};