[PM-8027] Reworking inline menu to qualify and setup the listeners for each form field after page deatils have been collected

This commit is contained in:
Cesar Gonzalez 2024-05-31 14:58:21 -05:00
parent 43246056a3
commit f3d41f91aa
No known key found for this signature in database
GPG Key ID: 3381A5457F8CCECF
7 changed files with 102 additions and 47 deletions

View File

@ -1,6 +1,5 @@
import AutofillPageDetails from "../models/autofill-page-details";
import { AutofillOverlayContentService } from "../services/abstractions/autofill-overlay-content.service";
import { AutofillFieldQualificationService } from "../services/autofill-field-qualification.service";
import CollectAutofillContentService from "../services/collect-autofill-content.service";
import DomElementVisibilityService from "../services/dom-element-visibility.service";
import InsertAutofillContentService from "../services/insert-autofill-content.service";
@ -13,7 +12,6 @@ import {
} from "./abstractions/autofill-init";
class AutofillInit implements AutofillInitInterface {
private readonly autofillFieldQualificationService: AutofillFieldQualificationService;
private readonly autofillOverlayContentService: AutofillOverlayContentService | undefined;
private readonly domElementVisibilityService: DomElementVisibilityService;
private readonly collectAutofillContentService: CollectAutofillContentService;
@ -40,7 +38,6 @@ class AutofillInit implements AutofillInitInterface {
* @param autofillOverlayContentService - The autofill overlay content service, potentially undefined.
*/
constructor(autofillOverlayContentService?: AutofillOverlayContentService) {
this.autofillFieldQualificationService = new AutofillFieldQualificationService();
this.autofillOverlayContentService = autofillOverlayContentService;
this.domElementVisibilityService = new DomElementVisibilityService();
this.collectAutofillContentService = new CollectAutofillContentService(
@ -102,16 +99,6 @@ class AutofillInit implements AutofillInitInterface {
const pageDetails: AutofillPageDetails =
await this.collectAutofillContentService.getPageDetails();
// console.log(pageDetails);
// pageDetails.fields.forEach((field) => {
// const isLoginField = this.autofillFieldQualificationService.isFieldForLoginForm(
// field,
// pageDetails,
// );
//
// console.log(isLoginField, field);
// });
if (sendDetailsInResponse) {
return pageDetails;
}

View File

@ -1,6 +1,7 @@
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import AutofillField from "../../models/autofill-field";
import AutofillPageDetails from "../../models/autofill-page-details";
import { ElementWithOpId, FormFieldElement } from "../../types";
type OpenAutofillOverlayOptions = {
@ -19,6 +20,7 @@ interface AutofillOverlayContentService {
setupAutofillOverlayListenerOnField(
autofillFieldElement: ElementWithOpId<FormFieldElement>,
autofillFieldData: AutofillField,
pageDetails: AutofillPageDetails,
): Promise<void>;
openAutofillOverlay(options: OpenAutofillOverlayOptions): void;
removeAutofillOverlay(): void;

View File

@ -4,6 +4,7 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
import { EVENTS, AutofillOverlayVisibility } from "@bitwarden/common/autofill/constants";
import AutofillField from "../models/autofill-field";
import AutofillPageDetails from "../models/autofill-page-details";
import { createAutofillFieldMock } from "../spec/autofill-mocks";
import { flushPromises } from "../spec/testing-utils";
import { ElementWithOpId, FormFieldElement } from "../types";
@ -27,6 +28,8 @@ function createMutationRecordMock(customFields = {}): MutationRecord {
};
}
const temporaryPageDetailsMock = mock<AutofillPageDetails>();
const defaultWindowReadyState = document.readyState;
const defaultDocumentVisibilityState = document.visibilityState;
describe("AutofillOverlayContentService", () => {
@ -179,6 +182,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillFieldElement.addEventListener).not.toHaveBeenCalled();
@ -190,6 +194,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillFieldElement.addEventListener).not.toHaveBeenCalled();
@ -201,6 +206,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillFieldElement.addEventListener).not.toHaveBeenCalled();
@ -213,6 +219,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillFieldElement.addEventListener).not.toHaveBeenCalled();
@ -225,6 +232,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillFieldElement.addEventListener).not.toHaveBeenCalled();
@ -236,6 +244,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillFieldElement.addEventListener).not.toHaveBeenCalled();
@ -247,6 +256,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillFieldElement.addEventListener).not.toHaveBeenCalled();
@ -259,6 +269,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillFieldElement.addEventListener).not.toHaveBeenCalled();
@ -272,6 +283,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("getAutofillOverlayVisibility");
@ -287,6 +299,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillOverlayContentService["autofillOverlayVisibility"]).toEqual(
@ -310,6 +323,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillFieldElement.removeEventListener).toHaveBeenNthCalledWith(
@ -334,6 +348,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
});
@ -357,6 +372,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
jest.spyOn(globalThis.customElements, "define").mockImplementation();
});
@ -440,6 +456,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
spanAutofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
spanAutofillFieldElement.dispatchEvent(new Event("input"));
@ -451,6 +468,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("input"));
@ -467,6 +485,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
passwordFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
passwordFieldElement.dispatchEvent(new Event("input"));
@ -486,6 +505,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("input"));
@ -504,6 +524,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("input"));
@ -517,6 +538,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("input"));
@ -531,6 +553,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("input"));
@ -546,6 +569,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("input"));
@ -563,6 +587,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
});
@ -613,6 +638,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("focus"));
@ -624,6 +650,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("focus"));
@ -641,6 +668,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("focus"));
@ -660,6 +688,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("focus"));
@ -678,6 +707,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("focus"));
@ -695,6 +725,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("focus"));
@ -711,6 +742,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillFieldElement.dispatchEvent(new Event("focus"));
@ -733,6 +765,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("openAutofillOverlay");
@ -747,6 +780,7 @@ describe("AutofillOverlayContentService", () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
expect(autofillOverlayContentService["mostRecentlyFocusedField"]).toEqual(
@ -1613,6 +1647,7 @@ describe("AutofillOverlayContentService", () => {
autofillOverlayContentService.setupAutofillOverlayListenerOnField(
autofillFieldElement,
autofillFieldData,
temporaryPageDetailsMock,
);
autofillOverlayContentService["mostRecentlyFocusedField"] = autofillFieldElement;
});

View File

@ -7,6 +7,7 @@ import { EVENTS, AutofillOverlayVisibility } from "@bitwarden/common/autofill/co
import { FocusedFieldData } from "../background/abstractions/overlay.background";
import AutofillField from "../models/autofill-field";
import AutofillPageDetails from "../models/autofill-page-details";
import AutofillOverlayButtonIframe from "../overlay/iframe-content/autofill-overlay-button-iframe";
import AutofillOverlayListIframe from "../overlay/iframe-content/autofill-overlay-list-iframe";
import { ElementWithOpId, FillableFormFieldElement, FormFieldElement } from "../types";
@ -23,8 +24,10 @@ import {
OpenAutofillOverlayOptions,
} from "./abstractions/autofill-overlay-content.service";
import { AutoFillConstants } from "./autofill-constants";
import { InlineMenuFieldQualificationService } from "./inline-menu-field-qualification.service";
class AutofillOverlayContentService implements AutofillOverlayContentServiceInterface {
private readonly inlineMenuFieldQualificationService: InlineMenuFieldQualificationService;
isFieldCurrentlyFocused = false;
isCurrentlyFilling = false;
isOverlayCiphersPopulated = false;
@ -62,6 +65,10 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
zIndex: "2147483647",
};
constructor() {
this.inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService();
}
/**
* Initializes the autofill overlay content service by setting up the mutation observers.
* The observers will be instantiated on DOMContentLoaded if the page is current loading.
@ -81,12 +88,17 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
*
* @param formFieldElement - Form field elements identified during the page details collection process.
* @param autofillFieldData - Autofill field data captured from the form field element.
* @param pageDetails - The collected page details from the tab.
*/
async setupAutofillOverlayListenerOnField(
formFieldElement: ElementWithOpId<FormFieldElement>,
autofillFieldData: AutofillField,
pageDetails: AutofillPageDetails,
) {
if (this.isIgnoredField(autofillFieldData) || this.formFieldElements.has(formFieldElement)) {
if (
this.formFieldElements.has(formFieldElement) ||
!this.inlineMenuFieldQualificationService.isFieldForLoginForm(autofillFieldData, pageDetails)
) {
return;
}
@ -745,15 +757,15 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
autofillFieldData.readonly ||
autofillFieldData.disabled ||
!autofillFieldData.viewable ||
this.ignoredFieldTypes.has(autofillFieldData.type) ||
this.keywordsFoundInFieldData(autofillFieldData, ["search", "captcha"])
this.ignoredFieldTypes.has(autofillFieldData.type)
// || this.keywordsFoundInFieldData(autofillFieldData, ["search", "captcha"])
) {
return true;
}
const isLoginCipherField =
autofillFieldData.type === "password" ||
this.keywordsFoundInFieldData(autofillFieldData, AutoFillConstants.UsernameFieldNames);
this.inlineMenuFieldQualificationService.isCurrentPasswordField(autofillFieldData) ||
this.inlineMenuFieldQualificationService.isUsernameField(autofillFieldData);
return !isLoginCipherField;
}

View File

@ -72,14 +72,17 @@ describe("CollectAutofillContentService", () => {
it("returns an object with empty forms and fields if no fields were found on a previous iteration", async () => {
collectAutofillContentService["domRecentlyMutated"] = false;
collectAutofillContentService["noFieldsFound"] = true;
jest.spyOn(collectAutofillContentService as any, "getFormattedPageDetails");
jest.spyOn(collectAutofillContentService as any, "buildFormattedPageDetails");
jest.spyOn(collectAutofillContentService as any, "queryAutofillFormAndFieldElements");
jest.spyOn(collectAutofillContentService as any, "buildAutofillFormsData");
jest.spyOn(collectAutofillContentService as any, "buildAutofillFieldsData");
await collectAutofillContentService.getPageDetails();
expect(collectAutofillContentService["getFormattedPageDetails"]).toHaveBeenCalledWith({}, []);
expect(collectAutofillContentService["buildFormattedPageDetails"]).toHaveBeenCalledWith(
{},
[],
);
expect(
collectAutofillContentService["queryAutofillFormAndFieldElements"],
).not.toHaveBeenCalled();
@ -156,7 +159,7 @@ describe("CollectAutofillContentService", () => {
collectAutofillContentService["autofillFieldElements"] = new Map([
[fieldElement, autofillField],
]);
jest.spyOn(collectAutofillContentService as any, "getFormattedPageDetails");
jest.spyOn(collectAutofillContentService as any, "buildFormattedPageDetails");
jest.spyOn(collectAutofillContentService as any, "getFormattedAutofillFormsData");
jest.spyOn(collectAutofillContentService as any, "getFormattedAutofillFieldsData");
jest.spyOn(collectAutofillContentService as any, "queryAutofillFormAndFieldElements");
@ -165,7 +168,7 @@ describe("CollectAutofillContentService", () => {
await collectAutofillContentService.getPageDetails();
expect(collectAutofillContentService["getFormattedPageDetails"]).toHaveBeenCalled();
expect(collectAutofillContentService["buildFormattedPageDetails"]).toHaveBeenCalled();
expect(collectAutofillContentService["getFormattedAutofillFormsData"]).toHaveBeenCalled();
expect(collectAutofillContentService["getFormattedAutofillFieldsData"]).toHaveBeenCalled();
expect(

View File

@ -17,7 +17,6 @@ import {
elementIsSelectElement,
elementIsSpanElement,
nodeIsElement,
elementIsInputElement,
elementIsTextAreaElement,
nodeIsFormElement,
nodeIsInputElement,
@ -46,6 +45,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
private mutationObserver: MutationObserver;
private updateAutofillElementsAfterMutationTimeout: number | NodeJS.Timeout;
private mutationsQueue: MutationRecord[][] = [];
private cachedAutofillPageDetails: AutofillPageDetails;
private readonly updateAfterMutationTimeoutDelay = 1000;
private readonly formFieldQueryString;
private readonly nonInputFormFieldTags = new Set(["textarea", "select"]);
@ -95,13 +95,13 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
}
if (!this.domRecentlyMutated && this.noFieldsFound) {
return this.getFormattedPageDetails({}, []);
return this.buildFormattedPageDetails({}, []);
}
if (!this.domRecentlyMutated && this.autofillFieldElements.size) {
this.updateCachedAutofillFieldVisibility();
return this.getFormattedPageDetails(
return this.buildFormattedPageDetails(
this.getFormattedAutofillFormsData(),
this.getFormattedAutofillFieldsData(),
);
@ -120,7 +120,25 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
}
this.domRecentlyMutated = false;
return this.getFormattedPageDetails(autofillFormsData, autofillFieldsData);
const pageDetails = this.buildFormattedPageDetails(autofillFormsData, autofillFieldsData);
this.setupInlineMenuListeners(pageDetails);
return pageDetails;
}
private setupInlineMenuListeners(pageDetails: AutofillPageDetails) {
if (!this.autofillOverlayContentService) {
return;
}
const formFieldElements = Array.from(this.autofillFieldElements.keys());
for (const element of formFieldElements) {
void this.autofillOverlayContentService.setupAutofillOverlayListenerOnField(
element,
this.autofillFieldElements.get(element),
pageDetails,
);
}
}
/**
@ -256,11 +274,11 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
* @param autofillFormsData - The data for all the forms found in the page
* @param autofillFieldsData - The data for all the fields found in the page
*/
private getFormattedPageDetails(
private buildFormattedPageDetails(
autofillFormsData: Record<string, AutofillForm>,
autofillFieldsData: AutofillField[],
): AutofillPageDetails {
return {
this.cachedAutofillPageDetails = {
title: document.title,
url: (document.defaultView || globalThis).location.href,
documentUrl: document.location.href,
@ -268,6 +286,8 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
fields: autofillFieldsData,
collectedTimestamp: Date.now(),
};
return this.cachedAutofillPageDetails;
}
/**
@ -453,10 +473,10 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
if (elementIsSpanElement(element)) {
this.cacheAutofillFieldElement(index, element, autofillFieldBase);
void this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField(
element,
autofillFieldBase,
);
// void this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField(
// element,
// autofillFieldBase,
// );
return autofillFieldBase;
}
@ -496,10 +516,10 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
};
this.cacheAutofillFieldElement(index, element, autofillField);
void this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField(
element,
autofillField,
);
// void this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField(
// element,
// autofillField,
// );
return autofillField;
};
@ -1428,6 +1448,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
void this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField(
formFieldElement,
cachedAutofillFieldElement,
this.cachedAutofillPageDetails,
);
this.intersectionObserver?.unobserve(entry.target);

View File

@ -3,7 +3,7 @@ import AutofillPageDetails from "../models/autofill-page-details";
import { AutoFillConstants } from "./autofill-constants";
export class AutofillFieldQualificationService {
export class InlineMenuFieldQualificationService {
private searchFieldNamesSet = new Set(AutoFillConstants.SearchFieldNames);
private excludedAutofillLoginTypesSet = new Set(AutoFillConstants.ExcludedAutofillLoginTypes);
private usernameFieldTypes = new Set(["text", "email", "tel"]);
@ -13,13 +13,8 @@ export class AutofillFieldQualificationService {
private invalidAutocompleteValuesSet = new Set(["off", "false"]);
isFieldForLoginForm(field: AutofillField, pageDetails: AutofillPageDetails): boolean {
// TODO: Determine whether it makes sense to even incorporate this.
if (!field.viewable) {
return false;
}
const isExistingPasswordField = this.isExistingPasswordField(field);
if (isExistingPasswordField) {
const isCurrentPasswordField = this.isCurrentPasswordField(field);
if (isCurrentPasswordField) {
return this.isPasswordFieldForLoginForm(field, pageDetails);
}
@ -43,7 +38,7 @@ export class AutofillFieldQualificationService {
// Check if the field has a form parent
const parentForm = pageDetails.forms[field.form];
const usernameFieldsInPageDetails = pageDetails.fields.filter(this.isUsernameField);
const passwordFieldsInPageDetails = pageDetails.fields.filter(this.isExistingPasswordField);
const passwordFieldsInPageDetails = pageDetails.fields.filter(this.isCurrentPasswordField);
// If no form parent is found, check if a username field exists and no other password fields are found in the page details, if so treat this as a password field
if (
!parentForm &&
@ -100,7 +95,7 @@ export class AutofillFieldQualificationService {
// Check if the field has a form parent
const parentForm = pageDetails.forms[field.form];
const passwordFieldsInPageDetails = pageDetails.fields.filter(this.isExistingPasswordField);
const passwordFieldsInPageDetails = pageDetails.fields.filter(this.isCurrentPasswordField);
// console.log(passwordFieldsInPageDetails);
// If no form parent is found, check if a single password field is found in the page details, if so treat this as a username field
@ -177,7 +172,7 @@ export class AutofillFieldQualificationService {
return this.keywordsFoundInFieldData(field, AutoFillConstants.UsernameFieldNames);
};
isExistingPasswordField = (field: AutofillField): boolean => {
isCurrentPasswordField = (field: AutofillField): boolean => {
if (field.autoCompleteType === "new-password") {
return false;
}