diff --git a/src/background/contentScript.ts b/src/background/contentScript.ts index 22628da316..d31535fd94 100644 --- a/src/background/contentScript.ts +++ b/src/background/contentScript.ts @@ -46,19 +46,19 @@ function makeTargetKey(target: Target): string { return JSON.stringify({ tabId: target.tabId, frameId: target.frameId }); } -/** - * Runtime message handler to handle ENSURE_CONTENT_SCRIPT_READY messages sent from the contentScript - */ // eslint-disable-next-line @typescript-eslint/promise-function-async -- Message handlers must return undefined to "pass through", not Promise -function onContentScriptReadyMessage( +function onMessage( message: unknown, sender: Runtime.MessageSender, -): Promise | undefined { +): Promise | undefined { if ( - isRemoteProcedureCallRequest(message) && - message.type === ENSURE_CONTENT_SCRIPT_READY && - sender.id === browser.runtime.id + !isRemoteProcedureCallRequest(message) || + sender.id !== browser.runtime.id ) { + return; // Don't handle message + } + + if (message.type === ENSURE_CONTENT_SCRIPT_READY) { const key = makeSenderKey(sender); try { @@ -73,6 +73,10 @@ function onContentScriptReadyMessage( return Promise.resolve(); } + if (message.type === "WHO_AM_I") { + return Promise.resolve(sender); + } + // Don't return anything to indicate this didn't handle the message } @@ -162,5 +166,5 @@ async function ensureContentScriptWithoutTimeout( } export function initContentScriptReadyListener() { - browser.runtime.onMessage.addListener(onContentScriptReadyMessage); + browser.runtime.onMessage.addListener(onMessage); } diff --git a/src/contentScript/contentScript.ts b/src/contentScript/contentScript.ts index fc3ddbce44..349453f9b2 100644 --- a/src/contentScript/contentScript.ts +++ b/src/contentScript/contentScript.ts @@ -31,6 +31,7 @@ import { import { onContextInvalidated } from "webext-events"; import { logPromiseDuration } from "@/utils/promiseUtils"; import { initRuntimeLogging } from "@/development/runtimeLogging"; +import { type Runtime } from "webextension-polyfill"; // eslint-disable-next-line prefer-destructuring -- process.env substitution const DEBUG = process.env.DEBUG; @@ -53,7 +54,7 @@ void initRuntimeLogging(); // See note in `@/contentScript/ready.ts` for further details about the lifecycle of content scripts async function initContentScript() { - const context = top === self ? "" : `in frame ${location.href}`; + const urlInfo = top === self ? "" : `in frame ${location.href}`; const uuid = uuidv4(); if (isInstalledInThisSession()) { @@ -62,12 +63,26 @@ async function initContentScript() { // Prior to 1.7.31 we had been using `webext-dynamic-content-scripts` which can inject the same content script // multiple times: https://github.com/pixiebrix/pixiebrix-extension/pull/5743 console.warn( - `contentScript: was requested twice in the same context, skipping content script initialization ${context}`, + `contentScript: was requested twice in the same context, skipping content script initialization ${urlInfo}`, ); return; } - console.debug(`contentScript: importing ${uuid} ${context}`); + // Do not use the Messenger, it cannot appear in this bundle + const context: Runtime.MessageSender | undefined = + await browser.runtime.sendMessage({ type: "WHO_AM_I" }); + if (!context) { + console.error( + "contentScript: nobody answered the WHO_AM_I context check. Loading might fail later.", + ); + } else if (!("tab" in context)) { + console.warn("contentScript: not available in tabless iframes", { + context, + }); + return; + } + + console.debug(`contentScript: importing ${uuid} ${urlInfo}`); setInstalledInThisSession();