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 eefd15afb17..04ae7554112 100644 --- a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts +++ b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts @@ -28,6 +28,8 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte private readonly findTabs = tabbable; private readonly sendExtensionMessage = sendExtensionMessage; private formFieldElements: Set> = new Set([]); + private hiddenFormFieldElements: WeakMap, AutofillField> = + new WeakMap(); private ignoredFieldTypes: Set = new Set(AutoFillConstants.ExcludedOverlayTypes); private userFilledFields: Record = {}; private authStatus: AuthenticationStatus; @@ -80,6 +82,10 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte return; } + if (this.isHiddenField(formFieldElement, autofillFieldData)) { + return; + } + this.formFieldElements.add(formFieldElement); if (!this.mostRecentlyFocusedField) { @@ -658,9 +664,6 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte */ private isIgnoredField(autofillFieldData: AutofillField): boolean { if ( - autofillFieldData.readonly || - autofillFieldData.disabled || - !autofillFieldData.viewable || this.ignoredFieldTypes.has(autofillFieldData.type) || this.keywordsFoundInFieldData(autofillFieldData, ["search", "captcha"]) ) { @@ -674,6 +677,44 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte return !isLoginCipherField; } + private isHiddenField( + formFieldElement: ElementWithOpId, + autofillFieldData: AutofillField, + ): boolean { + if (!autofillFieldData.readonly && !autofillFieldData.disabled && autofillFieldData.viewable) { + this.removeHiddenFieldFallbackListener(formFieldElement); + return false; + } + + this.setupHiddenFieldFallbackListener(formFieldElement, autofillFieldData); + + return true; + } + + private setupHiddenFieldFallbackListener( + formFieldElement: ElementWithOpId, + autofillFieldData: AutofillField, + ) { + this.hiddenFormFieldElements.set(formFieldElement, autofillFieldData); + formFieldElement.addEventListener(EVENTS.FOCUS, this.handleHiddenFieldFocusEvent); + } + + private removeHiddenFieldFallbackListener(formFieldElement: ElementWithOpId) { + formFieldElement.removeEventListener(EVENTS.FOCUS, this.handleHiddenFieldFocusEvent); + this.hiddenFormFieldElements.delete(formFieldElement); + } + + private handleHiddenFieldFocusEvent = (event: FocusEvent) => { + const formFieldElement = event.target as ElementWithOpId; + const autofillFieldData = this.hiddenFormFieldElements.get(formFieldElement); + if (autofillFieldData) { + autofillFieldData.viewable = true; + void this.setupAutofillOverlayListenerOnField(formFieldElement, autofillFieldData); + } + + this.removeHiddenFieldFallbackListener(formFieldElement); + }; + /** * Queries the background script for the autofill overlay visibility setting. * If the setting is not found, a default value of OnFieldFocus will be used @@ -820,7 +861,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte * autofill overlay if the document is not visible. */ private handleVisibilityChangeEvent = () => { - if (document.visibilityState === "visible") { + if (!this.mostRecentlyFocusedField || document.visibilityState === "visible") { return; }