diff options
| -rw-r--r-- | ext/js/background/backend.js | 102 | ||||
| -rw-r--r-- | ext/js/comm/api.js | 4 | ||||
| -rw-r--r-- | ext/js/comm/cross-frame-api.js | 31 | 
3 files changed, 68 insertions, 69 deletions
| diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index dd233abb..3cac2e4d 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -139,7 +139,8 @@ class Backend {              ['textHasJapaneseCharacters',    {async: false, contentScript: true,  handler: this._onApiTextHasJapaneseCharacters.bind(this)}],              ['getTermFrequencies',           {async: true,  contentScript: true,  handler: this._onApiGetTermFrequencies.bind(this)}],              ['findAnkiNotes',                {async: true,  contentScript: true,  handler: this._onApiFindAnkiNotes.bind(this)}], -            ['loadExtensionScripts',         {async: true,  contentScript: true,  handler: this._onApiLoadExtensionScripts.bind(this)}] +            ['loadExtensionScripts',         {async: true,  contentScript: true,  handler: this._onApiLoadExtensionScripts.bind(this)}], +            ['openCrossFramePort',           {async: false, contentScript: true,  handler: this._onApiOpenCrossFramePort.bind(this)}]          ]);          this._messageHandlersWithProgress = new Map([          ]); @@ -189,9 +190,6 @@ class Backend {              chrome.tabs.onZoomChange.addListener(onZoomChange);          } -        const onConnect = this._onWebExtensionEventWrapper(this._onConnect.bind(this)); -        chrome.runtime.onConnect.addListener(onConnect); -          const onMessage = this._onMessageWrapper.bind(this);          chrome.runtime.onMessage.addListener(onMessage); @@ -331,58 +329,6 @@ class Backend {          return invokeMessageHandler(messageHandler, params, callback, sender);      } -    _onConnect(port) { -        try { -            let details; -            try { -                details = JSON.parse(port.name); -            } catch (e) { -                return; -            } -            if (details.name !== 'background-cross-frame-communication-port') { return; } - -            const senderTabId = (port.sender && port.sender.tab ? port.sender.tab.id : null); -            if (typeof senderTabId !== 'number') { -                throw new Error('Port does not have an associated tab ID'); -            } -            const senderFrameId = port.sender.frameId; -            if (typeof senderFrameId !== 'number') { -                throw new Error('Port does not have an associated frame ID'); -            } -            let {targetTabId, targetFrameId} = details; -            if (typeof targetTabId !== 'number') { -                targetTabId = senderTabId; -            } - -            const details2 = { -                name: 'cross-frame-communication-port', -                sourceTabId: senderTabId, -                sourceFrameId: senderFrameId -            }; -            let forwardPort = chrome.tabs.connect(targetTabId, {frameId: targetFrameId, name: JSON.stringify(details2)}); - -            const cleanup = () => { -                this._checkLastError(chrome.runtime.lastError); -                if (forwardPort !== null) { -                    forwardPort.disconnect(); -                    forwardPort = null; -                } -                if (port !== null) { -                    port.disconnect(); -                    port = null; -                } -            }; - -            port.onMessage.addListener((message) => { forwardPort.postMessage(message); }); -            forwardPort.onMessage.addListener((message) => { port.postMessage(message); }); -            port.onDisconnect.addListener(cleanup); -            forwardPort.onDisconnect.addListener(cleanup); -        } catch (e) { -            port.disconnect(); -            log.error(e); -        } -    } -      _onZoomChange({tabId, oldZoomFactor, newZoomFactor}) {          this._sendMessageTabIgnoreResponse(tabId, {action: 'Yomichan.zoomChanged', params: {oldZoomFactor, newZoomFactor}});      } @@ -2273,4 +2219,48 @@ class Backend {          }          return results;      } + +    _onApiOpenCrossFramePort({targetTabId, targetFrameId}, sender) { +        const sourceTabId = (sender && sender.tab ? sender.tab.id : null); +        if (typeof sourceTabId !== 'number') { +            throw new Error('Port does not have an associated tab ID'); +        } +        const sourceFrameId = sender.frameId; +        if (typeof sourceFrameId !== 'number') { +            throw new Error('Port does not have an associated frame ID'); +        } + +        const sourceDetails = { +            name: 'cross-frame-communication-port', +            otherTabId: targetTabId, +            otherFrameId: targetFrameId +        }; +        const targetDetails = { +            name: 'cross-frame-communication-port', +            otherTabId: sourceTabId, +            otherFrameId: sourceFrameId +        }; +        let sourcePort = chrome.tabs.connect(sourceTabId, {frameId: sourceFrameId, name: JSON.stringify(sourceDetails)}); +        let targetPort = chrome.tabs.connect(targetTabId, {frameId: targetFrameId, name: JSON.stringify(targetDetails)}); + +        const cleanup = () => { +            console.log('cross-frame cleanup', targetPort, sourcePort); +            this._checkLastError(chrome.runtime.lastError); +            if (targetPort !== null) { +                targetPort.disconnect(); +                targetPort = null; +            } +            if (sourcePort !== null) { +                sourcePort.disconnect(); +                sourcePort = null; +            } +        }; + +        sourcePort.onMessage.addListener((message) => { targetPort.postMessage(message); }); +        targetPort.onMessage.addListener((message) => { sourcePort.postMessage(message); }); +        sourcePort.onDisconnect.addListener(cleanup); +        targetPort.onDisconnect.addListener(cleanup); + +        return {targetTabId, targetFrameId}; +    }  } diff --git a/ext/js/comm/api.js b/ext/js/comm/api.js index de12bb6c..72d2ba07 100644 --- a/ext/js/comm/api.js +++ b/ext/js/comm/api.js @@ -181,6 +181,10 @@ class API {          return this._invoke('loadExtensionScripts', {files});      } +    openCrossFramePort(targetTabId, targetFrameId) { +        return this._invoke('openCrossFramePort', {targetTabId, targetFrameId}); +    } +      // Utilities      _createActionPort(timeout=5000) { diff --git a/ext/js/comm/cross-frame-api.js b/ext/js/comm/cross-frame-api.js index 7892eb4c..fb2a1718 100644 --- a/ext/js/comm/cross-frame-api.js +++ b/ext/js/comm/cross-frame-api.js @@ -224,10 +224,13 @@ class CrossFrameAPI {          this._commPorts = new Map();          this._messageHandlers = new Map();          this._onDisconnectBind = this._onDisconnect.bind(this); +        this._tabId = null; +        this._frameId = null;      } -    prepare() { +    async prepare() {          chrome.runtime.onConnect.addListener(this._onConnect.bind(this)); +        ({tabId: this._tabId, frameId: this._frameId} = await yomichan.api.frameInformationGet());      }      invoke(targetFrameId, action, params={}) { @@ -235,8 +238,8 @@ class CrossFrameAPI {      }      async invokeTab(targetTabId, targetFrameId, action, params={}) { -        if (typeof targetTabId !== 'number') { targetTabId = null; } -        const commPort = this._getOrCreateCommPort(targetTabId, targetFrameId); +        if (typeof targetTabId !== 'number') { targetTabId = this._tabId; } +        const commPort = await this._getOrCreateCommPort(targetTabId, targetFrameId);          return await commPort.invoke(action, params, this._ackTimeout, this._responseTimeout);      } @@ -265,8 +268,8 @@ class CrossFrameAPI {              }              if (details.name !== 'cross-frame-communication-port') { return; } -            const otherTabId = details.sourceTabId; -            const otherFrameId = details.sourceFrameId; +            const otherTabId = details.otherTabId; +            const otherFrameId = details.otherFrameId;              this._setupCommPort(otherTabId, otherFrameId, port);          } catch (e) {              port.disconnect(); @@ -297,14 +300,16 @@ class CrossFrameAPI {          return this._createCommPort(otherTabId, otherFrameId);      } -    _createCommPort(otherTabId, otherFrameId) { -        const details = { -            name: 'background-cross-frame-communication-port', -            targetTabId: otherTabId, -            targetFrameId: otherFrameId -        }; -        const port = yomichan.connect(null, {name: JSON.stringify(details)}); -        return this._setupCommPort(otherTabId, otherFrameId, port); +    async _createCommPort(otherTabId, otherFrameId) { +        await yomichan.api.openCrossFramePort(otherTabId, otherFrameId); + +        const tabPorts = this._commPorts.get(otherTabId); +        if (typeof tabPorts !== 'undefined') { +            const commPort = tabPorts.get(otherFrameId); +            if (typeof commPort !== 'undefined') { +                return commPort; +            } +        }      }      _setupCommPort(otherTabId, otherFrameId, port) { |