1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-01-10 19:38:11 +01:00

[PM-5189] Fixing issues found with focusing elements between iframes, as well as fade in of the inline menu in a simultaneous manner for all visual elements

This commit is contained in:
Cesar Gonzalez 2024-05-22 06:50:51 -05:00
parent 0dfdad07e2
commit 2ed62cc6a4
No known key found for this signature in database
GPG Key ID: 3381A5457F8CCECF
7 changed files with 45 additions and 18 deletions

View File

@ -54,6 +54,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
private pageDetailsForTab: PageDetailsForTab = {};
private subFrameOffsetsForTab: SubFrameOffsetsForTab = {};
private updateInlineMenuPositionTimeout: number | NodeJS.Timeout;
private inlineMenuFadeInTimeout: number | NodeJS.Timeout;
private userAuthStatus: AuthenticationStatus = AuthenticationStatus.LoggedOut;
private inlineMenuButtonPort: chrome.runtime.Port;
private inlineMenuListPort: chrome.runtime.Port;
@ -440,7 +441,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
return;
}
if (sender.frameId === this.focusedFieldData?.frameId && this.isFieldCurrentlyFocused) {
if (this.isFieldCurrentlyFocused) {
return;
}
@ -518,9 +519,11 @@ export class OverlayBackground implements OverlayBackgroundInterface {
subFrameOffsets = subFrameOffsetsForTab.get(this.focusedFieldData.frameId);
}
this.setInlineMenuFadeInTimeout();
if (overlayElement === AutofillOverlayElement.Button) {
this.inlineMenuButtonPort?.postMessage({
command: "updateIframePosition",
command: "updateInlineMenuIframePosition",
styles: this.getInlineMenuButtonPosition(subFrameOffsets),
});
@ -528,11 +531,23 @@ export class OverlayBackground implements OverlayBackgroundInterface {
}
this.inlineMenuListPort?.postMessage({
command: "updateIframePosition",
command: "updateInlineMenuIframePosition",
styles: this.getInlineMenuListPosition(subFrameOffsets),
});
}
private setInlineMenuFadeInTimeout() {
if (this.inlineMenuFadeInTimeout) {
globalThis.clearTimeout(this.inlineMenuFadeInTimeout);
}
const message = { command: "updateInlineMenuIframePosition", styles: { opacity: "1" } };
this.inlineMenuFadeInTimeout = globalThis.setTimeout(() => {
this.inlineMenuButtonPort?.postMessage(message);
this.inlineMenuListPort?.postMessage(message);
}, 75);
}
/**
* Gets the position of the focused field and calculates the position
* of the inline menu button based on the focused field's position and dimensions.
@ -600,6 +615,14 @@ export class OverlayBackground implements OverlayBackgroundInterface {
{ focusedFieldData }: OverlayBackgroundExtensionMessage,
sender: chrome.runtime.MessageSender,
) {
if (this.focusedFieldData?.frameId && this.focusedFieldData.frameId !== sender.frameId) {
void BrowserApi.tabSendMessage(
sender.tab,
{ command: "unsetMostRecentlyFocusedField" },
{ frameId: this.focusedFieldData.frameId },
);
}
this.focusedFieldData = { ...focusedFieldData, tabId: sender.tab.id, frameId: sender.frameId };
}
@ -922,7 +945,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
private updateInlineMenuListHeight(message: OverlayBackgroundExtensionMessage) {
this.inlineMenuListPort?.postMessage({
command: "updateIframePosition",
command: "updateInlineMenuIframePosition",
styles: message.styles,
});
}

View File

@ -15,7 +15,9 @@ export type BackgroundPortMessageHandlers = {
message,
}: AutofillInlineMenuIframeExtensionMessageParam) => void;
initAutofillInlineMenuList: ({ message }: AutofillInlineMenuIframeExtensionMessageParam) => void;
updateIframePosition: ({ message }: AutofillInlineMenuIframeExtensionMessageParam) => void;
updateInlineMenuIframePosition: ({
message,
}: AutofillInlineMenuIframeExtensionMessageParam) => void;
updateInlineMenuHidden: ({ message }: AutofillInlineMenuIframeExtensionMessageParam) => void;
updateAutofillInlineMenuColorScheme: () => void;
};

View File

@ -104,9 +104,7 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
}
this.buttonElement.remove();
this.isButtonVisible = false;
void this.sendExtensionMessage("autofillOverlayElementClosed", {
overlayElement: AutofillOverlayElement.Button,
});
@ -121,9 +119,7 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
}
this.listElement.remove();
this.isListVisible = false;
void this.sendExtensionMessage("autofillOverlayElementClosed", {
overlayElement: AutofillOverlayElement.List,
});

View File

@ -193,9 +193,9 @@ describe("AutofillInlineMenuIframeService", () => {
});
it("handles port messages that are registered with the message handlers and does not pass the message on to the iframe", () => {
jest.spyOn(autofillInlineMenuIframeService as any, "updateIframePosition");
jest.spyOn(autofillInlineMenuIframeService as any, "updateInlineMenuIframePosition");
sendPortMessage(portSpy, { command: "updateIframePosition" });
sendPortMessage(portSpy, { command: "updateInlineMenuIframePosition" });
expect(
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
@ -344,7 +344,7 @@ describe("AutofillInlineMenuIframeService", () => {
jest.spyOn(globalThis.document, "hasFocus").mockReturnValue(false);
sendPortMessage(portSpy, {
command: "updateIframePosition",
command: "updateInlineMenuIframePosition",
styles: { top: 100, left: 100 },
});
@ -355,7 +355,7 @@ describe("AutofillInlineMenuIframeService", () => {
const styles = { top: "100px", left: "100px" };
sendPortMessage(portSpy, {
command: "updateIframePosition",
command: "updateInlineMenuIframePosition",
styles,
});
@ -368,7 +368,7 @@ describe("AutofillInlineMenuIframeService", () => {
const styles = { top: "100px", left: "100px" };
sendPortMessage(portSpy, {
command: "updateIframePosition",
command: "updateInlineMenuIframePosition",
styles,
});
@ -382,7 +382,7 @@ describe("AutofillInlineMenuIframeService", () => {
const styles = { top: "100px", left: "100px" };
sendPortMessage(portSpy, {
command: "updateIframePosition",
command: "updateInlineMenuIframePosition",
styles,
});

View File

@ -44,7 +44,7 @@ export class AutofillInlineMenuIframeService implements AutofillInlineMenuIframe
private readonly backgroundPortMessageHandlers: BackgroundPortMessageHandlers = {
initAutofillInlineMenuButton: ({ message }) => this.initAutofillInlineMenu(message),
initAutofillInlineMenuList: ({ message }) => this.initAutofillInlineMenu(message),
updateIframePosition: ({ message }) => this.updateIframePosition(message.styles),
updateInlineMenuIframePosition: ({ message }) => this.updateIframePosition(message.styles),
updateInlineMenuHidden: ({ message }) => this.updateElementStyles(this.iframe, message.styles),
updateAutofillInlineMenuColorScheme: () => this.updateAutofillInlineMenuColorScheme(),
};
@ -248,7 +248,7 @@ export class AutofillInlineMenuIframeService implements AutofillInlineMenuIframe
}
this.updateElementStyles(this.iframe, position);
setTimeout(() => this.updateElementStyles(this.iframe, { opacity: "1" }), 0);
// setTimeout(() => this.updateElementStyles(this.iframe, { opacity: "1" }), 0);
this.announceAriaAlert();
}

View File

@ -16,6 +16,7 @@ export type AutofillOverlayContentExtensionMessageHandlers = {
openAutofillInlineMenu: ({ message }: AutofillExtensionMessageParam) => void;
addNewVaultItemFromOverlay: () => void;
blurMostRecentlyFocusedField: () => void;
unsetMostRecentlyFocusedField: () => void;
bgUnlockPopoutOpened: () => void;
bgVaultItemRepromptPopoutOpened: () => void;
redirectAutofillInlineMenuFocusOut: ({ message }: AutofillExtensionMessageParam) => void;

View File

@ -44,6 +44,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
openAutofillInlineMenu: ({ message }) => this.openAutofillInlineMenu(message),
addNewVaultItemFromOverlay: () => this.addNewVaultItem(),
blurMostRecentlyFocusedField: () => this.blurMostRecentlyFocusedField(),
unsetMostRecentlyFocusedField: () => this.unsetMostRecentlyFocusedField(),
bgUnlockPopoutOpened: () => this.blurMostRecentlyFocusedField(true),
bgVaultItemRepromptPopoutOpened: () => this.blurMostRecentlyFocusedField(true),
redirectAutofillInlineMenuFocusOut: ({ message }) =>
@ -162,6 +163,10 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
}
}
unsetMostRecentlyFocusedField() {
this.mostRecentlyFocusedField = null;
}
/**
* Formats any found user filled fields for a login cipher and sends a message
* to the background script to add a new cipher.
@ -797,7 +802,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
await this.updateMostRecentlyFocusedField(this.mostRecentlyFocusedField);
this.updateAutofillInlineMenuElementsPosition();
setTimeout(async () => {
this.toggleAutofillInlineMenuHidden(false);
this.toggleAutofillInlineMenuHidden(false, true);
if (
await this.hideAutofillInlineMenuListOnFilledField(
this.mostRecentlyFocusedField as FillableFormFieldElement,