extracted blobSlicer, fixed download cancel tests
This commit is contained in:
parent
5483dc2506
commit
5e9e63944b
|
@ -0,0 +1,27 @@
|
||||||
|
export default class BlobSlicer {
|
||||||
|
constructor(blob, size) {
|
||||||
|
this.blob = blob;
|
||||||
|
this.index = 0;
|
||||||
|
this.chunkSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
pull(controller) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const bytesLeft = this.blob.size - this.index;
|
||||||
|
if (bytesLeft <= 0) {
|
||||||
|
controller.close();
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
const size = Math.min(this.chunkSize, bytesLeft);
|
||||||
|
const blob = this.blob.slice(this.index, this.index + size);
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = () => {
|
||||||
|
controller.enqueue(new Uint8Array(reader.result));
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
reader.onerror = reject;
|
||||||
|
reader.readAsArrayBuffer(blob);
|
||||||
|
this.index += size;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
37
app/ece.js
37
app/ece.js
|
@ -1,4 +1,5 @@
|
||||||
import 'buffer';
|
import 'buffer';
|
||||||
|
import BlobSlicer from './blobSlicer';
|
||||||
import { transformStream } from './streams';
|
import { transformStream } from './streams';
|
||||||
|
|
||||||
const NONCE_LENGTH = 12;
|
const NONCE_LENGTH = 12;
|
||||||
|
@ -225,40 +226,6 @@ class ECETransformer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BlobSlicer {
|
|
||||||
constructor(blob, rs, mode) {
|
|
||||||
this.blob = blob;
|
|
||||||
this.index = 0;
|
|
||||||
this.mode = mode;
|
|
||||||
this.chunkSize = mode === MODE_ENCRYPT ? rs - 17 : rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
pull(controller) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const bytesLeft = this.blob.size - this.index;
|
|
||||||
if (bytesLeft <= 0) {
|
|
||||||
controller.close();
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
let size = 1;
|
|
||||||
if (this.mode === MODE_DECRYPT && this.index === 0) {
|
|
||||||
size = Math.min(21, bytesLeft);
|
|
||||||
} else {
|
|
||||||
size = Math.min(this.chunkSize, bytesLeft);
|
|
||||||
}
|
|
||||||
const blob = this.blob.slice(this.index, this.index + size);
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = () => {
|
|
||||||
controller.enqueue(new Uint8Array(reader.result));
|
|
||||||
resolve();
|
|
||||||
};
|
|
||||||
reader.onerror = reject;
|
|
||||||
reader.readAsArrayBuffer(blob);
|
|
||||||
this.index += size;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StreamSlicer {
|
class StreamSlicer {
|
||||||
constructor(rs, mode) {
|
constructor(rs, mode) {
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
@ -350,7 +317,7 @@ export default class ECE {
|
||||||
|
|
||||||
if (this.input instanceof Blob) {
|
if (this.input instanceof Blob) {
|
||||||
inputStream = new ReadableStream(
|
inputStream = new ReadableStream(
|
||||||
new BlobSlicer(this.input, this.rs, this.mode)
|
new BlobSlicer(this.input, this.rs - 17)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
inputStream = transformStream(
|
inputStream = transformStream(
|
||||||
|
|
|
@ -148,7 +148,7 @@ export default class FileReceiver extends Nanobus {
|
||||||
this.state = 'complete';
|
this.state = 'complete';
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.downloadRequest = null;
|
this.downloadRequest = null;
|
||||||
if (e === 'cancelled') {
|
if (e === 'cancelled' || e.message === '400') {
|
||||||
throw new Error(0);
|
throw new Error(0);
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -15,8 +15,11 @@ self.addEventListener('activate', event => {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function decryptStream(id) {
|
async function decryptStream(id) {
|
||||||
try {
|
|
||||||
const file = map.get(id);
|
const file = map.get(id);
|
||||||
|
if (!file) {
|
||||||
|
return new Response(null, { status: 400 });
|
||||||
|
}
|
||||||
|
try {
|
||||||
const keychain = new Keychain(file.key, file.nonce);
|
const keychain = new Keychain(file.key, file.nonce);
|
||||||
if (file.requiresPassword) {
|
if (file.requiresPassword) {
|
||||||
keychain.setPassword(file.password, file.url);
|
keychain.setPassword(file.password, file.url);
|
||||||
|
|
|
@ -3,6 +3,7 @@ require('buffer');
|
||||||
|
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import { b64ToArray } from '../../../app/utils';
|
import { b64ToArray } from '../../../app/utils';
|
||||||
|
import BlobSlicer from '../../../app/blobSlicer';
|
||||||
import ECE from '../../../app/ece.js';
|
import ECE from '../../../app/ece.js';
|
||||||
|
|
||||||
const rs = 36;
|
const rs = 36;
|
||||||
|
@ -47,8 +48,10 @@ describe('Streaming', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can decrypt', async function() {
|
it('can decrypt', async function() {
|
||||||
const encBlob = new Blob([encrypted]);
|
const blobStream = new ReadableStream(
|
||||||
const ece = new ECE(encBlob, key, 'decrypt', rs);
|
new BlobSlicer(new Blob([encrypted]), rs)
|
||||||
|
);
|
||||||
|
const ece = new ECE(blobStream, key, 'decrypt', rs);
|
||||||
const decStream = await ece.transform();
|
const decStream = await ece.transform();
|
||||||
|
|
||||||
const reader = decStream.getReader();
|
const reader = decStream.getReader();
|
||||||
|
|
|
@ -153,26 +153,26 @@ describe('Upload / Download flow', function() {
|
||||||
assert.equal(file.dtotal, 1);
|
assert.equal(file.dtotal, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('does not increase download count when download cancelled', async function() {
|
it('does not increase download count when download cancelled', async function() {
|
||||||
// const fs = new FileSender(blob);
|
const fs = new FileSender(blob);
|
||||||
// const file = await fs.upload();
|
const file = await fs.upload();
|
||||||
// const fr = new FileReceiver({
|
const fr = new FileReceiver({
|
||||||
// secretKey: file.toJSON().secretKey,
|
secretKey: file.toJSON().secretKey,
|
||||||
// id: file.id,
|
id: file.id,
|
||||||
// nonce: file.keychain.nonce,
|
nonce: file.keychain.nonce,
|
||||||
// requiresPassword: false
|
requiresPassword: false
|
||||||
// });
|
});
|
||||||
// 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(noSave);
|
||||||
// assert.fail('not cancelled');
|
assert.fail('not cancelled');
|
||||||
// } catch (e) {
|
} catch (e) {
|
||||||
// await file.updateDownloadCount();
|
await file.updateDownloadCount();
|
||||||
// assert.equal(file.dtotal, 0);
|
assert.equal(file.dtotal, 0);
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
|
|
||||||
it('can allow multiple downloads', async function() {
|
it('can allow multiple downloads', async function() {
|
||||||
const fs = new FileSender(blob);
|
const fs = new FileSender(blob);
|
||||||
|
|
Loading…
Reference in New Issue