diff options
| -rw-r--r-- | ext/fg/js/frame-offset-forwarder.js | 17 | ||||
| -rw-r--r-- | ext/fg/js/frontend-initialize.js | 18 | ||||
| -rw-r--r-- | ext/mixed/js/core.js | 36 | 
3 files changed, 50 insertions, 21 deletions
| diff --git a/ext/fg/js/frame-offset-forwarder.js b/ext/fg/js/frame-offset-forwarder.js index 09eb89a6..781a9018 100644 --- a/ext/fg/js/frame-offset-forwarder.js +++ b/ext/fg/js/frame-offset-forwarder.js @@ -44,17 +44,14 @@ class FrameOffsetForwarder {      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); +        const frameOffsetPromise = yomichan.getTemporaryListenerResult( +            chrome.runtime.onMessage, +            ({action, params}, {resolve}) => { +                if (action === 'frameOffset' && isObject(params) && params.uniqueId === uniqueId) { +                    resolve(params); +                }              } -        }; -        chrome.runtime.onMessage.addListener(runtimeMessageCallback); +        );          window.parent.postMessage({              action: 'getFrameOffset', diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 51fa8d7a..97e315b5 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -32,19 +32,15 @@ async function main() {      let popup;      if (!proxy && (window !== window.parent)) { -        let rootPopupInformationResolve; -        const rootPopupInformationPromise = new Promise((resolve) => (rootPopupInformationResolve = resolve)); - -        const runtimeMessageCallback = ({action, params}, sender, callback) => { -            if (action === 'rootPopupInformation') { -                chrome.runtime.onMessage.removeListener(runtimeMessageCallback); -                callback(); -                rootPopupInformationResolve(params); +        const rootPopupInformationPromise = yomichan.getTemporaryListenerResult( +            chrome.runtime.onMessage, +            ({action, params}, {resolve}) => { +                if (action === 'rootPopupInformation') { +                    resolve(params); +                }              } -        }; -        chrome.runtime.onMessage.addListener(runtimeMessageCallback); +        );          apiForward('rootPopupRequestInformationBroadcast'); -          const {popupId, frameId} = await rootPopupInformationPromise;          const frameOffsetForwarder = new FrameOffsetForwarder(); diff --git a/ext/mixed/js/core.js b/ext/mixed/js/core.js index fd762e97..f21bac23 100644 --- a/ext/mixed/js/core.js +++ b/ext/mixed/js/core.js @@ -312,6 +312,42 @@ const yomichan = (() => {              this.trigger('orphaned', {error});          } +        getTemporaryListenerResult(eventHandler, userCallback, timeout=30000) { +            let resolved = false; +            let resolve; +            let reject; +            const listenerPromise = new Promise((_resolve, _reject) => { +                resolve = _resolve; +                reject = _reject; +            }); + +            if (eventHandler === chrome.runtime.onMessage) { +                const runtimeMessageCallback = ({action, params}, sender, sendResponse) => { +                    const cleanupResolve = (value) => { +                        resolved = true; +                        eventHandler.removeListener(runtimeMessageCallback); +                        sendResponse(); +                        resolve(value); +                    }; + +                    setTimeout(() => { +                        if (!resolved) { +                            reject(new Error(`Listener timed out in ${timeout} ms`)); +                            eventHandler.removeListener(runtimeMessageCallback); +                        } +                    }, timeout); + +                    userCallback({action, params}, {resolve: cleanupResolve, sender}); +                }; + +                eventHandler.addListener(runtimeMessageCallback); +            } else { +                throw new Error('Event handler type not supported'); +            } + +            return listenerPromise; +        } +          // Private          _onMessage({action, params}, sender, callback) { |