Commit 9980098d authored by Maxim Kolosovskiy's avatar Maxim Kolosovskiy Committed by Commit Bot

[Password Manager] Fix bug in crowdsourcing of |ACCOUNT_CREATION_PASSWORD| vote

When Chrome uploads |ACCOUNT_CREATION_PASSWORD| vote, the uploaded form data should
belong to the saved credential(i.e. |PasswordFormManager::pending_credentials|), but
not to |submitted_form_| or |observed_form_|. This CL fixes it.

The CL also changes how |password_element| is set in |CreatePendingCredentials|. If
|pending_credentials_| is an already saved credential, then |password_element| should
be from the saved credential, but not from the submitted form.

Bug: 552420
Change-Id: I84dec939e097f0356d3ad7af8cdf3dc9ec97e2a5
Reviewed-on: https://chromium-review.googlesource.com/1014105Reviewed-by: default avatarVadym Doroshenko <dvadym@chromium.org>
Commit-Queue: Maxim Kolosovskiy <kolos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551322}
parent f04621c5
...@@ -152,7 +152,7 @@ void SetFieldLabelsOnUpdate(const autofill::ServerFieldType password_type, ...@@ -152,7 +152,7 @@ void SetFieldLabelsOnUpdate(const autofill::ServerFieldType password_type,
// Sets the autofill type of the password field stored in |submitted_form| to // Sets the autofill type of the password field stored in |submitted_form| to
// |password_type| in |field_types| map. // |password_type| in |field_types| map.
void SetFieldLabelsOnSave(const autofill::ServerFieldType password_type, void SetFieldLabelsOnSave(const autofill::ServerFieldType password_type,
const autofill::PasswordForm& submitted_form, const autofill::PasswordForm& form,
FieldTypeMap* field_types) { FieldTypeMap* field_types) {
DCHECK(password_type == autofill::PASSWORD || DCHECK(password_type == autofill::PASSWORD ||
password_type == autofill::PROBABLY_ACCOUNT_CREATION_PASSWORD || password_type == autofill::PROBABLY_ACCOUNT_CREATION_PASSWORD ||
...@@ -160,11 +160,11 @@ void SetFieldLabelsOnSave(const autofill::ServerFieldType password_type, ...@@ -160,11 +160,11 @@ void SetFieldLabelsOnSave(const autofill::ServerFieldType password_type,
password_type == autofill::NOT_ACCOUNT_CREATION_PASSWORD) password_type == autofill::NOT_ACCOUNT_CREATION_PASSWORD)
<< password_type; << password_type;
if (!submitted_form.new_password_element.empty()) { if (!form.new_password_element.empty()) {
(*field_types)[submitted_form.new_password_element] = password_type; (*field_types)[form.new_password_element] = password_type;
} else { } else {
DCHECK(!submitted_form.password_element.empty()); DCHECK(!form.password_element.empty());
(*field_types)[submitted_form.password_element] = password_type; (*field_types)[form.password_element] = password_type;
} }
} }
...@@ -914,18 +914,18 @@ bool PasswordFormManager::UploadPasswordVote( ...@@ -914,18 +914,18 @@ bool PasswordFormManager::UploadPasswordVote(
autofill::AutofillUploadContents::Field::NO_INFORMATION; autofill::AutofillUploadContents::Field::NO_INFORMATION;
if (autofill_type != autofill::USERNAME) { if (autofill_type != autofill::USERNAME) {
if (has_autofill_vote) { if (has_autofill_vote) {
DCHECK(submitted_form_);
bool is_update = autofill_type == autofill::NEW_PASSWORD || bool is_update = autofill_type == autofill::NEW_PASSWORD ||
autofill_type == autofill::PROBABLY_NEW_PASSWORD || autofill_type == autofill::PROBABLY_NEW_PASSWORD ||
autofill_type == autofill::NOT_NEW_PASSWORD; autofill_type == autofill::NOT_NEW_PASSWORD;
if (is_update) { if (is_update) {
if (submitted_form_->new_password_element.empty()) if (form_to_upload.new_password_element.empty())
return false; return false;
SetFieldLabelsOnUpdate(autofill_type, *submitted_form_, &field_types); SetFieldLabelsOnUpdate(autofill_type, form_to_upload, &field_types);
} else { // Saving. } else { // Saving.
SetFieldLabelsOnSave(autofill_type, *submitted_form_, &field_types); SetFieldLabelsOnSave(autofill_type, form_to_upload, &field_types);
} }
field_types[submitted_form_->confirmation_password_element] = field_types[form_to_upload.confirmation_password_element] =
autofill::CONFIRMATION_PASSWORD; autofill::CONFIRMATION_PASSWORD;
} }
if (autofill_type != autofill::ACCOUNT_CREATION_PASSWORD) { if (autofill_type != autofill::ACCOUNT_CREATION_PASSWORD) {
...@@ -1146,7 +1146,7 @@ void PasswordFormManager::CreatePendingCredentials() { ...@@ -1146,7 +1146,7 @@ void PasswordFormManager::CreatePendingCredentials() {
// If a password was generated and we didn't find a match, we have to save // If a password was generated and we didn't find a match, we have to save
// it in a separate entry since we have to store it but we don't know // it in a separate entry since we have to store it but we don't know
// where. // where.
CreatePendingCredentialsForNewCredentials(); CreatePendingCredentialsForNewCredentials(password_to_save.second);
is_new_login_ = true; is_new_login_ = true;
} else { } else {
// We don't have a good candidate to choose as the default credential for // We don't have a good candidate to choose as the default credential for
...@@ -1159,7 +1159,7 @@ void PasswordFormManager::CreatePendingCredentials() { ...@@ -1159,7 +1159,7 @@ void PasswordFormManager::CreatePendingCredentials() {
is_new_login_ = true; is_new_login_ = true;
// No stored credentials can be matched to the submitted form. Offer to // No stored credentials can be matched to the submitted form. Offer to
// save new credentials. // save new credentials.
CreatePendingCredentialsForNewCredentials(); CreatePendingCredentialsForNewCredentials(password_to_save.second);
// Generate username correction votes. // Generate username correction votes.
bool username_correction_found = FindCorrectedUsernameElement( bool username_correction_found = FindCorrectedUsernameElement(
submitted_form_->username_value, submitted_form_->password_value); submitted_form_->username_value, submitted_form_->password_value);
...@@ -1174,7 +1174,6 @@ void PasswordFormManager::CreatePendingCredentials() { ...@@ -1174,7 +1174,6 @@ void PasswordFormManager::CreatePendingCredentials() {
if (!IsValidAndroidFacetURI(pending_credentials_.signon_realm)) { if (!IsValidAndroidFacetURI(pending_credentials_.signon_realm)) {
pending_credentials_.action = submitted_form_->action; pending_credentials_.action = submitted_form_->action;
pending_credentials_.password_element = password_to_save.second;
// If the user selected credentials we autofilled from a PasswordForm // If the user selected credentials we autofilled from a PasswordForm
// that contained no action URL (IE6/7 imported passwords, for example), // that contained no action URL (IE6/7 imported passwords, for example),
// bless it with the action URL from the observed form. See b/1107719. // bless it with the action URL from the observed form. See b/1107719.
...@@ -1348,7 +1347,8 @@ const PasswordForm* PasswordFormManager::FindBestSavedMatch( ...@@ -1348,7 +1347,8 @@ const PasswordForm* PasswordFormManager::FindBestSavedMatch(
return nullptr; return nullptr;
} }
void PasswordFormManager::CreatePendingCredentialsForNewCredentials() { void PasswordFormManager::CreatePendingCredentialsForNewCredentials(
const base::string16& password_element) {
// User typed in a new, unknown username. // User typed in a new, unknown username.
SetUserAction(UserAction::kOverrideUsernameAndPassword); SetUserAction(UserAction::kOverrideUsernameAndPassword);
pending_credentials_ = observed_form_; pending_credentials_ = observed_form_;
...@@ -1361,7 +1361,9 @@ void PasswordFormManager::CreatePendingCredentialsForNewCredentials() { ...@@ -1361,7 +1361,9 @@ void PasswordFormManager::CreatePendingCredentialsForNewCredentials() {
// The password value will be filled in later, remove any garbage for now. // The password value will be filled in later, remove any garbage for now.
pending_credentials_.password_value.clear(); pending_credentials_.password_value.clear();
pending_credentials_.password_element.clear(); // The password element should be determined earlier in |PasswordToSave|.
pending_credentials_.password_element = password_element;
// The new password's value and element name should be empty.
pending_credentials_.new_password_value.clear(); pending_credentials_.new_password_value.clear();
pending_credentials_.new_password_element.clear(); pending_credentials_.new_password_element.clear();
} }
......
...@@ -411,7 +411,8 @@ class PasswordFormManager : public FormFetcher::Consumer { ...@@ -411,7 +411,8 @@ class PasswordFormManager : public FormFetcher::Consumer {
// Create pending credentials from provisionally saved form when this form // Create pending credentials from provisionally saved form when this form
// represents credentials that were not previosly saved. // represents credentials that were not previosly saved.
void CreatePendingCredentialsForNewCredentials(); void CreatePendingCredentialsForNewCredentials(
const base::string16& password_element);
// If |best_matches_| contains only one entry, then return this entry. // If |best_matches_| contains only one entry, then return this entry.
// Otherwise for empty |password| return nullptr and for non-empty |password| // Otherwise for empty |password| return nullptr and for non-empty |password|
......
...@@ -478,6 +478,7 @@ class PasswordFormManagerTest : public testing::Test { ...@@ -478,6 +478,7 @@ class PasswordFormManagerTest : public testing::Test {
PasswordForm form_to_save(form); PasswordForm form_to_save(form);
form_to_save.preferred = true; form_to_save.preferred = true;
form_to_save.username_element = ASCIIToUTF16("observed-username-field"); form_to_save.username_element = ASCIIToUTF16("observed-username-field");
form_to_save.password_element = ASCIIToUTF16("observed-password-field");
form_to_save.username_value = match.username_value; form_to_save.username_value = match.username_value;
form_to_save.password_value = match.password_value; form_to_save.password_value = match.password_value;
...@@ -1241,7 +1242,7 @@ TEST_F(PasswordFormManagerTest, TestUpdatePasswordFromNewPasswordElement) { ...@@ -1241,7 +1242,7 @@ TEST_F(PasswordFormManagerTest, TestUpdatePasswordFromNewPasswordElement) {
// The password should be updated. // The password should be updated.
EXPECT_EQ(credentials.new_password_value, new_credentials.password_value); EXPECT_EQ(credentials.new_password_value, new_credentials.password_value);
EXPECT_EQ(saved_match()->username_element, new_credentials.username_element); EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
EXPECT_EQ(credentials.new_password_element, new_credentials.password_element); EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element); EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element);
} }
...@@ -2023,13 +2024,13 @@ TEST_F(PasswordFormManagerTest, UploadFormData_NewPassword_Blacklist) { ...@@ -2023,13 +2024,13 @@ TEST_F(PasswordFormManagerTest, UploadFormData_NewPassword_Blacklist) {
TEST_F(PasswordFormManagerTest, UploadPasswordForm) { TEST_F(PasswordFormManagerTest, UploadPasswordForm) {
autofill::FormData observed_form_data; autofill::FormData observed_form_data;
autofill::FormFieldData field; autofill::FormFieldData field;
field.label = ASCIIToUTF16("Email"); field.label = ASCIIToUTF16("Email:");
field.name = ASCIIToUTF16("observed-username-field"); field.name = ASCIIToUTF16("observed-username-field");
field.form_control_type = "text"; field.form_control_type = "text";
observed_form_data.fields.push_back(field); observed_form_data.fields.push_back(field);
field.label = ASCIIToUTF16("password"); field.label = ASCIIToUTF16("Password:");
field.name = ASCIIToUTF16("password"); field.name = ASCIIToUTF16("observed-password-field");
field.form_control_type = "password"; field.form_control_type = "password";
observed_form_data.fields.push_back(field); observed_form_data.fields.push_back(field);
...@@ -2310,9 +2311,9 @@ TEST_F(PasswordFormManagerTest, TestUpdateNoUsernameTextfieldPresent) { ...@@ -2310,9 +2311,9 @@ TEST_F(PasswordFormManagerTest, TestUpdateNoUsernameTextfieldPresent) {
EXPECT_EQ(saved_match()->username_value, new_credentials.username_value); EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
EXPECT_EQ(credentials.new_password_value, new_credentials.password_value); EXPECT_EQ(credentials.new_password_value, new_credentials.password_value);
EXPECT_EQ(saved_match()->username_element, new_credentials.username_element); EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
EXPECT_EQ(credentials.new_password_element, new_credentials.password_element); EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
EXPECT_EQ(base::string16(), new_credentials.new_password_value); EXPECT_TRUE(new_credentials.new_password_value.empty());
EXPECT_EQ(base::string16(), new_credentials.new_password_element); EXPECT_TRUE(new_credentials.new_password_element.empty());
EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element); EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_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