diff options
-rw-r--r-- | ext/bg/js/backend.js | 47 | ||||
-rw-r--r-- | ext/mixed/js/api.js | 26 |
2 files changed, 46 insertions, 27 deletions
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 20d31efc..0af64377 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -805,6 +805,7 @@ class Backend { _createActionListenerPort(port, sender, handlers) { let hasStarted = false; + let messageString = ''; const onProgress = (...data) => { try { @@ -815,12 +816,34 @@ class Backend { } }; - const onMessage = async ({action, params}) => { + const onMessage = (message) => { if (hasStarted) { return; } - hasStarted = true; - port.onMessage.removeListener(onMessage); try { + const {action, data} = message; + switch (action) { + case 'fragment': + messageString += data; + break; + case 'invoke': + { + hasStarted = true; + port.onMessage.removeListener(onMessage); + + const messageData = JSON.parse(messageString); + messageString = null; + onMessageComplete(messageData); + } + break; + } + } catch (e) { + cleanup(e); + } + }; + + const onMessageComplete = async (message) => { + try { + const {action, params} = message; port.postMessage({type: 'ack'}); const messageHandler = handlers.get(action); @@ -837,25 +860,29 @@ class Backend { const result = async ? await promiseOrResult : promiseOrResult; port.postMessage({type: 'complete', data: result}); } catch (e) { - if (port !== null) { - port.postMessage({type: 'error', data: errorToJson(e)}); - } - cleanup(); + cleanup(e); } }; - const cleanup = () => { + const onDisconnect = () => { + cleanup(null); + }; + + const cleanup = (error) => { if (port === null) { return; } + if (error !== null) { + port.postMessage({type: 'error', data: errorToJson(error)}); + } if (!hasStarted) { port.onMessage.removeListener(onMessage); } - port.onDisconnect.removeListener(cleanup); + port.onDisconnect.removeListener(onDisconnect); port = null; handlers = null; }; port.onMessage.addListener(onMessage); - port.onDisconnect.addListener(cleanup); + port.onDisconnect.addListener(onDisconnect); } _getErrorLevelValue(errorLevel) { diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index 0bc91759..d2be12aa 100644 --- a/ext/mixed/js/api.js +++ b/ext/mixed/js/api.js @@ -204,7 +204,6 @@ function _apiCreateActionPort(timeout=5000) { function _apiInvokeWithProgress(action, params, onProgress, timeout=5000) { return new Promise((resolve, reject) => { - let timer = null; let port = null; if (typeof onProgress !== 'function') { @@ -213,12 +212,6 @@ function _apiInvokeWithProgress(action, params, onProgress, timeout=5000) { const onMessage = (message) => { switch (message.type) { - case 'ack': - if (timer !== null) { - clearTimeout(timer); - timer = null; - } - break; case 'progress': try { onProgress(...message.data); @@ -243,10 +236,6 @@ function _apiInvokeWithProgress(action, params, onProgress, timeout=5000) { }; const cleanup = () => { - if (timer !== null) { - clearTimeout(timer); - timer = null; - } if (port !== null) { port.onMessage.removeListener(onMessage); port.onDisconnect.removeListener(onDisconnect); @@ -256,17 +245,20 @@ function _apiInvokeWithProgress(action, params, onProgress, timeout=5000) { onProgress = null; }; - timer = setTimeout(() => { - cleanup(); - reject(new Error('Timeout')); - }, timeout); - (async () => { try { port = await _apiCreateActionPort(timeout); port.onMessage.addListener(onMessage); 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) { cleanup(); reject(e); |