mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-02 18:17:46 +01:00
[PM-10420] Autofill focus jumps around after autofilling identity (#10361)
* [PM-10420] Autofill focus jumps around after autofilling identity ciphers * [PM-10420] Autofill focus jumps around after autofilling identity ciphers * [PM-10420] Autofill focus jumps around after autofilling identity ciphers * [PM-10420] Incorporating the feature flag within jest to test the validity of both implementations * [PM-10420] Refactoring how we compile the combined list of keywords * [PM-10420] Adding JSDocs to the implemented methods
This commit is contained in:
parent
c50a9063bc
commit
76351ce750
@ -76,6 +76,11 @@ export class AutoFillConstants {
|
|||||||
"textarea",
|
"textarea",
|
||||||
...AutoFillConstants.ExcludedAutofillTypes,
|
...AutoFillConstants.ExcludedAutofillTypes,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static readonly ExcludedIdentityAutocompleteTypes: Set<string> = new Set([
|
||||||
|
"current-password",
|
||||||
|
"new-password",
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CreditCardAutoFillConstants {
|
export class CreditCardAutoFillConstants {
|
||||||
|
@ -60,7 +60,7 @@ import {
|
|||||||
GenerateFillScriptOptions,
|
GenerateFillScriptOptions,
|
||||||
PageDetail,
|
PageDetail,
|
||||||
} from "./abstractions/autofill.service";
|
} from "./abstractions/autofill.service";
|
||||||
import { AutoFillConstants, IdentityAutoFillConstants } from "./autofill-constants";
|
import { AutoFillConstants } from "./autofill-constants";
|
||||||
import AutofillService from "./autofill.service";
|
import AutofillService from "./autofill.service";
|
||||||
|
|
||||||
const mockEquivalentDomains = [
|
const mockEquivalentDomains = [
|
||||||
@ -3056,12 +3056,12 @@ describe("AutofillService", () => {
|
|||||||
options.cipher.identity = mock<IdentityView>();
|
options.cipher.identity = mock<IdentityView>();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns null if an identify is not found within the cipher", () => {
|
it("returns null if an identify is not found within the cipher", async () => {
|
||||||
options.cipher.identity = null;
|
options.cipher.identity = null;
|
||||||
jest.spyOn(autofillService as any, "makeScriptAction");
|
jest.spyOn(autofillService as any, "makeScriptAction");
|
||||||
jest.spyOn(autofillService as any, "makeScriptActionWithValue");
|
jest.spyOn(autofillService as any, "makeScriptActionWithValue");
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
fillScript,
|
fillScript,
|
||||||
pageDetails,
|
pageDetails,
|
||||||
filledFields,
|
filledFields,
|
||||||
@ -3087,432 +3087,389 @@ describe("AutofillService", () => {
|
|||||||
jest.spyOn(autofillService as any, "makeScriptActionWithValue");
|
jest.spyOn(autofillService as any, "makeScriptActionWithValue");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("will not attempt to match custom fields", () => {
|
let isRefactorFeatureFlagSet = false;
|
||||||
const customField = createAutofillFieldMock({ tagName: "span" });
|
for (let index = 0; index < 2; index++) {
|
||||||
pageDetails.fields.push(customField);
|
describe(`when the isRefactorFeatureFlagSet is ${isRefactorFeatureFlagSet}`, () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
configService.getFeatureFlag.mockResolvedValue(isRefactorFeatureFlagSet);
|
||||||
|
});
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
afterAll(() => {
|
||||||
fillScript,
|
isRefactorFeatureFlagSet = true;
|
||||||
pageDetails,
|
});
|
||||||
filledFields,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(AutofillService.forCustomFieldsOnly).toHaveBeenCalledWith(customField);
|
it("will not attempt to match custom fields", async () => {
|
||||||
expect(AutofillService["isExcludedFieldType"]).toHaveBeenCalled();
|
const customField = createAutofillFieldMock({ tagName: "span" });
|
||||||
expect(AutofillService["isFieldMatch"]).not.toHaveBeenCalled();
|
pageDetails.fields.push(customField);
|
||||||
expect(value.script).toStrictEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will not attempt to match a field that is of an excluded type", () => {
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
const excludedField = createAutofillFieldMock({ type: "hidden" });
|
fillScript,
|
||||||
pageDetails.fields.push(excludedField);
|
pageDetails,
|
||||||
|
filledFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
expect(AutofillService.forCustomFieldsOnly).toHaveBeenCalledWith(customField);
|
||||||
fillScript,
|
expect(AutofillService["isExcludedFieldType"]).toHaveBeenCalled();
|
||||||
pageDetails,
|
expect(AutofillService["isFieldMatch"]).not.toHaveBeenCalled();
|
||||||
filledFields,
|
expect(value.script).toStrictEqual([]);
|
||||||
options,
|
});
|
||||||
);
|
|
||||||
|
|
||||||
expect(AutofillService.forCustomFieldsOnly).toHaveBeenCalledWith(excludedField);
|
it("will not attempt to match a field that is of an excluded type", async () => {
|
||||||
expect(AutofillService["isExcludedFieldType"]).toHaveBeenCalledWith(
|
const excludedField = createAutofillFieldMock({ type: "hidden" });
|
||||||
excludedField,
|
pageDetails.fields.push(excludedField);
|
||||||
AutoFillConstants.ExcludedAutofillTypes,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).not.toHaveBeenCalled();
|
|
||||||
expect(value.script).toStrictEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will not attempt to match a field that is not viewable", () => {
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
const viewableField = createAutofillFieldMock({ viewable: false });
|
fillScript,
|
||||||
pageDetails.fields.push(viewableField);
|
pageDetails,
|
||||||
|
filledFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
expect(AutofillService.forCustomFieldsOnly).toHaveBeenCalledWith(excludedField);
|
||||||
fillScript,
|
expect(AutofillService["isExcludedFieldType"]).toHaveBeenCalledWith(
|
||||||
pageDetails,
|
excludedField,
|
||||||
filledFields,
|
AutoFillConstants.ExcludedAutofillTypes,
|
||||||
options,
|
);
|
||||||
);
|
expect(AutofillService["isFieldMatch"]).not.toHaveBeenCalled();
|
||||||
|
expect(value.script).toStrictEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
expect(AutofillService.forCustomFieldsOnly).toHaveBeenCalledWith(viewableField);
|
it("will not attempt to match a field that is not viewable", async () => {
|
||||||
expect(AutofillService["isExcludedFieldType"]).toHaveBeenCalled();
|
const viewableField = createAutofillFieldMock({ viewable: false });
|
||||||
expect(AutofillService["isFieldMatch"]).not.toHaveBeenCalled();
|
pageDetails.fields.push(viewableField);
|
||||||
expect(value.script).toStrictEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will match a full name field to the vault item identity value", () => {
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
const fullNameField = createAutofillFieldMock({ opid: "fullName", htmlName: "full-name" });
|
fillScript,
|
||||||
pageDetails.fields = [fullNameField];
|
pageDetails,
|
||||||
options.cipher.identity.firstName = firstName;
|
filledFields,
|
||||||
options.cipher.identity.middleName = middleName;
|
options,
|
||||||
options.cipher.identity.lastName = lastName;
|
);
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
expect(AutofillService.forCustomFieldsOnly).toHaveBeenCalledWith(viewableField);
|
||||||
fillScript,
|
expect(AutofillService["isExcludedFieldType"]).toHaveBeenCalled();
|
||||||
pageDetails,
|
expect(AutofillService["isFieldMatch"]).not.toHaveBeenCalled();
|
||||||
filledFields,
|
expect(value.script).toStrictEqual([]);
|
||||||
options,
|
});
|
||||||
);
|
|
||||||
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
it("will match a full name field to the vault item identity value", async () => {
|
||||||
fullNameField.htmlName,
|
const fullNameField = createAutofillFieldMock({
|
||||||
IdentityAutoFillConstants.FullNameFieldNames,
|
opid: "fullName",
|
||||||
IdentityAutoFillConstants.FullNameFieldNameValues,
|
htmlName: "full-name",
|
||||||
);
|
});
|
||||||
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
pageDetails.fields = [fullNameField];
|
||||||
fillScript,
|
options.cipher.identity.firstName = firstName;
|
||||||
`${firstName} ${middleName} ${lastName}`,
|
options.cipher.identity.middleName = middleName;
|
||||||
fullNameField,
|
options.cipher.identity.lastName = lastName;
|
||||||
filledFields,
|
|
||||||
);
|
|
||||||
expect(value.script[2]).toStrictEqual([
|
|
||||||
"fill_by_opid",
|
|
||||||
fullNameField.opid,
|
|
||||||
`${firstName} ${middleName} ${lastName}`,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will match a full name field to the a vault item that only has a last name", () => {
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
const fullNameField = createAutofillFieldMock({ opid: "fullName", htmlName: "full-name" });
|
fillScript,
|
||||||
pageDetails.fields = [fullNameField];
|
pageDetails,
|
||||||
options.cipher.identity.firstName = "";
|
filledFields,
|
||||||
options.cipher.identity.middleName = "";
|
options,
|
||||||
options.cipher.identity.lastName = lastName;
|
);
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
fillScript,
|
fillScript,
|
||||||
pageDetails,
|
`${firstName} ${middleName} ${lastName}`,
|
||||||
filledFields,
|
fullNameField,
|
||||||
options,
|
filledFields,
|
||||||
);
|
);
|
||||||
|
expect(value.script[2]).toStrictEqual([
|
||||||
|
"fill_by_opid",
|
||||||
|
fullNameField.opid,
|
||||||
|
`${firstName} ${middleName} ${lastName}`,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
it("will match a full name field to the a vault item that only has a last name", async () => {
|
||||||
fullNameField.htmlName,
|
const fullNameField = createAutofillFieldMock({
|
||||||
IdentityAutoFillConstants.FullNameFieldNames,
|
opid: "fullName",
|
||||||
IdentityAutoFillConstants.FullNameFieldNameValues,
|
htmlName: "full-name",
|
||||||
);
|
});
|
||||||
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
pageDetails.fields = [fullNameField];
|
||||||
fillScript,
|
options.cipher.identity.firstName = "";
|
||||||
lastName,
|
options.cipher.identity.middleName = "";
|
||||||
fullNameField,
|
options.cipher.identity.lastName = lastName;
|
||||||
filledFields,
|
|
||||||
);
|
|
||||||
expect(value.script[2]).toStrictEqual(["fill_by_opid", fullNameField.opid, lastName]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will match first name, middle name, and last name fields to the vault item identity value", () => {
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
const firstNameField = createAutofillFieldMock({
|
fillScript,
|
||||||
opid: "firstName",
|
pageDetails,
|
||||||
htmlName: "first-name",
|
filledFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
|
fillScript,
|
||||||
|
lastName,
|
||||||
|
fullNameField,
|
||||||
|
filledFields,
|
||||||
|
);
|
||||||
|
expect(value.script[2]).toStrictEqual(["fill_by_opid", fullNameField.opid, lastName]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will match first name, middle name, and last name fields to the vault item identity value", async () => {
|
||||||
|
const firstNameField = createAutofillFieldMock({
|
||||||
|
opid: "firstName",
|
||||||
|
htmlName: "first-name",
|
||||||
|
});
|
||||||
|
const middleNameField = createAutofillFieldMock({
|
||||||
|
opid: "middleName",
|
||||||
|
htmlName: "middle-name",
|
||||||
|
});
|
||||||
|
const lastNameField = createAutofillFieldMock({
|
||||||
|
opid: "lastName",
|
||||||
|
htmlName: "last-name",
|
||||||
|
});
|
||||||
|
pageDetails.fields = [firstNameField, middleNameField, lastNameField];
|
||||||
|
options.cipher.identity.firstName = firstName;
|
||||||
|
options.cipher.identity.middleName = middleName;
|
||||||
|
options.cipher.identity.lastName = lastName;
|
||||||
|
|
||||||
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
|
fillScript,
|
||||||
|
pageDetails,
|
||||||
|
filledFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
|
fillScript,
|
||||||
|
options.cipher.identity.firstName,
|
||||||
|
firstNameField,
|
||||||
|
filledFields,
|
||||||
|
);
|
||||||
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
|
fillScript,
|
||||||
|
options.cipher.identity.middleName,
|
||||||
|
middleNameField,
|
||||||
|
filledFields,
|
||||||
|
);
|
||||||
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
|
fillScript,
|
||||||
|
options.cipher.identity.lastName,
|
||||||
|
lastNameField,
|
||||||
|
filledFields,
|
||||||
|
);
|
||||||
|
expect(value.script[2]).toStrictEqual(["fill_by_opid", firstNameField.opid, firstName]);
|
||||||
|
expect(value.script[5]).toStrictEqual([
|
||||||
|
"fill_by_opid",
|
||||||
|
middleNameField.opid,
|
||||||
|
middleName,
|
||||||
|
]);
|
||||||
|
expect(value.script[8]).toStrictEqual(["fill_by_opid", lastNameField.opid, lastName]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will match title and email fields to the vault item identity value", async () => {
|
||||||
|
const titleField = createAutofillFieldMock({ opid: "title", htmlName: "title" });
|
||||||
|
const emailField = createAutofillFieldMock({ opid: "email", htmlName: "email" });
|
||||||
|
pageDetails.fields = [titleField, emailField];
|
||||||
|
const title = "Mr.";
|
||||||
|
const email = "email@example.com";
|
||||||
|
options.cipher.identity.title = title;
|
||||||
|
options.cipher.identity.email = email;
|
||||||
|
|
||||||
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
|
fillScript,
|
||||||
|
pageDetails,
|
||||||
|
filledFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
|
fillScript,
|
||||||
|
options.cipher.identity.title,
|
||||||
|
titleField,
|
||||||
|
filledFields,
|
||||||
|
);
|
||||||
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
|
fillScript,
|
||||||
|
options.cipher.identity.email,
|
||||||
|
emailField,
|
||||||
|
filledFields,
|
||||||
|
);
|
||||||
|
expect(value.script[2]).toStrictEqual(["fill_by_opid", titleField.opid, title]);
|
||||||
|
expect(value.script[5]).toStrictEqual(["fill_by_opid", emailField.opid, email]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will match a full address field to the vault item identity values", async () => {
|
||||||
|
const fullAddressField = createAutofillFieldMock({
|
||||||
|
opid: "fullAddress",
|
||||||
|
htmlName: "address",
|
||||||
|
});
|
||||||
|
pageDetails.fields = [fullAddressField];
|
||||||
|
const address1 = "123 Main St.";
|
||||||
|
const address2 = "Apt. 1";
|
||||||
|
const address3 = "P.O. Box 123";
|
||||||
|
options.cipher.identity.address1 = address1;
|
||||||
|
options.cipher.identity.address2 = address2;
|
||||||
|
options.cipher.identity.address3 = address3;
|
||||||
|
|
||||||
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
|
fillScript,
|
||||||
|
pageDetails,
|
||||||
|
filledFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
|
fillScript,
|
||||||
|
`${address1}, ${address2}, ${address3}`,
|
||||||
|
fullAddressField,
|
||||||
|
filledFields,
|
||||||
|
);
|
||||||
|
expect(value.script[2]).toStrictEqual([
|
||||||
|
"fill_by_opid",
|
||||||
|
fullAddressField.opid,
|
||||||
|
`${address1}, ${address2}, ${address3}`,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will match address1, address2, address3, postalCode, city, state, country, phone, username, and company fields to their corresponding vault item identity values", async () => {
|
||||||
|
const address1Field = createAutofillFieldMock({
|
||||||
|
opid: "address1",
|
||||||
|
htmlName: "address-1",
|
||||||
|
});
|
||||||
|
const address2Field = createAutofillFieldMock({
|
||||||
|
opid: "address2",
|
||||||
|
htmlName: "address-2",
|
||||||
|
});
|
||||||
|
const address3Field = createAutofillFieldMock({
|
||||||
|
opid: "address3",
|
||||||
|
htmlName: "address-3",
|
||||||
|
});
|
||||||
|
const postalCodeField = createAutofillFieldMock({
|
||||||
|
opid: "postalCode",
|
||||||
|
htmlName: "postal-code",
|
||||||
|
});
|
||||||
|
const cityField = createAutofillFieldMock({ opid: "city", htmlName: "city" });
|
||||||
|
const stateField = createAutofillFieldMock({ opid: "state", htmlName: "state" });
|
||||||
|
const countryField = createAutofillFieldMock({ opid: "country", htmlName: "country" });
|
||||||
|
const phoneField = createAutofillFieldMock({ opid: "phone", htmlName: "phone" });
|
||||||
|
const usernameField = createAutofillFieldMock({
|
||||||
|
opid: "username",
|
||||||
|
htmlName: "username",
|
||||||
|
});
|
||||||
|
const companyField = createAutofillFieldMock({ opid: "company", htmlName: "company" });
|
||||||
|
pageDetails.fields = [
|
||||||
|
address1Field,
|
||||||
|
address2Field,
|
||||||
|
address3Field,
|
||||||
|
postalCodeField,
|
||||||
|
cityField,
|
||||||
|
stateField,
|
||||||
|
countryField,
|
||||||
|
phoneField,
|
||||||
|
usernameField,
|
||||||
|
companyField,
|
||||||
|
];
|
||||||
|
const address1 = "123 Main St.";
|
||||||
|
const address2 = "Apt. 1";
|
||||||
|
const address3 = "P.O. Box 123";
|
||||||
|
const postalCode = "12345";
|
||||||
|
const city = "City";
|
||||||
|
const state = "TX";
|
||||||
|
const country = "US";
|
||||||
|
const phone = "123-456-7890";
|
||||||
|
const username = "username";
|
||||||
|
const company = "Company";
|
||||||
|
options.cipher.identity.address1 = address1;
|
||||||
|
options.cipher.identity.address2 = address2;
|
||||||
|
options.cipher.identity.address3 = address3;
|
||||||
|
options.cipher.identity.postalCode = postalCode;
|
||||||
|
options.cipher.identity.city = city;
|
||||||
|
options.cipher.identity.state = state;
|
||||||
|
options.cipher.identity.country = country;
|
||||||
|
options.cipher.identity.phone = phone;
|
||||||
|
options.cipher.identity.username = username;
|
||||||
|
options.cipher.identity.company = company;
|
||||||
|
|
||||||
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
|
fillScript,
|
||||||
|
pageDetails,
|
||||||
|
filledFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(value.script).toContainEqual(["fill_by_opid", address1Field.opid, address1]);
|
||||||
|
expect(value.script).toContainEqual(["fill_by_opid", address2Field.opid, address2]);
|
||||||
|
expect(value.script).toContainEqual(["fill_by_opid", address3Field.opid, address3]);
|
||||||
|
expect(value.script).toContainEqual(["fill_by_opid", postalCodeField.opid, postalCode]);
|
||||||
|
expect(value.script).toContainEqual(["fill_by_opid", cityField.opid, city]);
|
||||||
|
expect(value.script).toContainEqual(["fill_by_opid", stateField.opid, state]);
|
||||||
|
expect(value.script).toContainEqual(["fill_by_opid", countryField.opid, country]);
|
||||||
|
expect(value.script).toContainEqual(["fill_by_opid", phoneField.opid, phone]);
|
||||||
|
expect(value.script).toContainEqual(["fill_by_opid", usernameField.opid, username]);
|
||||||
|
expect(value.script).toContainEqual(["fill_by_opid", companyField.opid, company]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will find the two character IsoState value for an identity cipher that contains the full name of a state", async () => {
|
||||||
|
const stateField = createAutofillFieldMock({ opid: "state", htmlName: "state" });
|
||||||
|
pageDetails.fields = [stateField];
|
||||||
|
const state = "California";
|
||||||
|
options.cipher.identity.state = state;
|
||||||
|
|
||||||
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
|
fillScript,
|
||||||
|
pageDetails,
|
||||||
|
filledFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
|
fillScript,
|
||||||
|
"CA",
|
||||||
|
expect.anything(),
|
||||||
|
expect.anything(),
|
||||||
|
);
|
||||||
|
expect(value.script[2]).toStrictEqual(["fill_by_opid", stateField.opid, "CA"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will find the two character IsoProvince value for an identity cipher that contains the full name of a province", async () => {
|
||||||
|
const stateField = createAutofillFieldMock({ opid: "state", htmlName: "state" });
|
||||||
|
pageDetails.fields = [stateField];
|
||||||
|
const state = "Ontario";
|
||||||
|
options.cipher.identity.state = state;
|
||||||
|
|
||||||
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
|
fillScript,
|
||||||
|
pageDetails,
|
||||||
|
filledFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
|
fillScript,
|
||||||
|
"ON",
|
||||||
|
expect.anything(),
|
||||||
|
expect.anything(),
|
||||||
|
);
|
||||||
|
expect(value.script[2]).toStrictEqual(["fill_by_opid", stateField.opid, "ON"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will find the two character IsoCountry value for an identity cipher that contains the full name of a country", async () => {
|
||||||
|
const countryField = createAutofillFieldMock({ opid: "country", htmlName: "country" });
|
||||||
|
pageDetails.fields = [countryField];
|
||||||
|
const country = "Somalia";
|
||||||
|
options.cipher.identity.country = country;
|
||||||
|
|
||||||
|
const value = await autofillService["generateIdentityFillScript"](
|
||||||
|
fillScript,
|
||||||
|
pageDetails,
|
||||||
|
filledFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
||||||
|
fillScript,
|
||||||
|
"SO",
|
||||||
|
expect.anything(),
|
||||||
|
expect.anything(),
|
||||||
|
);
|
||||||
|
expect(value.script[2]).toStrictEqual(["fill_by_opid", countryField.opid, "SO"]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
const middleNameField = createAutofillFieldMock({
|
}
|
||||||
opid: "middleName",
|
|
||||||
htmlName: "middle-name",
|
|
||||||
});
|
|
||||||
const lastNameField = createAutofillFieldMock({ opid: "lastName", htmlName: "last-name" });
|
|
||||||
pageDetails.fields = [firstNameField, middleNameField, lastNameField];
|
|
||||||
options.cipher.identity.firstName = firstName;
|
|
||||||
options.cipher.identity.middleName = middleName;
|
|
||||||
options.cipher.identity.lastName = lastName;
|
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
|
||||||
fillScript,
|
|
||||||
pageDetails,
|
|
||||||
filledFields,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
firstNameField.htmlName,
|
|
||||||
IdentityAutoFillConstants.FirstnameFieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
middleNameField.htmlName,
|
|
||||||
IdentityAutoFillConstants.MiddlenameFieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
lastNameField.htmlName,
|
|
||||||
IdentityAutoFillConstants.LastnameFieldNames,
|
|
||||||
);
|
|
||||||
expect(autofillService["makeScriptAction"]).toHaveBeenCalledWith(
|
|
||||||
fillScript,
|
|
||||||
options.cipher.identity,
|
|
||||||
expect.anything(),
|
|
||||||
filledFields,
|
|
||||||
firstNameField.opid,
|
|
||||||
);
|
|
||||||
expect(autofillService["makeScriptAction"]).toHaveBeenCalledWith(
|
|
||||||
fillScript,
|
|
||||||
options.cipher.identity,
|
|
||||||
expect.anything(),
|
|
||||||
filledFields,
|
|
||||||
middleNameField.opid,
|
|
||||||
);
|
|
||||||
expect(autofillService["makeScriptAction"]).toHaveBeenCalledWith(
|
|
||||||
fillScript,
|
|
||||||
options.cipher.identity,
|
|
||||||
expect.anything(),
|
|
||||||
filledFields,
|
|
||||||
lastNameField.opid,
|
|
||||||
);
|
|
||||||
expect(value.script[2]).toStrictEqual(["fill_by_opid", firstNameField.opid, firstName]);
|
|
||||||
expect(value.script[5]).toStrictEqual(["fill_by_opid", middleNameField.opid, middleName]);
|
|
||||||
expect(value.script[8]).toStrictEqual(["fill_by_opid", lastNameField.opid, lastName]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will match title and email fields to the vault item identity value", () => {
|
|
||||||
const titleField = createAutofillFieldMock({ opid: "title", htmlName: "title" });
|
|
||||||
const emailField = createAutofillFieldMock({ opid: "email", htmlName: "email" });
|
|
||||||
pageDetails.fields = [titleField, emailField];
|
|
||||||
const title = "Mr.";
|
|
||||||
const email = "email@example.com";
|
|
||||||
options.cipher.identity.title = title;
|
|
||||||
options.cipher.identity.email = email;
|
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
|
||||||
fillScript,
|
|
||||||
pageDetails,
|
|
||||||
filledFields,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
titleField.htmlName,
|
|
||||||
IdentityAutoFillConstants.TitleFieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
emailField.htmlName,
|
|
||||||
IdentityAutoFillConstants.EmailFieldNames,
|
|
||||||
);
|
|
||||||
expect(autofillService["makeScriptAction"]).toHaveBeenCalledWith(
|
|
||||||
fillScript,
|
|
||||||
options.cipher.identity,
|
|
||||||
expect.anything(),
|
|
||||||
filledFields,
|
|
||||||
titleField.opid,
|
|
||||||
);
|
|
||||||
expect(autofillService["makeScriptAction"]).toHaveBeenCalledWith(
|
|
||||||
fillScript,
|
|
||||||
options.cipher.identity,
|
|
||||||
expect.anything(),
|
|
||||||
filledFields,
|
|
||||||
emailField.opid,
|
|
||||||
);
|
|
||||||
expect(value.script[2]).toStrictEqual(["fill_by_opid", titleField.opid, title]);
|
|
||||||
expect(value.script[5]).toStrictEqual(["fill_by_opid", emailField.opid, email]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will match a full address field to the vault item identity values", () => {
|
|
||||||
const fullAddressField = createAutofillFieldMock({
|
|
||||||
opid: "fullAddress",
|
|
||||||
htmlName: "address",
|
|
||||||
});
|
|
||||||
pageDetails.fields = [fullAddressField];
|
|
||||||
const address1 = "123 Main St.";
|
|
||||||
const address2 = "Apt. 1";
|
|
||||||
const address3 = "P.O. Box 123";
|
|
||||||
options.cipher.identity.address1 = address1;
|
|
||||||
options.cipher.identity.address2 = address2;
|
|
||||||
options.cipher.identity.address3 = address3;
|
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
|
||||||
fillScript,
|
|
||||||
pageDetails,
|
|
||||||
filledFields,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
fullAddressField.htmlName,
|
|
||||||
IdentityAutoFillConstants.AddressFieldNames,
|
|
||||||
IdentityAutoFillConstants.AddressFieldNameValues,
|
|
||||||
);
|
|
||||||
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
|
||||||
fillScript,
|
|
||||||
`${address1}, ${address2}, ${address3}`,
|
|
||||||
fullAddressField,
|
|
||||||
filledFields,
|
|
||||||
);
|
|
||||||
expect(value.script[2]).toStrictEqual([
|
|
||||||
"fill_by_opid",
|
|
||||||
fullAddressField.opid,
|
|
||||||
`${address1}, ${address2}, ${address3}`,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will match address1, address2, address3, postalCode, city, state, country, phone, username, and company fields to their corresponding vault item identity values", () => {
|
|
||||||
const address1Field = createAutofillFieldMock({ opid: "address1", htmlName: "address-1" });
|
|
||||||
const address2Field = createAutofillFieldMock({ opid: "address2", htmlName: "address-2" });
|
|
||||||
const address3Field = createAutofillFieldMock({ opid: "address3", htmlName: "address-3" });
|
|
||||||
const postalCodeField = createAutofillFieldMock({
|
|
||||||
opid: "postalCode",
|
|
||||||
htmlName: "postal-code",
|
|
||||||
});
|
|
||||||
const cityField = createAutofillFieldMock({ opid: "city", htmlName: "city" });
|
|
||||||
const stateField = createAutofillFieldMock({ opid: "state", htmlName: "state" });
|
|
||||||
const countryField = createAutofillFieldMock({ opid: "country", htmlName: "country" });
|
|
||||||
const phoneField = createAutofillFieldMock({ opid: "phone", htmlName: "phone" });
|
|
||||||
const usernameField = createAutofillFieldMock({ opid: "username", htmlName: "username" });
|
|
||||||
const companyField = createAutofillFieldMock({ opid: "company", htmlName: "company" });
|
|
||||||
pageDetails.fields = [
|
|
||||||
address1Field,
|
|
||||||
address2Field,
|
|
||||||
address3Field,
|
|
||||||
postalCodeField,
|
|
||||||
cityField,
|
|
||||||
stateField,
|
|
||||||
countryField,
|
|
||||||
phoneField,
|
|
||||||
usernameField,
|
|
||||||
companyField,
|
|
||||||
];
|
|
||||||
const address1 = "123 Main St.";
|
|
||||||
const address2 = "Apt. 1";
|
|
||||||
const address3 = "P.O. Box 123";
|
|
||||||
const postalCode = "12345";
|
|
||||||
const city = "City";
|
|
||||||
const state = "State";
|
|
||||||
const country = "Country";
|
|
||||||
const phone = "123-456-7890";
|
|
||||||
const username = "username";
|
|
||||||
const company = "Company";
|
|
||||||
options.cipher.identity.address1 = address1;
|
|
||||||
options.cipher.identity.address2 = address2;
|
|
||||||
options.cipher.identity.address3 = address3;
|
|
||||||
options.cipher.identity.postalCode = postalCode;
|
|
||||||
options.cipher.identity.city = city;
|
|
||||||
options.cipher.identity.state = state;
|
|
||||||
options.cipher.identity.country = country;
|
|
||||||
options.cipher.identity.phone = phone;
|
|
||||||
options.cipher.identity.username = username;
|
|
||||||
options.cipher.identity.company = company;
|
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
|
||||||
fillScript,
|
|
||||||
pageDetails,
|
|
||||||
filledFields,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
address1Field.htmlName,
|
|
||||||
IdentityAutoFillConstants.Address1FieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
address2Field.htmlName,
|
|
||||||
IdentityAutoFillConstants.Address2FieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
address3Field.htmlName,
|
|
||||||
IdentityAutoFillConstants.Address3FieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
postalCodeField.htmlName,
|
|
||||||
IdentityAutoFillConstants.PostalCodeFieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
cityField.htmlName,
|
|
||||||
IdentityAutoFillConstants.CityFieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
stateField.htmlName,
|
|
||||||
IdentityAutoFillConstants.StateFieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
countryField.htmlName,
|
|
||||||
IdentityAutoFillConstants.CountryFieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
phoneField.htmlName,
|
|
||||||
IdentityAutoFillConstants.PhoneFieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
usernameField.htmlName,
|
|
||||||
IdentityAutoFillConstants.UserNameFieldNames,
|
|
||||||
);
|
|
||||||
expect(AutofillService["isFieldMatch"]).toHaveBeenCalledWith(
|
|
||||||
companyField.htmlName,
|
|
||||||
IdentityAutoFillConstants.CompanyFieldNames,
|
|
||||||
);
|
|
||||||
expect(autofillService["makeScriptAction"]).toHaveBeenCalled();
|
|
||||||
expect(value.script[2]).toStrictEqual(["fill_by_opid", address1Field.opid, address1]);
|
|
||||||
expect(value.script[5]).toStrictEqual(["fill_by_opid", address2Field.opid, address2]);
|
|
||||||
expect(value.script[8]).toStrictEqual(["fill_by_opid", address3Field.opid, address3]);
|
|
||||||
expect(value.script[11]).toStrictEqual(["fill_by_opid", cityField.opid, city]);
|
|
||||||
expect(value.script[14]).toStrictEqual(["fill_by_opid", postalCodeField.opid, postalCode]);
|
|
||||||
expect(value.script[17]).toStrictEqual(["fill_by_opid", companyField.opid, company]);
|
|
||||||
expect(value.script[20]).toStrictEqual(["fill_by_opid", phoneField.opid, phone]);
|
|
||||||
expect(value.script[23]).toStrictEqual(["fill_by_opid", usernameField.opid, username]);
|
|
||||||
expect(value.script[26]).toStrictEqual(["fill_by_opid", stateField.opid, state]);
|
|
||||||
expect(value.script[29]).toStrictEqual(["fill_by_opid", countryField.opid, country]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will find the two character IsoState value for an identity cipher that contains the full name of a state", () => {
|
|
||||||
const stateField = createAutofillFieldMock({ opid: "state", htmlName: "state" });
|
|
||||||
pageDetails.fields = [stateField];
|
|
||||||
const state = "California";
|
|
||||||
options.cipher.identity.state = state;
|
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
|
||||||
fillScript,
|
|
||||||
pageDetails,
|
|
||||||
filledFields,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
|
||||||
fillScript,
|
|
||||||
"CA",
|
|
||||||
expect.anything(),
|
|
||||||
expect.anything(),
|
|
||||||
);
|
|
||||||
expect(value.script[2]).toStrictEqual(["fill_by_opid", stateField.opid, "CA"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will find the two character IsoProvince value for an identity cipher that contains the full name of a province", () => {
|
|
||||||
const stateField = createAutofillFieldMock({ opid: "state", htmlName: "state" });
|
|
||||||
pageDetails.fields = [stateField];
|
|
||||||
const state = "Ontario";
|
|
||||||
options.cipher.identity.state = state;
|
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
|
||||||
fillScript,
|
|
||||||
pageDetails,
|
|
||||||
filledFields,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
|
||||||
fillScript,
|
|
||||||
"ON",
|
|
||||||
expect.anything(),
|
|
||||||
expect.anything(),
|
|
||||||
);
|
|
||||||
expect(value.script[2]).toStrictEqual(["fill_by_opid", stateField.opid, "ON"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will find the two character IsoCountry value for an identity cipher that contains the full name of a country", () => {
|
|
||||||
const countryField = createAutofillFieldMock({ opid: "country", htmlName: "country" });
|
|
||||||
pageDetails.fields = [countryField];
|
|
||||||
const country = "Somalia";
|
|
||||||
options.cipher.identity.country = country;
|
|
||||||
|
|
||||||
const value = autofillService["generateIdentityFillScript"](
|
|
||||||
fillScript,
|
|
||||||
pageDetails,
|
|
||||||
filledFields,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(autofillService["makeScriptActionWithValue"]).toHaveBeenCalledWith(
|
|
||||||
fillScript,
|
|
||||||
"SO",
|
|
||||||
expect.anything(),
|
|
||||||
expect.anything(),
|
|
||||||
);
|
|
||||||
expect(value.script[2]).toStrictEqual(["fill_by_opid", countryField.opid, "SO"]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import { FieldType, CipherType } from "@bitwarden/common/vault/enums";
|
|||||||
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
import { FieldView } from "@bitwarden/common/vault/models/view/field.view";
|
import { FieldView } from "@bitwarden/common/vault/models/view/field.view";
|
||||||
|
import { IdentityView } from "@bitwarden/common/vault/models/view/identity.view";
|
||||||
|
|
||||||
import { BrowserApi } from "../../platform/browser/browser-api";
|
import { BrowserApi } from "../../platform/browser/browser-api";
|
||||||
import { ScriptInjectorService } from "../../platform/services/abstractions/script-injector.service";
|
import { ScriptInjectorService } from "../../platform/services/abstractions/script-injector.service";
|
||||||
@ -478,6 +479,12 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
return totpCode;
|
return totpCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the cipher requires password reprompt and opens the password reprompt popout if necessary.
|
||||||
|
*
|
||||||
|
* @param cipher - The cipher to autofill
|
||||||
|
* @param tab - The tab to autofill
|
||||||
|
*/
|
||||||
async isPasswordRepromptRequired(cipher: CipherView, tab: chrome.tabs.Tab): Promise<boolean> {
|
async isPasswordRepromptRequired(cipher: CipherView, tab: chrome.tabs.Tab): Promise<boolean> {
|
||||||
const userHasMasterPasswordAndKeyHash =
|
const userHasMasterPasswordAndKeyHash =
|
||||||
await this.userVerificationService.hasMasterPasswordAndMasterKeyHash();
|
await this.userVerificationService.hasMasterPasswordAndMasterKeyHash();
|
||||||
@ -654,7 +661,7 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
fillScript = this.generateCardFillScript(fillScript, pageDetails, filledFields, options);
|
fillScript = this.generateCardFillScript(fillScript, pageDetails, filledFields, options);
|
||||||
break;
|
break;
|
||||||
case CipherType.Identity:
|
case CipherType.Identity:
|
||||||
fillScript = this.generateIdentityFillScript(
|
fillScript = await this.generateIdentityFillScript(
|
||||||
fillScript,
|
fillScript,
|
||||||
pageDetails,
|
pageDetails,
|
||||||
filledFields,
|
filledFields,
|
||||||
@ -1243,12 +1250,16 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
* @returns {AutofillScript}
|
* @returns {AutofillScript}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private generateIdentityFillScript(
|
private async generateIdentityFillScript(
|
||||||
fillScript: AutofillScript,
|
fillScript: AutofillScript,
|
||||||
pageDetails: AutofillPageDetails,
|
pageDetails: AutofillPageDetails,
|
||||||
filledFields: { [id: string]: AutofillField },
|
filledFields: { [id: string]: AutofillField },
|
||||||
options: GenerateFillScriptOptions,
|
options: GenerateFillScriptOptions,
|
||||||
): AutofillScript {
|
): Promise<AutofillScript> {
|
||||||
|
if (await this.configService.getFeatureFlag(FeatureFlag.GenerateIdentityFillScriptRefactor)) {
|
||||||
|
return this._generateIdentityFillScript(fillScript, pageDetails, filledFields, options);
|
||||||
|
}
|
||||||
|
|
||||||
if (!options.cipher.identity) {
|
if (!options.cipher.identity) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -1476,6 +1487,589 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
return fillScript;
|
return fillScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the autofill script for the specified page details and identity cipher item.
|
||||||
|
*
|
||||||
|
* @param fillScript - Object to store autofill script, passed between method references
|
||||||
|
* @param pageDetails - The details of the page to autofill
|
||||||
|
* @param filledFields - The fields that have already been filled, passed between method references
|
||||||
|
* @param options - Contains data used to fill cipher items
|
||||||
|
*/
|
||||||
|
private _generateIdentityFillScript(
|
||||||
|
fillScript: AutofillScript,
|
||||||
|
pageDetails: AutofillPageDetails,
|
||||||
|
filledFields: { [id: string]: AutofillField },
|
||||||
|
options: GenerateFillScriptOptions,
|
||||||
|
): AutofillScript {
|
||||||
|
const identity = options.cipher.identity;
|
||||||
|
if (!identity) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let fieldsIndex = 0; fieldsIndex < pageDetails.fields.length; fieldsIndex++) {
|
||||||
|
const field = pageDetails.fields[fieldsIndex];
|
||||||
|
if (this.excludeFieldFromIdentityFill(field)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keywordsList = this.getIdentityAutofillFieldKeywords(field);
|
||||||
|
const keywordsCombined = keywordsList.join(",");
|
||||||
|
if (this.shouldMakeIdentityTitleFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.title, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityNameFillScript(filledFields, keywordsList)) {
|
||||||
|
this.makeIdentityNameFillScript(fillScript, filledFields, field, identity);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityFirstNameFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.firstName, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityMiddleNameFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.middleName, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityLastNameFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.lastName, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityEmailFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.email, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityAddressFillScript(filledFields, keywordsList)) {
|
||||||
|
this.makeIdentityAddressFillScript(fillScript, filledFields, field, identity);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityAddress1FillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.address1, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityAddress2FillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.address2, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityAddress3FillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.address3, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityPostalCodeFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.postalCode, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityCityFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.city, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityStateFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeIdentityStateFillScript(fillScript, filledFields, field, identity);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityCountryFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeIdentityCountryFillScript(fillScript, filledFields, field, identity);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityPhoneFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.phone, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityUserNameFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.username, field, filledFields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shouldMakeIdentityCompanyFillScript(filledFields, keywordsCombined)) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.company, field, filledFields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fillScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if the current field should be excluded from triggering autofill of the identity cipher.
|
||||||
|
*
|
||||||
|
* @param field - The field to check
|
||||||
|
*/
|
||||||
|
private excludeFieldFromIdentityFill(field: AutofillField): boolean {
|
||||||
|
return (
|
||||||
|
AutofillService.isExcludedFieldType(field, AutoFillConstants.ExcludedAutofillTypes) ||
|
||||||
|
AutoFillConstants.ExcludedIdentityAutocompleteTypes.has(field.autoCompleteType) ||
|
||||||
|
!field.viewable
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gathers all unique keyword identifiers from a field that can be used to determine what
|
||||||
|
* identity value should be filled.
|
||||||
|
*
|
||||||
|
* @param field - The field to gather keywords from
|
||||||
|
*/
|
||||||
|
private getIdentityAutofillFieldKeywords(field: AutofillField): string[] {
|
||||||
|
const keywords: Set<string> = new Set();
|
||||||
|
for (let index = 0; index < IdentityAutoFillConstants.IdentityAttributes.length; index++) {
|
||||||
|
const attribute = IdentityAutoFillConstants.IdentityAttributes[index];
|
||||||
|
if (field[attribute]) {
|
||||||
|
keywords.add(
|
||||||
|
field[attribute]
|
||||||
|
.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-zA-Z0-9]+/g, ""),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(keywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity title
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityTitleFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.title &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.TitleFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity name
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityNameFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string[],
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.name &&
|
||||||
|
keywords.some((keyword) =>
|
||||||
|
AutofillService.isFieldMatch(
|
||||||
|
keyword,
|
||||||
|
IdentityAutoFillConstants.FullNameFieldNames,
|
||||||
|
IdentityAutoFillConstants.FullNameFieldNameValues,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity first name
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityFirstNameFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.firstName &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.FirstnameFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity middle name
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityMiddleNameFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.middleName &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.MiddlenameFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity last name
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityLastNameFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.lastName &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.LastnameFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity email
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityEmailFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.email &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.EmailFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity address
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityAddressFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string[],
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.address &&
|
||||||
|
keywords.some((keyword) =>
|
||||||
|
AutofillService.isFieldMatch(
|
||||||
|
keyword,
|
||||||
|
IdentityAutoFillConstants.AddressFieldNames,
|
||||||
|
IdentityAutoFillConstants.AddressFieldNameValues,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity address1
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityAddress1FillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.address1 &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.Address1FieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity address2
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityAddress2FillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.address2 &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.Address2FieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity address3
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityAddress3FillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.address3 &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.Address3FieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity postal code
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityPostalCodeFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.postalCode &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.PostalCodeFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity city
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityCityFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.city &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.CityFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity state
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityStateFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.state &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.StateFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity country
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityCountryFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.country &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.CountryFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity phone
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityPhoneFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.phone &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.PhoneFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity username
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityUserNameFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.username &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.UserNameFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a fill script action for the identity company
|
||||||
|
* field should be created for the provided field.
|
||||||
|
*
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param keywords - The keywords from the field
|
||||||
|
*/
|
||||||
|
private shouldMakeIdentityCompanyFillScript(
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
keywords: string,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
!filledFields.company &&
|
||||||
|
AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.CompanyFieldNames)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an identity name fill script action for the provided field. This is used
|
||||||
|
* when filling a `full name` field, using the first, middle, and last name from the
|
||||||
|
* identity cipher item.
|
||||||
|
*
|
||||||
|
* @param fillScript - The autofill script to add the action to
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param field - The field to fill
|
||||||
|
* @param identity - The identity cipher item
|
||||||
|
*/
|
||||||
|
private makeIdentityNameFillScript(
|
||||||
|
fillScript: AutofillScript,
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
field: AutofillField,
|
||||||
|
identity: IdentityView,
|
||||||
|
) {
|
||||||
|
let name = "";
|
||||||
|
if (identity.firstName) {
|
||||||
|
name += identity.firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identity.middleName) {
|
||||||
|
name += !name ? identity.middleName : ` ${identity.middleName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identity.lastName) {
|
||||||
|
name += !name ? identity.lastName : ` ${identity.lastName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeScriptActionWithValue(fillScript, name, field, filledFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an identity address fill script action for the provided field. This is used
|
||||||
|
* when filling a generic `address` field, using the address1, address2, and address3
|
||||||
|
* from the identity cipher item.
|
||||||
|
*
|
||||||
|
* @param fillScript - The autofill script to add the action to
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param field - The field to fill
|
||||||
|
* @param identity - The identity cipher item
|
||||||
|
*/
|
||||||
|
private makeIdentityAddressFillScript(
|
||||||
|
fillScript: AutofillScript,
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
field: AutofillField,
|
||||||
|
identity: IdentityView,
|
||||||
|
) {
|
||||||
|
if (!identity.address1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let address = identity.address1;
|
||||||
|
|
||||||
|
if (identity.address2) {
|
||||||
|
address += `, ${identity.address2}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identity.address3) {
|
||||||
|
address += `, ${identity.address3}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeScriptActionWithValue(fillScript, address, field, filledFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an identity state fill script action for the provided field. This is used
|
||||||
|
* when filling a `state` field, using the state value from the identity cipher item.
|
||||||
|
* If the state value is a full name, it will be converted to an ISO code.
|
||||||
|
*
|
||||||
|
* @param fillScript - The autofill script to add the action to
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param field - The field to fill
|
||||||
|
* @param identity - The identity cipher item
|
||||||
|
*/
|
||||||
|
private makeIdentityStateFillScript(
|
||||||
|
fillScript: AutofillScript,
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
field: AutofillField,
|
||||||
|
identity: IdentityView,
|
||||||
|
) {
|
||||||
|
if (!identity.state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identity.state.length <= 2) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.state, field, filledFields);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stateLower = identity.state.toLowerCase();
|
||||||
|
const isoState =
|
||||||
|
IdentityAutoFillConstants.IsoStates[stateLower] ||
|
||||||
|
IdentityAutoFillConstants.IsoProvinces[stateLower];
|
||||||
|
if (isoState) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, isoState, field, filledFields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an identity country fill script action for the provided field. This is used
|
||||||
|
* when filling a `country` field, using the country value from the identity cipher item.
|
||||||
|
* If the country value is a full name, it will be converted to an ISO code.
|
||||||
|
*
|
||||||
|
* @param fillScript - The autofill script to add the action to
|
||||||
|
* @param filledFields - The fields that have already been filled
|
||||||
|
* @param field - The field to fill
|
||||||
|
* @param identity - The identity cipher item
|
||||||
|
*/
|
||||||
|
private makeIdentityCountryFillScript(
|
||||||
|
fillScript: AutofillScript,
|
||||||
|
filledFields: Record<string, AutofillField>,
|
||||||
|
field: AutofillField,
|
||||||
|
identity: IdentityView,
|
||||||
|
) {
|
||||||
|
if (!identity.country) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identity.country.length <= 2) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, identity.country, field, filledFields);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const countryLower = identity.country.toLowerCase();
|
||||||
|
const isoCountry = IdentityAutoFillConstants.IsoCountries[countryLower];
|
||||||
|
if (isoCountry) {
|
||||||
|
this.makeScriptActionWithValue(fillScript, isoCountry, field, filledFields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accepts an HTMLInputElement type value and a list of
|
* Accepts an HTMLInputElement type value and a list of
|
||||||
* excluded types and returns true if the type is excluded.
|
* excluded types and returns true if the type is excluded.
|
||||||
|
@ -1057,7 +1057,7 @@ export class InlineMenuFieldQualificationService
|
|||||||
returnStringValue: boolean,
|
returnStringValue: boolean,
|
||||||
) {
|
) {
|
||||||
if (!this.autofillFieldKeywordsMap.has(autofillFieldData)) {
|
if (!this.autofillFieldKeywordsMap.has(autofillFieldData)) {
|
||||||
const keywords = [
|
const keywordsSet = new Set<string>([
|
||||||
autofillFieldData.htmlID,
|
autofillFieldData.htmlID,
|
||||||
autofillFieldData.htmlName,
|
autofillFieldData.htmlName,
|
||||||
autofillFieldData.htmlClass,
|
autofillFieldData.htmlClass,
|
||||||
@ -1071,9 +1071,8 @@ export class InlineMenuFieldQualificationService
|
|||||||
autofillFieldData["label-right"],
|
autofillFieldData["label-right"],
|
||||||
autofillFieldData["label-tag"],
|
autofillFieldData["label-tag"],
|
||||||
autofillFieldData["label-top"],
|
autofillFieldData["label-top"],
|
||||||
];
|
]);
|
||||||
const keywordsSet = new Set<string>(keywords);
|
const stringValue = Array.from(keywordsSet).join(",").toLowerCase();
|
||||||
const stringValue = keywords.join(",").toLowerCase();
|
|
||||||
this.autofillFieldKeywordsMap.set(autofillFieldData, { keywordsSet, stringValue });
|
this.autofillFieldKeywordsMap.set(autofillFieldData, { keywordsSet, stringValue });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ export enum FeatureFlag {
|
|||||||
AuthenticatorTwoFactorToken = "authenticator-2fa-token",
|
AuthenticatorTwoFactorToken = "authenticator-2fa-token",
|
||||||
UnauthenticatedExtensionUIRefresh = "unauth-ui-refresh",
|
UnauthenticatedExtensionUIRefresh = "unauth-ui-refresh",
|
||||||
EnableUpgradePasswordManagerSub = "AC-2708-upgrade-password-manager-sub",
|
EnableUpgradePasswordManagerSub = "AC-2708-upgrade-password-manager-sub",
|
||||||
|
GenerateIdentityFillScriptRefactor = "generate-identity-fill-script-refactor",
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AllowedFeatureFlagTypes = boolean | number | string;
|
export type AllowedFeatureFlagTypes = boolean | number | string;
|
||||||
@ -68,6 +69,7 @@ export const DefaultFeatureFlagValue = {
|
|||||||
[FeatureFlag.AuthenticatorTwoFactorToken]: FALSE,
|
[FeatureFlag.AuthenticatorTwoFactorToken]: FALSE,
|
||||||
[FeatureFlag.UnauthenticatedExtensionUIRefresh]: FALSE,
|
[FeatureFlag.UnauthenticatedExtensionUIRefresh]: FALSE,
|
||||||
[FeatureFlag.EnableUpgradePasswordManagerSub]: FALSE,
|
[FeatureFlag.EnableUpgradePasswordManagerSub]: FALSE,
|
||||||
|
[FeatureFlag.GenerateIdentityFillScriptRefactor]: FALSE,
|
||||||
} satisfies Record<FeatureFlag, AllowedFeatureFlagTypes>;
|
} satisfies Record<FeatureFlag, AllowedFeatureFlagTypes>;
|
||||||
|
|
||||||
export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue;
|
export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue;
|
||||||
|
Loading…
Reference in New Issue
Block a user