1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 09:43:23 +00:00

[PM-5189] Separating the inline menu UI elements from the base AutofillOverlayContentService and setting up messaging to allow for propagation of those elements

This commit is contained in:
Cesar Gonzalez
2024-03-20 13:58:39 -05:00
parent 0af95bb2be
commit 94271201a2
9 changed files with 112 additions and 49 deletions

View File

@@ -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 = {

View File

@@ -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,
// );
};
/**

View File

@@ -13,6 +13,7 @@ export type AutofillExtensionMessage = {
pageDetailsUrl?: string;
ciphers?: any;
isInlineMenuHidden?: boolean;
overlayElement?: string;
data?: {
authStatus?: AuthenticationStatus;
isFocusingFieldElement?: boolean;

View File

@@ -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,
);
}
/**

View File

@@ -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<void>;
toggleInlineMenuHidden: ({ message }: AutofillExtensionMessageParam) => void;
checkIsInlineMenuButtonVisible: () => boolean;
checkIsInlineMenuListVisible: () => boolean;
};
export interface InlineMenuElements {

View File

@@ -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();
}
/**

View File

@@ -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();
}

View File

@@ -15,8 +15,8 @@ export type AutofillOverlayContentExtensionMessageHandlers = {
};
export interface AutofillOverlayContentService {
isFieldCurrentlyFocused: boolean;
isCurrentlyFilling: boolean;
// isFieldCurrentlyFocused: boolean;
// isCurrentlyFilling: boolean;
isOverlayCiphersPopulated: boolean;
pageDetailsUpdateRequired: boolean;
autofillOverlayVisibility: number;

View File

@@ -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<string, FillableFormFieldElement> = {};
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<FormFieldElement>;
@@ -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<FormFieldElement>) {
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<FormFieldElement>) {
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;
}