Chromium Code Reviews| Index: components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc |
| diff --git a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc |
| index 57ac2053d9ba42c0655fb17b7e72a8ea5814e719..7ed82014ba7bb59a062139b237f5ec9e82ce2f14 100644 |
| --- a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc |
| +++ b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc |
| @@ -9,6 +9,7 @@ |
| #include "components/autofill/content/renderer/password_form_conversion_utils.h" |
| #include "components/autofill/core/common/password_form.h" |
| #include "content/public/test/render_view_test.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/WebKit/public/platform/WebVector.h" |
| #include "third_party/WebKit/public/web/WebDocument.h" |
| @@ -112,7 +113,7 @@ class PasswordFormConversionUtilsTest : public content::RenderViewTest { |
| } // namespace |
| -TEST_F(PasswordFormConversionUtilsTest, ValidWebFormElementToPasswordForm) { |
| +TEST_F(PasswordFormConversionUtilsTest, BasicFormAttributes) { |
| PasswordFormBuilder builder(kTestFormActionURL); |
| builder.AddUsernameField("username", "johnsmith", NULL); |
| builder.AddSubmitButton(); |
| @@ -121,7 +122,7 @@ TEST_F(PasswordFormConversionUtilsTest, ValidWebFormElementToPasswordForm) { |
| scoped_ptr<PasswordForm> password_form; |
| ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| - ASSERT_NE(static_cast<PasswordForm*>(NULL), password_form.get()); |
| + ASSERT_TRUE(password_form); |
| EXPECT_EQ("data:", password_form->signon_realm); |
| EXPECT_EQ(GURL(kTestFormActionURL), password_form->action); |
| @@ -134,75 +135,11 @@ TEST_F(PasswordFormConversionUtilsTest, ValidWebFormElementToPasswordForm) { |
| EXPECT_FALSE(password_form->preferred); |
| EXPECT_FALSE(password_form->blacklisted_by_user); |
| EXPECT_EQ(PasswordForm::TYPE_MANUAL, password_form->type); |
| -} |
| - |
| -TEST_F(PasswordFormConversionUtilsTest, InvalidWebFormElementToPasswordForm) { |
| - PasswordFormBuilder builder("invalid_target"); |
| - builder.AddUsernameField("username", "johnsmith", NULL); |
| - builder.AddSubmitButton(); |
| - builder.AddPasswordField("password", "secret", NULL); |
| - std::string html = builder.ProduceHTML(); |
| - |
| - scoped_ptr<PasswordForm> password_form; |
| - ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| - ASSERT_EQ(static_cast<PasswordForm*>(NULL), password_form.get()); |
| -} |
| - |
| -TEST_F(PasswordFormConversionUtilsTest, |
| - WebFormWithMultipleUseNameAndPassWordFieldsToPasswordForm) { |
|
vabr (Chromium)
2014/07/07 12:12:19
If I understand it correctly, this test was replac
engedy
2014/07/09 16:58:35
This test was exploded into three parts: the usern
|
| - PasswordFormBuilder builder(kTestFormActionURL); |
| - builder.AddUsernameField("username1", "John", NULL); |
| - builder.AddPasswordField("password1", "oldsecret", NULL); |
| - builder.AddUsernameField("username2", "William", NULL); |
| - builder.AddPasswordField("password2", "secret", NULL); |
| - builder.AddUsernameField("username3", "Smith", NULL); |
| - builder.AddPasswordField("password3", "secret", NULL); |
| - builder.AddSubmitButton(); |
| - std::string html = builder.ProduceHTML(); |
| - |
| - scoped_ptr<PasswordForm> password_form; |
| - ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| - ASSERT_NE(static_cast<PasswordForm*>(NULL), password_form.get()); |
| - |
| - EXPECT_EQ("data:", password_form->signon_realm); |
| - EXPECT_EQ(GURL(kTestFormActionURL), password_form->action); |
| - EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element); |
| - EXPECT_EQ(base::UTF8ToUTF16("John"), password_form->username_value); |
| - EXPECT_EQ(base::UTF8ToUTF16("password1"), |
| - password_form->password_element); |
| - EXPECT_EQ(base::UTF8ToUTF16("oldsecret"), password_form->password_value); |
| - EXPECT_EQ(base::UTF8ToUTF16("password2"), |
| - password_form->new_password_element); |
| - EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->new_password_value); |
| - ASSERT_EQ(2u, password_form->other_possible_usernames.size()); |
| - EXPECT_EQ(base::UTF8ToUTF16("William"), |
| - password_form->other_possible_usernames[0]); |
| - EXPECT_EQ(base::UTF8ToUTF16("Smith"), |
| - password_form->other_possible_usernames[1]); |
| - EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form->scheme); |
| - EXPECT_FALSE(password_form->ssl_valid); |
| - EXPECT_FALSE(password_form->preferred); |
| - EXPECT_FALSE(password_form->blacklisted_by_user); |
| - EXPECT_EQ(PasswordForm::TYPE_MANUAL, password_form->type); |
| -} |
| - |
| -TEST_F(PasswordFormConversionUtilsTest, |
| - WebFormwithThreeDifferentPasswordsToPasswordForm) { |
| - PasswordFormBuilder builder(kTestFormActionURL); |
| - builder.AddUsernameField("username1", "John", NULL); |
| - builder.AddPasswordField("password1", "alpha", NULL); |
| - builder.AddPasswordField("password2", "beta", NULL); |
| - builder.AddPasswordField("password3", "gamma", NULL); |
| - builder.AddSubmitButton(); |
| - std::string html = builder.ProduceHTML(); |
| - |
| - scoped_ptr<PasswordForm> password_form; |
| - ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| - ASSERT_EQ(static_cast<PasswordForm*>(NULL), password_form.get()); |
| + EXPECT_FALSE(password_form->use_additional_authentication); |
| } |
| TEST_F(PasswordFormConversionUtilsTest, |
| - UsernameFieldsWithAutocompleteAttributes) { |
| + IdentifyingUsernameFields) { |
| // Each test case consists of a set of parameters to be plugged into the |
| // PasswordFormBuilder below, plus the corresponding expectations. |
| struct TestCase { |
| @@ -211,6 +148,10 @@ TEST_F(PasswordFormConversionUtilsTest, |
| const char* expected_username_value; |
| const char* expected_other_possible_usernames; |
| } cases[] = { |
| + // When no elements are marked with autocomplete='username', the text-type |
| + // input field before the first password element should get selected as |
| + // the username, and the rest should be marked as alternatives. |
| + {{NULL, NULL, NULL}, "username2", "William", "John+Smith"}, |
| // When a sole element is marked with autocomplete='username', it should |
| // be treated as the username for sure, with no other_possible_usernames. |
| {{"username", NULL, NULL}, "username1", "John", ""}, |
| @@ -245,21 +186,136 @@ TEST_F(PasswordFormConversionUtilsTest, |
| scoped_ptr<PasswordForm> password_form; |
| ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| - ASSERT_NE(static_cast<PasswordForm*>(NULL), password_form.get()); |
| + ASSERT_TRUE(password_form); |
| EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element), |
| password_form->username_element); |
| EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_value), |
| password_form->username_value); |
| - EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element); |
| - EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value); |
| EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_other_possible_usernames), |
| JoinString(password_form->other_possible_usernames, '+')); |
| + |
| + // Do a basic sanity check that we are still having a password field. |
| + EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element); |
| + EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value); |
| + } |
| +} |
| + |
| +TEST_F(PasswordFormConversionUtilsTest, IdentifyingTwoPasswordFields) { |
| + // Each test case consists of a set of parameters to be plugged into the |
| + // PasswordFormBuilder below, plus the corresponding expectations. |
| + struct TestCase { |
| + const char* password_values[2]; |
| + const char* expected_password_element; |
| + const char* expected_password_value; |
| + const char* expected_new_password_element; |
| + const char* expected_new_password_value; |
| + } cases[] = { |
| + // Twp non-empty fields with the same value should be treated as a new |
| + // password field plus a confirmation field for the new password. |
| + {{"alpha", "alpha"}, "", "", "password1", "alpha"}, |
| + // The same goes if the fields are yet empty: we speculate that we will |
| + // identify them as new password fields once they are filled out, and we |
| + // want to keep our abstract interpretation of the form less flaky. |
| + {{"", ""}, "", "", "password1", ""}, |
| + // Two different values should be treated as a password change form, one |
| + // that also asks for the current password, but only once for the new. |
| + {{"alpha", ""}, "password1", "alpha", "password2", ""}, |
| + {{"", "beta"}, "password1", "", "password2", "beta"}, |
| + {{"alpha", "beta"}, "password1", "alpha", "password2", "beta"}}; |
| + |
| + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { |
| + SCOPED_TRACE(testing::Message() << "Iteration " << i); |
| + |
| + PasswordFormBuilder builder(kTestFormActionURL); |
| + builder.AddPasswordField("password1", cases[i].password_values[0], NULL); |
| + builder.AddUsernameField("username1", "William", NULL); |
| + builder.AddPasswordField("password2", cases[i].password_values[1], NULL); |
| + builder.AddUsernameField("username2", "Smith", NULL); |
| + builder.AddSubmitButton(); |
| + std::string html = builder.ProduceHTML(); |
| + |
| + scoped_ptr<PasswordForm> password_form; |
| + ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| + ASSERT_TRUE(password_form); |
| + |
| + EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element), |
| + password_form->password_element); |
| + EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value), |
| + password_form->password_value); |
| + EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element), |
| + password_form->new_password_element); |
| + EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value), |
| + password_form->new_password_value); |
| + |
| + // Do a basic sanity check that we are still selecting the right username. |
| + EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element); |
| + EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value); |
| + EXPECT_THAT(password_form->other_possible_usernames, |
| + testing::ElementsAre(base::UTF8ToUTF16("Smith"))); |
| + } |
| +} |
| + |
| +TEST_F(PasswordFormConversionUtilsTest, IdentifyingThreePasswordFields) { |
| + // Each test case consists of a set of parameters to be plugged into the |
| + // PasswordFormBuilder below, plus the corresponding expectations. |
| + struct TestCase { |
| + const char* password_values[3]; |
| + const char* expected_password_element; |
| + const char* expected_password_value; |
| + const char* expected_new_password_element; |
| + const char* expected_new_password_value; |
| + } cases[] = { |
| + // Two fields with the same value, and one different: we should treat this |
| + // as a password change form with confirmation for the new password. Note |
| + // that we only recognize (current + new + new) and (new + new + current) |
| + // without autocomplete attributes. |
| + {{"alpha", "", ""}, "password1", "alpha", "password2", ""}, |
| + {{"", "beta", "beta"}, "password1", "", "password2", "beta"}, |
| + {{"alpha", "beta", "beta"}, "password1", "alpha", "password2", "beta"}, |
| + {{"beta", "beta", "alpha"}, "password3", "alpha", "password1", "beta"}, |
| + // If the fields are yet empty, we speculate that we will identify them as |
| + // (current + new + new) once they are filled out, so we should classify |
| + // them the same for now to keep our abstract interpretation less flaky. |
| + {{"", "", ""}, "password1", "", "password2", ""}}; |
| + // Note: In all other cases, we give up and consider the form invalid. |
| + // This is tested in InvalidFormDueToConfusingPasswordFields. |
| + |
| + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { |
| + SCOPED_TRACE(testing::Message() << "Iteration " << i); |
| + |
| + PasswordFormBuilder builder(kTestFormActionURL); |
| + builder.AddPasswordField("password1", cases[i].password_values[0], NULL); |
| + builder.AddUsernameField("username1", "William", NULL); |
| + builder.AddPasswordField("password2", cases[i].password_values[1], NULL); |
| + builder.AddUsernameField("username2", "Smith", NULL); |
| + builder.AddPasswordField("password3", cases[i].password_values[2], NULL); |
| + builder.AddSubmitButton(); |
| + std::string html = builder.ProduceHTML(); |
| + |
| + scoped_ptr<PasswordForm> password_form; |
| + ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| + ASSERT_TRUE(password_form); |
| + |
| + EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element), |
| + password_form->password_element); |
| + EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value), |
| + password_form->password_value); |
| + EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element), |
| + password_form->new_password_element); |
| + EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value), |
| + password_form->new_password_value); |
| + |
| + // Do a basic sanity check that we are still selecting the right username. |
| + EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element); |
| + EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value); |
| + EXPECT_THAT(password_form->other_possible_usernames, |
| + testing::ElementsAre(base::UTF8ToUTF16("Smith"))); |
| } |
| } |
| TEST_F(PasswordFormConversionUtilsTest, |
| - PasswordFieldsWithAutocompleteAttributes) { |
| + IdentifyingPasswordFieldsWithAutocompleteAttributes) { |
| // Each test case consists of a set of parameters to be plugged into the |
| // PasswordFormBuilder below, plus the corresponding expectations. |
| struct TestCase { |
| @@ -361,14 +417,8 @@ TEST_F(PasswordFormConversionUtilsTest, |
| scoped_ptr<PasswordForm> password_form; |
| ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| - ASSERT_NE(static_cast<PasswordForm*>(NULL), password_form.get()); |
| + ASSERT_TRUE(password_form); |
| - // Any constellation of password autocomplete attributes should have no |
| - // effect on that the first text-type input field before a password field |
| - // should be selected as the username. |
| - // TODO(engedy): Double-check whether this is the intended behavior. |
| - EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element); |
| - EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value); |
| EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element), |
| password_form->password_element); |
| EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value), |
| @@ -377,9 +427,70 @@ TEST_F(PasswordFormConversionUtilsTest, |
| password_form->new_password_element); |
| EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value), |
| password_form->new_password_value); |
| - ASSERT_EQ(1u, password_form->other_possible_usernames.size()); |
| - EXPECT_EQ(base::UTF8ToUTF16("Smith"), |
| - password_form->other_possible_usernames[0]); |
| + |
| + // Any constellation of password autocomplete attributes should have no |
| + // effect on that the text-type input field before the first password field |
| + // should be selected as the username. |
| + // TODO(engedy): Double-check whether this is the intended behavior. |
| + EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element); |
| + EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value); |
| + EXPECT_THAT(password_form->other_possible_usernames, |
| + testing::ElementsAre(base::UTF8ToUTF16("Smith"))); |
| + } |
| +} |
| + |
| +TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToBadActionURL) { |
| + PasswordFormBuilder builder("invalid_target"); |
| + builder.AddUsernameField("username", "JohnSmith", NULL); |
| + builder.AddSubmitButton(); |
| + builder.AddPasswordField("password", "secret", NULL); |
| + std::string html = builder.ProduceHTML(); |
| + |
| + scoped_ptr<PasswordForm> password_form; |
| + ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| + EXPECT_FALSE(password_form); |
| +} |
| + |
| +TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToNoPasswordFields) { |
| + PasswordFormBuilder builder(kTestFormActionURL); |
| + builder.AddUsernameField("username1", "John", NULL); |
| + builder.AddUsernameField("username2", "Smith", NULL); |
| + builder.AddSubmitButton(); |
| + std::string html = builder.ProduceHTML(); |
| + |
| + scoped_ptr<PasswordForm> password_form; |
| + ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| + EXPECT_FALSE(password_form); |
| +} |
| + |
| +TEST_F(PasswordFormConversionUtilsTest, |
| + InvalidFormDueToConfusingPasswordFields) { |
| + // Each test case consists of a set of parameters to be plugged into the |
| + // PasswordFormBuilder below. |
| + const char* cases[][3] = { |
| + // No autocomplete attributes to guide us, and we see: |
| + // * three password values that are all different, |
| + // * three password values that are all the same; |
| + // * three password values with the first and last matching. |
| + // In any case, we are lost, and we should just give up on this form. |
| + {"alpha", "beta", "gamma"}, |
| + {"alpha", "alpha", "alpha"}, |
| + {"alpha", "beta", "alpha"}}; |
| + |
| + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { |
| + SCOPED_TRACE(testing::Message() << "Iteration " << i); |
| + |
| + PasswordFormBuilder builder(kTestFormActionURL); |
| + builder.AddUsernameField("username1", "John", NULL); |
| + builder.AddPasswordField("password1", cases[i][0], NULL); |
| + builder.AddPasswordField("password2", cases[i][1], NULL); |
| + builder.AddPasswordField("password3", cases[i][2], NULL); |
| + builder.AddSubmitButton(); |
| + std::string html = builder.ProduceHTML(); |
| + |
| + scoped_ptr<PasswordForm> password_form; |
| + ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| + EXPECT_FALSE(password_form); |
| } |
| } |