mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 16:23:44 +00:00
[PM-5189] Fixing an issue with how we handle closing the inline menu after a programmtic redirection
This commit is contained in:
@@ -1488,6 +1488,7 @@ describe("OverlayBackground", () => {
|
||||
|
||||
describe("triggerDelayedAutofillInlineMenuClosure message handler", () => {
|
||||
it("skips triggering the delayed closure of the inline menu if a field is currently focused", async () => {
|
||||
jest.useFakeTimers();
|
||||
sendMockExtensionMessage({
|
||||
command: "updateIsFieldCurrentlyFocused",
|
||||
isFieldCurrentlyFocused: true,
|
||||
@@ -1499,6 +1500,7 @@ describe("OverlayBackground", () => {
|
||||
portKey,
|
||||
});
|
||||
await flushPromises();
|
||||
jest.advanceTimersByTime(100);
|
||||
|
||||
const message = { command: "triggerDelayedAutofillInlineMenuClosure" };
|
||||
expect(buttonPortSpy.postMessage).not.toHaveBeenCalledWith(message);
|
||||
@@ -1506,16 +1508,42 @@ describe("OverlayBackground", () => {
|
||||
});
|
||||
|
||||
it("sends a message to the button and list ports that triggers a delayed closure of the inline menu", async () => {
|
||||
jest.useFakeTimers();
|
||||
sendPortMessage(buttonMessageConnectorSpy, {
|
||||
command: "triggerDelayedAutofillInlineMenuClosure",
|
||||
portKey,
|
||||
});
|
||||
await flushPromises();
|
||||
jest.advanceTimersByTime(100);
|
||||
|
||||
const message = { command: "triggerDelayedAutofillInlineMenuClosure" };
|
||||
expect(buttonPortSpy.postMessage).toHaveBeenCalledWith(message);
|
||||
expect(listPortSpy.postMessage).toHaveBeenCalledWith(message);
|
||||
});
|
||||
|
||||
it("triggers a single delayed closure if called again within a 100ms threshold", async () => {
|
||||
jest.useFakeTimers();
|
||||
sendPortMessage(buttonMessageConnectorSpy, {
|
||||
command: "triggerDelayedAutofillInlineMenuClosure",
|
||||
portKey,
|
||||
});
|
||||
await flushPromises();
|
||||
jest.advanceTimersByTime(50);
|
||||
sendPortMessage(buttonMessageConnectorSpy, {
|
||||
command: "triggerDelayedAutofillInlineMenuClosure",
|
||||
portKey,
|
||||
});
|
||||
await flushPromises();
|
||||
jest.advanceTimersByTime(100);
|
||||
|
||||
const message = { command: "triggerDelayedAutofillInlineMenuClosure" };
|
||||
expect(buttonPortSpy.postMessage).toHaveBeenCalledTimes(2);
|
||||
expect(buttonPortSpy.postMessage).not.toHaveBeenNthCalledWith(1, message);
|
||||
expect(buttonPortSpy.postMessage).toHaveBeenNthCalledWith(2, message);
|
||||
expect(listPortSpy.postMessage).toHaveBeenCalledTimes(2);
|
||||
expect(listPortSpy.postMessage).not.toHaveBeenNthCalledWith(1, message);
|
||||
expect(listPortSpy.postMessage).toHaveBeenNthCalledWith(2, message);
|
||||
});
|
||||
});
|
||||
|
||||
describe("autofillInlineMenuBlurred message handler", () => {
|
||||
|
||||
@@ -60,6 +60,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
private inlineMenuPageTranslations: Record<string, string>;
|
||||
private inlineMenuFadeInTimeout: number | NodeJS.Timeout;
|
||||
private updateInlineMenuPositionTimeout: number | NodeJS.Timeout;
|
||||
private delayedCloseTimeout: number | NodeJS.Timeout;
|
||||
private focusedFieldData: FocusedFieldData;
|
||||
private isFieldCurrentlyFocused: boolean = false;
|
||||
private isFieldCurrentlyFilling: boolean = false;
|
||||
@@ -99,8 +100,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
deletedCipher: () => this.updateInlineMenuCiphers(),
|
||||
};
|
||||
private readonly inlineMenuButtonPortMessageHandlers: InlineMenuButtonPortMessageHandlers = {
|
||||
triggerDelayedAutofillInlineMenuClosure: ({ port }) =>
|
||||
this.triggerDelayedInlineMenuClosure(port.sender),
|
||||
triggerDelayedAutofillInlineMenuClosure: ({ port }) => this.triggerDelayedInlineMenuClosure(),
|
||||
autofillInlineMenuButtonClicked: ({ port }) => this.handleInlineMenuButtonClicked(port),
|
||||
autofillInlineMenuBlurred: () => this.checkInlineMenuListFocused(),
|
||||
redirectAutofillInlineMenuFocusOut: ({ message, port }) =>
|
||||
@@ -372,7 +372,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
}
|
||||
}
|
||||
|
||||
this.updateInlineMenuPositionTimeout = setTimeout(
|
||||
this.updateInlineMenuPositionTimeout = globalThis.setTimeout(
|
||||
() => this.updateInlineMenuPositionAfterSubFrameRebuild(sender),
|
||||
650,
|
||||
);
|
||||
@@ -510,17 +510,29 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
* Sends a message to the sender tab to trigger a delayed closure of the inline menu.
|
||||
* This is used to ensure that we capture click events on the inline menu in the case
|
||||
* that some on page programmatic method attempts to force focus redirection.
|
||||
*
|
||||
* @param sender - The sender of the port message
|
||||
*/
|
||||
private triggerDelayedInlineMenuClosure(sender: chrome.runtime.MessageSender) {
|
||||
private triggerDelayedInlineMenuClosure() {
|
||||
if (this.isFieldCurrentlyFocused) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clearDelayedInlineMenuClosure();
|
||||
|
||||
this.delayedCloseTimeout = globalThis.setTimeout(() => {
|
||||
const message = { command: "triggerDelayedAutofillInlineMenuClosure" };
|
||||
this.inlineMenuButtonPort?.postMessage(message);
|
||||
this.inlineMenuListPort?.postMessage(message);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the delayed closure timeout for the inline menu, effectively
|
||||
* cancelling the event from occurring.
|
||||
*/
|
||||
private clearDelayedInlineMenuClosure() {
|
||||
if (this.delayedCloseTimeout) {
|
||||
clearTimeout(this.delayedCloseTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -772,6 +784,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clearDelayedInlineMenuClosure();
|
||||
await this.openInlineMenu(false, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -416,7 +416,7 @@ describe("AutofillInlineMenuIframeService", () => {
|
||||
"opacity 65ms ease-out 0s",
|
||||
);
|
||||
|
||||
jest.advanceTimersByTime(200);
|
||||
jest.advanceTimersByTime(100);
|
||||
expect(autofillInlineMenuIframeService["iframe"].style.transition).toBe(
|
||||
"opacity 125ms ease-out 0s",
|
||||
);
|
||||
|
||||
@@ -322,7 +322,7 @@ export class AutofillInlineMenuIframeService implements AutofillInlineMenuIframe
|
||||
this.delayedCloseTimeout = globalThis.setTimeout(() => {
|
||||
this.updateElementStyles(this.iframe, { transition: this.fadeInOpacityTransition });
|
||||
this.forceCloseInlineMenu();
|
||||
}, 200);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user