Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Unified Diff: components/password_manager/core/browser/password_form_manager.cc

Issue 2542093002: [Password Generation] Fixes sending votes about the usage of the password generation popup (Closed)
Patch Set: Fix for the failed Mac test Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/password_manager/core/browser/password_form_manager.cc
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index e916b8cefa7c7ee6523eb3cd781833f537a3bb60..4c82699add8cb06066c625d7f3ffc2397cd3dccd 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -354,8 +354,8 @@ void PasswordFormManager::Update(
const autofill::PasswordForm& credentials_to_update) {
if (observed_form_.IsPossibleChangePasswordForm()) {
FormStructure form_structure(credentials_to_update.form_data);
- UploadChangePasswordForm(autofill::NEW_PASSWORD,
- form_structure.FormSignatureAsStr());
+ UploadPasswordVote(base::string16(), autofill::NEW_PASSWORD,
+ form_structure.FormSignatureAsStr());
}
base::string16 password_to_save = pending_credentials_.password_value;
bool skip_zero_click = pending_credentials_.skip_zero_click;
@@ -607,17 +607,17 @@ bool PasswordFormManager::UpdatePendingCredentialsIfOtherPossibleUsername(
void PasswordFormManager::SendAutofillVotes(const PasswordForm& observed,
PasswordForm* pending) {
+ // Ignore |pending_structure| if its FormData has no fields. This is to
+ // weed out those credentials that were saved before FormData was added
+ // to PasswordForm. Even without this check, these FormStructure's won't
+ // be uploaded, but it makes it hard to see if we are encountering
+ // unexpected errors.
if (pending->form_data.fields.empty())
return;
FormStructure pending_structure(pending->form_data);
FormStructure observed_structure(observed.form_data);
- // Ignore |pending_structure| if its FormData has no fields. This is to
- // weed out those credentials that were saved before FormData was added
- // to PasswordForm. Even without this check, these FormStructure's won't
- // be uploaded, but it makes it hard to see if we are encountering
- // unexpected errors.
if (pending_structure.FormSignatureAsStr() !=
observed_structure.FormSignatureAsStr()) {
// Only upload if this is the first time the password has been used.
@@ -627,7 +627,7 @@ void PasswordFormManager::SendAutofillVotes(const PasswordForm& observed,
// in cases where we currently save the wrong username isn't great.
// TODO(gcasto): Determine if generation should be offered in this case.
if (pending->times_used == 1 && selected_username_.empty()) {
- if (UploadPasswordForm(pending->form_data, pending->username_element,
+ if (UploadPasswordVote(pending->username_element,
autofill::ACCOUNT_CREATION_PASSWORD,
observed_structure.FormSignatureAsStr())) {
pending->generation_upload_status =
@@ -639,63 +639,62 @@ void PasswordFormManager::SendAutofillVotes(const PasswordForm& observed,
// A signal was sent that this was an account creation form, but the
// credential is now being used on the same form again. This cancels out
// the previous vote.
- if (UploadPasswordForm(pending->form_data, base::string16(),
+ if (UploadPasswordVote(base::string16(),
autofill::NOT_ACCOUNT_CREATION_PASSWORD,
std::string())) {
pending->generation_upload_status =
autofill::PasswordForm::NEGATIVE_SIGNAL_SENT;
}
+ } else if (generation_popup_was_shown_) {
+ // Even if there is no autofill vote to be sent, send the vote about the
+ // usage of the generation popup.
+ UploadPasswordVote(base::string16(), autofill::UNKNOWN_TYPE, std::string());
}
}
-bool PasswordFormManager::UploadPasswordForm(
- const autofill::FormData& form_data,
+bool PasswordFormManager::UploadPasswordVote(
const base::string16& username_field,
const autofill::ServerFieldType& password_type,
const std::string& login_form_signature) {
- DCHECK(password_type == autofill::PASSWORD ||
- password_type == autofill::PROBABLY_ACCOUNT_CREATION_PASSWORD ||
- password_type == autofill::ACCOUNT_CREATION_PASSWORD ||
- password_type == autofill::NOT_ACCOUNT_CREATION_PASSWORD);
+ // Check if there is any vote to be sent.
+ bool has_autofill_vote = password_type != autofill::UNKNOWN_TYPE;
+ bool has_password_generation_vote = generation_popup_was_shown_;
+ if (!has_autofill_vote && !has_password_generation_vote)
+ return false;
+
autofill::AutofillManager* autofill_manager =
client_->GetAutofillManagerForMainFrame();
if (!autofill_manager || !autofill_manager->download_manager())
return false;
- FormStructure form_structure(form_data);
+ bool is_update = password_type == autofill::NEW_PASSWORD ||
+ password_type == autofill::PROBABLY_NEW_PASSWORD ||
+ password_type == autofill::NOT_NEW_PASSWORD;
+ // If this is an update, a vote about the observed form is sent. If the user
+ // re-uses credentials, a vote about the saved form is sent. If the user saves
+ // credentials, the observed and pending forms are the same.
+ FormStructure form_structure(is_update ? observed_form_.form_data
+ : pending_credentials_.form_data);
if (!autofill_manager->ShouldUploadForm(form_structure) ||
!form_structure.ShouldBeCrowdsourced()) {
UMA_HISTOGRAM_BOOLEAN("PasswordGeneration.UploadStarted", false);
return false;
}
- // Find the first password field to label. If the provided username field name
- // is not empty, then also find the first field with that name to label.
- // We don't try to label anything else.
- bool found_password_field = false;
- bool should_find_username_field = !username_field.empty();
- for (size_t i = 0; i < form_structure.field_count(); ++i) {
- autofill::AutofillField* field = form_structure.field(i);
+ autofill::ServerFieldTypeSet available_field_types;
+ if (has_autofill_vote) {
+ if (is_update) {
+ if (!provisionally_saved_form_ ||
+ provisionally_saved_form_->new_password_element.empty())
+ return false;
+ SetAutofillTypesOnUpdate(password_type, &form_structure,
+ &available_field_types);
- autofill::ServerFieldType type = autofill::UNKNOWN_TYPE;
- if (!found_password_field && field->form_control_type == "password") {
- type = password_type;
- found_password_field = true;
- } else if (should_find_username_field && field->name == username_field) {
- type = autofill::USERNAME;
- should_find_username_field = false;
+ } else {
+ SetAutofillTypesOnSave(username_field, password_type, &form_structure,
+ &available_field_types);
}
-
- autofill::ServerFieldTypeSet types;
- types.insert(type);
- field->set_possible_types(types);
}
- DCHECK(found_password_field);
- DCHECK(!should_find_username_field);
-
- autofill::ServerFieldTypeSet available_field_types;
- available_field_types.insert(password_type);
- available_field_types.insert(autofill::USERNAME);
if (generation_popup_was_shown_)
AddGeneratedVote(&form_structure);
@@ -719,32 +718,28 @@ bool PasswordFormManager::UploadPasswordForm(
return success;
}
-bool PasswordFormManager::UploadChangePasswordForm(
- const autofill::ServerFieldType& password_type,
- const std::string& login_form_signature) {
+void PasswordFormManager::SetAutofillTypesOnUpdate(
+ const autofill::ServerFieldType password_type,
+ FormStructure* form_structure,
+ autofill::ServerFieldTypeSet* available_field_types) {
DCHECK(password_type == autofill::NEW_PASSWORD ||
password_type == autofill::PROBABLY_NEW_PASSWORD ||
- password_type == autofill::NOT_NEW_PASSWORD);
- if (!provisionally_saved_form_ ||
- provisionally_saved_form_->new_password_element.empty()) {
- // |new_password_element| is empty for non change password forms, for
- // example when the password was overriden.
- return false;
- }
- autofill::AutofillManager* autofill_manager =
- client_->GetAutofillManagerForMainFrame();
- if (!autofill_manager || !autofill_manager->download_manager())
- return false;
+ password_type == autofill::NOT_NEW_PASSWORD)
+ << password_type;
+ DCHECK(!provisionally_saved_form_->new_password_element.empty());
// Create a map from field names to field types.
std::map<base::string16, autofill::ServerFieldType> field_types;
- if (!pending_credentials_.username_element.empty())
+ if (!provisionally_saved_form_->username_element.empty()) {
field_types[provisionally_saved_form_->username_element] =
autofill::USERNAME;
- if (!pending_credentials_.password_element.empty())
+ }
+ if (!provisionally_saved_form_->password_element.empty()) {
field_types[provisionally_saved_form_->password_element] =
autofill::PASSWORD;
+ }
field_types[provisionally_saved_form_->new_password_element] = password_type;
+
// Find all password fields after |new_password_element| and set their type to
// |password_type|. They are considered to be confirmation fields.
const autofill::FormData& form_data = observed_form_.form_data;
@@ -763,45 +758,58 @@ bool PasswordFormManager::UploadChangePasswordForm(
}
DCHECK(is_new_password_field_found);
- // Create FormStructure with field type information for uploading a vote.
- FormStructure form_structure(form_data);
- if (!autofill_manager->ShouldUploadForm(form_structure) ||
- !form_structure.ShouldBeCrowdsourced())
- return false;
-
- autofill::ServerFieldTypeSet available_field_types;
- for (size_t i = 0; i < form_structure.field_count(); ++i) {
- autofill::AutofillField* field = form_structure.field(i);
+ for (size_t i = 0; i < form_structure->field_count(); ++i) {
+ autofill::AutofillField* field = form_structure->field(i);
autofill::ServerFieldType type = autofill::UNKNOWN_TYPE;
auto iter = field_types.find(field->name);
if (iter != field_types.end()) {
type = iter->second;
- available_field_types.insert(type);
+ available_field_types->insert(type);
}
autofill::ServerFieldTypeSet types;
types.insert(type);
field->set_possible_types(types);
}
+}
- if (generation_popup_was_shown_)
- AddGeneratedVote(&form_structure);
- if (form_classifier_outcome_ != kNoOutcome)
- AddFormClassifierVote(&form_structure);
+void PasswordFormManager::SetAutofillTypesOnSave(
+ const base::string16& username_field,
+ const autofill::ServerFieldType password_type,
+ FormStructure* form_structure,
+ autofill::ServerFieldTypeSet* available_field_types) {
+ DCHECK(password_type == autofill::PASSWORD ||
+ password_type == autofill::PROBABLY_ACCOUNT_CREATION_PASSWORD ||
+ password_type == autofill::ACCOUNT_CREATION_PASSWORD ||
+ password_type == autofill::NOT_ACCOUNT_CREATION_PASSWORD)
+ << password_type;
- // Force uploading as these events are relatively rare and we want to make
- // sure to receive them. It also makes testing easier if these requests
- // always pass.
- form_structure.set_upload_required(UPLOAD_REQUIRED);
+ // Find the first password field to label. If the provided username field
+ // name is not empty, then also find the first field with that name to label.
+ // We don't try to label anything else.
+ bool found_password_field = false;
+ bool should_find_username_field = !username_field.empty();
+ for (size_t i = 0; i < form_structure->field_count(); ++i) {
+ autofill::AutofillField* field = form_structure->field(i);
- if (password_manager_util::IsLoggingActive(client_)) {
- BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
- logger.LogFormStructure(Logger::STRING_FORM_VOTES, form_structure);
+ autofill::ServerFieldType type = autofill::UNKNOWN_TYPE;
+ if (!found_password_field && field->form_control_type == "password") {
+ type = password_type;
+ found_password_field = true;
+ } else if (should_find_username_field && field->name == username_field) {
+ type = autofill::USERNAME;
+ should_find_username_field = false;
+ }
+
+ autofill::ServerFieldTypeSet types;
+ types.insert(type);
+ field->set_possible_types(types);
}
+ DCHECK(found_password_field);
+ DCHECK(!should_find_username_field);
- return autofill_manager->download_manager()->StartUploadRequest(
- form_structure, false /* was_autofilled */, available_field_types,
- login_form_signature, true /* observed_submission */);
+ available_field_types->insert(password_type);
+ available_field_types->insert(autofill::USERNAME);
}
void PasswordFormManager::AddGeneratedVote(
@@ -1174,11 +1182,24 @@ void PasswordFormManager::CreatePendingCredentialsForNewCredentials() {
}
void PasswordFormManager::OnNopeUpdateClicked() {
- UploadChangePasswordForm(autofill::NOT_NEW_PASSWORD, std::string());
+ UploadPasswordVote(base::string16(), autofill::NOT_NEW_PASSWORD,
+ std::string());
+}
+
+void PasswordFormManager::OnNeverClicked() {
+ UploadPasswordVote(pending_credentials_.username_element,
+ autofill::UNKNOWN_TYPE, std::string());
+ PermanentlyBlacklist();
}
-void PasswordFormManager::OnNoInteractionOnUpdate() {
- UploadChangePasswordForm(autofill::PROBABLY_NEW_PASSWORD, std::string());
+void PasswordFormManager::OnNoInteraction(bool is_update) {
+ if (is_update)
+ UploadPasswordVote(base::string16(), autofill::PROBABLY_NEW_PASSWORD,
+ std::string());
+ else {
+ UploadPasswordVote(pending_credentials_.username_element,
+ autofill::UNKNOWN_TYPE, std::string());
+ }
}
void PasswordFormManager::LogSubmitPassed() {
@@ -1224,25 +1245,23 @@ void PasswordFormManager::SaveGenerationFieldDetectedByClassifier(
}
void PasswordFormManager::SendVotesOnSave() {
+ if (observed_form_.IsPossibleChangePasswordFormWithoutUsername())
+ return;
+
// Upload credentials the first time they are saved. This data is used
// by password generation to help determine account creation sites.
// Credentials that have been previously used (e.g., PSL matches) are checked
// to see if they are valid account creation forms.
if (pending_credentials_.times_used == 0) {
- if (!observed_form_.IsPossibleChangePasswordFormWithoutUsername()) {
base::string16 username_field;
autofill::ServerFieldType password_type = autofill::PASSWORD;
if (does_look_like_signup_form_) {
username_field = pending_credentials_.username_element;
password_type = autofill::PROBABLY_ACCOUNT_CREATION_PASSWORD;
}
- UploadPasswordForm(pending_credentials_.form_data, username_field,
- password_type, std::string());
- }
- } else {
- if (!observed_form_.IsPossibleChangePasswordFormWithoutUsername())
- SendAutofillVotes(observed_form_, &pending_credentials_);
- }
+ UploadPasswordVote(username_field, password_type, std::string());
+ } else
+ SendAutofillVotes(observed_form_, &pending_credentials_);
}
void PasswordFormManager::SetUserAction(UserAction user_action) {

Powered by Google App Engine
This is Rietveld 408576698