Chromium Code Reviews| Index: components/password_manager/core/browser/credential_manager_pending_request_task.cc |
| diff --git a/components/password_manager/core/browser/credential_manager_pending_request_task.cc b/components/password_manager/core/browser/credential_manager_pending_request_task.cc |
| index 96a5ed29ea91e8e1a698653f97c98e5910250ddf..5c1e6e9bb69bbc33f6116e32e6bccf6b4289a212 100644 |
| --- a/components/password_manager/core/browser/credential_manager_pending_request_task.cc |
| +++ b/components/password_manager/core/browser/credential_manager_pending_request_task.cc |
| @@ -5,6 +5,7 @@ |
| #include "components/password_manager/core/browser/credential_manager_pending_request_task.h" |
| #include <algorithm> |
| +#include <map> |
| #include <utility> |
| #include "base/memory/ptr_util.h" |
| @@ -24,27 +25,45 @@ namespace { |
| // Send a UMA histogram about if |local_results| has empty or duplicate |
| // usernames. |
| -void ReportAccountChooserMetrics( |
| - const ScopedVector<autofill::PasswordForm>& local_results, |
| - bool had_empty_username) { |
| - std::vector<base::string16> usernames; |
| - for (const auto* form : local_results) |
| - usernames.push_back(form->username_value); |
| - std::sort(usernames.begin(), usernames.end()); |
| - bool has_duplicates = |
| - std::adjacent_find(usernames.begin(), usernames.end()) != usernames.end(); |
| +void ReportAccountChooserMetrics(bool had_duplicates, bool had_empty_username) { |
| metrics_util::AccountChooserUsabilityMetric metric; |
| - if (had_empty_username && has_duplicates) |
| + if (had_empty_username && had_duplicates) |
| metric = metrics_util::ACCOUNT_CHOOSER_EMPTY_USERNAME_AND_DUPLICATES; |
| else if (had_empty_username) |
| metric = metrics_util::ACCOUNT_CHOOSER_EMPTY_USERNAME; |
| - else if (has_duplicates) |
| + else if (had_duplicates) |
| metric = metrics_util::ACCOUNT_CHOOSER_DUPLICATES; |
| else |
| metric = metrics_util::ACCOUNT_CHOOSER_LOOKS_OK; |
| metrics_util::LogAccountChooserUsability(metric); |
| } |
| +// Returns true iff |form1| is better suitable for showing in the account |
| +// chooser than |form2|. Inspired by PasswordFormManager::ScoreResult. |
| +bool IsBetterMatch(const autofill::PasswordForm& form1, |
| + const autofill::PasswordForm& form2) { |
| + if (!form1.is_public_suffix_match && form2.is_public_suffix_match) |
| + return true; |
| + if (!form1.preferred && form2.preferred) |
|
vabr (Chromium)
2016/08/24 15:56:17
Should this be the other way round? (I.e. preferre
vasilii
2016/08/24 16:51:15
Done.
|
| + return true; |
| + return form1.date_created > form2.date_created; |
| +} |
| + |
| +// Remove duplicates in |forms| before displaying them in the account chooser. |
| +void FilterDuplicates(ScopedVector<autofill::PasswordForm>* forms) { |
| + std::map<base::string16, std::unique_ptr<autofill::PasswordForm>> credentials; |
| + for (auto& form : *forms) { |
| + auto it = credentials.find(form->username_value); |
| + if (it == credentials.end() || IsBetterMatch(*form, *it->second)) { |
| + credentials[form->username_value] = base::WrapUnique(form); |
| + form = nullptr; |
| + } |
| + } |
| + forms->clear(); |
| + for (auto& form_pair : credentials) |
| + forms->push_back(std::move(form_pair.second)); |
| +} |
| + |
| } // namespace |
| CredentialManagerPendingRequestTask::CredentialManagerPendingRequestTask( |
| @@ -126,6 +145,10 @@ void CredentialManagerPendingRequestTask::OnGetPasswordStoreResults( |
| const bool has_empty_username = (begin_empty != local_results.end()); |
| local_results.erase(begin_empty, local_results.end()); |
| + const size_t local_results_size = local_results.size(); |
| + FilterDuplicates(&local_results); |
| + const bool has_duplicates = (local_results_size != local_results.size()); |
| + |
| if ((local_results.empty() && federated_results.empty())) { |
| delegate_->SendCredential(send_callback_, CredentialInfo()); |
| return; |
| @@ -157,9 +180,10 @@ void CredentialManagerPendingRequestTask::OnGetPasswordStoreResults( |
| // or if the user chooses not to return a credential, and the credential the |
| // user chooses if they pick one. |
| std::unique_ptr<autofill::PasswordForm> potential_autosignin_form( |
| - new autofill::PasswordForm(*local_results[0])); |
| + can_use_autosignin ? new autofill::PasswordForm(*local_results[0]) |
| + : nullptr); |
| if (!zero_click_only_) |
| - ReportAccountChooserMetrics(local_results, has_empty_username); |
| + ReportAccountChooserMetrics(has_duplicates, has_empty_username); |
| if (zero_click_only_ || |
| !delegate_->client()->PromptUserToChooseCredentials( |
| std::move(local_results), std::move(federated_results), origin_, |