From 51e03ad99af5afb340f4896ce69970fa4129a614 Mon Sep 17 00:00:00 2001 From: Constantin Piber Date: Sat, 17 Aug 2024 14:12:24 +0200 Subject: [PATCH] [#56] Refactor message sending to work with Chrome With MV3, there is a second handler in offscreen.ts. `sendResponse` must be called synchronously, or one must return `true`. This does not seem to be handled properly by the polyfill, so do it ourselves. Also remove an unnecessary handler causing problems. --- src/scripts/background/misc.ts | 25 +++---------------------- src/scripts/background_script.ts | 12 +++++++----- src/scripts/content/nebula/index.ts | 7 +++---- src/scripts/content/youtube/index.ts | 4 +++- src/scripts/offscreen.ts | 10 +++------- 5 files changed, 19 insertions(+), 39 deletions(-) diff --git a/src/scripts/background/misc.ts b/src/scripts/background/misc.ts index 09d0c3a..cc851ca 100644 --- a/src/scripts/background/misc.ts +++ b/src/scripts/background/misc.ts @@ -36,34 +36,15 @@ async function closeOffscreenDocument() { await getBrowserInstance().offscreen.closeDocument(); } -let dataPromiseResolve: (data: Creator[]) => void | undefined = undefined; -getBrowserInstance().runtime.onMessage.addListener(async (message: { [key: string]: any; }) => { - if (message.target !== 'background') { - return false; - } - console.dev.log('Received message from offcanvas', message); - switch (message.type) { - case 'receiveCreatorInformation': { - console.dev.log('dataPromiseResolve is set?', !!dataPromiseResolve); - if (dataPromiseResolve) dataPromiseResolve(message.data); - } break; - } -}); - export const loadCreators: () => Promise = (() => { if (__MV3__) { console.info('MV3! Using offscreen API instead'); return async () => { await setupOffscreenDocument('offscreen.html'); - const data = await new Promise(async resolve => { - dataPromiseResolve = resolve; - - await getBrowserInstance().runtime.sendMessage({ - type: 'getCreatorInformation', - target: 'offscreen', - }); + const data: Creator[] = await getBrowserInstance().runtime.sendMessage({ + type: 'getCreatorInformation', + target: 'offscreen', }); - dataPromiseResolve = undefined; await closeOffscreenDocument(); console.dev.log('Creator data:', data); return data; diff --git a/src/scripts/background_script.ts b/src/scripts/background_script.ts index 672bea8..35eedf0 100644 --- a/src/scripts/background_script.ts +++ b/src/scripts/background_script.ts @@ -14,7 +14,9 @@ if (getBrowserInstance().action) { getBrowserInstance().browserAction.onClicked.addListener(() => openOptions()); } -getBrowserInstance().runtime.onMessage.addListener((message: string | { [key: string]: any; }) => { +// NOTE: not promise-based, because Chrome really doesn't like it, when there are multiple listeners +// need to return immediately, then call sendResponse manually, otherwise the other listener in offscreen.ts interferes +getBrowserInstance().runtime.onMessage.addListener((message: string | { [key: string]: any; }, sender, sendResponse) => { // Return early if this message isn't meant for the background script if (typeof message !== 'string' && message.target !== undefined && message.target !== 'background') { return; @@ -23,7 +25,7 @@ getBrowserInstance().runtime.onMessage.addListener((message: string | { [key: st const keepAlive = setInterval(getBrowserInstance().runtime.getPlatformInfo, 25 * 1000); let ret: Promise; try { - const msg = parseTypeObject(message); + const msg = parseTypeObject<{ type: string, name?: string; }>(message); console.dev.log('Handling message', msg); switch (msg.type) { case BrowserMessage.INIT_PAGE: @@ -41,11 +43,11 @@ getBrowserInstance().runtime.onMessage.addListener((message: string | { [key: st } if (ret) { ret.then( - res => console.dev.log('Result for', msg.type, ':', res), - err => console.dev.log('Error running', msg.type, ':', err), + res => { console.dev.log('Result for', msg.type, ':', res); sendResponse({ res }); }, + err => { console.dev.log('Error running', msg.type, ':', err); sendResponse({ err }); }, ); + return true; } - return ret; } catch { } finally { clearInterval(keepAlive); diff --git a/src/scripts/content/nebula/index.ts b/src/scripts/content/nebula/index.ts index 5ca8c8e..171d2b3 100644 --- a/src/scripts/content/nebula/index.ts +++ b/src/scripts/content/nebula/index.ts @@ -238,10 +238,9 @@ const loadComments = async () => { console.debug(`Requesting '${title}' by ${creator} (${nebula})`); try { - // TODO: in MV3 this always returns false for some reason, even if the creator loading is fixed, so disable for now - const vid: ytvideo = await getBrowserInstance().runtime.sendMessage({ type: BrowserMessage.GET_YTID, creator, title, nebula }); - console.dev.log('got:', vid); - if (vid as any === false) throw new Error('Unknown error'); + const { res: vid, err }: { res?: ytvideo, err?: any; } = await getBrowserInstance().runtime.sendMessage({ type: BrowserMessage.GET_YTID, creator, title, nebula }); + console.dev.log('got:', vid, err); + if (!vid) throw new Error(err); e.querySelectorAll('.enhancer-yt, .enhancer-yt-err, .enhancer-yt-outside, .enhancer-yt-inside').forEach(e => e.remove()); console.debug('Found video:', vid); const v = document.createElement('span'); diff --git a/src/scripts/content/youtube/index.ts b/src/scripts/content/youtube/index.ts index bf634fa..d8e8498 100644 --- a/src/scripts/content/youtube/index.ts +++ b/src/scripts/content/youtube/index.ts @@ -123,7 +123,9 @@ const run = debounce(async ({ vidID, videoTitle, channelID, channelNice }: { vid } else { yield* videoDetailsFromDOMDesktop(); } - const vid: nebulavideo = await getBrowserInstance().runtime.sendMessage({ type: BrowserMessage.GET_VID, channelID, channelName, channelNice, videoTitle }); + const { res: vid, err }: { res?: nebulavideo, err?: any; } = await getBrowserInstance().runtime.sendMessage({ type: BrowserMessage.GET_VID, channelID, channelName, channelNice, videoTitle }); + console.dev.log('got:', vid, err); + if (!vid) throw new Error(err); console.debug('got video information', '\nchannelID:', channelID, 'channelName:', channelName, '(', channelNice, ')', 'videoTitle:', videoTitle, 'vidID:', vidID, '\non nebula?', !!vid); diff --git a/src/scripts/offscreen.ts b/src/scripts/offscreen.ts index 34e3b97..911fc21 100644 --- a/src/scripts/offscreen.ts +++ b/src/scripts/offscreen.ts @@ -1,19 +1,15 @@ import browser from 'webextension-polyfill'; import { getInformation } from './page/offscreen'; -browser.runtime.onMessage.addListener(async (message: { [key: string]: any; }) => { +browser.runtime.onMessage.addListener((message: { [key: string]: any; }, sender, sendMessage) => { if (message.target !== 'offscreen') { return false; } console.dev.log('Received message for offcanvas', message); switch (message.type) { case 'getCreatorInformation': { - const data = await getInformation(); - await browser.runtime.sendMessage({ - type: 'receiveCreatorInformation', - target: 'background', - data - }); + getInformation().then(sendMessage); + return true; } break; } }); \ No newline at end of file