Commit 4b06d0ab authored by Ioana Pandele's avatar Ioana Pandele Committed by Commit Bot

[Password Manager] Autofill forms with prefilled values matching list of known placeholders

Currently, the password manager doesn't autofill forms with prefilled values in the username
field in order to preserve existing information. This CL changes the behavior to autofill
in cases where the prefilled username value is part of a list of known placeholders.

Bug:832622

Change-Id: I9178eac0e609655c61e5e1caf35d083414e14b8b
Reviewed-on: https://chromium-review.googlesource.com/1007723Reviewed-by: default avatarVaclav Brozek <vabr@chromium.org>
Reviewed-by: default avatarChristos Froussios <cfroussios@chromium.org>
Commit-Queue: Ioana Pandele <ioanap@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551290}
parent ff2de6c1
......@@ -793,6 +793,29 @@ TEST_F(PasswordAutofillAgentTest,
UTF16ToUTF8(password3_), true);
}
// Fill username and password fields when username field contains a prefilled
// value that matches the list of known possible prefilled values usually used
// as placeholders.
TEST_F(PasswordAutofillAgentTest, AutocompleteForPrefilledUsernameValue) {
// Set the username element to a value from the prefilled values list.
// Comparison should be insensitive to leading and trailing whitespaces.
username_element_.SetValue(
WebString::FromUTF16(base::UTF8ToUTF16(" User Name ")));
// Simulate the browser sending back the login info, it triggers the
// autocomplete.
SimulateOnFillPasswordForm(fill_data_);
// The username and password should both have suggested values.
CheckTextFieldsSuggestedState(kAliceUsername, true, kAlicePassword, true);
// Simulate a user click so that the password field's real value is filled.
SimulateElementClick(kUsernameName);
// The username and password should have been autocompleted.
CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
}
// Fill a password field if the stored username is a prefix of username in
// read-only field.
TEST_F(PasswordAutofillAgentTest,
......@@ -864,8 +887,9 @@ TEST_F(PasswordAutofillAgentTest, NoAutocompleteForFilledFieldUnmatched) {
false);
}
// Don't try to complete a prefilled value even if it's a partial match
// to a username.
// Don't try to complete a prefilled value that is a partial match
// to a username if the prefilled value isn't on the list of known values
// used as placeholders.
TEST_F(PasswordAutofillAgentTest, NoPartialMatchForPrefilledUsername) {
username_element_.SetValue(WebString::FromUTF8("ali"));
......
......@@ -13,10 +13,12 @@
#include <vector>
#include "base/bind.h"
#include "base/containers/flat_set.h"
#include "base/i18n/case_conversion.h"
#include "base/memory/linked_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
......@@ -79,6 +81,61 @@ bool FillDataContainsFillableUsername(const PasswordFormFillData& fill_data) {
!fill_data.username_field.value.empty());
}
// Checks if the prefilled value of the username element is one of the known
// values possibly used as placeholders. The list of possible placeholder
// values comes from popular sites exhibiting this issue.
// TODO(crbug.com/832622): Remove this once a stable solution is in place.
bool PossiblePrefilledUsernameValue(const std::string& username_value) {
static base::NoDestructor<base::flat_set<std::string, std::less<>>>
kPrefilledUsernameValues({"3~15个字符,中文字符7个以内",
"Benutzername",
"Digite seu CPF ou e-mail",
"DS Logon Username",
"Email Address",
"email address",
"Email masih kosong",
"Email/手機號碼",
"Enter User Name",
"Identifiant",
"Kullanıcı Adı",
"Kunden-ID",
"Nick",
"Nom Utilisateur",
"Rut",
"Siret",
"this is usually your email address",
"UID/用戶名/Email",
"User Id",
"User Name",
"Username",
"username",
"username or email",
"Username or email:",
"Username/Email",
"Usuario",
"Your email address",
"Имя",
"Логин",
"Логин...",
"כתובת דוא''ל",
"اسم العضو",
"اسم المستخدم",
"الاسم",
"نام کاربری",
"メールアドレス",
"用户名",
"用户名/Email",
"請輸入身份證字號",
"请用微博帐号登录",
"请输入手机号或邮箱",
"请输入邮箱或手机号",
"邮箱/手机/展位号"});
return kPrefilledUsernameValues->find(
base::TrimWhitespaceASCII(username_value, base::TRIM_ALL)) !=
kPrefilledUsernameValues->end();
}
// Returns true if password form has username and password fields with either
// same or no name and id attributes supplied.
bool DoesFormContainAmbiguousOrEmptyNames(
......@@ -1751,7 +1808,8 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
// |current_username| is the username for credentials that are going to be
// autofilled. It is selected according to the algorithm:
// 1. If the page already contain a non-empty value in |username_element|,
// 1. If the page already contains a non-empty value in |username_element|
// that is not found in the list of values known to be used as placeholders,
// this is adopted and not overridden.
// 2. Default username from |fill_data| if the username field is
// autocompletable.
......@@ -1759,7 +1817,8 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
// not autocompletable (no username case).
base::string16 current_username;
if (!username_element->IsNull()) {
if (!username_element->Value().IsEmpty())
if (!username_element->Value().IsEmpty() &&
!PossiblePrefilledUsernameValue(username_element->Value().Utf8()))
current_username = username_element->Value().Utf16();
else if (IsElementAutocompletable(*username_element))
current_username = fill_data.username_field.value;
......@@ -1783,8 +1842,12 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
// Input matches the username, fill in required values.
if (!username_element->IsNull() &&
IsElementAutocompletable(*username_element)) {
// Fill username only when it's not empty and not set by the page.
if (!username.empty() && username_element->Value().IsEmpty()) {
// Fill a non-empty username if it is safe to override the value of the
// username element. It is safe to override if the value is empty or a known
// placeholder value.
if (!username.empty() &&
(username_element->Value().IsEmpty() ||
PossiblePrefilledUsernameValue(username_element->Value().Utf8()))) {
username_element->SetSuggestedValue(
blink::WebString::FromUTF16(username));
registration_callback.Run(username_element);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment