From 23c40d4a34f0f7c34dce06e29dfdac34cca53b3a Mon Sep 17 00:00:00 2001 From: Cesar Gonzalez Date: Thu, 20 Jun 2024 08:47:44 -0500 Subject: [PATCH] [PM-5189] Adding documentation for the AutofillOverlayContentService --- .../autofill-overlay-content.service.spec.ts | 9 -- .../autofill-overlay-content.service.ts | 89 ++++++++++--------- 2 files changed, 47 insertions(+), 51 deletions(-) diff --git a/apps/browser/src/autofill/services/autofill-overlay-content.service.spec.ts b/apps/browser/src/autofill/services/autofill-overlay-content.service.spec.ts index 152aeba7f7..fbe8867d2d 100644 --- a/apps/browser/src/autofill/services/autofill-overlay-content.service.spec.ts +++ b/apps/browser/src/autofill/services/autofill-overlay-content.service.spec.ts @@ -28,15 +28,6 @@ describe("AutofillOverlayContentService", () => { let autofillOverlayContentService: AutofillOverlayContentService; let sendExtensionMessageSpy: jest.SpyInstance; const sendResponseSpy = jest.fn(); - beforeAll(() => { - const mockPerformanceObserver = jest.fn(); - mockPerformanceObserver.mockReturnValue({ - observe: jest.fn(), - disconnect: jest.fn(), - }); - // @ts-expect-error Need to mock the performance observer - global.PerformanceObserver = mockPerformanceObserver; - }); beforeEach(() => { inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService(); 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 a8315bf366..742f2de576 100644 --- a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts +++ b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts @@ -126,26 +126,6 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ await this.setupInlineMenuOnQualifiedField(formFieldElement); } - private async setupInlineMenuOnQualifiedField( - formFieldElement: ElementWithOpId, - ) { - this.formFieldElements.add(formFieldElement); - - if (!this.mostRecentlyFocusedField) { - await this.updateMostRecentlyFocusedField(formFieldElement); - } - - if (!this.inlineMenuVisibility) { - await this.getInlineMenuVisibility(); - } - - this.setupFormFieldElementEventListeners(formFieldElement); - - if (this.getRootNodeActiveElement(formFieldElement) === formFieldElement) { - await this.triggerFormFieldFocusedAction(formFieldElement); - } - } - /** * Handles opening the autofill inline menu. Will conditionally open * the inline menu based on the current inline menu visibility setting. @@ -741,6 +721,31 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ this.removeHiddenFieldFallbackListener(formFieldElement); }; + /** + * Sets up the inline menu on a qualified form field element. + * + * @param formFieldElement - The form field element to set up the inline menu on. + */ + private async setupInlineMenuOnQualifiedField( + formFieldElement: ElementWithOpId, + ) { + this.formFieldElements.add(formFieldElement); + + if (!this.mostRecentlyFocusedField) { + await this.updateMostRecentlyFocusedField(formFieldElement); + } + + if (!this.inlineMenuVisibility) { + await this.getInlineMenuVisibility(); + } + + this.setupFormFieldElementEventListeners(formFieldElement); + + if (this.getRootNodeActiveElement(formFieldElement) === formFieldElement) { + await this.triggerFormFieldFocusedAction(formFieldElement); + } + } + /** * Queries the background script for the autofill inline menu visibility setting. * If the setting is not found, a default value of OnFieldFocus will be used @@ -811,14 +816,6 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ return (await this.sendExtensionMessage("checkIsInlineMenuCiphersPopulated")) === true; } - /** - * Triggers a validation to ensure that the inline menu is repositioned only when the - * current frame contains the focused field at any given depth level. - */ - private async checkShouldRepositionInlineMenu() { - return (await this.sendExtensionMessage("checkShouldRepositionInlineMenu")) === true; - } - /** * Gets the root node of the passed element and returns the active element within that root node. * @@ -1048,6 +1045,10 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ await this.sendExtensionMessage("triggerAutofillOverlayReposition"); }; + /** + * Sets up listeners that facilitate a rebuild of the sub frame offsets + * when a user interacts or focuses an element within the frame. + */ private setupRebuildSubFrameOffsetsListeners = () => { if (globalThis.window.top === globalThis.window || this.formFieldElements.size < 1) { return; @@ -1057,6 +1058,11 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ globalThis.document.body.addEventListener(EVENTS.MOUSEENTER, this.handleSubFrameFocusInEvent); }; + /** + * Sends a message to the background script to trigger a rebuild of the sub frame + * offsets. Will deregister the listeners to ensure that other focus and mouse + * events do not unnecessarily re-trigger a sub frame rebuild. + */ private handleSubFrameFocusInEvent = () => { void this.sendExtensionMessage("triggerSubFrameFocusInRebuild"); @@ -1072,17 +1078,14 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ ); }; + /** + * Triggers an update in the most recently focused field's data and returns + * whether the field is within the viewport bounds. If not within the bounds + * of the viewport, the inline menu will be closed. + */ private async checkIsMostRecentlyFocusedFieldWithinViewport() { await this.updateMostRecentlyFocusedField(this.mostRecentlyFocusedField); - return this.isFocusedFieldWithinViewportBounds(); - } - - /** - * Checks if the focused field is present within the bounds of the viewport. - * If not present, the inline menu will be closed. - */ - private isFocusedFieldWithinViewportBounds() { const focusedFieldRectsTop = this.focusedFieldData?.focusedFieldRects?.top; const focusedFieldRectsBottom = focusedFieldRectsTop + this.focusedFieldData?.focusedFieldRects?.height; @@ -1095,29 +1098,31 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ ); } + /** + * Clears the timeout that triggers a debounced focus of the inline menu list. + */ private clearFocusInlineMenuListTimeout() { if (this.focusInlineMenuListTimeout) { globalThis.clearTimeout(this.focusInlineMenuListTimeout); } } + /** + * Clears the timeout that triggers the closing of the inline menu on a focus redirection. + */ private clearCloseInlineMenuOnRedirectTimeout() { if (this.closeInlineMenuOnRedirectTimeout) { globalThis.clearTimeout(this.closeInlineMenuOnRedirectTimeout); } } - private clearAllTimeouts() { - this.clearFocusInlineMenuListTimeout(); - this.clearCloseInlineMenuOnRedirectTimeout(); - } - /** * Destroys the autofill overlay content service. This method will * disconnect the mutation observers and remove all event listeners. */ destroy() { - this.clearAllTimeouts(); + this.clearFocusInlineMenuListTimeout(); + this.clearCloseInlineMenuOnRedirectTimeout(); this.formFieldElements.forEach((formFieldElement) => { this.removeCachedFormFieldEventListeners(formFieldElement); formFieldElement.removeEventListener(EVENTS.BLUR, this.handleFormFieldBlurEvent);