Limit action port message size (#587)
* Add onDisconnect handler * Update how error is posted * Update action ports to send long messages in fragments * Remove ack timer * Move message destructuring into try block
This commit is contained in:
parent
cfd3a1ec3a
commit
2c58b1c109
@ -861,6 +861,7 @@ class Backend {
|
|||||||
|
|
||||||
_createActionListenerPort(port, sender, handlers) {
|
_createActionListenerPort(port, sender, handlers) {
|
||||||
let hasStarted = false;
|
let hasStarted = false;
|
||||||
|
let messageString = '';
|
||||||
|
|
||||||
const onProgress = (...data) => {
|
const onProgress = (...data) => {
|
||||||
try {
|
try {
|
||||||
@ -871,12 +872,34 @@ class Backend {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMessage = async ({action, params}) => {
|
const onMessage = (message) => {
|
||||||
if (hasStarted) { return; }
|
if (hasStarted) { return; }
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {action, data} = message;
|
||||||
|
switch (action) {
|
||||||
|
case 'fragment':
|
||||||
|
messageString += data;
|
||||||
|
break;
|
||||||
|
case 'invoke':
|
||||||
|
{
|
||||||
hasStarted = true;
|
hasStarted = true;
|
||||||
port.onMessage.removeListener(onMessage);
|
port.onMessage.removeListener(onMessage);
|
||||||
|
|
||||||
|
const messageData = JSON.parse(messageString);
|
||||||
|
messageString = null;
|
||||||
|
onMessageComplete(messageData);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
cleanup(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMessageComplete = async (message) => {
|
||||||
try {
|
try {
|
||||||
|
const {action, params} = message;
|
||||||
port.postMessage({type: 'ack'});
|
port.postMessage({type: 'ack'});
|
||||||
|
|
||||||
const messageHandler = handlers.get(action);
|
const messageHandler = handlers.get(action);
|
||||||
@ -893,25 +916,29 @@ class Backend {
|
|||||||
const result = async ? await promiseOrResult : promiseOrResult;
|
const result = async ? await promiseOrResult : promiseOrResult;
|
||||||
port.postMessage({type: 'complete', data: result});
|
port.postMessage({type: 'complete', data: result});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (port !== null) {
|
cleanup(e);
|
||||||
port.postMessage({type: 'error', data: errorToJson(e)});
|
|
||||||
}
|
|
||||||
cleanup();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanup = () => {
|
const onDisconnect = () => {
|
||||||
|
cleanup(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const cleanup = (error) => {
|
||||||
if (port === null) { return; }
|
if (port === null) { return; }
|
||||||
|
if (error !== null) {
|
||||||
|
port.postMessage({type: 'error', data: errorToJson(error)});
|
||||||
|
}
|
||||||
if (!hasStarted) {
|
if (!hasStarted) {
|
||||||
port.onMessage.removeListener(onMessage);
|
port.onMessage.removeListener(onMessage);
|
||||||
}
|
}
|
||||||
port.onDisconnect.removeListener(cleanup);
|
port.onDisconnect.removeListener(onDisconnect);
|
||||||
port = null;
|
port = null;
|
||||||
handlers = null;
|
handlers = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
port.onMessage.addListener(onMessage);
|
port.onMessage.addListener(onMessage);
|
||||||
port.onDisconnect.addListener(cleanup);
|
port.onDisconnect.addListener(onDisconnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getErrorLevelValue(errorLevel) {
|
_getErrorLevelValue(errorLevel) {
|
||||||
|
@ -236,7 +236,6 @@ const api = (() => {
|
|||||||
|
|
||||||
_invokeWithProgress(action, params, onProgress, timeout=5000) {
|
_invokeWithProgress(action, params, onProgress, timeout=5000) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let timer = null;
|
|
||||||
let port = null;
|
let port = null;
|
||||||
|
|
||||||
if (typeof onProgress !== 'function') {
|
if (typeof onProgress !== 'function') {
|
||||||
@ -245,12 +244,6 @@ const api = (() => {
|
|||||||
|
|
||||||
const onMessage = (message) => {
|
const onMessage = (message) => {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'ack':
|
|
||||||
if (timer !== null) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
timer = null;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'progress':
|
case 'progress':
|
||||||
try {
|
try {
|
||||||
onProgress(...message.data);
|
onProgress(...message.data);
|
||||||
@ -275,10 +268,6 @@ const api = (() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const cleanup = () => {
|
const cleanup = () => {
|
||||||
if (timer !== null) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
timer = null;
|
|
||||||
}
|
|
||||||
if (port !== null) {
|
if (port !== null) {
|
||||||
port.onMessage.removeListener(onMessage);
|
port.onMessage.removeListener(onMessage);
|
||||||
port.onDisconnect.removeListener(onDisconnect);
|
port.onDisconnect.removeListener(onDisconnect);
|
||||||
@ -288,17 +277,20 @@ const api = (() => {
|
|||||||
onProgress = null;
|
onProgress = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
cleanup();
|
|
||||||
reject(new Error('Timeout'));
|
|
||||||
}, timeout);
|
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
port = await this._createActionPort(timeout);
|
port = await this._createActionPort(timeout);
|
||||||
port.onMessage.addListener(onMessage);
|
port.onMessage.addListener(onMessage);
|
||||||
port.onDisconnect.addListener(onDisconnect);
|
port.onDisconnect.addListener(onDisconnect);
|
||||||
port.postMessage({action, params});
|
|
||||||
|
// Chrome has a maximum message size that can be sent, so longer messages must be fragmented.
|
||||||
|
const messageString = JSON.stringify({action, params});
|
||||||
|
const fragmentSize = 1e7; // 10 MB
|
||||||
|
for (let i = 0, ii = messageString.length; i < ii; i += fragmentSize) {
|
||||||
|
const data = messageString.substring(i, i + fragmentSize);
|
||||||
|
port.postMessage({action: 'fragment', data});
|
||||||
|
}
|
||||||
|
port.postMessage({action: 'invoke'});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
cleanup();
|
cleanup();
|
||||||
reject(e);
|
reject(e);
|
||||||
|
Loading…
Reference in New Issue
Block a user