Merge branch 'vnext' of https://github.com/mozilla/send into ios-prototype-3
This commit is contained in:
commit
c13b63ec9c
|
@ -135,7 +135,7 @@ async function upload(stream, metadata, verifierB64, onprogress, canceller) {
|
||||||
const endpoint =
|
const endpoint =
|
||||||
window.location.protocol === 'file:'
|
window.location.protocol === 'file:'
|
||||||
? 'wss://send2.dev.lcip.org/api/ws'
|
? 'wss://send2.dev.lcip.org/api/ws'
|
||||||
: `${protocol}//${host}:${port}/api/ws`;
|
: `${protocol}//${host}${port ? ':' : ''}${port}/api/ws`;
|
||||||
|
|
||||||
const ws = await asyncInitWebSocket(endpoint);
|
const ws = await asyncInitWebSocket(endpoint);
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ function download(id, keychain, onprogress, canceller) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const auth = await keychain.authHeader();
|
const auth = await keychain.authHeader();
|
||||||
xhr.open('get', `/api/download/${id}`);
|
xhr.open('get', `/api/download/blob/${id}`);
|
||||||
xhr.setRequestHeader('Authorization', auth);
|
xhr.setRequestHeader('Authorization', auth);
|
||||||
xhr.responseType = 'blob';
|
xhr.responseType = 'blob';
|
||||||
xhr.send();
|
xhr.send();
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
async function checkCrypto() {
|
||||||
|
try {
|
||||||
|
const key = await crypto.subtle.generateKey(
|
||||||
|
{
|
||||||
|
name: 'AES-GCM',
|
||||||
|
length: 128
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
['encrypt', 'decrypt']
|
||||||
|
);
|
||||||
|
await crypto.subtle.exportKey('raw', key);
|
||||||
|
await crypto.subtle.encrypt(
|
||||||
|
{
|
||||||
|
name: 'AES-GCM',
|
||||||
|
iv: crypto.getRandomValues(new Uint8Array(12)),
|
||||||
|
tagLength: 128
|
||||||
|
},
|
||||||
|
key,
|
||||||
|
new ArrayBuffer(8)
|
||||||
|
);
|
||||||
|
await crypto.subtle.importKey(
|
||||||
|
'raw',
|
||||||
|
crypto.getRandomValues(new Uint8Array(16)),
|
||||||
|
'PBKDF2',
|
||||||
|
false,
|
||||||
|
['deriveKey']
|
||||||
|
);
|
||||||
|
await crypto.subtle.importKey(
|
||||||
|
'raw',
|
||||||
|
crypto.getRandomValues(new Uint8Array(16)),
|
||||||
|
'HKDF',
|
||||||
|
false,
|
||||||
|
['deriveKey']
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkStreams() {
|
||||||
|
try {
|
||||||
|
new ReadableStream({
|
||||||
|
pull() {}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function polyfillStreams() {
|
||||||
|
try {
|
||||||
|
require('@mattiasbuelens/web-streams-polyfill');
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function capabilities() {
|
||||||
|
const crypto = await checkCrypto();
|
||||||
|
const nativeStreams = checkStreams();
|
||||||
|
const polyStreams = nativeStreams ? false : polyfillStreams();
|
||||||
|
|
||||||
|
return {
|
||||||
|
crypto,
|
||||||
|
streamUpload: nativeStreams || polyStreams,
|
||||||
|
streamDownload:
|
||||||
|
nativeStreams &&
|
||||||
|
'serviceWorker' in navigator &&
|
||||||
|
!/safari/i.test(navigator.userAgent),
|
||||||
|
multifile: nativeStreams || polyStreams
|
||||||
|
};
|
||||||
|
}
|
|
@ -48,7 +48,7 @@ class ECETransformer {
|
||||||
name: 'AES-GCM',
|
name: 'AES-GCM',
|
||||||
length: 128
|
length: 128
|
||||||
},
|
},
|
||||||
false,
|
true, // Edge polyfill requires key to be extractable to encrypt :/
|
||||||
['encrypt', 'decrypt']
|
['encrypt', 'decrypt']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,9 @@ export default function(state, emitter) {
|
||||||
try {
|
try {
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
metrics.startedDownload({ size: file.size, ttl: file.ttl });
|
metrics.startedDownload({ size: file.size, ttl: file.ttl });
|
||||||
const dl = state.transfer.download();
|
const dl = state.transfer.download({
|
||||||
|
stream: state.capabilities.streamDownload
|
||||||
|
});
|
||||||
render();
|
render();
|
||||||
await dl;
|
await dl;
|
||||||
const time = Date.now() - start;
|
const time = Date.now() - start;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import Nanobus from 'nanobus';
|
import Nanobus from 'nanobus';
|
||||||
import Keychain from './keychain';
|
import Keychain from './keychain';
|
||||||
import { delay, bytes } from './utils';
|
import { delay, bytes } from './utils';
|
||||||
import { metadata } from './api';
|
import { downloadFile, metadata } from './api';
|
||||||
|
import { blobStream } from './streams';
|
||||||
|
import Zip from './zip';
|
||||||
|
|
||||||
export default class FileReceiver extends Nanobus {
|
export default class FileReceiver extends Nanobus {
|
||||||
constructor(fileInfo) {
|
constructor(fileInfo) {
|
||||||
|
@ -52,22 +54,6 @@ export default class FileReceiver extends Nanobus {
|
||||||
this.state = 'ready';
|
this.state = 'ready';
|
||||||
}
|
}
|
||||||
|
|
||||||
async streamToArrayBuffer(stream, streamSize, onprogress) {
|
|
||||||
const result = new Uint8Array(streamSize);
|
|
||||||
let offset = 0;
|
|
||||||
const reader = stream.getReader();
|
|
||||||
let state = await reader.read();
|
|
||||||
while (!state.done) {
|
|
||||||
result.set(state.value, offset);
|
|
||||||
offset += state.value.length;
|
|
||||||
state = await reader.read();
|
|
||||||
onprogress([offset, streamSize]);
|
|
||||||
}
|
|
||||||
|
|
||||||
onprogress([streamSize, streamSize]);
|
|
||||||
return result.slice(0, offset).buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendMessageToSw(msg) {
|
sendMessageToSw(msg) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const channel = new MessageChannel();
|
const channel = new MessageChannel();
|
||||||
|
@ -86,7 +72,46 @@ export default class FileReceiver extends Nanobus {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async download(noSave = false) {
|
async downloadBlob(noSave = false) {
|
||||||
|
this.state = 'downloading';
|
||||||
|
this.downloadRequest = await downloadFile(
|
||||||
|
this.fileInfo.id,
|
||||||
|
this.keychain,
|
||||||
|
p => {
|
||||||
|
this.progress = p;
|
||||||
|
this.emit('progress');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
const ciphertext = await this.downloadRequest.result;
|
||||||
|
this.downloadRequest = null;
|
||||||
|
this.msg = 'decryptingFile';
|
||||||
|
this.state = 'decrypting';
|
||||||
|
this.emit('decrypting');
|
||||||
|
let size = this.fileInfo.size;
|
||||||
|
let plainStream = this.keychain.decryptStream(blobStream(ciphertext));
|
||||||
|
if (this.fileInfo.type === 'send-archive') {
|
||||||
|
const zip = new Zip(this.fileInfo.manifest, plainStream);
|
||||||
|
plainStream = zip.stream;
|
||||||
|
size = zip.size;
|
||||||
|
}
|
||||||
|
const plaintext = await streamToArrayBuffer(plainStream, size);
|
||||||
|
if (!noSave) {
|
||||||
|
await saveFile({
|
||||||
|
plaintext,
|
||||||
|
name: decodeURIComponent(this.fileInfo.name),
|
||||||
|
type: this.fileInfo.type
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.msg = 'downloadFinish';
|
||||||
|
this.state = 'complete';
|
||||||
|
} catch (e) {
|
||||||
|
this.downloadRequest = null;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async downloadStream(noSave = false) {
|
||||||
const onprogress = p => {
|
const onprogress = p => {
|
||||||
this.progress = p;
|
this.progress = p;
|
||||||
this.emit('progress');
|
this.emit('progress');
|
||||||
|
@ -156,4 +181,64 @@ export default class FileReceiver extends Nanobus {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
download(options) {
|
||||||
|
if (options.stream) {
|
||||||
|
return this.downloadStream(options.noSave);
|
||||||
|
}
|
||||||
|
return this.downloadBlob(options.noSave);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function streamToArrayBuffer(stream, size) {
|
||||||
|
const result = new Uint8Array(size);
|
||||||
|
let offset = 0;
|
||||||
|
const reader = stream.getReader();
|
||||||
|
let state = await reader.read();
|
||||||
|
while (!state.done) {
|
||||||
|
result.set(state.value, offset);
|
||||||
|
offset += state.value.length;
|
||||||
|
state = await reader.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveFile(file) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
const dataView = new DataView(file.plaintext);
|
||||||
|
const blob = new Blob([dataView], { type: file.type });
|
||||||
|
|
||||||
|
if (navigator.msSaveBlob) {
|
||||||
|
navigator.msSaveBlob(blob, file.name);
|
||||||
|
return resolve();
|
||||||
|
} else if (/iPhone|fxios/i.test(navigator.userAgent)) {
|
||||||
|
// This method is much slower but createObjectURL
|
||||||
|
// is buggy on iOS
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.addEventListener('loadend', function() {
|
||||||
|
if (reader.error) {
|
||||||
|
return reject(reader.error);
|
||||||
|
}
|
||||||
|
if (reader.result) {
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = reader.result;
|
||||||
|
a.download = file.name;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
|
} else {
|
||||||
|
const downloadUrl = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = downloadUrl;
|
||||||
|
a.download = file.name;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(downloadUrl);
|
||||||
|
setTimeout(resolve, 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
20
app/main.js
20
app/main.js
|
@ -1,29 +1,33 @@
|
||||||
import 'fast-text-encoding'; // MS Edge support
|
import 'fast-text-encoding'; // MS Edge support
|
||||||
import 'fluent-intl-polyfill';
|
import 'fluent-intl-polyfill';
|
||||||
import app from './routes';
|
import app from './routes';
|
||||||
|
import capabilities from './capabilities';
|
||||||
import locale from '../common/locales';
|
import locale from '../common/locales';
|
||||||
import fileManager from './fileManager';
|
import fileManager from './fileManager';
|
||||||
import dragManager from './dragManager';
|
import dragManager from './dragManager';
|
||||||
import pasteManager from './pasteManager';
|
import pasteManager from './pasteManager';
|
||||||
import { canHasSend } from './utils';
|
|
||||||
import storage from './storage';
|
import storage from './storage';
|
||||||
import metrics from './metrics';
|
import metrics from './metrics';
|
||||||
import experiments from './experiments';
|
import experiments from './experiments';
|
||||||
import Raven from 'raven-js';
|
import Raven from 'raven-js';
|
||||||
import './main.css';
|
import './main.css';
|
||||||
|
|
||||||
|
(async function start() {
|
||||||
if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) {
|
if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) {
|
||||||
Raven.config(window.SENTRY_ID, window.RAVEN_CONFIG).install();
|
Raven.config(window.SENTRY_ID, window.RAVEN_CONFIG).install();
|
||||||
}
|
}
|
||||||
|
const capa = await capabilities();
|
||||||
|
if (capa.streamDownload) {
|
||||||
|
navigator.serviceWorker.register('/serviceWorker.js');
|
||||||
|
}
|
||||||
app.use((state, emitter) => {
|
app.use((state, emitter) => {
|
||||||
|
state.capabilities = capa;
|
||||||
state.transfer = null;
|
state.transfer = null;
|
||||||
state.fileInfo = null;
|
state.fileInfo = null;
|
||||||
state.translate = locale.getTranslator();
|
state.translate = locale.getTranslator();
|
||||||
state.storage = storage;
|
state.storage = storage;
|
||||||
state.raven = Raven;
|
state.raven = Raven;
|
||||||
window.appState = state;
|
window.appState = state;
|
||||||
emitter.on('DOMContentLoaded', async function checkSupport() {
|
|
||||||
let unsupportedReason = null;
|
let unsupportedReason = null;
|
||||||
if (
|
if (
|
||||||
// Firefox < 50
|
// Firefox < 50
|
||||||
|
@ -32,8 +36,7 @@ app.use((state, emitter) => {
|
||||||
) {
|
) {
|
||||||
unsupportedReason = 'outdated';
|
unsupportedReason = 'outdated';
|
||||||
}
|
}
|
||||||
const ok = await canHasSend();
|
if (!state.capabilities.crypto) {
|
||||||
if (!ok) {
|
|
||||||
unsupportedReason = /firefox/i.test(navigator.userAgent)
|
unsupportedReason = /firefox/i.test(navigator.userAgent)
|
||||||
? 'outdated'
|
? 'outdated'
|
||||||
: 'gcm';
|
: 'gcm';
|
||||||
|
@ -44,15 +47,10 @@ app.use((state, emitter) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
app.use(() => {
|
|
||||||
navigator.serviceWorker.register('/serviceWorker.js');
|
|
||||||
});
|
|
||||||
app.use(metrics);
|
app.use(metrics);
|
||||||
app.use(fileManager);
|
app.use(fileManager);
|
||||||
app.use(dragManager);
|
app.use(dragManager);
|
||||||
app.use(experiments);
|
app.use(experiments);
|
||||||
app.use(pasteManager);
|
app.use(pasteManager);
|
||||||
|
|
||||||
app.mount('body');
|
app.mount('body');
|
||||||
|
})();
|
||||||
|
|
|
@ -75,7 +75,7 @@ async function decryptStream(id) {
|
||||||
|
|
||||||
self.onfetch = event => {
|
self.onfetch = event => {
|
||||||
const req = event.request;
|
const req = event.request;
|
||||||
if (req.url.includes('/api/download')) {
|
if (/\/api\/download\/[A-Fa-f0-9]{4,}/.test(req.url)) {
|
||||||
const id = req.url.split('/')[5];
|
const id = req.url.split('/')[5];
|
||||||
event.respondWith(decryptStream(id));
|
event.respondWith(decryptStream(id));
|
||||||
}
|
}
|
||||||
|
|
41
app/utils.js
41
app/utils.js
|
@ -22,46 +22,6 @@ function loadShim(polyfill) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function canHasSend() {
|
|
||||||
try {
|
|
||||||
const key = await crypto.subtle.generateKey(
|
|
||||||
{
|
|
||||||
name: 'AES-GCM',
|
|
||||||
length: 128
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
['encrypt', 'decrypt']
|
|
||||||
);
|
|
||||||
await crypto.subtle.encrypt(
|
|
||||||
{
|
|
||||||
name: 'AES-GCM',
|
|
||||||
iv: crypto.getRandomValues(new Uint8Array(12)),
|
|
||||||
tagLength: 128
|
|
||||||
},
|
|
||||||
key,
|
|
||||||
new ArrayBuffer(8)
|
|
||||||
);
|
|
||||||
await crypto.subtle.importKey(
|
|
||||||
'raw',
|
|
||||||
crypto.getRandomValues(new Uint8Array(16)),
|
|
||||||
'PBKDF2',
|
|
||||||
false,
|
|
||||||
['deriveKey']
|
|
||||||
);
|
|
||||||
await crypto.subtle.importKey(
|
|
||||||
'raw',
|
|
||||||
crypto.getRandomValues(new Uint8Array(16)),
|
|
||||||
'HKDF',
|
|
||||||
false,
|
|
||||||
['deriveKey']
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isFile(id) {
|
function isFile(id) {
|
||||||
return /^[0-9a-fA-F]{10}$/.test(id);
|
return /^[0-9a-fA-F]{10}$/.test(id);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +139,6 @@ module.exports = {
|
||||||
arrayToB64,
|
arrayToB64,
|
||||||
b64ToArray,
|
b64ToArray,
|
||||||
loadShim,
|
loadShim,
|
||||||
canHasSend,
|
|
||||||
isFile,
|
isFile,
|
||||||
openLinksInNewTab
|
openLinksInNewTab
|
||||||
};
|
};
|
||||||
|
|
|
@ -88,6 +88,15 @@
|
||||||
"integrity": "sha1-9vGlzl05caSt6RoR0i1MRZrNN18=",
|
"integrity": "sha1-9vGlzl05caSt6RoR0i1MRZrNN18=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@mattiasbuelens/web-streams-polyfill": {
|
||||||
|
"version": "0.1.0-alpha.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mattiasbuelens/web-streams-polyfill/-/web-streams-polyfill-0.1.0-alpha.5.tgz",
|
||||||
|
"integrity": "sha512-KduiboN8xXQT+XAe76935VriUy62Yv/1EyTE43xmP+GEtPKpyUklKvYaXPq1fZpibMgXIIi/B2Qx0dReam5RKQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/whatwg-streams": "0.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@mrmlnc/readdir-enhanced": {
|
"@mrmlnc/readdir-enhanced": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
||||||
|
@ -122,6 +131,12 @@
|
||||||
"samsam": "1.3.0"
|
"samsam": "1.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/whatwg-streams": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/whatwg-streams/-/whatwg-streams-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-O4Hat94N1RUCObqAbVUtd6EcucseqBcpfbFXzy12CYF6BQVHWR+ztDA3YPjewCmdKHYZ5VA7TZ5hq2bMyqxiBw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@webassemblyjs/ast": {
|
"@webassemblyjs/ast": {
|
||||||
"version": "1.5.13",
|
"version": "1.5.13",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.13.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.13.tgz",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@dannycoates/webpack-dev-server": "^3.1.4",
|
"@dannycoates/webpack-dev-server": "^3.1.4",
|
||||||
|
"@mattiasbuelens/web-streams-polyfill": "0.1.0-alpha.5",
|
||||||
"asmcrypto.js": "^0.22.0",
|
"asmcrypto.js": "^0.22.0",
|
||||||
"babel-core": "^6.26.3",
|
"babel-core": "^6.26.3",
|
||||||
"babel-loader": "^7.1.4",
|
"babel-loader": "^7.1.4",
|
||||||
|
|
|
@ -57,6 +57,7 @@ module.exports = function(app) {
|
||||||
app.get('/completed', language, pages.blank);
|
app.get('/completed', language, pages.blank);
|
||||||
app.get('/unsupported/:reason', language, pages.unsupported);
|
app.get('/unsupported/:reason', language, pages.unsupported);
|
||||||
app.get(`/api/download/:id${ID_REGEX}`, auth, require('./download'));
|
app.get(`/api/download/:id${ID_REGEX}`, auth, require('./download'));
|
||||||
|
app.get(`/api/download/blob/:id${ID_REGEX}`, auth, require('./download'));
|
||||||
app.get(`/api/exists/:id${ID_REGEX}`, require('./exists'));
|
app.get(`/api/exists/:id${ID_REGEX}`, require('./exists'));
|
||||||
app.get(`/api/metadata/:id${ID_REGEX}`, auth, require('./metadata'));
|
app.get(`/api/metadata/:id${ID_REGEX}`, auth, require('./metadata'));
|
||||||
app.post('/api/upload', require('./upload'));
|
app.post('/api/upload', require('./upload'));
|
||||||
|
|
|
@ -7,7 +7,7 @@ const headless = /Headless/.test(navigator.userAgent);
|
||||||
// TODO: save on headless doesn't work as it used to since it now
|
// TODO: save on headless doesn't work as it used to since it now
|
||||||
// follows a link instead of fetch. Maybe there's a way to make it
|
// follows a link instead of fetch. Maybe there's a way to make it
|
||||||
// work? For now always set noSave.
|
// work? For now always set noSave.
|
||||||
const noSave = true || !headless; // only run the saveFile code if headless
|
const options = { noSave: true || !headless, stream: true }; // only run the saveFile code if headless
|
||||||
|
|
||||||
// FileSender uses a File in real life but a Blob works for testing
|
// FileSender uses a File in real life but a Blob works for testing
|
||||||
const blob = new Blob([new ArrayBuffer(1024 * 128)], { type: 'text/plain' });
|
const blob = new Blob([new ArrayBuffer(1024 * 128)], { type: 'text/plain' });
|
||||||
|
@ -27,10 +27,10 @@ describe('Upload / Download flow', function() {
|
||||||
requiresPassword: false
|
requiresPassword: false
|
||||||
});
|
});
|
||||||
await fr.getMetadata();
|
await fr.getMetadata();
|
||||||
await fr.download(noSave);
|
await fr.download(options);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fr.download(noSave);
|
await fr.download(options);
|
||||||
assert.fail('downloaded again');
|
assert.fail('downloaded again');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
assert.equal(e.message, '404');
|
assert.equal(e.message, '404');
|
||||||
|
@ -50,7 +50,7 @@ describe('Upload / Download flow', function() {
|
||||||
password: 'magic'
|
password: 'magic'
|
||||||
});
|
});
|
||||||
await fr.getMetadata();
|
await fr.getMetadata();
|
||||||
await fr.download(noSave);
|
await fr.download(options);
|
||||||
assert.equal(fr.state, 'complete');
|
assert.equal(fr.state, 'complete');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ describe('Upload / Download flow', function() {
|
||||||
try {
|
try {
|
||||||
// We can't decrypt without IV from metadata
|
// We can't decrypt without IV from metadata
|
||||||
// but let's try to download anyway
|
// but let's try to download anyway
|
||||||
await fr.download(noSave);
|
await fr.download(options);
|
||||||
assert.fail('downloaded file with bad password');
|
assert.fail('downloaded file with bad password');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
assert.equal(e.message, '401');
|
assert.equal(e.message, '401');
|
||||||
|
@ -135,7 +135,7 @@ describe('Upload / Download flow', function() {
|
||||||
await fr.getMetadata();
|
await fr.getMetadata();
|
||||||
fr.once('progress', () => fr.cancel());
|
fr.once('progress', () => fr.cancel());
|
||||||
try {
|
try {
|
||||||
await fr.download(noSave);
|
await fr.download(options);
|
||||||
assert.fail('not cancelled');
|
assert.fail('not cancelled');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
assert.equal(e.message, '0');
|
assert.equal(e.message, '0');
|
||||||
|
@ -153,7 +153,7 @@ describe('Upload / Download flow', function() {
|
||||||
requiresPassword: false
|
requiresPassword: false
|
||||||
});
|
});
|
||||||
await fr.getMetadata();
|
await fr.getMetadata();
|
||||||
await fr.download(noSave);
|
await fr.download(options);
|
||||||
await file.updateDownloadCount();
|
await file.updateDownloadCount();
|
||||||
assert.equal(file.dtotal, 1);
|
assert.equal(file.dtotal, 1);
|
||||||
});
|
});
|
||||||
|
@ -171,7 +171,7 @@ describe('Upload / Download flow', function() {
|
||||||
fr.once('progress', () => fr.cancel());
|
fr.once('progress', () => fr.cancel());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fr.download(noSave);
|
await fr.download(options);
|
||||||
assert.fail('not cancelled');
|
assert.fail('not cancelled');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await file.updateDownloadCount();
|
await file.updateDownloadCount();
|
||||||
|
@ -190,15 +190,15 @@ describe('Upload / Download flow', function() {
|
||||||
});
|
});
|
||||||
await file.changeLimit(2);
|
await file.changeLimit(2);
|
||||||
await fr.getMetadata();
|
await fr.getMetadata();
|
||||||
await fr.download(noSave);
|
await fr.download(options);
|
||||||
await file.updateDownloadCount();
|
await file.updateDownloadCount();
|
||||||
assert.equal(file.dtotal, 1);
|
assert.equal(file.dtotal, 1);
|
||||||
|
|
||||||
await fr.download(noSave);
|
await fr.download(options);
|
||||||
await file.updateDownloadCount();
|
await file.updateDownloadCount();
|
||||||
assert.equal(file.dtotal, 2);
|
assert.equal(file.dtotal, 2);
|
||||||
try {
|
try {
|
||||||
await fr.download(noSave);
|
await fr.download(options);
|
||||||
assert.fail('downloaded too many times');
|
assert.fail('downloaded too many times');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
assert.equal(e.message, '404');
|
assert.equal(e.message, '404');
|
||||||
|
|
|
@ -89,6 +89,7 @@ const web = {
|
||||||
{
|
{
|
||||||
// Strip asserts from our deps, mainly choojs family
|
// Strip asserts from our deps, mainly choojs family
|
||||||
include: [path.resolve(__dirname, 'node_modules')],
|
include: [path.resolve(__dirname, 'node_modules')],
|
||||||
|
exclude: [path.resolve(__dirname, 'node_modules/crc')],
|
||||||
loader: 'webpack-unassert-loader'
|
loader: 'webpack-unassert-loader'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue