use async and removed jquery from download.js
This commit is contained in:
parent
24917f8aa5
commit
c6a4b089d9
|
@ -5,26 +5,29 @@ import Storage from './storage';
|
||||||
import * as links from './links';
|
import * as links from './links';
|
||||||
import * as metrics from './metrics';
|
import * as metrics from './metrics';
|
||||||
import * as progress from './progress';
|
import * as progress from './progress';
|
||||||
import $ from 'jquery/dist/jquery.slim';
|
|
||||||
|
|
||||||
const storage = new Storage();
|
const storage = new Storage();
|
||||||
function onUnload(size) {
|
function onUnload(size) {
|
||||||
metrics.cancelledDownload({ size });
|
metrics.cancelledDownload({ size });
|
||||||
}
|
}
|
||||||
|
|
||||||
function download() {
|
async function download() {
|
||||||
const $downloadBtn = $('#download-btn');
|
const downloadBtn = document.getElementById('download-btn');
|
||||||
const $title = $('.title');
|
const downloadPanel = document.getElementById('download-page-one');
|
||||||
const $file = $('#dl-file');
|
const progressPanel = document.getElementById('download-progress');
|
||||||
const size = Number($file.attr('data-size'));
|
const file = document.getElementById('dl-file');
|
||||||
const ttl = Number($file.attr('data-ttl'));
|
const size = Number(file.getAttribute('data-size'));
|
||||||
|
const ttl = Number(file.getAttribute('data-ttl'));
|
||||||
const unloadHandler = onUnload.bind(null, size);
|
const unloadHandler = onUnload.bind(null, size);
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const fileReceiver = new FileReceiver();
|
const fileReceiver = new FileReceiver(
|
||||||
|
'/assets' + location.pathname.slice(0, -1),
|
||||||
|
location.hash.slice(1)
|
||||||
|
);
|
||||||
|
|
||||||
$downloadBtn.attr('disabled', 'disabled');
|
downloadBtn.disabled = true;
|
||||||
$('#download-page-one').attr('hidden', true);
|
downloadPanel.hidden = true;
|
||||||
$('#download-progress').removeAttr('hidden');
|
progressPanel.hidden = false;
|
||||||
metrics.startedDownload({ size, ttl });
|
metrics.startedDownload({ size, ttl });
|
||||||
links.setOpenInNewTab(true);
|
links.setOpenInNewTab(true);
|
||||||
window.addEventListener('unload', unloadHandler);
|
window.addEventListener('unload', unloadHandler);
|
||||||
|
@ -41,28 +44,14 @@ function download() {
|
||||||
document.l10n.formatValue('decryptingFile').then(progress.setText);
|
document.l10n.formatValue('decryptingFile').then(progress.setText);
|
||||||
});
|
});
|
||||||
|
|
||||||
fileReceiver
|
try {
|
||||||
.download()
|
const file = await fileReceiver.download();
|
||||||
.catch(err => {
|
|
||||||
metrics.stoppedDownload({ size, err });
|
|
||||||
|
|
||||||
if (err.message === 'notfound') {
|
|
||||||
location.reload();
|
|
||||||
} else {
|
|
||||||
document.l10n.formatValue('errorPageHeader').then(translated => {
|
|
||||||
$title.text(translated);
|
|
||||||
});
|
|
||||||
$downloadBtn.attr('hidden', true);
|
|
||||||
$('#expired-img').removeAttr('hidden');
|
|
||||||
}
|
|
||||||
throw err;
|
|
||||||
})
|
|
||||||
.then(([decrypted, file]) => {
|
|
||||||
const fname = file.name;
|
|
||||||
const endTime = Date.now();
|
const endTime = Date.now();
|
||||||
const time = endTime - startTime;
|
const time = endTime - startTime;
|
||||||
const downloadTime = endTime - downloadEnd;
|
const downloadTime = endTime - downloadEnd;
|
||||||
const speed = size / (downloadTime / 1000);
|
const speed = size / (downloadTime / 1000);
|
||||||
|
|
||||||
|
links.setOpenInNewTab(false);
|
||||||
storage.totalDownloads += 1;
|
storage.totalDownloads += 1;
|
||||||
metrics.completedDownload({ size, time, speed });
|
metrics.completedDownload({ size, time, speed });
|
||||||
progress.setText(' ');
|
progress.setText(' ');
|
||||||
|
@ -70,47 +59,57 @@ function download() {
|
||||||
.formatValues('downloadNotification', 'downloadFinish')
|
.formatValues('downloadNotification', 'downloadFinish')
|
||||||
.then(translated => {
|
.then(translated => {
|
||||||
notify(translated[0]);
|
notify(translated[0]);
|
||||||
$title.text(translated[1]);
|
document.getElementById('dl-title').textContent = translated[1];
|
||||||
|
document.querySelector('#download-progress .description').textContent =
|
||||||
|
' ';
|
||||||
});
|
});
|
||||||
|
const dataView = new DataView(file.plaintext);
|
||||||
const dataView = new DataView(decrypted);
|
|
||||||
const blob = new Blob([dataView], { type: file.type });
|
const blob = new Blob([dataView], { type: file.type });
|
||||||
const downloadUrl = URL.createObjectURL(blob);
|
const downloadUrl = URL.createObjectURL(blob);
|
||||||
|
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.href = downloadUrl;
|
a.href = downloadUrl;
|
||||||
if (window.navigator.msSaveBlob) {
|
if (window.navigator.msSaveBlob) {
|
||||||
// if we are in microsoft edge or IE
|
window.navigator.msSaveBlob(blob, file.name);
|
||||||
window.navigator.msSaveBlob(blob, fname);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
a.download = fname;
|
a.download = file.name;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
URL.revokeObjectURL(downloadUrl);
|
URL.revokeObjectURL(downloadUrl);
|
||||||
})
|
} catch (err) {
|
||||||
.catch(err => {
|
metrics.stoppedDownload({ size, err });
|
||||||
|
|
||||||
|
if (err.message === 'notfound') {
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
progressPanel.hidden = true;
|
||||||
|
downloadPanel.hidden = true;
|
||||||
|
document.getElementById('upload-error').hidden = false;
|
||||||
|
}
|
||||||
Raven.captureException(err);
|
Raven.captureException(err);
|
||||||
return Promise.reject(err);
|
}
|
||||||
})
|
|
||||||
.then(() => links.setOpenInNewTab(false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$(() => {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const $file = $('#dl-file');
|
const file = document.getElementById('dl-file');
|
||||||
const filename = $file.attr('data-filename');
|
const filename = file.getAttribute('data-filename');
|
||||||
const b = Number($file.attr('data-size'));
|
const b = Number(file.getAttribute('data-size'));
|
||||||
const size = bytes(b);
|
const size = bytes(b);
|
||||||
document.l10n
|
document.l10n.formatValue('downloadFileSize', { size }).then(str => {
|
||||||
.formatValue('downloadFileSize', { size })
|
document.getElementById('dl-filesize').textContent = str;
|
||||||
.then(str => $('#dl-filesize').text(str));
|
});
|
||||||
document.l10n
|
document.l10n
|
||||||
.formatValue('downloadingPageProgress', { filename, size })
|
.formatValue('downloadingPageProgress', { filename, size })
|
||||||
.then(str => $('#dl-title').text(str));
|
.then(str => {
|
||||||
|
document.getElementById('dl-title').textContent = str;
|
||||||
|
});
|
||||||
|
|
||||||
gcmCompliant()
|
gcmCompliant()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
$('#download-btn').on('click', download);
|
document
|
||||||
|
.getElementById('download-btn')
|
||||||
|
.addEventListener('click', download);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
metrics.unsupported({ err }).then(() => {
|
metrics.unsupported({ err }).then(() => {
|
||||||
|
|
|
@ -2,27 +2,26 @@ import EventEmitter from 'events';
|
||||||
import { hexToArray } from './utils';
|
import { hexToArray } from './utils';
|
||||||
|
|
||||||
export default class FileReceiver extends EventEmitter {
|
export default class FileReceiver extends EventEmitter {
|
||||||
constructor() {
|
constructor(url, k) {
|
||||||
super();
|
super();
|
||||||
}
|
this.key = window.crypto.subtle.importKey(
|
||||||
|
|
||||||
download() {
|
|
||||||
return window.crypto.subtle
|
|
||||||
.importKey(
|
|
||||||
'jwk',
|
'jwk',
|
||||||
{
|
{
|
||||||
|
k,
|
||||||
kty: 'oct',
|
kty: 'oct',
|
||||||
k: location.hash.slice(1),
|
|
||||||
alg: 'A128GCM',
|
alg: 'A128GCM',
|
||||||
ext: true
|
ext: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AES-GCM'
|
name: 'AES-GCM'
|
||||||
},
|
},
|
||||||
true,
|
false,
|
||||||
['encrypt', 'decrypt']
|
['decrypt']
|
||||||
)
|
);
|
||||||
.then(key => {
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadFile() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
@ -43,46 +42,40 @@ export default class FileReceiver extends EventEmitter {
|
||||||
const meta = JSON.parse(xhr.getResponseHeader('X-File-Metadata'));
|
const meta = JSON.parse(xhr.getResponseHeader('X-File-Metadata'));
|
||||||
const fileReader = new FileReader();
|
const fileReader = new FileReader();
|
||||||
fileReader.onload = function() {
|
fileReader.onload = function() {
|
||||||
resolve([
|
resolve({
|
||||||
{
|
|
||||||
data: this.result,
|
data: this.result,
|
||||||
filename: meta.filename,
|
name: meta.filename,
|
||||||
type,
|
type,
|
||||||
iv: meta.id
|
iv: meta.id
|
||||||
},
|
});
|
||||||
key
|
|
||||||
]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fileReader.readAsArrayBuffer(blob);
|
fileReader.readAsArrayBuffer(blob);
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.open('get', '/assets' + location.pathname.slice(0, -1), true);
|
xhr.open('get', this.url);
|
||||||
xhr.responseType = 'blob';
|
xhr.responseType = 'blob';
|
||||||
xhr.send();
|
xhr.send();
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
.then(([fdata, key]) => {
|
|
||||||
|
async download() {
|
||||||
|
const key = await this.key;
|
||||||
|
const file = await this.downloadFile();
|
||||||
this.emit('decrypting');
|
this.emit('decrypting');
|
||||||
return Promise.all([
|
const plaintext = await window.crypto.subtle.decrypt(
|
||||||
window.crypto.subtle
|
|
||||||
.decrypt(
|
|
||||||
{
|
{
|
||||||
name: 'AES-GCM',
|
name: 'AES-GCM',
|
||||||
iv: hexToArray(fdata.iv),
|
iv: hexToArray(file.iv),
|
||||||
tagLength: 128
|
tagLength: 128
|
||||||
},
|
},
|
||||||
key,
|
key,
|
||||||
fdata.data
|
file.data
|
||||||
)
|
);
|
||||||
.then(decrypted => {
|
return {
|
||||||
return Promise.resolve(decrypted);
|
plaintext,
|
||||||
}),
|
name: decodeURIComponent(file.name),
|
||||||
{
|
type: file.type
|
||||||
name: decodeURIComponent(fdata.filename),
|
};
|
||||||
type: fdata.type
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,5 +35,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="upload-error" hidden="true">
|
||||||
|
<div class="title" data-l10n-id="errorPageHeader"></div>
|
||||||
|
<img id="upload-error-img" data-l10n-id="errorAltText" src="/resources/illustration_error.svg"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a class="send-new" data-state="completed" data-l10n-id="sendYourFilesLink" href="/"></a>
|
<a class="send-new" data-state="completed" data-l10n-id="sendYourFilesLink" href="/"></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue