diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-06-07 21:40:11 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-07 21:40:11 -0400 | 
| commit | 9767b765536279023045ed4280b12d297ec78f0a (patch) | |
| tree | 672e5754ca6950dbca87e8aabc408ddeba21f9ae | |
| parent | b614aca3ddd04b9d533959b2eabaa6db43b79f8f (diff) | |
Use cross frame API (#553)
* Use new CrossFrameAPI for popup proxy communication
* Remove use of old cross-frame communication classes
* Remove use of old cross-frame communication files
* Make the crossFrame object a member of the api object
| -rw-r--r-- | ext/bg/background.html | 1 | ||||
| -rw-r--r-- | ext/bg/context.html | 1 | ||||
| -rw-r--r-- | ext/bg/js/backend-api-forwarder.js | 44 | ||||
| -rw-r--r-- | ext/bg/js/backend.js | 4 | ||||
| -rw-r--r-- | ext/bg/js/search-main.js | 1 | ||||
| -rw-r--r-- | ext/bg/search.html | 1 | ||||
| -rw-r--r-- | ext/bg/settings-popup-preview.html | 2 | ||||
| -rw-r--r-- | ext/bg/settings.html | 1 | ||||
| -rw-r--r-- | ext/fg/float.html | 1 | ||||
| -rw-r--r-- | ext/fg/js/float-main.js | 1 | ||||
| -rw-r--r-- | ext/fg/js/frontend-api-receiver.js | 76 | ||||
| -rw-r--r-- | ext/fg/js/frontend-api-sender.js | 128 | ||||
| -rw-r--r-- | ext/fg/js/popup-factory.js | 7 | ||||
| -rw-r--r-- | ext/fg/js/popup-proxy.js | 6 | ||||
| -rw-r--r-- | ext/manifest.json | 3 | ||||
| -rw-r--r-- | ext/mixed/js/api.js | 18 | 
16 files changed, 29 insertions, 266 deletions
| diff --git a/ext/bg/background.html b/ext/bg/background.html index 53e8b140..d51858a7 100644 --- a/ext/bg/background.html +++ b/ext/bg/background.html @@ -28,7 +28,6 @@          <script src="/bg/js/backend.js"></script>          <script src="/bg/js/mecab.js"></script>          <script src="/bg/js/audio-uri-builder.js"></script> -        <script src="/bg/js/backend-api-forwarder.js"></script>          <script src="/bg/js/clipboard-monitor.js"></script>          <script src="/bg/js/conditions.js"></script>          <script src="/bg/js/database.js"></script> diff --git a/ext/bg/context.html b/ext/bg/context.html index 93012d70..89695d0e 100644 --- a/ext/bg/context.html +++ b/ext/bg/context.html @@ -180,6 +180,7 @@          </div>          <script src="/mixed/js/core.js"></script> +        <script src="/mixed/js/comm.js"></script>          <script src="/mixed/js/dom.js"></script>          <script src="/mixed/js/api.js"></script> diff --git a/ext/bg/js/backend-api-forwarder.js b/ext/bg/js/backend-api-forwarder.js deleted file mode 100644 index 4ac12730..00000000 --- a/ext/bg/js/backend-api-forwarder.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2019-2020  Yomichan Authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ - - -class BackendApiForwarder { -    prepare() { -        chrome.runtime.onConnect.addListener(this._onConnect.bind(this)); -    } - -    _onConnect(port) { -        if (port.name !== 'backend-api-forwarder') { return; } - -        let tabId; -        if (!( -            port.sender && -            port.sender.tab && -            (typeof (tabId = port.sender.tab.id)) === 'number' -        )) { -            port.disconnect(); -            return; -        } - -        const forwardPort = chrome.tabs.connect(tabId, {name: 'frontend-api-receiver'}); - -        port.onMessage.addListener((message) => forwardPort.postMessage(message)); -        forwardPort.onMessage.addListener((message) => port.postMessage(message)); -        port.onDisconnect.addListener(() => forwardPort.disconnect()); -        forwardPort.onDisconnect.addListener(() => port.disconnect()); -    } -} diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 5eb7982d..7971d16f 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -20,7 +20,6 @@   * AnkiNoteBuilder   * AudioSystem   * AudioUriBuilder - * BackendApiForwarder   * ClipboardMonitor   * Database   * DictionaryImporter @@ -76,9 +75,6 @@ class Backend {          this.popupWindow = null; -        const apiForwarder = new BackendApiForwarder(); -        apiForwarder.prepare(); -          this._defaultBrowserActionTitle = null;          this._isPrepared = false;          this._prepareError = false; diff --git a/ext/bg/js/search-main.js b/ext/bg/js/search-main.js index 3e089594..f18d6d88 100644 --- a/ext/bg/js/search-main.js +++ b/ext/bg/js/search-main.js @@ -24,7 +24,6 @@  async function injectSearchFrontend() {      await dynamicLoader.loadScripts([          '/mixed/js/text-scanner.js', -        '/fg/js/frontend-api-receiver.js',          '/fg/js/frame-offset-forwarder.js',          '/fg/js/popup.js',          '/fg/js/popup-factory.js', diff --git a/ext/bg/search.html b/ext/bg/search.html index c0721e5c..de08cdae 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -71,6 +71,7 @@          <script src="/mixed/lib/wanakana.min.js"></script>          <script src="/mixed/js/core.js"></script> +        <script src="/mixed/js/comm.js"></script>          <script src="/mixed/js/dom.js"></script>          <script src="/mixed/js/api.js"></script>          <script src="/mixed/js/japanese.js"></script> diff --git a/ext/bg/settings-popup-preview.html b/ext/bg/settings-popup-preview.html index 2f0b841b..fe92f24f 100644 --- a/ext/bg/settings-popup-preview.html +++ b/ext/bg/settings-popup-preview.html @@ -119,13 +119,13 @@          </div></div></div>          <script src="/mixed/js/core.js"></script> +        <script src="/mixed/js/comm.js"></script>          <script src="/mixed/js/dom.js"></script>          <script src="/mixed/js/api.js"></script>          <script src="/mixed/js/dynamic-loader.js"></script>          <script src="/mixed/js/text-scanner.js"></script>          <script src="/fg/js/document.js"></script> -        <script src="/fg/js/frontend-api-receiver.js"></script>          <script src="/fg/js/popup.js"></script>          <script src="/fg/js/source.js"></script>          <script src="/fg/js/popup-factory.js"></script> diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 7c295f0d..a530534c 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -1121,6 +1121,7 @@          <script src="/mixed/lib/wanakana.min.js"></script>          <script src="/mixed/js/core.js"></script> +        <script src="/mixed/js/comm.js"></script>          <script src="/mixed/js/dom.js"></script>          <script src="/mixed/js/environment.js"></script>          <script src="/mixed/js/api.js"></script> diff --git a/ext/fg/float.html b/ext/fg/float.html index e9f5acae..17dbcc6d 100644 --- a/ext/fg/float.html +++ b/ext/fg/float.html @@ -40,6 +40,7 @@          </div>          <script src="/mixed/js/core.js"></script> +        <script src="/mixed/js/comm.js"></script>          <script src="/mixed/js/dom.js"></script>          <script src="/mixed/js/api.js"></script>          <script src="/mixed/js/japanese.js"></script> diff --git a/ext/fg/js/float-main.js b/ext/fg/js/float-main.js index 249b4dbe..2ec334c8 100644 --- a/ext/fg/js/float-main.js +++ b/ext/fg/js/float-main.js @@ -24,7 +24,6 @@  async function injectPopupNested() {      await dynamicLoader.loadScripts([          '/mixed/js/text-scanner.js', -        '/fg/js/frontend-api-sender.js',          '/fg/js/popup.js',          '/fg/js/popup-proxy.js',          '/fg/js/frontend.js', diff --git a/ext/fg/js/frontend-api-receiver.js b/ext/fg/js/frontend-api-receiver.js deleted file mode 100644 index 3fa9e8b6..00000000 --- a/ext/fg/js/frontend-api-receiver.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2019-2020  Yomichan Authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ - - -class FrontendApiReceiver { -    constructor(source, messageHandlers) { -        this._source = source; -        this._messageHandlers = messageHandlers; -    } - -    prepare() { -        chrome.runtime.onConnect.addListener(this._onConnect.bind(this)); -    } - -    _onConnect(port) { -        if (port.name !== 'frontend-api-receiver') { return; } - -        port.onMessage.addListener(this._onMessage.bind(this, port)); -    } - -    _onMessage(port, {id, action, params, target, senderId}) { -        if (target !== this._source) { return; } - -        const messageHandler = this._messageHandlers.get(action); -        if (typeof messageHandler === 'undefined') { return; } - -        const {handler, async} = messageHandler; - -        this._sendAck(port, id, senderId); -        if (async) { -            this._invokeHandlerAsync(handler, params, port, id, senderId); -        } else { -            this._invokeHandler(handler, params, port, id, senderId); -        } -    } - -    _invokeHandler(handler, params, port, id, senderId) { -        try { -            const result = handler(params); -            this._sendResult(port, id, senderId, {result}); -        } catch (error) { -            this._sendResult(port, id, senderId, {error: errorToJson(error)}); -        } -    } - -    async _invokeHandlerAsync(handler, params, port, id, senderId) { -        try { -            const result = await handler(params); -            this._sendResult(port, id, senderId, {result}); -        } catch (error) { -            this._sendResult(port, id, senderId, {error: errorToJson(error)}); -        } -    } - -    _sendAck(port, id, senderId) { -        port.postMessage({type: 'ack', id, senderId}); -    } - -    _sendResult(port, id, senderId, data) { -        port.postMessage({type: 'result', id, senderId, data}); -    } -} diff --git a/ext/fg/js/frontend-api-sender.js b/ext/fg/js/frontend-api-sender.js deleted file mode 100644 index 4dcde638..00000000 --- a/ext/fg/js/frontend-api-sender.js +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2019-2020  Yomichan Authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ - - -class FrontendApiSender { -    constructor(target) { -        this._target = target; -        this._senderId = yomichan.generateId(16); -        this._ackTimeout = 3000; // 3 seconds -        this._responseTimeout = 10000; // 10 seconds -        this._callbacks = new Map(); -        this._disconnected = false; -        this._nextId = 0; -        this._port = null; -    } - -    invoke(action, params) { -        if (this._disconnected) { -            // attempt to reconnect the next time -            this._disconnected = false; -            return Promise.reject(new Error('Disconnected')); -        } - -        if (this._port === null) { -            this._createPort(); -        } - -        const id = `${this._nextId}`; -        ++this._nextId; - -        return new Promise((resolve, reject) => { -            const info = {id, resolve, reject, ack: false, timer: null}; -            this._callbacks.set(id, info); -            info.timer = setTimeout(() => this._onError(id, 'Timeout (ack)'), this._ackTimeout); - -            this._port.postMessage({id, action, params, target: this._target, senderId: this._senderId}); -        }); -    } - -    _createPort() { -        this._port = chrome.runtime.connect(null, {name: 'backend-api-forwarder'}); -        this._port.onDisconnect.addListener(this._onDisconnect.bind(this)); -        this._port.onMessage.addListener(this._onMessage.bind(this)); -    } - -    _onMessage({type, id, data, senderId}) { -        if (senderId !== this._senderId) { return; } -        switch (type) { -            case 'ack': -                this._onAck(id); -                break; -            case 'result': -                this._onResult(id, data); -                break; -        } -    } - -    _onDisconnect() { -        this._disconnected = true; -        this._port = null; - -        for (const id of this._callbacks.keys()) { -            this._onError(id, 'Disconnected'); -        } -    } - -    _onAck(id) { -        const info = this._callbacks.get(id); -        if (typeof info === 'undefined') { -            yomichan.logWarning(new Error(`ID ${id} not found for ack`)); -            return; -        } - -        if (info.ack) { -            yomichan.logWarning(new Error(`Request ${id} already ack'd`)); -            return; -        } - -        info.ack = true; -        clearTimeout(info.timer); -        info.timer = setTimeout(() => this._onError(id, 'Timeout (response)'), this._responseTimeout); -    } - -    _onResult(id, data) { -        const info = this._callbacks.get(id); -        if (typeof info === 'undefined') { -            yomichan.logWarning(new Error(`ID ${id} not found`)); -            return; -        } - -        if (!info.ack) { -            yomichan.logWarning(new Error(`Request ${id} not ack'd`)); -            return; -        } - -        this._callbacks.delete(id); -        clearTimeout(info.timer); -        info.timer = null; - -        if (typeof data.error !== 'undefined') { -            info.reject(jsonToError(data.error)); -        } else { -            info.resolve(data.result); -        } -    } - -    _onError(id, reason) { -        const info = this._callbacks.get(id); -        if (typeof info === 'undefined') { return; } -        this._callbacks.delete(id); -        info.timer = null; -        info.reject(new Error(reason)); -    } -} diff --git a/ext/fg/js/popup-factory.js b/ext/fg/js/popup-factory.js index b10acbaf..b5997253 100644 --- a/ext/fg/js/popup-factory.js +++ b/ext/fg/js/popup-factory.js @@ -16,8 +16,8 @@   */  /* global - * FrontendApiReceiver   * Popup + * api   */  class PopupFactory { @@ -29,7 +29,7 @@ class PopupFactory {      // Public functions      async prepare() { -        const apiReceiver = new FrontendApiReceiver(`popup-factory#${this._frameId}`, new Map([ +        api.crossFrame.registerHandlers([              ['getOrCreatePopup',   {async: false, handler: this._onApiGetOrCreatePopup.bind(this)}],              ['setOptionsContext',  {async: true,  handler: this._onApiSetOptionsContext.bind(this)}],              ['hide',               {async: false, handler: this._onApiHide.bind(this)}], @@ -41,8 +41,7 @@ class PopupFactory {              ['clearAutoPlayTimer', {async: false, handler: this._onApiClearAutoPlayTimer.bind(this)}],              ['setContentScale',    {async: false, handler: this._onApiSetContentScale.bind(this)}],              ['getUrl',             {async: false, handler: this._onApiGetUrl.bind(this)}] -        ])); -        apiReceiver.prepare(); +        ]);      }      getOrCreatePopup(id=null, parentId=null, depth=null) { diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index 82da839a..3387d941 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -16,7 +16,7 @@   */  /* global - * FrontendApiSender + * api   */  class PopupProxy { @@ -24,7 +24,7 @@ class PopupProxy {          this._id = id;          this._depth = depth;          this._parentPopupId = parentPopupId; -        this._apiSender = new FrontendApiSender(`popup-factory#${parentFrameId}`); +        this._parentFrameId = parentFrameId;          this._getFrameOffset = getFrameOffset;          this._setDisabled = setDisabled; @@ -111,7 +111,7 @@ class PopupProxy {      // Private      _invoke(action, params={}) { -        return this._apiSender.invoke(action, params); +        return api.crossFrame.invoke(this._parentFrameId, action, params);      }      async _updateFrameOffset() { diff --git a/ext/manifest.json b/ext/manifest.json index 6db257d7..75334675 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -36,13 +36,12 @@          "matches": ["http://*/*", "https://*/*", "file://*/*"],          "js": [              "mixed/js/core.js", +            "mixed/js/comm.js",              "mixed/js/dom.js",              "mixed/js/api.js",              "mixed/js/dynamic-loader.js",              "mixed/js/text-scanner.js",              "fg/js/document.js", -            "fg/js/frontend-api-sender.js", -            "fg/js/frontend-api-receiver.js",              "fg/js/popup.js",              "fg/js/source.js",              "fg/js/popup-factory.js", diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index 5e3195d6..c54196e2 100644 --- a/ext/mixed/js/api.js +++ b/ext/mixed/js/api.js @@ -15,10 +15,23 @@   * along with this program.  If not, see <https://www.gnu.org/licenses/>.   */ +/* global + * CrossFrameAPI + */ +  const api = (() => {      class API {          constructor() {              this._forwardLogsToBackendEnabled = false; +            this._crossFrame = new CrossFrameAPI(); +        } + +        get crossFrame() { +            return this._crossFrame; +        } + +        prepare() { +            this._crossFrame.prepare();          }          forwardLogsToBackend() { @@ -331,5 +344,8 @@ const api = (() => {          }      } -    return new API(); +    // eslint-disable-next-line no-shadow +    const api = new API(); +    api.prepare(); +    return api;  })(); |