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); |