From 94271201a29e5a120227876f087fa67c9f9da160 Mon Sep 17 00:00:00 2001 From: Cesar Gonzalez Date: Wed, 20 Mar 2024 13:58:39 -0500 Subject: [PATCH] [PM-5189] Separating the inline menu UI elements from the base AutofillOverlayContentService and setting up messaging to allow for propagation of those elements --- .../abstractions/overlay.background.ts | 8 +++ .../autofill/background/overlay.background.ts | 43 ++++++++++--- .../content/abstractions/autofill-init.ts | 1 + .../src/autofill/content/autofill-init.ts | 21 ++---- .../abstractions/inline-menu-elements.ts | 4 +- .../overlay/content/inline-menu-elements.ts | 14 +++- .../autofill-overlay-iframe.service.ts | 2 +- .../autofill-overlay-content.service.ts | 4 +- .../autofill-overlay-content.service.ts | 64 +++++++++++++------ 9 files changed, 112 insertions(+), 49 deletions(-) diff --git a/apps/browser/src/autofill/background/abstractions/overlay.background.ts b/apps/browser/src/autofill/background/abstractions/overlay.background.ts index 068efeafca9..0d3785de321 100644 --- a/apps/browser/src/autofill/background/abstractions/overlay.background.ts +++ b/apps/browser/src/autofill/background/abstractions/overlay.background.ts @@ -48,6 +48,8 @@ type OverlayBackgroundExtensionMessage = { forceCloseOverlay?: boolean; isOverlayHidden?: boolean; data?: LockedVaultPendingNotificationsData; + isFieldCurrentlyFocused?: boolean; + isCurrentlyFilling?: boolean; } & OverlayAddNewItemMessage; type OverlayPortMessage = { @@ -102,6 +104,12 @@ type OverlayBackgroundExtensionMessageHandlers = { unlockCompleted: ({ message }: BackgroundMessageParam) => void; addEditCipherSubmitted: () => void; deletedCipher: () => void; + checkIsFieldCurrentlyFocused: () => boolean; + checkIsFieldCurrentlyFilling: () => boolean; + updateIsFieldCurrentlyFocused: ({ message }: BackgroundMessageParam) => void; + updateIsFieldCurrentlyFilling: ({ message }: BackgroundMessageParam) => void; + checkIsInlineMenuButtonVisible: ({ sender }: BackgroundSenderParam) => void; + checkIsInlineMenuListVisible: ({ sender }: BackgroundSenderParam) => void; }; type PortMessageParam = { diff --git a/apps/browser/src/autofill/background/overlay.background.ts b/apps/browser/src/autofill/background/overlay.background.ts index d1983272334..b685d69106e 100644 --- a/apps/browser/src/autofill/background/overlay.background.ts +++ b/apps/browser/src/autofill/background/overlay.background.ts @@ -76,6 +76,14 @@ class OverlayBackground implements OverlayBackgroundInterface { unlockCompleted: ({ message }) => this.unlockCompleted(message), addEditCipherSubmitted: () => this.updateOverlayCiphers(), deletedCipher: () => this.updateOverlayCiphers(), + checkIsFieldCurrentlyFocused: () => this.isFieldCurrentlyFocused, + checkIsFieldCurrentlyFilling: () => this.isCurrentlyFilling, + updateIsFieldCurrentlyFocused: ({ message }) => + (this.isFieldCurrentlyFocused = message.isFieldCurrentlyFocused), + updateIsFieldCurrentlyFilling: ({ message }) => + (this.isCurrentlyFilling = message.isFieldCurrentlyFilling), + checkIsInlineMenuButtonVisible: ({ sender }) => this.checkIsInlineMenuButtonVisible(sender), + checkIsInlineMenuListVisible: ({ sender }) => this.checkIsInlineMenuListVisible(sender), }; private readonly overlayButtonPortMessageHandlers: OverlayButtonPortMessageHandlers = { overlayButtonClicked: ({ port }) => this.handleOverlayButtonClicked(port), @@ -112,6 +120,23 @@ class OverlayBackground implements OverlayBackgroundInterface { this.iconsServerUrl = this.environmentService.getIconsUrl(); } + private async checkIsInlineMenuButtonVisible(sender: chrome.runtime.MessageSender) { + const value = await BrowserApi.tabSendMessage( + sender.tab, + { command: "checkIsInlineMenuButtonVisible" }, + { frameId: 0 }, + ); + return value; + } + + private async checkIsInlineMenuListVisible(sender: chrome.runtime.MessageSender) { + return await BrowserApi.tabSendMessage( + sender.tab, + { command: "checkIsInlineMenuListVisible" }, + { frameId: 0 }, + ); + } + /** * Removes cached page details for a tab * based on the passed tabId. @@ -414,7 +439,7 @@ class OverlayBackground implements OverlayBackgroundInterface { await BrowserApi.tabSendMessage( sender.tab, - { command: "updateInlineMenuElementsPosition" }, + { command: "updateInlineMenuElementsPosition", overlayElement }, { frameId: 0 }, ); @@ -827,14 +852,14 @@ class OverlayBackground implements OverlayBackgroundInterface { translations: this.getTranslations(), ciphers: isOverlayListPort ? await this.getOverlayCipherData() : null, }); - void this.updateOverlayPosition( - { - overlayElement: isOverlayListPort - ? AutofillOverlayElement.List - : AutofillOverlayElement.Button, - }, - port.sender, - ); + // void this.updateOverlayPosition( + // { + // overlayElement: isOverlayListPort + // ? AutofillOverlayElement.List + // : AutofillOverlayElement.Button, + // }, + // port.sender, + // ); }; /** diff --git a/apps/browser/src/autofill/content/abstractions/autofill-init.ts b/apps/browser/src/autofill/content/abstractions/autofill-init.ts index 2bbd25278fe..da3d58950dd 100644 --- a/apps/browser/src/autofill/content/abstractions/autofill-init.ts +++ b/apps/browser/src/autofill/content/abstractions/autofill-init.ts @@ -13,6 +13,7 @@ export type AutofillExtensionMessage = { pageDetailsUrl?: string; ciphers?: any; isInlineMenuHidden?: boolean; + overlayElement?: string; data?: { authStatus?: AuthenticationStatus; isFocusingFieldElement?: boolean; diff --git a/apps/browser/src/autofill/content/autofill-init.ts b/apps/browser/src/autofill/content/autofill-init.ts index 929beda9832..01d619ea24b 100644 --- a/apps/browser/src/autofill/content/autofill-init.ts +++ b/apps/browser/src/autofill/content/autofill-init.ts @@ -143,27 +143,18 @@ class AutofillInit implements AutofillInitInterface { } this.blurAndRemoveOverlay(); - this.updateOverlayIsCurrentlyFilling(true); + await sendExtensionMessage("updateIsFieldCurrentlyFilling", { isFieldCurrentlyFilling: true }); await this.insertAutofillContentService.fillForm(fillScript); if (!this.autofillOverlayContentService) { return; } - setTimeout(() => this.updateOverlayIsCurrentlyFilling(false), 250); - } - - /** - * Handles updating the overlay is currently filling value. - * - * @param isCurrentlyFilling - Indicates if the overlay is currently filling - */ - private updateOverlayIsCurrentlyFilling(isCurrentlyFilling: boolean) { - if (!this.autofillOverlayContentService) { - return; - } - - this.autofillOverlayContentService.isCurrentlyFilling = isCurrentlyFilling; + setTimeout( + () => + sendExtensionMessage("updateIsFieldCurrentlyFilling", { isFieldCurrentlyFilling: false }), + 250, + ); } /** diff --git a/apps/browser/src/autofill/overlay/abstractions/inline-menu-elements.ts b/apps/browser/src/autofill/overlay/abstractions/inline-menu-elements.ts index cf4dc2b9889..c1123bbfc62 100644 --- a/apps/browser/src/autofill/overlay/abstractions/inline-menu-elements.ts +++ b/apps/browser/src/autofill/overlay/abstractions/inline-menu-elements.ts @@ -3,8 +3,10 @@ import { AutofillExtensionMessageParam } from "../../content/abstractions/autofi export type InlineMenuExtensionMessageHandlers = { [key: string]: CallableFunction; closeInlineMenu: ({ message }: AutofillExtensionMessageParam) => void; - updateInlineMenuElementsPosition: () => Promise<[void, void]>; + updateInlineMenuElementsPosition: ({ message }: AutofillExtensionMessageParam) => Promise; toggleInlineMenuHidden: ({ message }: AutofillExtensionMessageParam) => void; + checkIsInlineMenuButtonVisible: () => boolean; + checkIsInlineMenuListVisible: () => boolean; }; export interface InlineMenuElements { diff --git a/apps/browser/src/autofill/overlay/content/inline-menu-elements.ts b/apps/browser/src/autofill/overlay/content/inline-menu-elements.ts index a899afc43f3..1f42b3273ce 100644 --- a/apps/browser/src/autofill/overlay/content/inline-menu-elements.ts +++ b/apps/browser/src/autofill/overlay/content/inline-menu-elements.ts @@ -1,3 +1,4 @@ +import { AutofillExtensionMessage } from "../../content/abstractions/autofill-init"; import { sendExtensionMessage, generateRandomCustomElementName, @@ -35,9 +36,12 @@ export class InlineMenuElements implements InlineMenuElementsInterface { }; private readonly _extensionMessageHandlers: InlineMenuExtensionMessageHandlers = { closeInlineMenu: ({ message }) => this.removeInlineMenu(), - updateInlineMenuElementsPosition: () => this.updateInlineMenuElementsPosition(), + updateInlineMenuElementsPosition: ({ message }) => + this.updateInlineMenuElementsPosition(message), toggleInlineMenuHidden: ({ message }) => this.toggleInlineMenuHidden(message.isInlineMenuHidden), + checkIsInlineMenuButtonVisible: () => this.isButtonVisible, + checkIsInlineMenuListVisible: () => this.isListVisible, }; constructor() { @@ -107,8 +111,12 @@ export class InlineMenuElements implements InlineMenuElementsInterface { /** * Updates the position of both the overlay button and overlay list. */ - private async updateInlineMenuElementsPosition() { - return Promise.all([this.updateButtonPosition(), this.updateListPosition()]); + private async updateInlineMenuElementsPosition({ overlayElement }: AutofillExtensionMessage) { + if (overlayElement === AutofillOverlayElement.Button) { + return this.updateButtonPosition(); + } + + return this.updateListPosition(); } /** diff --git a/apps/browser/src/autofill/overlay/iframe-content/autofill-overlay-iframe.service.ts b/apps/browser/src/autofill/overlay/iframe-content/autofill-overlay-iframe.service.ts index 51621dd98e1..0ec7db131c5 100644 --- a/apps/browser/src/autofill/overlay/iframe-content/autofill-overlay-iframe.service.ts +++ b/apps/browser/src/autofill/overlay/iframe-content/autofill-overlay-iframe.service.ts @@ -245,7 +245,7 @@ class AutofillOverlayIframeService implements AutofillOverlayIframeServiceInterf } this.updateElementStyles(this.iframe, position); - setTimeout(() => this.updateElementStyles(this.iframe, { opacity: "1" }), 75); + setTimeout(() => this.updateElementStyles(this.iframe, { opacity: "1" }), 0); this.announceAriaAlert(); } diff --git a/apps/browser/src/autofill/services/abstractions/autofill-overlay-content.service.ts b/apps/browser/src/autofill/services/abstractions/autofill-overlay-content.service.ts index 3813a6506fc..addeef186b3 100644 --- a/apps/browser/src/autofill/services/abstractions/autofill-overlay-content.service.ts +++ b/apps/browser/src/autofill/services/abstractions/autofill-overlay-content.service.ts @@ -15,8 +15,8 @@ export type AutofillOverlayContentExtensionMessageHandlers = { }; export interface AutofillOverlayContentService { - isFieldCurrentlyFocused: boolean; - isCurrentlyFilling: boolean; + // isFieldCurrentlyFocused: boolean; + // isCurrentlyFilling: boolean; isOverlayCiphersPopulated: boolean; pageDetailsUpdateRequired: boolean; autofillOverlayVisibility: number; diff --git a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts index 6c49f502368..ec889a51773 100644 --- a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts +++ b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts @@ -26,8 +26,8 @@ import { import { AutoFillConstants } from "./autofill-constants"; class AutofillOverlayContentService implements AutofillOverlayContentServiceInterface { - isFieldCurrentlyFocused = false; - isCurrentlyFilling = false; + // isFieldCurrentlyFocused = false; + // isCurrentlyFilling = false; isOverlayCiphersPopulated = false; pageDetailsUpdateRequired = false; autofillOverlayVisibility: number; @@ -42,8 +42,8 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte private userFilledFields: Record = {}; private authStatus: AuthenticationStatus; private focusableElements: FocusableElement[] = []; - private isOverlayButtonVisible = false; - private isOverlayListVisible = false; + // private isOverlayButtonVisible = false; + // private isOverlayListVisible = false; // private overlayButtonElement: HTMLElement; // private overlayListElement: HTMLElement; private mostRecentlyFocusedField: ElementWithOpId; @@ -217,8 +217,9 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte * Formats any found user filled fields for a login cipher and sends a message * to the background script to add a new cipher. */ - addNewVaultItem() { - if (!this.isOverlayListVisible) { + async addNewVaultItem() { + // if (!this.isOverlayListVisible) { + if ((await this.sendExtensionMessage("checkIsInlineMenuListVisible")) !== true) { return; } @@ -239,8 +240,12 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte * * @param direction - The direction to redirect the focus. */ - redirectOverlayFocusOut(direction: string) { - if (!this.isOverlayListVisible || !this.mostRecentlyFocusedField) { + async redirectOverlayFocusOut(direction: string) { + // if (!this.isOverlayListVisible || !this.mostRecentlyFocusedField) { + if ( + !this.mostRecentlyFocusedField || + (await this.sendExtensionMessage("checkIsInlineMenuListVisible")) !== true + ) { return; } @@ -340,7 +345,10 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte * is currently focused. */ private handleFormFieldBlurEvent = () => { - this.isFieldCurrentlyFocused = false; + // this.isFieldCurrentlyFocused = false; + void this.sendExtensionMessage("updateIsFieldCurrentlyFocused", { + isFieldCurrentlyFocused: false, + }); void this.sendExtensionMessage("checkAutofillOverlayFocused"); }; @@ -352,7 +360,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte * * @param event - The keyup event. */ - private handleFormFieldKeyupEvent = (event: KeyboardEvent) => { + private handleFormFieldKeyupEvent = async (event: KeyboardEvent) => { const eventCode = event.code; if (eventCode === "Escape") { // this.removeAutofillOverlay(); @@ -360,8 +368,12 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte return; } - if (eventCode === "Enter" && !this.isCurrentlyFilling) { - this.handleOverlayRepositionEvent(); + // if (eventCode === "Enter" && !this.isCurrentlyFilling) { + if ( + eventCode === "Enter" && + !(await this.sendExtensionMessage("checkIsFieldCurrentlyFilling")) === true + ) { + void this.handleOverlayRepositionEvent(); return; } @@ -381,7 +393,11 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte * that the overlay list is focused when the user presses the down arrow key. */ private async focusOverlayList() { - if (!this.isOverlayListVisible && this.mostRecentlyFocusedField) { + // if (!this.isOverlayListVisible && this.mostRecentlyFocusedField) { + if ( + this.mostRecentlyFocusedField && + (await this.sendExtensionMessage("checkIsInlineMenuListVisible")) !== true + ) { await this.updateMostRecentlyFocusedField(this.mostRecentlyFocusedField); this.openAutofillOverlay({ isOpeningFullOverlay: true }); setTimeout(() => this.sendExtensionMessage("focusAutofillOverlayList"), 125); @@ -470,7 +486,11 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte * @param formFieldElement - The form field element that triggered the click event. */ private async triggerFormFieldClickedAction(formFieldElement: ElementWithOpId) { - if (this.isOverlayButtonVisible || this.isOverlayListVisible) { + // if (this.isOverlayButtonVisible || this.isOverlayListVisible) { + if ( + (await this.sendExtensionMessage("checkIsInlineMenuButtonVisible")) === true || + (await this.sendExtensionMessage("checkIsInlineMenuListVisible")) === true + ) { return; } @@ -497,11 +517,15 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte * @param formFieldElement - The form field element that triggered the focus event. */ private async triggerFormFieldFocusedAction(formFieldElement: ElementWithOpId) { - if (this.isCurrentlyFilling) { + // if (this.isCurrentlyFilling) { + if ((await this.sendExtensionMessage("checkIsFieldCurrentlyFilling")) === true) { return; } - this.isFieldCurrentlyFocused = true; + // this.isFieldCurrentlyFocused = true; + void this.sendExtensionMessage("updateIsFieldCurrentlyFocused", { + isFieldCurrentlyFocused: true, + }); this.clearUserInteractionEventTimeout(); const initiallyFocusedField = this.mostRecentlyFocusedField; await this.updateMostRecentlyFocusedField(formFieldElement); @@ -848,8 +872,12 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte * Handles the resize or scroll events that enact * repositioning of the overlay. */ - private handleOverlayRepositionEvent = () => { - if (!this.isOverlayButtonVisible && !this.isOverlayListVisible) { + private handleOverlayRepositionEvent = async () => { + // if (!this.isOverlayButtonVisible && !this.isOverlayListVisible) { + if ( + (await this.sendExtensionMessage("checkIsInlineMenuButtonVisible")) !== true && + (await this.sendExtensionMessage("checkIsInlineMenuListVisible")) !== true + ) { return; }