1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-31 00:33:33 +00:00

Handle when events are intercepted by the host site

This commit is contained in:
Jeffrey Holland
2025-12-03 11:40:56 +01:00
parent 4a4ce8312c
commit ba628d549a
4 changed files with 56 additions and 0 deletions

View File

@@ -1226,6 +1226,36 @@ describe("AutofillInlineMenuList", () => {
});
});
describe("pointerdown event", () => {
it("prevents list updates from destroying buttons mid-click", async () => {
postWindowMessage(
createInitAutofillInlineMenuListMessageMock({
authStatus: AuthenticationStatus.Unlocked,
ciphers: [],
portKey,
}),
);
await flushPromises();
const newItemButton = autofillInlineMenuList["newItemButtonElement"];
expect(newItemButton).toBeDefined();
const pointerDownEvent = new Event("pointerdown", { bubbles: true });
globalThis.document.dispatchEvent(pointerDownEvent);
postWindowMessage({
command: "updateAutofillInlineMenuListCiphers",
ciphers: [],
showInlineMenuAccountCreation: true,
portKey,
token: "test-token",
});
await flushPromises();
expect(autofillInlineMenuList["newItemButtonElement"]).toBe(newItemButton);
});
});
describe("keydown event", () => {
beforeEach(() => {
postWindowMessage(createInitAutofillInlineMenuListMessageMock({ portKey }));

View File

@@ -476,6 +476,11 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
ciphers,
showInlineMenuAccountCreation,
}: UpdateAutofillInlineMenuListCiphersParams) {
// Skip updates while user is actively clicking to prevent destroying buttons mid-click
if (this.pointerIsDown) {
return;
}
if (this.isPasskeyAuthInProgress) {
return;
}

View File

@@ -17,6 +17,7 @@ export class AutofillInlineMenuPageElement extends HTMLElement {
/** Non-null asserted. */
protected windowMessageHandlers!: AutofillInlineMenuPageElementWindowMessageHandlers;
private token?: string;
protected pointerIsDown = false;
constructor() {
super();
@@ -94,8 +95,25 @@ export class AutofillInlineMenuPageElement extends HTMLElement {
globalThis.addEventListener(EVENTS.MESSAGE, this.handleWindowMessage);
globalThis.addEventListener(EVENTS.BLUR, this.handleWindowBlurEvent);
globalThis.document.addEventListener(EVENTS.KEYDOWN, this.handleDocumentKeyDownEvent);
globalThis.document.addEventListener(EVENTS.POINTERDOWN, this.handlePointerDownEvent, true);
globalThis.document.addEventListener(EVENTS.POINTERUP, this.handlePointerUpEvent, true);
globalThis.document.addEventListener(EVENTS.POINTERCANCEL, this.handlePointerUpEvent, true);
}
/**
* Handles pointerdown events. Sets a flag when the user is actively interacting with the menu.
*/
private handlePointerDownEvent = () => {
this.pointerIsDown = true;
};
/**
* Handles pointerup/pointercancel events. Clears the `pointerIsDown` flag.
*/
private handlePointerUpEvent = () => {
this.pointerIsDown = false;
};
/**
* Handles window messages from the parent window.
*

View File

@@ -25,6 +25,9 @@ export const EVENTS = {
MOUSELEAVE: "mouseleave",
MOUSEUP: "mouseup",
MOUSEOUT: "mouseout",
POINTERDOWN: "pointerdown",
POINTERUP: "pointerup",
POINTERCANCEL: "pointercancel",
SUBMIT: "submit",
} as const;