aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extensions/chrome-profile-bridge/browser-extension/service_worker.js18
-rw-r--r--test-suite/unit/overlay.test.mjs3
2 files changed, 13 insertions, 8 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}`);
diff --git a/test-suite/unit/overlay.test.mjs b/test-suite/unit/overlay.test.mjs
index a4247b3..87c8fb9 100644
--- a/test-suite/unit/overlay.test.mjs
+++ b/test-suite/unit/overlay.test.mjs
@@ -52,6 +52,7 @@ test("overlay.clear removes the frame and reports the tab usable", async () => {
assert.deepEqual(result.removedFrames, ["chrome-extension://aeblf/inline/universal-sign-on/x.html"]);
assert.equal(result.debuggerAttachable, true);
assert.equal(calls[0].options.args[0], "ours");
+ assert.equal(calls[0].options.world, "MAIN");
});
test("overlay.clear says so when the tab is still blocked (toolbar popup, desktop app)", async () => {
@@ -73,7 +74,7 @@ test("the injected clean-up removes foreign extension iframes, not ours, and blu
let blurred = false, escaped = false;
const bodyEvents = [];
const sandbox = {
- document: { querySelectorAll: () => [foreign, ours, page, host], activeElement: { blur: () => { blurred = true; } }, body: { dispatchEvent: (e) => { bodyEvents.push(e.type); } }, dispatchEvent: (e) => { escaped = e.key === "Escape"; } },
+ document: { querySelectorAll: () => [foreign, ours, page, host], activeElement: { blur: () => { blurred = true; } }, body: {}, documentElement: { dispatchEvent: (e) => { bodyEvents.push(e.type); }, click: () => { bodyEvents.push("click"); } }, dispatchEvent: (e) => { escaped = e.key === "Escape"; } },
KeyboardEvent: class { constructor(type, init) { this.type = type; Object.assign(this, init); } },
MouseEvent: class { constructor(type) { this.type = type; } },
PointerEvent: class { constructor(type) { this.type = type; } },