Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/strings/string16.h" | 5 #include "base/strings/string16.h" |
| 6 #include "base/strings/string_util.h" | 6 #include "base/strings/string_util.h" |
| 7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "components/autofill/content/renderer/password_form_conversion_utils.h" | 9 #include "components/autofill/content/renderer/password_form_conversion_utils.h" |
| 10 #include "components/autofill/core/common/password_form.h" | 10 #include "components/autofill/core/common/password_form.h" |
| 11 #include "content/public/test/render_view_test.h" | 11 #include "content/public/test/render_view_test.h" |
| 12 #include "testing/gmock/include/gmock/gmock.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 13 #include "third_party/WebKit/public/platform/WebVector.h" | 14 #include "third_party/WebKit/public/platform/WebVector.h" |
| 14 #include "third_party/WebKit/public/web/WebDocument.h" | 15 #include "third_party/WebKit/public/web/WebDocument.h" |
| 15 #include "third_party/WebKit/public/web/WebFormElement.h" | 16 #include "third_party/WebKit/public/web/WebFormElement.h" |
| 16 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 17 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| 17 | 18 |
| 18 using blink::WebFormElement; | 19 using blink::WebFormElement; |
| 19 using blink::WebFrame; | 20 using blink::WebFrame; |
| 20 using blink::WebVector; | 21 using blink::WebVector; |
| 21 | 22 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 | 106 |
| 106 *password_form = CreatePasswordForm(forms[0]); | 107 *password_form = CreatePasswordForm(forms[0]); |
| 107 } | 108 } |
| 108 | 109 |
| 109 private: | 110 private: |
| 110 DISALLOW_COPY_AND_ASSIGN(PasswordFormConversionUtilsTest); | 111 DISALLOW_COPY_AND_ASSIGN(PasswordFormConversionUtilsTest); |
| 111 }; | 112 }; |
| 112 | 113 |
| 113 } // namespace | 114 } // namespace |
| 114 | 115 |
| 115 TEST_F(PasswordFormConversionUtilsTest, ValidWebFormElementToPasswordForm) { | 116 TEST_F(PasswordFormConversionUtilsTest, BasicFormAttributes) { |
| 116 PasswordFormBuilder builder(kTestFormActionURL); | 117 PasswordFormBuilder builder(kTestFormActionURL); |
| 117 builder.AddUsernameField("username", "johnsmith", NULL); | 118 builder.AddUsernameField("username", "johnsmith", NULL); |
| 118 builder.AddSubmitButton(); | 119 builder.AddSubmitButton(); |
| 119 builder.AddPasswordField("password", "secret", NULL); | 120 builder.AddPasswordField("password", "secret", NULL); |
| 120 std::string html = builder.ProduceHTML(); | 121 std::string html = builder.ProduceHTML(); |
| 121 | 122 |
| 122 scoped_ptr<PasswordForm> password_form; | 123 scoped_ptr<PasswordForm> password_form; |
| 123 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | 124 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| 124 ASSERT_NE(static_cast<PasswordForm*>(NULL), password_form.get()); | 125 ASSERT_TRUE(password_form); |
| 125 | 126 |
| 126 EXPECT_EQ("data:", password_form->signon_realm); | 127 EXPECT_EQ("data:", password_form->signon_realm); |
| 127 EXPECT_EQ(GURL(kTestFormActionURL), password_form->action); | 128 EXPECT_EQ(GURL(kTestFormActionURL), password_form->action); |
| 128 EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element); | 129 EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element); |
| 129 EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value); | 130 EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value); |
| 130 EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element); | 131 EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element); |
| 131 EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value); | 132 EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value); |
| 132 EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form->scheme); | 133 EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form->scheme); |
| 133 EXPECT_FALSE(password_form->ssl_valid); | 134 EXPECT_FALSE(password_form->ssl_valid); |
| 134 EXPECT_FALSE(password_form->preferred); | 135 EXPECT_FALSE(password_form->preferred); |
| 135 EXPECT_FALSE(password_form->blacklisted_by_user); | 136 EXPECT_FALSE(password_form->blacklisted_by_user); |
| 136 EXPECT_EQ(PasswordForm::TYPE_MANUAL, password_form->type); | 137 EXPECT_EQ(PasswordForm::TYPE_MANUAL, password_form->type); |
| 137 } | 138 EXPECT_FALSE(password_form->use_additional_authentication); |
| 138 | |
| 139 TEST_F(PasswordFormConversionUtilsTest, InvalidWebFormElementToPasswordForm) { | |
| 140 PasswordFormBuilder builder("invalid_target"); | |
| 141 builder.AddUsernameField("username", "johnsmith", NULL); | |
| 142 builder.AddSubmitButton(); | |
| 143 builder.AddPasswordField("password", "secret", NULL); | |
| 144 std::string html = builder.ProduceHTML(); | |
| 145 | |
| 146 scoped_ptr<PasswordForm> password_form; | |
| 147 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | |
| 148 ASSERT_EQ(static_cast<PasswordForm*>(NULL), password_form.get()); | |
| 149 } | 139 } |
| 150 | 140 |
| 151 TEST_F(PasswordFormConversionUtilsTest, | 141 TEST_F(PasswordFormConversionUtilsTest, |
| 152 WebFormWithMultipleUseNameAndPassWordFieldsToPasswordForm) { | 142 IdentifyingUsernameFields) { |
|
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
| |
| 153 PasswordFormBuilder builder(kTestFormActionURL); | |
| 154 builder.AddUsernameField("username1", "John", NULL); | |
| 155 builder.AddPasswordField("password1", "oldsecret", NULL); | |
| 156 builder.AddUsernameField("username2", "William", NULL); | |
| 157 builder.AddPasswordField("password2", "secret", NULL); | |
| 158 builder.AddUsernameField("username3", "Smith", NULL); | |
| 159 builder.AddPasswordField("password3", "secret", NULL); | |
| 160 builder.AddSubmitButton(); | |
| 161 std::string html = builder.ProduceHTML(); | |
| 162 | |
| 163 scoped_ptr<PasswordForm> password_form; | |
| 164 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | |
| 165 ASSERT_NE(static_cast<PasswordForm*>(NULL), password_form.get()); | |
| 166 | |
| 167 EXPECT_EQ("data:", password_form->signon_realm); | |
| 168 EXPECT_EQ(GURL(kTestFormActionURL), password_form->action); | |
| 169 EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element); | |
| 170 EXPECT_EQ(base::UTF8ToUTF16("John"), password_form->username_value); | |
| 171 EXPECT_EQ(base::UTF8ToUTF16("password1"), | |
| 172 password_form->password_element); | |
| 173 EXPECT_EQ(base::UTF8ToUTF16("oldsecret"), password_form->password_value); | |
| 174 EXPECT_EQ(base::UTF8ToUTF16("password2"), | |
| 175 password_form->new_password_element); | |
| 176 EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->new_password_value); | |
| 177 ASSERT_EQ(2u, password_form->other_possible_usernames.size()); | |
| 178 EXPECT_EQ(base::UTF8ToUTF16("William"), | |
| 179 password_form->other_possible_usernames[0]); | |
| 180 EXPECT_EQ(base::UTF8ToUTF16("Smith"), | |
| 181 password_form->other_possible_usernames[1]); | |
| 182 EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form->scheme); | |
| 183 EXPECT_FALSE(password_form->ssl_valid); | |
| 184 EXPECT_FALSE(password_form->preferred); | |
| 185 EXPECT_FALSE(password_form->blacklisted_by_user); | |
| 186 EXPECT_EQ(PasswordForm::TYPE_MANUAL, password_form->type); | |
| 187 } | |
| 188 | |
| 189 TEST_F(PasswordFormConversionUtilsTest, | |
| 190 WebFormwithThreeDifferentPasswordsToPasswordForm) { | |
| 191 PasswordFormBuilder builder(kTestFormActionURL); | |
| 192 builder.AddUsernameField("username1", "John", NULL); | |
| 193 builder.AddPasswordField("password1", "alpha", NULL); | |
| 194 builder.AddPasswordField("password2", "beta", NULL); | |
| 195 builder.AddPasswordField("password3", "gamma", NULL); | |
| 196 builder.AddSubmitButton(); | |
| 197 std::string html = builder.ProduceHTML(); | |
| 198 | |
| 199 scoped_ptr<PasswordForm> password_form; | |
| 200 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | |
| 201 ASSERT_EQ(static_cast<PasswordForm*>(NULL), password_form.get()); | |
| 202 } | |
| 203 | |
| 204 TEST_F(PasswordFormConversionUtilsTest, | |
| 205 UsernameFieldsWithAutocompleteAttributes) { | |
| 206 // Each test case consists of a set of parameters to be plugged into the | 143 // Each test case consists of a set of parameters to be plugged into the |
| 207 // PasswordFormBuilder below, plus the corresponding expectations. | 144 // PasswordFormBuilder below, plus the corresponding expectations. |
| 208 struct TestCase { | 145 struct TestCase { |
| 209 const char* autocomplete[3]; | 146 const char* autocomplete[3]; |
| 210 const char* expected_username_element; | 147 const char* expected_username_element; |
| 211 const char* expected_username_value; | 148 const char* expected_username_value; |
| 212 const char* expected_other_possible_usernames; | 149 const char* expected_other_possible_usernames; |
| 213 } cases[] = { | 150 } cases[] = { |
| 151 // When no elements are marked with autocomplete='username', the text-type | |
| 152 // input field before the first password element should get selected as | |
| 153 // the username, and the rest should be marked as alternatives. | |
| 154 {{NULL, NULL, NULL}, "username2", "William", "John+Smith"}, | |
| 214 // When a sole element is marked with autocomplete='username', it should | 155 // When a sole element is marked with autocomplete='username', it should |
| 215 // be treated as the username for sure, with no other_possible_usernames. | 156 // be treated as the username for sure, with no other_possible_usernames. |
| 216 {{"username", NULL, NULL}, "username1", "John", ""}, | 157 {{"username", NULL, NULL}, "username1", "John", ""}, |
| 217 {{NULL, "username", NULL}, "username2", "William", ""}, | 158 {{NULL, "username", NULL}, "username2", "William", ""}, |
| 218 {{NULL, NULL, "username"}, "username3", "Smith", ""}, | 159 {{NULL, NULL, "username"}, "username3", "Smith", ""}, |
| 219 // When >=2 elements have the attribute, the first should be selected as | 160 // When >=2 elements have the attribute, the first should be selected as |
| 220 // the username, and the rest should go to other_possible_usernames. | 161 // the username, and the rest should go to other_possible_usernames. |
| 221 {{"username", "username", NULL}, "username1", "John", "William"}, | 162 {{"username", "username", NULL}, "username1", "John", "William"}, |
| 222 {{NULL, "username", "username"}, "username2", "William", "Smith"}, | 163 {{NULL, "username", "username"}, "username2", "William", "Smith"}, |
| 223 {{"username", NULL, "username"}, "username1", "John", "Smith"}, | 164 {{"username", NULL, "username"}, "username1", "John", "Smith"}, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 238 PasswordFormBuilder builder(kTestFormActionURL); | 179 PasswordFormBuilder builder(kTestFormActionURL); |
| 239 builder.AddUsernameField("username1", "John", cases[i].autocomplete[0]); | 180 builder.AddUsernameField("username1", "John", cases[i].autocomplete[0]); |
| 240 builder.AddUsernameField("username2", "William", cases[i].autocomplete[1]); | 181 builder.AddUsernameField("username2", "William", cases[i].autocomplete[1]); |
| 241 builder.AddPasswordField("password", "secret", NULL); | 182 builder.AddPasswordField("password", "secret", NULL); |
| 242 builder.AddUsernameField("username3", "Smith", cases[i].autocomplete[2]); | 183 builder.AddUsernameField("username3", "Smith", cases[i].autocomplete[2]); |
| 243 builder.AddSubmitButton(); | 184 builder.AddSubmitButton(); |
| 244 std::string html = builder.ProduceHTML(); | 185 std::string html = builder.ProduceHTML(); |
| 245 | 186 |
| 246 scoped_ptr<PasswordForm> password_form; | 187 scoped_ptr<PasswordForm> password_form; |
| 247 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | 188 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| 248 ASSERT_NE(static_cast<PasswordForm*>(NULL), password_form.get()); | 189 ASSERT_TRUE(password_form); |
| 249 | 190 |
| 250 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element), | 191 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element), |
| 251 password_form->username_element); | 192 password_form->username_element); |
| 252 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_value), | 193 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_value), |
| 253 password_form->username_value); | 194 password_form->username_value); |
| 195 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_other_possible_usernames), | |
| 196 JoinString(password_form->other_possible_usernames, '+')); | |
| 197 | |
| 198 // Do a basic sanity check that we are still having a password field. | |
| 254 EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element); | 199 EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element); |
| 255 EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value); | 200 EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value); |
| 256 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_other_possible_usernames), | 201 } |
| 257 JoinString(password_form->other_possible_usernames, '+')); | 202 } |
| 203 | |
| 204 TEST_F(PasswordFormConversionUtilsTest, IdentifyingTwoPasswordFields) { | |
| 205 // Each test case consists of a set of parameters to be plugged into the | |
| 206 // PasswordFormBuilder below, plus the corresponding expectations. | |
| 207 struct TestCase { | |
| 208 const char* password_values[2]; | |
| 209 const char* expected_password_element; | |
| 210 const char* expected_password_value; | |
| 211 const char* expected_new_password_element; | |
| 212 const char* expected_new_password_value; | |
| 213 } cases[] = { | |
| 214 // Twp non-empty fields with the same value should be treated as a new | |
| 215 // password field plus a confirmation field for the new password. | |
| 216 {{"alpha", "alpha"}, "", "", "password1", "alpha"}, | |
| 217 // The same goes if the fields are yet empty: we speculate that we will | |
| 218 // identify them as new password fields once they are filled out, and we | |
| 219 // want to keep our abstract interpretation of the form less flaky. | |
| 220 {{"", ""}, "", "", "password1", ""}, | |
| 221 // Two different values should be treated as a password change form, one | |
| 222 // that also asks for the current password, but only once for the new. | |
| 223 {{"alpha", ""}, "password1", "alpha", "password2", ""}, | |
| 224 {{"", "beta"}, "password1", "", "password2", "beta"}, | |
| 225 {{"alpha", "beta"}, "password1", "alpha", "password2", "beta"}}; | |
| 226 | |
| 227 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
| 228 SCOPED_TRACE(testing::Message() << "Iteration " << i); | |
| 229 | |
| 230 PasswordFormBuilder builder(kTestFormActionURL); | |
| 231 builder.AddPasswordField("password1", cases[i].password_values[0], NULL); | |
| 232 builder.AddUsernameField("username1", "William", NULL); | |
| 233 builder.AddPasswordField("password2", cases[i].password_values[1], NULL); | |
| 234 builder.AddUsernameField("username2", "Smith", NULL); | |
| 235 builder.AddSubmitButton(); | |
| 236 std::string html = builder.ProduceHTML(); | |
| 237 | |
| 238 scoped_ptr<PasswordForm> password_form; | |
| 239 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | |
| 240 ASSERT_TRUE(password_form); | |
| 241 | |
| 242 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element), | |
| 243 password_form->password_element); | |
| 244 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value), | |
| 245 password_form->password_value); | |
| 246 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element), | |
| 247 password_form->new_password_element); | |
| 248 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value), | |
| 249 password_form->new_password_value); | |
| 250 | |
| 251 // Do a basic sanity check that we are still selecting the right username. | |
| 252 EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element); | |
| 253 EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value); | |
| 254 EXPECT_THAT(password_form->other_possible_usernames, | |
| 255 testing::ElementsAre(base::UTF8ToUTF16("Smith"))); | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 TEST_F(PasswordFormConversionUtilsTest, IdentifyingThreePasswordFields) { | |
| 260 // Each test case consists of a set of parameters to be plugged into the | |
| 261 // PasswordFormBuilder below, plus the corresponding expectations. | |
| 262 struct TestCase { | |
| 263 const char* password_values[3]; | |
| 264 const char* expected_password_element; | |
| 265 const char* expected_password_value; | |
| 266 const char* expected_new_password_element; | |
| 267 const char* expected_new_password_value; | |
| 268 } cases[] = { | |
| 269 // Two fields with the same value, and one different: we should treat this | |
| 270 // as a password change form with confirmation for the new password. Note | |
| 271 // that we only recognize (current + new + new) and (new + new + current) | |
| 272 // without autocomplete attributes. | |
| 273 {{"alpha", "", ""}, "password1", "alpha", "password2", ""}, | |
| 274 {{"", "beta", "beta"}, "password1", "", "password2", "beta"}, | |
| 275 {{"alpha", "beta", "beta"}, "password1", "alpha", "password2", "beta"}, | |
| 276 {{"beta", "beta", "alpha"}, "password3", "alpha", "password1", "beta"}, | |
| 277 // If the fields are yet empty, we speculate that we will identify them as | |
| 278 // (current + new + new) once they are filled out, so we should classify | |
| 279 // them the same for now to keep our abstract interpretation less flaky. | |
| 280 {{"", "", ""}, "password1", "", "password2", ""}}; | |
| 281 // Note: In all other cases, we give up and consider the form invalid. | |
| 282 // This is tested in InvalidFormDueToConfusingPasswordFields. | |
| 283 | |
| 284 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
| 285 SCOPED_TRACE(testing::Message() << "Iteration " << i); | |
| 286 | |
| 287 PasswordFormBuilder builder(kTestFormActionURL); | |
| 288 builder.AddPasswordField("password1", cases[i].password_values[0], NULL); | |
| 289 builder.AddUsernameField("username1", "William", NULL); | |
| 290 builder.AddPasswordField("password2", cases[i].password_values[1], NULL); | |
| 291 builder.AddUsernameField("username2", "Smith", NULL); | |
| 292 builder.AddPasswordField("password3", cases[i].password_values[2], NULL); | |
| 293 builder.AddSubmitButton(); | |
| 294 std::string html = builder.ProduceHTML(); | |
| 295 | |
| 296 scoped_ptr<PasswordForm> password_form; | |
| 297 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | |
| 298 ASSERT_TRUE(password_form); | |
| 299 | |
| 300 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element), | |
| 301 password_form->password_element); | |
| 302 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value), | |
| 303 password_form->password_value); | |
| 304 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element), | |
| 305 password_form->new_password_element); | |
| 306 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value), | |
| 307 password_form->new_password_value); | |
| 308 | |
| 309 // Do a basic sanity check that we are still selecting the right username. | |
| 310 EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element); | |
| 311 EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value); | |
| 312 EXPECT_THAT(password_form->other_possible_usernames, | |
| 313 testing::ElementsAre(base::UTF8ToUTF16("Smith"))); | |
| 258 } | 314 } |
| 259 } | 315 } |
| 260 | 316 |
| 261 TEST_F(PasswordFormConversionUtilsTest, | 317 TEST_F(PasswordFormConversionUtilsTest, |
| 262 PasswordFieldsWithAutocompleteAttributes) { | 318 IdentifyingPasswordFieldsWithAutocompleteAttributes) { |
| 263 // Each test case consists of a set of parameters to be plugged into the | 319 // Each test case consists of a set of parameters to be plugged into the |
| 264 // PasswordFormBuilder below, plus the corresponding expectations. | 320 // PasswordFormBuilder below, plus the corresponding expectations. |
| 265 struct TestCase { | 321 struct TestCase { |
| 266 const char* autocomplete[3]; | 322 const char* autocomplete[3]; |
| 267 const char* expected_password_element; | 323 const char* expected_password_element; |
| 268 const char* expected_password_value; | 324 const char* expected_password_value; |
| 269 const char* expected_new_password_element; | 325 const char* expected_new_password_element; |
| 270 const char* expected_new_password_value; | 326 const char* expected_new_password_value; |
| 271 } cases[] = { | 327 } cases[] = { |
| 272 // When there are elements marked with autocomplete='current-password', | 328 // When there are elements marked with autocomplete='current-password', |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 builder.AddPasswordField("password1", "alpha", cases[i].autocomplete[0]); | 410 builder.AddPasswordField("password1", "alpha", cases[i].autocomplete[0]); |
| 355 builder.AddUsernameField("username1", "William", NULL); | 411 builder.AddUsernameField("username1", "William", NULL); |
| 356 builder.AddPasswordField("password2", "beta", cases[i].autocomplete[1]); | 412 builder.AddPasswordField("password2", "beta", cases[i].autocomplete[1]); |
| 357 builder.AddUsernameField("username2", "Smith", NULL); | 413 builder.AddUsernameField("username2", "Smith", NULL); |
| 358 builder.AddPasswordField("password3", "gamma", cases[i].autocomplete[2]); | 414 builder.AddPasswordField("password3", "gamma", cases[i].autocomplete[2]); |
| 359 builder.AddSubmitButton(); | 415 builder.AddSubmitButton(); |
| 360 std::string html = builder.ProduceHTML(); | 416 std::string html = builder.ProduceHTML(); |
| 361 | 417 |
| 362 scoped_ptr<PasswordForm> password_form; | 418 scoped_ptr<PasswordForm> password_form; |
| 363 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | 419 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); |
| 364 ASSERT_NE(static_cast<PasswordForm*>(NULL), password_form.get()); | 420 ASSERT_TRUE(password_form); |
| 365 | 421 |
| 366 // Any constellation of password autocomplete attributes should have no | |
| 367 // effect on that the first text-type input field before a password field | |
| 368 // should be selected as the username. | |
| 369 // TODO(engedy): Double-check whether this is the intended behavior. | |
| 370 EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element); | |
| 371 EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value); | |
| 372 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element), | 422 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element), |
| 373 password_form->password_element); | 423 password_form->password_element); |
| 374 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value), | 424 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value), |
| 375 password_form->password_value); | 425 password_form->password_value); |
| 376 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element), | 426 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element), |
| 377 password_form->new_password_element); | 427 password_form->new_password_element); |
| 378 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value), | 428 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value), |
| 379 password_form->new_password_value); | 429 password_form->new_password_value); |
| 380 ASSERT_EQ(1u, password_form->other_possible_usernames.size()); | 430 |
| 381 EXPECT_EQ(base::UTF8ToUTF16("Smith"), | 431 // Any constellation of password autocomplete attributes should have no |
| 382 password_form->other_possible_usernames[0]); | 432 // effect on that the text-type input field before the first password field |
| 433 // should be selected as the username. | |
| 434 // TODO(engedy): Double-check whether this is the intended behavior. | |
| 435 EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element); | |
| 436 EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value); | |
| 437 EXPECT_THAT(password_form->other_possible_usernames, | |
| 438 testing::ElementsAre(base::UTF8ToUTF16("Smith"))); | |
| 383 } | 439 } |
| 384 } | 440 } |
| 385 | 441 |
| 442 TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToBadActionURL) { | |
| 443 PasswordFormBuilder builder("invalid_target"); | |
| 444 builder.AddUsernameField("username", "JohnSmith", NULL); | |
| 445 builder.AddSubmitButton(); | |
| 446 builder.AddPasswordField("password", "secret", NULL); | |
| 447 std::string html = builder.ProduceHTML(); | |
| 448 | |
| 449 scoped_ptr<PasswordForm> password_form; | |
| 450 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | |
| 451 EXPECT_FALSE(password_form); | |
| 452 } | |
| 453 | |
| 454 TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToNoPasswordFields) { | |
| 455 PasswordFormBuilder builder(kTestFormActionURL); | |
| 456 builder.AddUsernameField("username1", "John", NULL); | |
| 457 builder.AddUsernameField("username2", "Smith", NULL); | |
| 458 builder.AddSubmitButton(); | |
| 459 std::string html = builder.ProduceHTML(); | |
| 460 | |
| 461 scoped_ptr<PasswordForm> password_form; | |
| 462 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | |
| 463 EXPECT_FALSE(password_form); | |
| 464 } | |
| 465 | |
| 466 TEST_F(PasswordFormConversionUtilsTest, | |
| 467 InvalidFormDueToConfusingPasswordFields) { | |
| 468 // Each test case consists of a set of parameters to be plugged into the | |
| 469 // PasswordFormBuilder below. | |
| 470 const char* cases[][3] = { | |
| 471 // No autocomplete attributes to guide us, and we see: | |
| 472 // * three password values that are all different, | |
| 473 // * three password values that are all the same; | |
| 474 // * three password values with the first and last matching. | |
| 475 // In any case, we are lost, and we should just give up on this form. | |
| 476 {"alpha", "beta", "gamma"}, | |
| 477 {"alpha", "alpha", "alpha"}, | |
| 478 {"alpha", "beta", "alpha"}}; | |
| 479 | |
| 480 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
| 481 SCOPED_TRACE(testing::Message() << "Iteration " << i); | |
| 482 | |
| 483 PasswordFormBuilder builder(kTestFormActionURL); | |
| 484 builder.AddUsernameField("username1", "John", NULL); | |
| 485 builder.AddPasswordField("password1", cases[i][0], NULL); | |
| 486 builder.AddPasswordField("password2", cases[i][1], NULL); | |
| 487 builder.AddPasswordField("password3", cases[i][2], NULL); | |
| 488 builder.AddSubmitButton(); | |
| 489 std::string html = builder.ProduceHTML(); | |
| 490 | |
| 491 scoped_ptr<PasswordForm> password_form; | |
| 492 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form)); | |
| 493 EXPECT_FALSE(password_form); | |
| 494 } | |
| 495 } | |
| 496 | |
| 386 } // namespace autofill | 497 } // namespace autofill |
| OLD | NEW |