Cleanup OpenPGP.js

This commit is contained in:
djmaze 2021-05-19 15:26:45 +02:00
parent e49405cd85
commit 37e1474650
2 changed files with 266 additions and 425 deletions

File diff suppressed because it is too large Load diff

View file

@ -32,102 +32,105 @@ const INITIAL_RANDOM_SEED = 50000, // random bytes seeded to worker
* @param {Object} worker alternative to path parameter: web worker initialized with 'openpgp.worker.js'
* @return {Promise}
*/
export default function AsyncProxy({ path='openpgp.worker.js', worker, config } = {}) {
this.worker = worker || new Worker(path);
this.worker.onmessage = this.onMessage.bind(this);
this.worker.onerror = e => {
throw new Error('Unhandled error in openpgp worker: ' + e.message + ' (' + e.filename + ':' + e.lineno + ')');
};
this.seedRandom(INITIAL_RANDOM_SEED);
export default class AsyncProxy {
if (config) {
this.worker.postMessage({ event:'configure', config });
constructor({ path='openpgp.worker.js', worker, config } = {}) {
this.worker = worker || new Worker(path);
this.worker.onmessage = this.onMessage.bind(this);
this.worker.onerror = e => {
throw new Error('Unhandled error in openpgp worker: ' + e.message + ' (' + e.filename + ':' + e.lineno + ')');
};
this.seedRandom(INITIAL_RANDOM_SEED);
if (config) {
this.worker.postMessage({ event:'configure', config });
}
// Cannot rely on task order being maintained, use object keyed by request ID to track tasks
this.tasks = {};
this.currentID = 0;
}
// Cannot rely on task order being maintained, use object keyed by request ID to track tasks
this.tasks = {};
this.currentID = 0;
/**
* Get new request ID
* @return {integer} New unique request ID
*/
getID() {
return this.currentID++;
}
/**
* Message handling
*/
onMessage(event) {
const msg = event.data;
switch (msg.event) {
case 'method-return':
if (msg.err) {
// fail
const err = new Error(msg.err);
// add worker stack
err.workerStack = msg.stack;
this.tasks[msg.id].reject(err);
} else {
// success
this.tasks[msg.id].resolve(msg.data);
}
delete this.tasks[msg.id];
break;
case 'request-seed':
this.seedRandom(RANDOM_SEED_REQUEST);
break;
default:
throw new Error('Unknown Worker Event.');
}
}
/**
* Send message to worker with random data
* @param {Integer} size Number of bytes to send
*/
seedRandom(size) {
const buf = this.getRandomBuffer(size);
this.worker.postMessage({ event:'seed-random', buf }, util.getTransferables.call(util, buf));
}
/**
* Get Uint8Array with random numbers
* @param {Integer} size Length of buffer
* @return {Uint8Array}
*/
getRandomBuffer(size) {
if (!size) {
return null;
}
const buf = new Uint8Array(size);
crypto.random.getRandomValues(buf);
return buf;
}
/**
* Terminates the worker
*/
terminate() {
this.worker.terminate();
}
/**
* Generic proxy function that handles all commands from the public api.
* @param {String} method the public api function to be delegated to the worker thread
* @param {Object} options the api function's options
* @return {Promise} see the corresponding public api functions for their return types
*/
delegate(method, options) {
const id = this.getID();
return new Promise((resolve, reject) => {
// clone packets (for web worker structured cloning algorithm)
this.worker.postMessage({ id:id, event:method, options:packet.clone.clonePackets(options) }, util.getTransferables.call(util, options));
// remember to handle parsing cloned packets from worker
this.tasks[id] = { resolve: data => resolve(packet.clone.parseClonedPackets(data, method)), reject };
});
}
}
/**
* Get new request ID
* @return {integer} New unique request ID
*/
AsyncProxy.prototype.getID = function() {
return this.currentID++;
};
/**
* Message handling
*/
AsyncProxy.prototype.onMessage = function(event) {
const msg = event.data;
switch (msg.event) {
case 'method-return':
if (msg.err) {
// fail
const err = new Error(msg.err);
// add worker stack
err.workerStack = msg.stack;
this.tasks[msg.id].reject(err);
} else {
// success
this.tasks[msg.id].resolve(msg.data);
}
delete this.tasks[msg.id];
break;
case 'request-seed':
this.seedRandom(RANDOM_SEED_REQUEST);
break;
default:
throw new Error('Unknown Worker Event.');
}
};
/**
* Send message to worker with random data
* @param {Integer} size Number of bytes to send
*/
AsyncProxy.prototype.seedRandom = function(size) {
const buf = this.getRandomBuffer(size);
this.worker.postMessage({ event:'seed-random', buf }, util.getTransferables.call(util, buf));
};
/**
* Get Uint8Array with random numbers
* @param {Integer} size Length of buffer
* @return {Uint8Array}
*/
AsyncProxy.prototype.getRandomBuffer = function(size) {
if (!size) {
return null;
}
const buf = new Uint8Array(size);
crypto.random.getRandomValues(buf);
return buf;
};
/**
* Terminates the worker
*/
AsyncProxy.prototype.terminate = function() {
this.worker.terminate();
};
/**
* Generic proxy function that handles all commands from the public api.
* @param {String} method the public api function to be delegated to the worker thread
* @param {Object} options the api function's options
* @return {Promise} see the corresponding public api functions for their return types
*/
AsyncProxy.prototype.delegate = function(method, options) {
const id = this.getID();
return new Promise((resolve, reject) => {
// clone packets (for web worker structured cloning algorithm)
this.worker.postMessage({ id:id, event:method, options:packet.clone.clonePackets(options) }, util.getTransferables.call(util, options));
// remember to handle parsing cloned packets from worker
this.tasks[id] = { resolve: data => resolve(packet.clone.parseClonedPackets(data, method)), reject };
});
};