diff options
| -rw-r--r-- | extensions/chrome-profile-bridge/browser-extension/service_worker.js | 16 | ||||
| -rw-r--r-- | extensions/chrome-profile-bridge/index.ts | 2 |
2 files changed, 13 insertions, 5 deletions
diff --git a/extensions/chrome-profile-bridge/browser-extension/service_worker.js b/extensions/chrome-profile-bridge/browser-extension/service_worker.js index e3f5a05..de4f340 100644 --- a/extensions/chrome-profile-bridge/browser-extension/service_worker.js +++ b/extensions/chrome-profile-bridge/browser-extension/service_worker.js @@ -682,6 +682,12 @@ async function findForeignExtensionTargets() { } } +// Other extensions' targets that belong to this tab: by the target's tabId, or by the tabId that +// password managers put in the frame's own URL (the frame target can come without a tabId). +function foreignTargetsForTab(all, tabId) { + return all.filter((t) => t.tabId === tabId || new RegExp(`[?&]tabId=${tabId}(?:[&#]|$)`).test(String(t.url || ""))); +} + function extractForeignExtId(targets) { for (const t of targets) { if (t.extensionId && t.extensionId !== chrome.runtime.id) return t.extensionId; @@ -699,7 +705,7 @@ const FOREIGN_EXTENSION_BLOCK = /Cannot access a chrome-extension:\/\/ URL of di // facts and lets it decide, with overlay.clear (chrome_clear_overlay) to close it when it is only // in the way. async function overlayBlockedError(tabId) { - const targets = (await findForeignExtensionTargets()).filter((t) => t.tabId === tabId); + const targets = foreignTargetsForTab(await findForeignExtensionTargets(), tabId); const url = String(targets[0]?.url || "").replace(/[?#].*$/, ""); const id = extractForeignExtId(targets) || "unknown"; return new Error( @@ -736,7 +742,8 @@ function clearForeignOverlays(ownId) { root.dispatchEvent(new PointerEvent("pointerup", { ...init, pointerId: 1, pointerType: "mouse", isPrimary: true, buttons: 0 })); root.dispatchEvent(new MouseEvent("mouseup", { ...init, buttons: 0 })); root.click(); - return { removed }; + const custom = Array.from(document.querySelectorAll("*")).filter((el) => el.tagName.includes("-")).map((el) => el.tagName.toLowerCase()); + return { removed, seen: { iframes: document.querySelectorAll("iframe").length, customElements: [...new Set(custom)].slice(0, 10), active: document.activeElement?.tagName ?? null } }; } async function clearOverlay(params) { @@ -757,8 +764,9 @@ async function clearOverlay(params) { debuggerAttachable = true; } catch {} } - const remaining = (await findForeignExtensionTargets()).filter((t) => t.tabId === tab.id).map((t) => String(t.url || "").replace(/[?#].*$/, "")); - return { tab: { id: tab.id, url: tab.url, title: tab.title }, removedFrames: injected.removed, remainingForeignTargets: remaining, debuggerAttachable, cleared: debuggerAttachable && remaining.length === 0 }; + const allForeign = await findForeignExtensionTargets(); + const remaining = foreignTargetsForTab(allForeign, tab.id).map((t) => String(t.url || "").replace(/[?#].*$/, "")); + return { tab: { id: tab.id, url: tab.url, title: tab.title }, removedFrames: injected.removed, remainingForeignTargets: remaining, foreignTargetsAnywhere: allForeign.map((t) => ({ type: t.type, tabId: t.tabId, url: String(t.url || "").replace(/[?#].*$/, "") })).slice(0, 20), injectedReport: injected, debuggerAttachable, cleared: debuggerAttachable && remaining.length === 0 }; } async function cdp(tabId, method, params, opts) { diff --git a/extensions/chrome-profile-bridge/index.ts b/extensions/chrome-profile-bridge/index.ts index 8442a58..4384967 100644 --- a/extensions/chrome-profile-bridge/index.ts +++ b/extensions/chrome-profile-bridge/index.ts @@ -2299,7 +2299,7 @@ Usage rules: const removed = result?.removedFrames ?? []; const text = result?.cleared ? `Cleared${removed.length ? `: removed ${removed.join(", ")}` : " (nothing to remove, the prompt had already gone)"}. Tab ${result.tab?.id} is usable again.` - : `The tab is still blocked${result?.remainingForeignTargets?.length ? ` by ${result.remainingForeignTargets.join(", ")}` : ""}${removed.length ? ` (removed ${removed.join(", ")} but it is still there or came back)` : ""}. The prompt may be the password manager's toolbar popup or desktop app, which this tool cannot close: tell the user, or navigate the tab away.`; + : `The tab is still blocked${result?.remainingForeignTargets?.length ? ` by ${result.remainingForeignTargets.join(", ")}` : ""}${removed.length ? ` (removed ${removed.join(", ")} but it is still there or came back)` : ""}. The prompt may be the password manager's toolbar popup or desktop app, which this tool cannot close: tell the user, or navigate the tab away. Diagnostics: ${JSON.stringify({ foreignTargetsAnywhere: (result as any)?.foreignTargetsAnywhere, injectedReport: (result as any)?.injectedReport })}`; return { content: [{ type: "text", text }], details: { value: (value ?? null) as Json } }; }, }); |
