| Index: chrome/renderer/autofill/password_autofill_agent_browsertest.cc
|
| diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
|
| index 01562c4c97913e6b23967874cb226a119dfc9f68..4e69d2c3974d86fb933287bc1247c81f42d3f9d2 100644
|
| --- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
|
| +++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
|
| @@ -2085,4 +2085,169 @@ TEST_F(PasswordAutofillAgentTest,
|
| ASSERT_FALSE(message);
|
| }
|
|
|
| +// Tests that credential suggestions are getting autofill on a password (and
|
| +// change password) forms having either ambiguous or empty name.
|
| +TEST_F(PasswordAutofillAgentTest,
|
| + SuggestionsOnFormContainingAmbiguousOrEmptyNames) {
|
| + const char kEmpty[] = "";
|
| + const char kDummyUsernameField[] = "anonymous_username";
|
| + const char kDummyPasswordField[] = "anonymous_password";
|
| + const char kFormContainsEmptyNamesHTML[] =
|
| + "<FORM name='WithoutNameIdForm' action='http://www.bidule.com' >"
|
| + " <INPUT type='text' placeholder='username'/>"
|
| + " <INPUT type='password' placeholder='Password'/>"
|
| + " <INPUT type='submit' />"
|
| + "</FORM>";
|
| +
|
| + const char kFormContainsAmbiguousNamesHTML[] =
|
| + "<FORM name='AmbiguousNameIdForm' action='http://www.bidule.com' >"
|
| + " <INPUT type='text' id='credentials' placeholder='username' />"
|
| + " <INPUT type='password' id='credentials' placeholder='Password' />"
|
| + " <INPUT type='submit' />"
|
| + "</FORM>";
|
| +
|
| + const char kChangePasswordFormContainsEmptyNamesHTML[] =
|
| + "<FORM name='ChangePwd' action='http://www.bidule.com' >"
|
| + " <INPUT type='text' placeholder='username' />"
|
| + " <INPUT type='password' placeholder='Old Password' "
|
| + " autocomplete='current-password' />"
|
| + " <INPUT type='password' placeholder='New Password' "
|
| + " autocomplete='new-password' />"
|
| + " <INPUT type='submit' />"
|
| + "</FORM>";
|
| +
|
| + const char kChangePasswordFormButNoUsername[] =
|
| + "<FORM name='ChangePwdButNosername' action='http://www.bidule.com' >"
|
| + " <INPUT type='password' placeholder='Old Password' "
|
| + " autocomplete='current-password' />"
|
| + " <INPUT type='password' placeholder='New Password' "
|
| + " autocomplete='new-password' />"
|
| + " <INPUT type='submit' />"
|
| + "</FORM>";
|
| +
|
| + const char kChangePasswordFormButNoOldPassword[] =
|
| + "<FORM name='ChangePwdButNoOldPwd' action='http://www.bidule.com' >"
|
| + " <INPUT type='text' placeholder='username' />"
|
| + " <INPUT type='password' placeholder='New Password' "
|
| + " autocomplete='new-password' />"
|
| + " <INPUT type='password' placeholder='Retype Password' "
|
| + " autocomplete='new-password' />"
|
| + " <INPUT type='submit' />"
|
| + "</FORM>";
|
| +
|
| + const char kChangePasswordFormButNoAutocompleteAttribute[] =
|
| + "<FORM name='ChangePwdButNoAutocomplete' action='http://www.bidule.com'>"
|
| + " <INPUT type='text' placeholder='username' />"
|
| + " <INPUT type='password' placeholder='Old Password' />"
|
| + " <INPUT type='password' placeholder='New Password' />"
|
| + " <INPUT type='submit' />"
|
| + "</FORM>";
|
| +
|
| + const struct {
|
| + const char* html_form;
|
| + bool is_possible_change_password_form;
|
| + bool does_trigger_autocomplete_on_fill;
|
| + const char* fill_data_username_field_name;
|
| + const char* fill_data_password_field_name;
|
| + const char* expected_username_suggestions;
|
| + const char* expected_password_suggestions;
|
| + bool expected_is_username_autofillable;
|
| + bool expected_is_password_autofillable;
|
| + } test_cases[] = {
|
| + // Password form without name or id attributes specified for the input
|
| + // fields.
|
| + {kFormContainsEmptyNamesHTML, false, true, kDummyUsernameField,
|
| + kDummyPasswordField, kAliceUsername, kAlicePassword, true, true},
|
| +
|
| + // Password form with ambiguous name or id attributes specified for the
|
| + // input fields.
|
| + {kFormContainsAmbiguousNamesHTML, false, true, "credentials",
|
| + "credentials", kAliceUsername, kAlicePassword, true, true},
|
| +
|
| + // Change password form without name or id attributes specified for the
|
| + // input fields and |autocomplete='current-password'| attribute for old
|
| + // password field.
|
| + {kChangePasswordFormContainsEmptyNamesHTML, true, true,
|
| + kDummyUsernameField, kDummyPasswordField, kAliceUsername, kAlicePassword,
|
| + true, true},
|
| +
|
| + // Change password form without optional username field.
|
| + {kChangePasswordFormButNoUsername, true, true, kEmpty,
|
| + kDummyPasswordField, kEmpty, kAlicePassword, false, true},
|
| +
|
| + // Change password form without name or id attributes specified for the
|
| + // input fields and |autocomplete='new-password'| attribute for new
|
| + // password fields. This form do not trigger |OnFillPasswordForm| from
|
| + // browser.
|
| + {kChangePasswordFormButNoOldPassword, true, false, kDummyUsernameField,
|
| + kDummyPasswordField, kEmpty, kEmpty, false, false},
|
| +
|
| + // Change password form without name or id attributes specified for the
|
| + // input fields but |autocomplete='current-password'| attribute is missing
|
| + // for old password field. This form do not trigger |OnFillPasswordForm|
|
| + // from browser.
|
| + {kChangePasswordFormButNoAutocompleteAttribute, true, false,
|
| + kDummyUsernameField, kDummyPasswordField, kEmpty, kEmpty, false, false},
|
| + };
|
| +
|
| + for (const auto& test_case : test_cases) {
|
| + SCOPED_TRACE(testing::Message() << "html_form: " << test_case.html_form
|
| + << ", fill_data_username_field_name: "
|
| + << test_case.fill_data_username_field_name
|
| + << ", fill_data_password_field_name: "
|
| + << test_case.fill_data_password_field_name);
|
| +
|
| + // Load a password form.
|
| + LoadHTML(test_case.html_form);
|
| +
|
| + // Get the username and password form input elelments.
|
| + blink::WebDocument document = GetMainFrame()->document();
|
| + blink::WebVector<blink::WebFormElement> forms;
|
| + document.forms(forms);
|
| + blink::WebFormElement form_element = forms[0];
|
| + std::vector<blink::WebFormControlElement> control_elements =
|
| + ExtractAutofillableElementsInForm(form_element);
|
| + bool has_fillable_username =
|
| + (kEmpty != test_case.fill_data_username_field_name);
|
| + if (has_fillable_username) {
|
| + username_element_ = control_elements[0].to<blink::WebInputElement>();
|
| + password_element_ = control_elements[1].to<blink::WebInputElement>();
|
| + } else {
|
| + password_element_ = control_elements[0].to<blink::WebInputElement>();
|
| + }
|
| +
|
| + UpdateOriginForHTML(test_case.html_form);
|
| +
|
| + if (test_case.does_trigger_autocomplete_on_fill) {
|
| + // Prepare to trigger autocomplete on filling the password form.
|
| + fill_data_.is_possible_change_password_form =
|
| + test_case.is_possible_change_password_form;
|
| + fill_data_.username_field.name =
|
| + ASCIIToUTF16(test_case.fill_data_username_field_name);
|
| + fill_data_.password_field.name =
|
| + ASCIIToUTF16(test_case.fill_data_password_field_name);
|
| + fill_data_.additional_logins.clear();
|
| + fill_data_.other_possible_usernames.clear();
|
| +
|
| + ClearUsernameAndPasswordFields();
|
| +
|
| + // Simulate the browser sending back the login info, it triggers the
|
| + // autocomplete.
|
| + SimulateOnFillPasswordForm(fill_data_);
|
| +
|
| + if (has_fillable_username) {
|
| + SimulateSuggestionChoice(username_element_);
|
| + } else {
|
| + SimulateSuggestionChoice(password_element_);
|
| + }
|
| +
|
| + // The username and password should now have been autocompleted.
|
| + CheckTextFieldsDOMState(test_case.expected_username_suggestions,
|
| + test_case.expected_is_username_autofillable,
|
| + test_case.expected_password_suggestions,
|
| + test_case.expected_is_password_autofillable);
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace autofill
|
|
|