1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 00:03:56 +00:00

Prefer autofilling login forms over registration forms (#16811)

This commit is contained in:
Jeffrey Holland
2025-10-21 10:35:05 +02:00
committed by GitHub
parent bbfdb60c34
commit a15d6867f9
2 changed files with 57 additions and 3 deletions

View File

@@ -59,6 +59,14 @@ export class AutoFillConstants {
"neue e-mail",
];
static readonly RegistrationKeywords: string[] = [
"register",
"signup",
"sign-up",
"join",
"create",
];
static readonly NewsletterFormNames: string[] = ["newsletter"];
static readonly FieldIgnoreList: string[] = ["captcha", "findanything", "forgot"];

View File

@@ -856,13 +856,28 @@ export default class AutofillService implements AutofillServiceInterface {
options.fillNewPassword,
);
const loginPasswordFields: AutofillField[] = [];
const registrationPasswordFields: AutofillField[] = [];
passwordFields.forEach((passField) => {
if (this.isRegistrationPasswordField(pageDetails, passField)) {
registrationPasswordFields.push(passField);
} else {
loginPasswordFields.push(passField);
}
});
// Prefer login fields over registration fields
const prioritizedPasswordFields =
loginPasswordFields.length > 0 ? loginPasswordFields : registrationPasswordFields;
for (const formKey in pageDetails.forms) {
// eslint-disable-next-line
if (!pageDetails.forms.hasOwnProperty(formKey)) {
continue;
}
passwordFields.forEach((passField) => {
prioritizedPasswordFields.forEach((passField) => {
pf = passField;
passwords.push(pf);
@@ -887,8 +902,7 @@ export default class AutofillService implements AutofillServiceInterface {
if (passwordFields.length && !passwords.length) {
// The page does not have any forms with password fields. Use the first password field on the page and the
// input field just before it as the username.
pf = passwordFields[0];
pf = prioritizedPasswordFields[0];
passwords.push(pf);
if (login.username && pf.elementNumber > 0) {
@@ -2251,6 +2265,38 @@ export default class AutofillService implements AutofillServiceInterface {
return arr;
}
/**
* Determines if a password field is part of a registration/signup form.
* @param {AutofillPageDetails} pageDetails
* @param {AutofillField} passwordField
* @returns {boolean}
* @private
*/
private isRegistrationPasswordField(
pageDetails: AutofillPageDetails,
passwordField: AutofillField,
): boolean {
if (!passwordField.form || !pageDetails.forms) {
return false;
}
const form = pageDetails.forms[passwordField.form];
if (!form) {
return false;
}
const formIdentifierValues = [
form.htmlID?.toLowerCase?.(),
form.htmlName?.toLowerCase?.(),
passwordField?.htmlID?.toLowerCase?.(),
passwordField?.htmlName?.toLowerCase?.(),
].filter(Boolean);
return formIdentifierValues.some((value) =>
AutoFillConstants.RegistrationKeywords.some((keyword) => value.includes(keyword)),
);
}
/**
* Accepts a pageDetails object with a list of fields and returns a list of
* fields that are likely to be username fields.