diff options
| author | siikamiika <siikamiika@users.noreply.github.com> | 2020-03-19 17:46:05 +0200 | 
|---|---|---|
| committer | siikamiika <siikamiika@users.noreply.github.com> | 2020-04-05 19:57:37 +0300 | 
| commit | d20ece9f074bb9d241a902f29344e5906e3c8210 (patch) | |
| tree | c496984fabf674081dc1360ea5c34bbae22e50c8 /ext/fg/js | |
| parent | 09151a1a860f35b8dcbdbe9a25c09be5abeb4e37 (diff) | |
move frame offset forwarding code to a class
Diffstat (limited to 'ext/fg/js')
| -rw-r--r-- | ext/fg/js/frame-offset-forwarder.js | 94 | ||||
| -rw-r--r-- | ext/fg/js/frontend-initialize.js | 6 | ||||
| -rw-r--r-- | ext/fg/js/popup-proxy-host.js | 31 | ||||
| -rw-r--r-- | ext/fg/js/popup-proxy.js | 67 | 
4 files changed, 103 insertions, 95 deletions
| diff --git a/ext/fg/js/frame-offset-forwarder.js b/ext/fg/js/frame-offset-forwarder.js new file mode 100644 index 00000000..b3715c2a --- /dev/null +++ b/ext/fg/js/frame-offset-forwarder.js @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2020  Alex Yatskov <alex@foosoft.net> + * Author: Alex Yatskov <alex@foosoft.net> + * + * 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/>. + */ + +/* global + * apiForward + */ + +class FrameOffsetForwarder { +    constructor() { +        this._forwardFrameOffset = window !== window.parent ? +            this._forwardFrameOffsetParent.bind(this) : +            this._forwardFrameOffsetOrigin.bind(this); + +        this._windowMessageHandlers = new Map([ +            ['getFrameOffset', ({offset, uniqueId}, e) => { return this._onGetFrameOffset(offset, uniqueId, e); }] +        ]); + +        window.addEventListener('message', this.onMessage.bind(this), false); +    } + +    async applyOffset(x, y) { +        const uniqueId = yomichan.generateId(16); + +        let frameOffsetResolve = null; +        const frameOffsetPromise = new Promise((resolve) => (frameOffsetResolve = resolve)); + +        const runtimeMessageCallback = ({action, params}, sender, callback) => { +            if (action === 'frameOffset' && isObject(params) && params.uniqueId === uniqueId) { +                chrome.runtime.onMessage.removeListener(runtimeMessageCallback); +                callback(); +                frameOffsetResolve(params); +                return false; +            } +        }; +        chrome.runtime.onMessage.addListener(runtimeMessageCallback); + +        window.parent.postMessage({ +            action: 'getFrameOffset', +            params: { +                uniqueId, +                offset: [x, y] +            } +        }, '*'); + +        const {offset} = await frameOffsetPromise; +        return offset; +    } + +    onMessage(e) { +        const {action, params} = e.data; +        const handler = this._windowMessageHandlers.get(action); +        if (typeof handler !== 'function') { return; } +        handler(params, e); +    } + +    _onGetFrameOffset(offset, uniqueId, e) { +        let sourceFrame = null; +        for (const frame of document.querySelectorAll('frame, iframe:not(.yomichan-float)')) { +            if (frame.contentWindow !== e.source) { continue; } +            sourceFrame = frame; +            break; +        } +        if (sourceFrame === null) { return; } + +        const [forwardedX, forwardedY] = offset; +        const {x, y} = sourceFrame.getBoundingClientRect(); +        offset = [forwardedX + x, forwardedY + y]; + +        this._forwardFrameOffset(offset, uniqueId); +    } + +    _forwardFrameOffsetParent(offset, uniqueId) { +        window.parent.postMessage({action: 'getFrameOffset', params: {offset, uniqueId}}, '*'); +    } + +    _forwardFrameOffsetOrigin(offset, uniqueId) { +        apiForward('frameOffset', {offset, uniqueId}); +    } +} diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 352c6bd9..777291fe 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -17,6 +17,7 @@   */  /* global + * FrameOffsetForwarder   * Frontend   * PopupProxy   * PopupProxyHost @@ -47,12 +48,15 @@ async function main() {          const {popupId, frameId} = await rootPopupInformationPromise; -        popup = new PopupProxy(popupId, 0, null, frameId, url); +        window._frameOffsetForwarder = new FrameOffsetForwarder(); +        const applyFrameOffset = window._frameOffsetForwarder.applyOffset.bind(window._frameOffsetForwarder); +        popup = new PopupProxy(popupId, 0, null, frameId, url, applyFrameOffset);          await popup.prepare();      } else if (proxy) {          popup = new PopupProxy(null, depth + 1, id, parentFrameId, url);          await popup.prepare();      } else { +        window._frameOffsetForwarder = new FrameOffsetForwarder();          const popupHost = new PopupProxyHost();          await popupHost.prepare(); diff --git a/ext/fg/js/popup-proxy-host.js b/ext/fg/js/popup-proxy-host.js index 487dda90..4b136e41 100644 --- a/ext/fg/js/popup-proxy-host.js +++ b/ext/fg/js/popup-proxy-host.js @@ -19,7 +19,6 @@  /* global   * FrontendApiReceiver   * Popup - * apiForward   * apiFrameInformationGet   */ @@ -49,12 +48,6 @@ class PopupProxyHost {              ['clearAutoPlayTimer', this._onApiClearAutoPlayTimer.bind(this)],              ['setContentScale', this._onApiSetContentScale.bind(this)]          ])); - -        this._windowMessageHandlers = new Map([ -            ['getIframeOffset', ({offset, uniqueId}, e) => { return this._onGetIframeOffset(offset, uniqueId, e); }] -        ]); - -        window.addEventListener('message', this.onMessage.bind(this), false);      }      getOrCreatePopup(id=null, parentId=null, depth=null) { @@ -159,30 +152,6 @@ class PopupProxyHost {          return popup.setContentScale(scale);      } -    // Window message handlers - -    onMessage(e) { -        const {action, params} = e.data; -        const handler = this._windowMessageHandlers.get(action); -        if (typeof handler !== 'function') { return; } -        handler(params, e); -    } - -    _onGetIframeOffset(offset, uniqueId, e) { -        let sourceIframe = null; -        for (const iframe of document.querySelectorAll('iframe:not(.yomichan-float)')) { -            if (iframe.contentWindow !== e.source) { continue; } -            sourceIframe = iframe; -            break; -        } -        if (sourceIframe === null) { return; } - -        const [forwardedX, forwardedY] = offset; -        const {x, y} = sourceIframe.getBoundingClientRect(); -        offset = [forwardedX + x, forwardedY + y]; -        apiForward('iframeOffset', {offset, uniqueId}); -    } -      // Private functions      _getPopup(id) { diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index 8693ef17..73148eee 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -21,19 +21,14 @@   */  class PopupProxy { -    constructor(id, depth, parentId, parentFrameId, url) { +    constructor(id, depth, parentId, parentFrameId, url, applyFrameOffset=async (x, y) => [x, y]) {          this._parentId = parentId;          this._parentFrameId = parentFrameId;          this._id = id;          this._depth = depth;          this._url = url;          this._apiSender = new FrontendApiSender(); - -        this._windowMessageHandlers = new Map([ -            ['getIframeOffset', ({offset, uniqueId}, e) => { return this._onGetIframeOffset(offset, uniqueId, e); }] -        ]); - -        window.addEventListener('message', this.onMessage.bind(this), false); +        this._applyFrameOffset = applyFrameOffset;      }      // Public properties @@ -87,7 +82,7 @@ class PopupProxy {      async containsPoint(x, y) {          if (this._depth === 0) { -            [x, y] = await PopupProxy._convertIframePointToRootPagePoint(x, y); +            [x, y] = await this._applyFrameOffset(x, y);          }          return await this._invokeHostApi('containsPoint', {id: this._id, x, y});      } @@ -95,7 +90,7 @@ class PopupProxy {      async showContent(elementRect, writingMode, type=null, details=null) {          let {x, y, width, height} = elementRect;          if (this._depth === 0) { -            [x, y] = await PopupProxy._convertIframePointToRootPagePoint(x, y); +            [x, y] = await this._applyFrameOffset(x, y);          }          elementRect = {x, y, width, height};          return await this._invokeHostApi('showContent', {id: this._id, elementRect, writingMode, type, details}); @@ -113,31 +108,6 @@ class PopupProxy {          this._invokeHostApi('setContentScale', {id: this._id, scale});      } -    // Window message handlers - -    onMessage(e) { -        const {action, params} = e.data; -        const handler = this._windowMessageHandlers.get(action); -        if (typeof handler !== 'function') { return; } -        handler(params, e); -    } - -    _onGetIframeOffset(offset, uniqueId, e) { -        let sourceIframe = null; -        for (const iframe of document.querySelectorAll('iframe:not(.yomichan-float)')) { -            if (iframe.contentWindow !== e.source) { continue; } -            sourceIframe = iframe; -            break; -        } -        if (sourceIframe === null) { return; } - -        const [forwardedX, forwardedY] = offset; -        const {x, y} = sourceIframe.getBoundingClientRect(); -        offset = [forwardedX + x, forwardedY + y]; -        window.parent.postMessage({action: 'getIframeOffset', params: {offset, uniqueId}}, '*'); -    } - -      // Private      _invokeHostApi(action, params={}) { @@ -146,33 +116,4 @@ class PopupProxy {          }          return this._apiSender.invoke(action, params, `popup-proxy-host#${this._parentFrameId}`);      } - -    static async _convertIframePointToRootPagePoint(x, y) { -        const uniqueId = yomichan.generateId(16); - -        let frameOffsetResolve = null; -        const frameOffsetPromise = new Promise((resolve) => (frameOffsetResolve = resolve)); - -        const runtimeMessageCallback = ({action, params}, sender, callback) => { -            if (action === 'iframeOffset' && isObject(params) && params.uniqueId === uniqueId) { -                chrome.runtime.onMessage.removeListener(runtimeMessageCallback); -                callback(); -                frameOffsetResolve(params); -                return false; -            } -        }; -        chrome.runtime.onMessage.addListener(runtimeMessageCallback); - -        window.parent.postMessage({ -            action: 'getIframeOffset', -            params: { -                uniqueId, -                offset: [x, y] -            } -        }, '*'); - -        const {offset} = await frameOffsetPromise; - -        return offset; -    }  } |