Chromium Code Reviews| Index: components/autofill/content/renderer/password_autofill_agent.cc |
| diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc |
| index 642f6ff863bf131e0268361f5924545bc5ba5fbc..f1505962828835b6c27eff934458875a02b44563 100644 |
| --- a/components/autofill/content/renderer/password_autofill_agent.cc |
| +++ b/components/autofill/content/renderer/password_autofill_agent.cc |
| @@ -267,13 +267,14 @@ bool IsElementEditable(const blink::WebInputElement& element) { |
| return element.IsEnabled() && !element.IsReadOnly(); |
| } |
| -bool DoUsernamesMatch(const base::string16& username1, |
| - const base::string16& username2, |
| +bool DoUsernamesMatch(const base::string16& potential_suggestion, |
| + const base::string16& current_username, |
| bool exact_match) { |
| - if (exact_match) |
| - return username1 == username2; |
| - return FieldIsSuggestionSubstringStartingOnTokenBoundary(username1, username2, |
| - true); |
| + bool match = (potential_suggestion == current_username); |
| + return exact_match |
| + ? match |
| + : (match || IsPrefixStartingOnTokenBoundary( |
| + current_username, potential_suggestion, true)); |
|
dvadym
2017/06/01 12:15:56
As far as I understand the main use case is emails
melandory
2017/06/12 14:56:12
My motivation was that since currently gmail suffe
vabr (Chromium)
2017/06/12 18:56:58
Currently case sensitive equality is required. Let
|
| } |
| // Returns |true| if the given element is editable. Otherwise, returns |false|. |
| @@ -358,6 +359,51 @@ void UpdateFieldValueAndPropertiesMaskMap( |
| } |
| } |
| +void FindMatchesByUsername(const PasswordFormFillData& fill_data, |
| + const base::string16& current_username, |
| + bool exact_username_match, |
| + RendererSavePasswordProgressLogger* logger, |
| + base::string16* username, |
| + base::string16* password) { |
| + // Look for any suitable matches to current field text. |
| + if (DoUsernamesMatch(fill_data.username_field.value, current_username, |
| + exact_username_match)) { |
| + *username = fill_data.username_field.value; |
| + *password = fill_data.password_field.value; |
| + if (logger) |
| + logger->LogMessage(Logger::STRING_USERNAMES_MATCH); |
| + } else { |
| + // Scan additional logins for a match. |
| + for (const auto& it : fill_data.additional_logins) { |
| + if (DoUsernamesMatch(it.first, current_username, exact_username_match)) { |
| + *username = it.first; |
| + *password = it.second.password; |
| + break; |
| + } |
| + } |
| + if (logger) { |
| + logger->LogBoolean(Logger::STRING_MATCH_IN_ADDITIONAL, |
| + !(username->empty() && password->empty())); |
| + } |
| + |
| + // Check possible usernames. |
| + if (username->empty() && password->empty()) { |
| + for (const auto& it : fill_data.other_possible_usernames) { |
| + for (size_t i = 0; i < it.second.size(); ++i) { |
| + if (DoUsernamesMatch(it.second[i], current_username, |
| + exact_username_match)) { |
| + *username = it.second[i]; |
| + *password = it.first.password; |
| + break; |
| + } |
| + } |
| + if (!username->empty() && !password->empty()) |
| + break; |
| + } |
| + } |
| + } |
| +} |
| + |
| // This function attempts to fill |username_element| and |password_element| |
| // with values from |fill_data|. The |password_element| will only have the |
| // suggestedValue set, and will be registered for copying that to the real |
| @@ -389,43 +435,9 @@ bool FillUserNameAndPassword( |
| base::string16 username; |
| base::string16 password; |
| - // Look for any suitable matches to current field text. |
| - if (DoUsernamesMatch(fill_data.username_field.value, current_username, |
| - exact_username_match)) { |
| - username = fill_data.username_field.value; |
| - password = fill_data.password_field.value; |
| - if (logger) |
| - logger->LogMessage(Logger::STRING_USERNAMES_MATCH); |
| - } else { |
| - // Scan additional logins for a match. |
| - for (const auto& it : fill_data.additional_logins) { |
| - if (DoUsernamesMatch(it.first, current_username, exact_username_match)) { |
| - username = it.first; |
| - password = it.second.password; |
| - break; |
| - } |
| - } |
| - if (logger) { |
| - logger->LogBoolean(Logger::STRING_MATCH_IN_ADDITIONAL, |
| - !(username.empty() && password.empty())); |
| - } |
| + FindMatchesByUsername(fill_data, current_username, exact_username_match, |
| + logger, &username, &password); |
| - // Check possible usernames. |
| - if (username.empty() && password.empty()) { |
| - for (const auto& it : fill_data.other_possible_usernames) { |
| - for (size_t i = 0; i < it.second.size(); ++i) { |
| - if (DoUsernamesMatch( |
| - it.second[i], current_username, exact_username_match)) { |
| - username = it.second[i]; |
| - password = it.first.password; |
| - break; |
| - } |
| - } |
| - if (!username.empty() && !password.empty()) |
| - break; |
| - } |
| - } |
| - } |
| if (password.empty()) |
| return false; |
| @@ -447,9 +459,10 @@ bool FillUserNameAndPassword( |
| form_util::PreviewSuggestion(username, current_username, |
| username_element); |
| } |
| - } else if (current_username != username) { |
| + } else if (exact_username_match && current_username != username) { |
| // If the username can't be filled and it doesn't match a saved password |
| - // as is, don't autofill a password. |
| + // as is, autofill the password only in case the username element id read |
| + // only. |
| return false; |
| } |
| @@ -535,12 +548,15 @@ bool FillFormOnPasswordReceived( |
| blink::WebString::FromUTF16(fill_data.username_field.value)); |
| } |
| - // Fill if we have an exact match for the username. Note that this sets |
| - // username to autofilled. |
| + bool exact_username_match = |
| + username_element.IsNull() || IsElementEditable(username_element); |
| + // User the exact match for the editable username fields and allow prefix |
| + // match for read-only username fields. |
| + // Note that this sets username to autofilled. |
| return FillUserNameAndPassword( |
| - &username_element, &password_element, fill_data, |
| - true /* exact_username_match */, false /* set_selection */, |
| - field_value_and_properties_map, registration_callback, logger); |
| + &username_element, &password_element, fill_data, exact_username_match, |
| + false /* set_selection */, field_value_and_properties_map, |
| + registration_callback, logger); |
| } |
| // Annotate |forms| with form and field signatures as HTML attributes. |