aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/fg/js/frame-offset-forwarder.js17
-rw-r--r--ext/fg/js/frontend-initialize.js18
-rw-r--r--ext/mixed/js/core.js36
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) {