mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 23:33:31 +00:00
[PM-9342] Inline menu does not show on username field for a form that has a password field with an invalid autocomplete value (#9860)
* [PM-9342] Inline menu does not show on username field for a form that has a password field with an invalid autocomplete value * [PM-9342] Incorporating logic to handle multiple autocomplete values within a captured set of page details * [PM-9342] Incorporating logic to handle multiple autocomplete values within a captured set of page details * [PM-9342] Changing logic for how we identify new password fields to reflect a more assertive qualification * [PM-9342] Adding feedback from code review
This commit is contained in:
@@ -34,10 +34,23 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("has a keyword value that indicates the field is for a create account form", () => {
|
||||||
|
const field = mock<AutofillField>({
|
||||||
|
type: "password",
|
||||||
|
placeholder: "create account password",
|
||||||
|
autoCompleteType: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe(
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("has a type that is an excluded type", () => {
|
it("has a type that is an excluded type", () => {
|
||||||
AutoFillConstants.ExcludedAutofillLoginTypes.forEach((excludedType) => {
|
AutoFillConstants.ExcludedAutofillLoginTypes.forEach((excludedType) => {
|
||||||
const field = mock<AutofillField>({
|
const field = mock<AutofillField>({
|
||||||
type: excludedType,
|
type: excludedType,
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -53,6 +66,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlID: index === 0 ? attribute : "",
|
htmlID: index === 0 ? attribute : "",
|
||||||
htmlName: index === 1 ? attribute : "",
|
htmlName: index === 1 ? attribute : "",
|
||||||
placeholder: index > 1 ? attribute : "",
|
placeholder: index > 1 ? attribute : "",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -67,6 +81,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlID: "not-password",
|
htmlID: "not-password",
|
||||||
htmlName: "not-password",
|
htmlName: "not-password",
|
||||||
placeholder: "not-password",
|
placeholder: "not-password",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe(
|
expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe(
|
||||||
@@ -80,6 +95,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlID: "something-else",
|
htmlID: "something-else",
|
||||||
htmlName: "something-else",
|
htmlName: "something-else",
|
||||||
placeholder: "something-else",
|
placeholder: "something-else",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe(
|
expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe(
|
||||||
@@ -93,6 +109,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlID: "search",
|
htmlID: "search",
|
||||||
htmlName: "something-else",
|
htmlName: "something-else",
|
||||||
placeholder: "something-else",
|
placeholder: "something-else",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe(
|
expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe(
|
||||||
@@ -112,12 +129,14 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlName: "user-password",
|
htmlName: "user-password",
|
||||||
placeholder: "user-password",
|
placeholder: "user-password",
|
||||||
form: "",
|
form: "",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
const secondField = mock<AutofillField>({
|
const secondField = mock<AutofillField>({
|
||||||
type: "password",
|
type: "password",
|
||||||
htmlID: "some-other-password",
|
htmlID: "some-other-password",
|
||||||
htmlName: "some-other-password",
|
htmlName: "some-other-password",
|
||||||
placeholder: "some-other-password",
|
placeholder: "some-other-password",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
pageDetails.fields = [field, secondField];
|
pageDetails.fields = [field, secondField];
|
||||||
|
|
||||||
@@ -133,18 +152,21 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlName: "user-password",
|
htmlName: "user-password",
|
||||||
placeholder: "user-password",
|
placeholder: "user-password",
|
||||||
form: "",
|
form: "",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
const usernameField = mock<AutofillField>({
|
const usernameField = mock<AutofillField>({
|
||||||
type: "text",
|
type: "text",
|
||||||
htmlID: "user-username",
|
htmlID: "user-username",
|
||||||
htmlName: "user-username",
|
htmlName: "user-username",
|
||||||
placeholder: "user-username",
|
placeholder: "user-username",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
const secondUsernameField = mock<AutofillField>({
|
const secondUsernameField = mock<AutofillField>({
|
||||||
type: "text",
|
type: "text",
|
||||||
htmlID: "some-other-user-username",
|
htmlID: "some-other-user-username",
|
||||||
htmlName: "some-other-user-username",
|
htmlName: "some-other-user-username",
|
||||||
placeholder: "some-other-user-username",
|
placeholder: "some-other-user-username",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
pageDetails.fields = [field, usernameField, secondUsernameField];
|
pageDetails.fields = [field, usernameField, secondUsernameField];
|
||||||
|
|
||||||
@@ -186,6 +208,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlName: "user-password",
|
htmlName: "user-password",
|
||||||
placeholder: "user-password",
|
placeholder: "user-password",
|
||||||
form: "validFormId",
|
form: "validFormId",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
const secondField = mock<AutofillField>({
|
const secondField = mock<AutofillField>({
|
||||||
type: "password",
|
type: "password",
|
||||||
@@ -193,6 +216,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlName: "some-other-password",
|
htmlName: "some-other-password",
|
||||||
placeholder: "some-other-password",
|
placeholder: "some-other-password",
|
||||||
form: "validFormId",
|
form: "validFormId",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
pageDetails.fields = [field, secondField];
|
pageDetails.fields = [field, secondField];
|
||||||
|
|
||||||
@@ -218,12 +242,35 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("is structured on a page with a single set of username and password fields", () => {
|
||||||
|
const field = mock<AutofillField>({
|
||||||
|
type: "password",
|
||||||
|
htmlID: "user-password",
|
||||||
|
htmlName: "user-password",
|
||||||
|
placeholder: "user-password",
|
||||||
|
autoCompleteType: "",
|
||||||
|
});
|
||||||
|
const usernameField = mock<AutofillField>({
|
||||||
|
type: "text",
|
||||||
|
htmlID: "user-username",
|
||||||
|
htmlName: "user-username",
|
||||||
|
placeholder: "user-username",
|
||||||
|
autoCompleteType: "",
|
||||||
|
});
|
||||||
|
pageDetails.fields = [field, usernameField];
|
||||||
|
|
||||||
|
expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("has a type of `text` with an attribute that indicates the field is a password field", () => {
|
it("has a type of `text` with an attribute that indicates the field is a password field", () => {
|
||||||
const field = mock<AutofillField>({
|
const field = mock<AutofillField>({
|
||||||
type: "text",
|
type: "text",
|
||||||
htmlID: null,
|
htmlID: null,
|
||||||
htmlName: "user-password",
|
htmlName: "user-password",
|
||||||
placeholder: "user-password",
|
placeholder: "user-password",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe(
|
expect(inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails)).toBe(
|
||||||
@@ -247,6 +294,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlID: "user-username",
|
htmlID: "user-username",
|
||||||
htmlName: "user-username",
|
htmlName: "user-username",
|
||||||
placeholder: "user-username",
|
placeholder: "user-username",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
pageDetails.fields = [field, usernameField];
|
pageDetails.fields = [field, usernameField];
|
||||||
|
|
||||||
@@ -273,6 +321,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlName: "user-password",
|
htmlName: "user-password",
|
||||||
placeholder: "user-password",
|
placeholder: "user-password",
|
||||||
form: "validFormId",
|
form: "validFormId",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
const secondPasswordField = mock<AutofillField>({
|
const secondPasswordField = mock<AutofillField>({
|
||||||
type: "password",
|
type: "password",
|
||||||
@@ -280,6 +329,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlName: "some-other-password",
|
htmlName: "some-other-password",
|
||||||
placeholder: "some-other-password",
|
placeholder: "some-other-password",
|
||||||
form: "anotherFormId",
|
form: "anotherFormId",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
const usernameField = mock<AutofillField>({
|
const usernameField = mock<AutofillField>({
|
||||||
type: "text",
|
type: "text",
|
||||||
@@ -287,6 +337,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlName: "user-username",
|
htmlName: "user-username",
|
||||||
placeholder: "user-username",
|
placeholder: "user-username",
|
||||||
form: "validFormId",
|
form: "validFormId",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
pageDetails.fields = [field, secondPasswordField, usernameField];
|
pageDetails.fields = [field, secondPasswordField, usernameField];
|
||||||
|
|
||||||
@@ -310,6 +361,7 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
htmlName: "some-other-password",
|
htmlName: "some-other-password",
|
||||||
placeholder: "some-other-password",
|
placeholder: "some-other-password",
|
||||||
form: "anotherFormId",
|
form: "anotherFormId",
|
||||||
|
autoCompleteType: "",
|
||||||
});
|
});
|
||||||
pageDetails.fields = [field, secondPasswordField];
|
pageDetails.fields = [field, secondPasswordField];
|
||||||
|
|
||||||
@@ -347,21 +399,23 @@ describe("InlineMenuFieldQualificationService", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
["new", "change", "neue", "ändern"].forEach((keyword) => {
|
["new", "change", "neue", "ändern", "register", "create", "registration"].forEach(
|
||||||
it(`has a keyword of ${keyword} that indicates a 'new or changed' username is being filled`, () => {
|
(keyword) => {
|
||||||
const field = mock<AutofillField>({
|
it(`has a keyword of ${keyword} that indicates a 'new or changed' username is being filled`, () => {
|
||||||
type: "text",
|
const field = mock<AutofillField>({
|
||||||
autoCompleteType: "",
|
type: "text",
|
||||||
htmlID: "user-username",
|
autoCompleteType: "",
|
||||||
htmlName: "user-username",
|
htmlID: "user-username",
|
||||||
placeholder: `${keyword} username`,
|
htmlName: "user-username",
|
||||||
});
|
placeholder: `${keyword} username`,
|
||||||
|
});
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails),
|
inlineMenuFieldQualificationService.isFieldForLoginForm(field, pageDetails),
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
describe("does not have a parent form element", () => {
|
describe("does not have a parent form element", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -14,9 +14,18 @@ export class InlineMenuFieldQualificationService
|
|||||||
private usernameAutocompleteValues = new Set(["username", "email"]);
|
private usernameAutocompleteValues = new Set(["username", "email"]);
|
||||||
private fieldIgnoreListString = AutoFillConstants.FieldIgnoreList.join(",");
|
private fieldIgnoreListString = AutoFillConstants.FieldIgnoreList.join(",");
|
||||||
private passwordFieldExcludeListString = AutoFillConstants.PasswordFieldExcludeList.join(",");
|
private passwordFieldExcludeListString = AutoFillConstants.PasswordFieldExcludeList.join(",");
|
||||||
|
private currentPasswordAutocompleteValues = new Set(["current-password"]);
|
||||||
|
private newPasswordAutoCompleteValues = new Set(["new-password"]);
|
||||||
private autofillFieldKeywordsMap: WeakMap<AutofillField, string> = new WeakMap();
|
private autofillFieldKeywordsMap: WeakMap<AutofillField, string> = new WeakMap();
|
||||||
private autocompleteDisabledValues = new Set(["off", "false"]);
|
private autocompleteDisabledValues = new Set(["off", "false"]);
|
||||||
private newFieldKeywords = new Set(["new", "change", "neue", "ändern"]);
|
private newFieldKeywords = new Set(["new", "change", "neue", "ändern"]);
|
||||||
|
private accountCreationFieldKeywords = new Set([
|
||||||
|
"register",
|
||||||
|
"registration",
|
||||||
|
"create",
|
||||||
|
"confirm",
|
||||||
|
...this.newFieldKeywords,
|
||||||
|
]);
|
||||||
private inlineMenuFieldQualificationFlagSet = false;
|
private inlineMenuFieldQualificationFlagSet = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -62,7 +71,12 @@ export class InlineMenuFieldQualificationService
|
|||||||
): boolean {
|
): boolean {
|
||||||
// If the provided field is set with an autocomplete value of "current-password", we should assume that
|
// If the provided field is set with an autocomplete value of "current-password", we should assume that
|
||||||
// the page developer intends for this field to be interpreted as a password field for a login form.
|
// the page developer intends for this field to be interpreted as a password field for a login form.
|
||||||
if (field.autoCompleteType === "current-password") {
|
if (
|
||||||
|
this.fieldContainsAutocompleteValues(
|
||||||
|
field.autoCompleteType,
|
||||||
|
this.currentPasswordAutocompleteValues,
|
||||||
|
)
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +109,11 @@ export class InlineMenuFieldQualificationService
|
|||||||
// If a single username field or less is present on the page, then we can assume that the
|
// If a single username field or less is present on the page, then we can assume that the
|
||||||
// provided field is for a login form. This will only be the case if the field does not
|
// provided field is for a login form. This will only be the case if the field does not
|
||||||
// explicitly have its autocomplete attribute set to "off" or "false".
|
// explicitly have its autocomplete attribute set to "off" or "false".
|
||||||
return !this.autocompleteDisabledValues.has(field.autoCompleteType);
|
|
||||||
|
return !this.fieldContainsAutocompleteValues(
|
||||||
|
field.autoCompleteType,
|
||||||
|
this.autocompleteDisabledValues,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the field has a form parent and there are multiple visible password fields
|
// If the field has a form parent and there are multiple visible password fields
|
||||||
@@ -117,7 +135,10 @@ export class InlineMenuFieldQualificationService
|
|||||||
|
|
||||||
// If the field has a form parent and no username field exists and the field has an
|
// If the field has a form parent and no username field exists and the field has an
|
||||||
// autocomplete attribute set to "off" or "false", this is not a password field
|
// autocomplete attribute set to "off" or "false", this is not a password field
|
||||||
return !this.autocompleteDisabledValues.has(field.autoCompleteType);
|
return !this.fieldContainsAutocompleteValues(
|
||||||
|
field.autoCompleteType,
|
||||||
|
this.autocompleteDisabledValues,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,7 +153,9 @@ export class InlineMenuFieldQualificationService
|
|||||||
): boolean {
|
): boolean {
|
||||||
// If the provided field is set with an autocomplete of "username", we should assume that
|
// If the provided field is set with an autocomplete of "username", we should assume that
|
||||||
// the page developer intends for this field to be interpreted as a username field.
|
// the page developer intends for this field to be interpreted as a username field.
|
||||||
if (this.usernameAutocompleteValues.has(field.autoCompleteType)) {
|
if (
|
||||||
|
this.fieldContainsAutocompleteValues(field.autoCompleteType, this.usernameAutocompleteValues)
|
||||||
|
) {
|
||||||
const newPasswordFieldsInPageDetails = pageDetails.fields.filter(this.isNewPasswordField);
|
const newPasswordFieldsInPageDetails = pageDetails.fields.filter(this.isNewPasswordField);
|
||||||
return newPasswordFieldsInPageDetails.length === 0;
|
return newPasswordFieldsInPageDetails.length === 0;
|
||||||
}
|
}
|
||||||
@@ -175,7 +198,10 @@ export class InlineMenuFieldQualificationService
|
|||||||
// If the page does not contain any password fields, it might be part of a multistep login form.
|
// If the page does not contain any password fields, it might be part of a multistep login form.
|
||||||
// That will only be the case if the field does not explicitly have its autocomplete attribute
|
// That will only be the case if the field does not explicitly have its autocomplete attribute
|
||||||
// set to "off" or "false".
|
// set to "off" or "false".
|
||||||
return !this.autocompleteDisabledValues.has(field.autoCompleteType);
|
return !this.fieldContainsAutocompleteValues(
|
||||||
|
field.autoCompleteType,
|
||||||
|
this.autocompleteDisabledValues,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the field is structured within a form, but no password fields are present in the form,
|
// If the field is structured within a form, but no password fields are present in the form,
|
||||||
@@ -183,7 +209,12 @@ export class InlineMenuFieldQualificationService
|
|||||||
if (passwordFieldsInPageDetails.length === 0) {
|
if (passwordFieldsInPageDetails.length === 0) {
|
||||||
// If the field's autocomplete is set to a disabled value, we should assume that the field is
|
// If the field's autocomplete is set to a disabled value, we should assume that the field is
|
||||||
// not part of a login form.
|
// not part of a login form.
|
||||||
if (this.autocompleteDisabledValues.has(field.autoCompleteType)) {
|
if (
|
||||||
|
this.fieldContainsAutocompleteValues(
|
||||||
|
field.autoCompleteType,
|
||||||
|
this.autocompleteDisabledValues,
|
||||||
|
)
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +243,10 @@ export class InlineMenuFieldQualificationService
|
|||||||
|
|
||||||
// If no visible password fields are found, this field might be part of a multipart form.
|
// If no visible password fields are found, this field might be part of a multipart form.
|
||||||
// Check for an invalid autocompleteType to determine if the field is part of a login form.
|
// Check for an invalid autocompleteType to determine if the field is part of a login form.
|
||||||
return !this.autocompleteDisabledValues.has(field.autoCompleteType);
|
return !this.fieldContainsAutocompleteValues(
|
||||||
|
field.autoCompleteType,
|
||||||
|
this.autocompleteDisabledValues,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -237,7 +271,13 @@ export class InlineMenuFieldQualificationService
|
|||||||
* @param field - The field to validate
|
* @param field - The field to validate
|
||||||
*/
|
*/
|
||||||
private isCurrentPasswordField = (field: AutofillField): boolean => {
|
private isCurrentPasswordField = (field: AutofillField): boolean => {
|
||||||
if (field.autoCompleteType === "new-password") {
|
if (
|
||||||
|
this.fieldContainsAutocompleteValues(
|
||||||
|
field.autoCompleteType,
|
||||||
|
this.newPasswordAutoCompleteValues,
|
||||||
|
) ||
|
||||||
|
this.keywordsFoundInFieldData(field, [...this.accountCreationFieldKeywords])
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,11 +290,19 @@ export class InlineMenuFieldQualificationService
|
|||||||
* @param field - The field to validate
|
* @param field - The field to validate
|
||||||
*/
|
*/
|
||||||
private isNewPasswordField = (field: AutofillField): boolean => {
|
private isNewPasswordField = (field: AutofillField): boolean => {
|
||||||
if (field.autoCompleteType === "current-password") {
|
if (
|
||||||
|
this.fieldContainsAutocompleteValues(
|
||||||
|
field.autoCompleteType,
|
||||||
|
this.currentPasswordAutocompleteValues,
|
||||||
|
)
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.isPasswordField(field);
|
return (
|
||||||
|
this.isPasswordField(field) &&
|
||||||
|
this.keywordsFoundInFieldData(field, [...this.accountCreationFieldKeywords])
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -422,6 +470,31 @@ export class InlineMenuFieldQualificationService
|
|||||||
return keywordValues;
|
return keywordValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Separates the provided field data into space-separated values and checks if any
|
||||||
|
* of the values are present in the provided set of autocomplete values.
|
||||||
|
*
|
||||||
|
* @param fieldAutocompleteValue - The field autocomplete value to validate
|
||||||
|
* @param compareValues - The set of autocomplete values to check against
|
||||||
|
*/
|
||||||
|
private fieldContainsAutocompleteValues(
|
||||||
|
fieldAutocompleteValue: string,
|
||||||
|
compareValues: Set<string>,
|
||||||
|
) {
|
||||||
|
if (!fieldAutocompleteValue) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const autocompleteValueParts = fieldAutocompleteValue.split(" ");
|
||||||
|
for (let index = 0; index < autocompleteValueParts.length; index++) {
|
||||||
|
if (compareValues.has(autocompleteValueParts[index])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method represents the previous rudimentary approach to qualifying fields for login forms.
|
* This method represents the previous rudimentary approach to qualifying fields for login forms.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user