Index: components/password_manager/core/browser/password_autofill_manager.cc |
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc |
index 15d5f7e3c8da005d4853f4dc3a8e78098bcaaebb..b727ab8d73b6b3698853ea6ede0da7234d63dd56 100644 |
--- a/components/password_manager/core/browser/password_autofill_manager.cc |
+++ b/components/password_manager/core/browser/password_autofill_manager.cc |
@@ -15,6 +15,7 @@ |
#include "components/autofill/core/browser/suggestion.h" |
#include "components/autofill/core/common/autofill_constants.h" |
#include "components/autofill/core/common/autofill_data_validation.h" |
+#include "components/autofill/core/common/autofill_util.h" |
#include "components/password_manager/core/browser/affiliation_utils.h" |
#include "components/password_manager/core/browser/password_manager_driver.h" |
#include "components/strings/grit/components_strings.h" |
@@ -57,43 +58,67 @@ base::string16 GetHumanReadableRealm(const std::string& signon_realm) { |
return base::UTF8ToUTF16(signon_realm); |
} |
+// Use this to check if a given suggestion matches the current contents of a |
+// field. |
+bool DoesSuggestionMatchContents(const base::string16& field_suggestion, |
+ const base::string16& field_contents) { |
+ return autofill::IsFeatureSubstringMatchEnabled() && |
+ autofill::IsContentsPrefixOfSuggestionToken( |
+ field_suggestion, field_contents, autofill::CASE_IGNORE); |
+} |
+ |
+// Helper function to order prefix matched suggestions prior to substring |
+// matched. |
+bool OrderPrefixBeforeSubstring(const autofill::Suggestion& suggestion1, |
+ const autofill::Suggestion& suggestion2) { |
+ return suggestion1.match < suggestion2.match; |
+} |
+ |
+// Helper function to fill username suggestion and adds it to |suggestions|. |
+void FillUsernameSuggestion(const base::string16& field_suggestion, |
+ const base::string16& field_contents, |
+ const std::string& signon_realm, |
+ bool show_all, |
+ std::vector<autofill::Suggestion>* suggestions) { |
+ bool substring_token_matched = false; |
+ if (show_all || StartsWith(field_suggestion, field_contents, false) || |
+ (substring_token_matched = |
+ DoesSuggestionMatchContents(field_suggestion, field_contents))) { |
+ autofill::Suggestion suggestion(ReplaceEmptyUsername(field_suggestion)); |
+ suggestion.label = GetHumanReadableRealm(signon_realm); |
+ suggestion.frontend_id = autofill::POPUP_ITEM_ID_PASSWORD_ENTRY; |
+ suggestion.match = substring_token_matched |
+ ? autofill::Suggestion::SUBSTRING_MATCH |
+ : autofill::Suggestion::PREFIX_MATCH; |
+ suggestions->push_back(suggestion); |
+ } |
+} |
+ |
// This function attempts to fill |suggestions| and |realms| form |fill_data| |
// based on |current_username|. Unless |show_all| is true, it only picks |
-// suggestions where the username has |current_username| as a prefix. |
+// suggestions where the username has |current_username| as a substring. |
void GetSuggestions(const autofill::PasswordFormFillData& fill_data, |
const base::string16& current_username, |
std::vector<autofill::Suggestion>* suggestions, |
bool show_all) { |
- if (show_all || |
- StartsWith(fill_data.username_field.value, current_username, false)) { |
- autofill::Suggestion suggestion( |
- ReplaceEmptyUsername(fill_data.username_field.value)); |
- suggestion.label = GetHumanReadableRealm(fill_data.preferred_realm); |
- suggestion.frontend_id = autofill::POPUP_ITEM_ID_PASSWORD_ENTRY; |
- suggestions->push_back(suggestion); |
- } |
+ FillUsernameSuggestion(fill_data.username_field.value, current_username, |
+ fill_data.preferred_realm, show_all, suggestions); |
for (const auto& login : fill_data.additional_logins) { |
- if (show_all || StartsWith(login.first, current_username, false)) { |
- autofill::Suggestion suggestion(ReplaceEmptyUsername(login.first)); |
- suggestion.label = GetHumanReadableRealm(login.second.realm); |
- suggestion.frontend_id = autofill::POPUP_ITEM_ID_PASSWORD_ENTRY; |
- suggestions->push_back(suggestion); |
- } |
+ FillUsernameSuggestion(login.first, current_username, login.second.realm, |
+ show_all, suggestions); |
} |
for (const auto& usernames : fill_data.other_possible_usernames) { |
for (size_t i = 0; i < usernames.second.size(); ++i) { |
- if (show_all || |
- StartsWith(usernames.second[i], current_username, false)) { |
- autofill::Suggestion suggestion( |
- ReplaceEmptyUsername(usernames.second[i])); |
- suggestion.label = GetHumanReadableRealm(usernames.first.realm); |
- suggestion.frontend_id = autofill::POPUP_ITEM_ID_PASSWORD_ENTRY; |
- suggestions->push_back(suggestion); |
- } |
+ FillUsernameSuggestion(usernames.second[i], current_username, |
+ usernames.first.realm, show_all, suggestions); |
} |
} |
+ |
+ // Prefix matches should precede other token matches. |
+ std::sort(suggestions->begin(), suggestions->end(), |
+ OrderPrefixBeforeSubstring); |
} |
} // namespace |