Skip to content

Commit

Permalink
[#56] Refactor message sending to work with Chrome
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cpiber committed Aug 17, 2024
1 parent 99603b5 commit 51e03ad
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 39 deletions.
25 changes: 3 additions & 22 deletions src/scripts/background/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Creator[]> = (() => {
if (__MV3__) {
console.info('MV3! Using offscreen API instead');
return async () => {
await setupOffscreenDocument('offscreen.html');
const data = await new Promise<Creator[]>(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;
Expand Down
12 changes: 7 additions & 5 deletions src/scripts/background_script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -23,7 +25,7 @@ getBrowserInstance().runtime.onMessage.addListener((message: string | { [key: st
const keepAlive = setInterval(getBrowserInstance().runtime.getPlatformInfo, 25 * 1000);
let ret: Promise<any>;
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:
Expand All @@ -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);
Expand Down
7 changes: 3 additions & 4 deletions src/scripts/content/nebula/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
4 changes: 3 additions & 1 deletion src/scripts/content/youtube/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 3 additions & 7 deletions src/scripts/offscreen.ts
Original file line number Diff line number Diff line change
@@ -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;
}
});

0 comments on commit 51e03ad

Please sign in to comment.