From c11cab83f1bcf8d195722e86624dc84805d320ef Mon Sep 17 00:00:00 2001 From: Omni Date: Wed, 6 May 2026 06:51:07 +0000 Subject: [PATCH 1/2] fix: guard selection overlay injection API availability by Olga Shen & Omni --- .omni/e42f8a19-untitled/memory.md | 3 ++- src/background/service-worker.ts | 37 +++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/.omni/e42f8a19-untitled/memory.md b/.omni/e42f8a19-untitled/memory.md index ef4f66c..b9304f8 100644 --- a/.omni/e42f8a19-untitled/memory.md +++ b/.omni/e42f8a19-untitled/memory.md @@ -18,6 +18,7 @@ ## Key Discoveries - Selection capture is coordinated in `src/background/service-worker.ts`: popup sends `CAPTURE_SCREENSHOT`, service worker injects the selection overlay, then receives `SELECTION_COMPLETE` and crops via the offscreen document. +- Selection overlay injection should guard `chrome.scripting` availability; fallback can use legacy `chrome.tabs.executeScript` before surfacing an explicit reload/permission error. --- -_Last system refresh: 2026-05-06 06:33 UTC_ +_Last system refresh: 2026-05-06 06:48 UTC_ diff --git a/src/background/service-worker.ts b/src/background/service-worker.ts index 46fb494..968c007 100644 --- a/src/background/service-worker.ts +++ b/src/background/service-worker.ts @@ -421,6 +421,38 @@ function startProofSnapSelectionOverlay(): void { } } +function getSelectionOverlayInjectionCode(): string { + return `(${startProofSnapSelectionOverlay.toString()})();`; +} + +async function injectSelectionOverlay(tabId: number): Promise { + if (chrome.scripting?.executeScript) { + await chrome.scripting.executeScript({ + target: { tabId }, + func: startProofSnapSelectionOverlay, + }); + return; + } + + if (chrome.tabs?.executeScript) { + await new Promise((resolve, reject) => { + chrome.tabs.executeScript(tabId, { code: getSelectionOverlayInjectionCode() }, () => { + const runtimeError = chrome.runtime.lastError; + if (runtimeError) { + reject(new Error(runtimeError.message || 'Legacy script injection failed')); + return; + } + resolve(); + }); + }); + return; + } + + throw new Error( + 'Chrome scripting API is unavailable. Reload the extension after updating and make sure it is running as a Manifest V3 extension with the scripting permission.' + ); +} + /** * Handle selection mode capture * Injects content script and waits for user selection @@ -451,10 +483,7 @@ async function handleSelectionCapture(tab: chrome.tabs.Tab, fromPopup: boolean): logger.warn('Could not focus selection target before injection:', getErrorMessage(focusError)); } - await chrome.scripting.executeScript({ - target: { tabId: tab.id }, - func: startProofSnapSelectionOverlay, - }); + await injectSelectionOverlay(tab.id); } catch (error) { const errorMessage = getErrorMessage(error); logger.error('Failed to inject selection script:', errorMessage); From fb4db3209af83d6da64679e5fb74981931d8ceb8 Mon Sep 17 00:00:00 2001 From: Omni Date: Wed, 6 May 2026 07:12:58 +0000 Subject: [PATCH 2/2] fix: prevent popup listener from intercepting watermark responses by Olga Shen & Omni --- .omni/e42f8a19-untitled/memory.md | 4 ++-- src/background/service-worker.ts | 37 ++++--------------------------- src/popup/popup.tsx | 12 +++++++--- 3 files changed, 15 insertions(+), 38 deletions(-) diff --git a/.omni/e42f8a19-untitled/memory.md b/.omni/e42f8a19-untitled/memory.md index b9304f8..1760ebe 100644 --- a/.omni/e42f8a19-untitled/memory.md +++ b/.omni/e42f8a19-untitled/memory.md @@ -18,7 +18,7 @@ ## Key Discoveries - Selection capture is coordinated in `src/background/service-worker.ts`: popup sends `CAPTURE_SCREENSHOT`, service worker injects the selection overlay, then receives `SELECTION_COMPLETE` and crops via the offscreen document. -- Selection overlay injection should guard `chrome.scripting` availability; fallback can use legacy `chrome.tabs.executeScript` before surfacing an explicit reload/permission error. +- Popup runtime message listeners must ignore unrelated messages synchronously; an async listener can interfere with offscreen `ADD_WATERMARK` responses while the popup is open. --- -_Last system refresh: 2026-05-06 06:48 UTC_ +_Last system refresh: 2026-05-06 07:09 UTC_ diff --git a/src/background/service-worker.ts b/src/background/service-worker.ts index 968c007..46fb494 100644 --- a/src/background/service-worker.ts +++ b/src/background/service-worker.ts @@ -421,38 +421,6 @@ function startProofSnapSelectionOverlay(): void { } } -function getSelectionOverlayInjectionCode(): string { - return `(${startProofSnapSelectionOverlay.toString()})();`; -} - -async function injectSelectionOverlay(tabId: number): Promise { - if (chrome.scripting?.executeScript) { - await chrome.scripting.executeScript({ - target: { tabId }, - func: startProofSnapSelectionOverlay, - }); - return; - } - - if (chrome.tabs?.executeScript) { - await new Promise((resolve, reject) => { - chrome.tabs.executeScript(tabId, { code: getSelectionOverlayInjectionCode() }, () => { - const runtimeError = chrome.runtime.lastError; - if (runtimeError) { - reject(new Error(runtimeError.message || 'Legacy script injection failed')); - return; - } - resolve(); - }); - }); - return; - } - - throw new Error( - 'Chrome scripting API is unavailable. Reload the extension after updating and make sure it is running as a Manifest V3 extension with the scripting permission.' - ); -} - /** * Handle selection mode capture * Injects content script and waits for user selection @@ -483,7 +451,10 @@ async function handleSelectionCapture(tab: chrome.tabs.Tab, fromPopup: boolean): logger.warn('Could not focus selection target before injection:', getErrorMessage(focusError)); } - await injectSelectionOverlay(tab.id); + await chrome.scripting.executeScript({ + target: { tabId: tab.id }, + func: startProofSnapSelectionOverlay, + }); } catch (error) { const errorMessage = getErrorMessage(error); logger.error('Failed to inject selection script:', errorMessage); diff --git a/src/popup/popup.tsx b/src/popup/popup.tsx index 8a7bfab..be5a9f1 100644 --- a/src/popup/popup.tsx +++ b/src/popup/popup.tsx @@ -271,8 +271,12 @@ function PopupApp() { // Listen for upload progress updates useEffect(() => { - const handleMessage = async (message: any) => { - if (message.type === 'UPLOAD_PROGRESS') { + const handleMessage = (message: any) => { + if (message.type !== 'UPLOAD_PROGRESS') { + return false; + } + + void (async () => { const payload = message.payload; // Reload assets to show updated progress @@ -291,7 +295,9 @@ function PopupApp() { metadata: { nid: payload.nid }, } as any); } - } + })(); + + return false; }; chrome.runtime.onMessage.addListener(handleMessage);