aboutsummaryrefslogtreecommitdiff
path: root/extensions
diff options
context:
space:
mode:
authorIgor Soarez <igor@soarez.org>2026-11-08 16:10:10 +0000
committerIgor Soarez <igor@soarez.org>2026-11-08 16:10:10 +0000
commit69d7159eef27d541cf01ea3ea1471ef0ce3a7677 (patch)
tree83c710c67e964b96da91b68c3825bc94a2ab24ea /extensions
parent56356bd3400c104eb0b7af1322ff515c155ef7a4 (diff)
overlay.clear: run in the page's own world with the click the fallback uses
The isolated-world body events did not free a 1Password-blocked tab; the DOM click fallback (MAIN world, full pointer event shape, el.click()) did. Use that shape, aimed at the page root so no control is clicked.
Diffstat (limited to 'extensions')
-rw-r--r--extensions/chrome-profile-bridge/browser-extension/service_worker.js18
1 files changed, 11 insertions, 7 deletions
diff --git a/extensions/chrome-profile-bridge/browser-extension/service_worker.js b/extensions/chrome-profile-bridge/browser-extension/service_worker.js
index b1710ef..e3f5a05 100644
--- a/extensions/chrome-profile-bridge/browser-extension/service_worker.js
+++ b/extensions/chrome-profile-bridge/browser-extension/service_worker.js
@@ -709,7 +709,7 @@ async function overlayBlockedError(tabId) {
}
// Injected into the page by overlay.clear. Removes other extensions' iframes (including inside
-// open shadow roots), blurs the focused field, sends Escape and clicks the page body.
+// open shadow roots), blurs the focused field, sends Escape and clicks the page root.
function clearForeignOverlays(ownId) {
const removed = [];
const visit = (root) => {
@@ -727,11 +727,15 @@ function clearForeignOverlays(ownId) {
if (active && active !== document.body && typeof active.blur === "function") active.blur();
document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", code: "Escape", bubbles: true }));
// A click outside is what closes a password manager's inline menu (measured on 1Password: this,
- // not Escape or blur, is what freed the tab). Sent to the body, so no page control is clicked.
- for (const type of ["pointerdown", "mousedown", "pointerup", "mouseup", "click"]) {
- const Ctor = type.startsWith("pointer") && typeof PointerEvent === "function" ? PointerEvent : MouseEvent;
- document.body.dispatchEvent(new Ctor(type, { bubbles: true, cancelable: true, view: window, button: 0, clientX: 900, clientY: 500 }));
- }
+ // not Escape or blur, is what freed the tab). Same event shape as domClickFallback, which worked,
+ // sent to the page root so no page control is clicked.
+ const root = document.documentElement;
+ const init = { bubbles: true, cancelable: true, view: window, clientX: 900, clientY: 500, button: 0, buttons: 1 };
+ root.dispatchEvent(new PointerEvent("pointerdown", { ...init, pointerId: 1, pointerType: "mouse", isPrimary: true }));
+ root.dispatchEvent(new MouseEvent("mousedown", init));
+ 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 };
}
@@ -739,7 +743,7 @@ async function clearOverlay(params) {
const tab = await getTabByParams(params, { createOwnedTarget: false });
let injected = { removed: [] };
try {
- const [first] = await executeScriptTimed({ target: { tabId: tab.id }, func: clearForeignOverlays, args: [chrome.runtime.id] }, "chrome_clear_overlay");
+ const [first] = await executeScriptTimed({ target: { tabId: tab.id, frameIds: [0] }, world: "MAIN", func: clearForeignOverlays, args: [chrome.runtime.id] }, "chrome_clear_overlay");
injected = first?.result ?? injected;
} catch (error) {
throw new Error(`Could not run the clean-up on tab ${tab.id}: ${error?.message || error}`);