diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-07-18 14:16:35 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-07-18 14:16:35 -0400 | 
| commit | a13a68990eac548f8439050222ddf3cb97146199 (patch) | |
| tree | cde32346ea25cc6fb685461ace3e1d512842f51b /ext/mixed/js | |
| parent | dac33e696145ad3c2cfe076a7fadc82c05732102 (diff) | |
Port name details (#667)
* Use a stringified JSON details object for extension port names
* Fix incorrect frame ID check
* Add support for connecting to different tabs
* Add function for invoking on a different tab
Diffstat (limited to 'ext/mixed/js')
| -rw-r--r-- | ext/mixed/js/api.js | 15 | ||||
| -rw-r--r-- | ext/mixed/js/comm.js | 77 | 
2 files changed, 66 insertions, 26 deletions
| diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index 534154ef..4009c86e 100644 --- a/ext/mixed/js/api.js +++ b/ext/mixed/js/api.js @@ -212,16 +212,13 @@ const api = (() => {          _createActionPort(timeout=5000) {              return new Promise((resolve, reject) => {                  let timer = null; -                const { -                    promise: portNamePromise, -                    resolve: portNameResolve, -                    reject: portNameReject -                } = deferPromise(); +                const portDetails = deferPromise();                  const onConnect = async (port) => {                      try { -                        const portName = await portNamePromise; -                        if (port.name !== portName || timer === null) { return; } +                        const {name: expectedName, id: expectedId} = await portDetails.promise; +                        const {name, id} = JSON.parse(port.name); +                        if (name !== expectedName || id !== expectedId || timer === null) { return; }                      } catch (e) {                          return;                      } @@ -239,14 +236,14 @@ const api = (() => {                          timer = null;                      }                      chrome.runtime.onConnect.removeListener(onConnect); -                    portNameReject(e); +                    portDetails.reject(e);                      reject(e);                  };                  timer = setTimeout(() => onError(new Error('Timeout')), timeout);                  chrome.runtime.onConnect.addListener(onConnect); -                this._invoke('createActionPort').then(portNameResolve, onError); +                this._invoke('createActionPort').then(portDetails.resolve, onError);              });          } diff --git a/ext/mixed/js/comm.js b/ext/mixed/js/comm.js index 1516a98f..1264a33e 100644 --- a/ext/mixed/js/comm.js +++ b/ext/mixed/js/comm.js @@ -16,8 +16,9 @@   */  class CrossFrameAPIPort extends EventDispatcher { -    constructor(otherFrameId, port, messageHandlers) { +    constructor(otherTabId, otherFrameId, port, messageHandlers) {          super(); +        this._otherTabId = otherTabId;          this._otherFrameId = otherFrameId;          this._port = port;          this._messageHandlers = messageHandlers; @@ -26,6 +27,10 @@ class CrossFrameAPIPort extends EventDispatcher {          this._eventListeners = new EventListenerCollection();      } +    get otherTabId() { +        return this._otherTabId; +    } +      get otherFrameId() {          return this._otherFrameId;      } @@ -211,8 +216,12 @@ class CrossFrameAPI {          chrome.runtime.onConnect.addListener(this._onConnect.bind(this));      } -    async invoke(targetFrameId, action, params={}) { -        const commPort = this._getOrCreateCommPort(targetFrameId); +    invoke(targetFrameId, action, params={}) { +        return this.invokeTab(null, targetFrameId, action, params); +    } + +    async invokeTab(targetTabId, targetFrameId, action, params={}) { +        const commPort = this._getOrCreateCommPort(targetTabId, targetFrameId);          return await commPort.invoke(action, params, this._ackTimeout, this._responseTimeout);      } @@ -226,31 +235,65 @@ class CrossFrameAPI {      }      _onConnect(port) { -        const match = /^cross-frame-communication-port-(\d+)$/.exec(`${port.name}`); -        if (match === null) { return; } +        try { +            let details; +            try { +                details = JSON.parse(port.name); +            } catch (e) { +                return; +            } +            if (details.name !== 'cross-frame-communication-port') { return; } -        const otherFrameId = parseInt(match[1], 10); -        this._setupCommPort(otherFrameId, port); +            const otherTabId = details.sourceTabId; +            const otherFrameId = details.sourceFrameId; +            this._setupCommPort(otherTabId, otherFrameId, port); +        } catch (e) { +            port.disconnect(); +            yomichan.logError(e); +        }      }      _onDisconnect(commPort) {          commPort.off('disconnect', this._onDisconnectBind); -        this._commPorts.delete(commPort.otherFrameId); +        const {otherTabId, otherFrameId} = commPort; +        const tabPorts = this._commPorts.get(otherTabId); +        if (typeof tabPorts !== 'undefined') { +            tabPorts.delete(otherFrameId); +            if (tabPorts.size === 0) { +                this._commPorts.delete(otherTabId); +            } +        }      } -    _getOrCreateCommPort(otherFrameId) { -        const commPort = this._commPorts.get(otherFrameId); -        return (typeof commPort !== 'undefined' ? commPort : this._createCommPort(otherFrameId)); +    _getOrCreateCommPort(otherTabId, otherFrameId) { +        const tabPorts = this._commPorts.get(otherTabId); +        if (typeof tabPorts !== 'undefined') { +            const commPort = tabPorts.get(otherFrameId); +            if (typeof commPort !== 'undefined') { +                return commPort; +            } +        } +        return this._createCommPort(otherTabId, otherFrameId);      } -    _createCommPort(otherFrameId) { -        const port = yomichan.connect(null, {name: `background-cross-frame-communication-port-${otherFrameId}`}); -        return this._setupCommPort(otherFrameId, port); +    _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);      } -    _setupCommPort(otherFrameId, port) { -        const commPort = new CrossFrameAPIPort(otherFrameId, port, this._messageHandlers); -        this._commPorts.set(otherFrameId, commPort); +    _setupCommPort(otherTabId, otherFrameId, port) { +        const commPort = new CrossFrameAPIPort(otherTabId, otherFrameId, port, this._messageHandlers); +        let tabPorts = this._commPorts.get(otherTabId); +        if (typeof tabPorts === 'undefined') { +            tabPorts = new Map(); +            this._commPorts.set(otherTabId, tabPorts); +        } +        tabPorts.set(otherFrameId, commPort);          commPort.prepare();          commPort.on('disconnect', this._onDisconnectBind);          return commPort; |