Make |track_| in MediaStreamTrack const. and a couple of other cosmetic changes.
[chromium-blink-merge.git] / components / autofill / content / renderer / password_form_conversion_utils_browsertest.cc
blobc5a082eeb97cc361ad13b16e2e09bde449f91f22
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
3 // found in the LICENSE file.
5 #include "base/strings/string16.h"
6 #include "base/strings/string_util.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "components/autofill/content/renderer/password_form_conversion_utils.h"
10 #include "components/autofill/core/common/password_form.h"
11 #include "content/public/test/render_view_test.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/WebKit/public/platform/WebVector.h"
15 #include "third_party/WebKit/public/web/WebDocument.h"
16 #include "third_party/WebKit/public/web/WebFormControlElement.h"
17 #include "third_party/WebKit/public/web/WebFormElement.h"
18 #include "third_party/WebKit/public/web/WebInputElement.h"
19 #include "third_party/WebKit/public/web/WebLocalFrame.h"
21 using blink::WebFormControlElement;
22 using blink::WebFormElement;
23 using blink::WebFrame;
24 using blink::WebInputElement;
25 using blink::WebVector;
27 namespace autofill {
28 namespace {
30 const char kTestFormActionURL[] = "http://cnn.com";
32 // A builder to produce HTML code for a password form composed of the desired
33 // number and kinds of username and password fields.
34 class PasswordFormBuilder {
35 public:
36 // Creates a builder to start composing a new form. The form will have the
37 // specified |action| URL.
38 explicit PasswordFormBuilder(const char* action) {
39 base::StringAppendF(
40 &html_, "<FORM name=\"Test\" action=\"%s\" method=\"post\">", action);
43 // Appends a new text-type field at the end of the form, having the specified
44 // |name_and_id|, |value|, and |autocomplete| attributes. The |autocomplete|
45 // argument can take two special values, namely:
46 // 1.) NULL, causing no autocomplete attribute to be added,
47 // 2.) "", causing an empty attribute (i.e. autocomplete="") to be added.
48 void AddUsernameField(const char* name_and_id,
49 const char* value,
50 const char* autocomplete) {
51 std::string autocomplete_attribute(autocomplete ?
52 base::StringPrintf("autocomplete=\"%s\"", autocomplete) : "");
53 base::StringAppendF(
54 &html_,
55 "<INPUT type=\"text\" name=\"%s\" id=\"%s\" value=\"%s\" %s/>",
56 name_and_id, name_and_id, value, autocomplete_attribute.c_str());
59 // Appends a new password-type field at the end of the form, having the
60 // specified |name_and_id|, |value|, and |autocomplete| attributes. Special
61 // values for |autocomplete| are the same as in AddUsernameField.
62 void AddPasswordField(const char* name_and_id,
63 const char* value,
64 const char* autocomplete) {
65 std::string autocomplete_attribute(autocomplete ?
66 base::StringPrintf("autocomplete=\"%s\"", autocomplete): "");
67 base::StringAppendF(
68 &html_,
69 "<INPUT type=\"password\" name=\"%s\" id=\"%s\" value=\"%s\" %s/>",
70 name_and_id, name_and_id, value, autocomplete_attribute.c_str());
73 // Appends a disabled text-type field at the end of the form.
74 void AddDisabledUsernameField() {
75 html_ += "<INPUT type=\"text\" disabled/>";
78 // Appends a disabled password-type field at the end of the form.
79 void AddDisabledPasswordField() {
80 html_ += "<INPUT type=\"password\" disabled/>";
83 // Appends a new submit-type field at the end of the form with the specified
84 // |name|. If |activated| is true, the test will emulate as if this button
85 // were used to submit the form.
86 void AddSubmitButton(const char* name, bool activated) {
87 base::StringAppendF(
88 &html_,
89 "<INPUT type=\"submit\" name=\"%s\" value=\"Submit\" %s/>",
90 name, activated ? "set-activated-submit" : "");
93 // Returns the HTML code for the form containing the fields that have been
94 // added so far.
95 std::string ProduceHTML() const {
96 return html_ + "</FORM>";
99 private:
100 std::string html_;
102 DISALLOW_COPY_AND_ASSIGN(PasswordFormBuilder);
105 class PasswordFormConversionUtilsTest : public content::RenderViewTest {
106 public:
107 PasswordFormConversionUtilsTest() : content::RenderViewTest() {}
108 virtual ~PasswordFormConversionUtilsTest() {}
110 protected:
111 // Loads the given |html|, retrieves the sole WebFormElement from it, and then
112 // calls CreatePasswordForm() to convert it into a |password_form|. Note that
113 // ASSERT() can only be used in void functions, this is why |password_form| is
114 // passed in as a pointer to a scoped_ptr.
115 void LoadHTMLAndConvertForm(const std::string& html,
116 scoped_ptr<PasswordForm>* password_form) {
117 LoadHTML(html.c_str());
119 WebFrame* frame = GetMainFrame();
120 ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
122 WebVector<WebFormElement> forms;
123 frame->document().forms(forms);
124 ASSERT_EQ(1U, forms.size());
126 WebVector<WebFormControlElement> control_elements;
127 forms[0].getFormControlElements(control_elements);
128 for (size_t i = 0; i < control_elements.size(); ++i) {
129 WebInputElement* input_element = toWebInputElement(&control_elements[i]);
130 if (input_element->hasAttribute("set-activated-submit"))
131 input_element->setActivatedSubmit(true);
134 *password_form = CreatePasswordForm(forms[0]);
137 private:
138 DISALLOW_COPY_AND_ASSIGN(PasswordFormConversionUtilsTest);
141 } // namespace
143 TEST_F(PasswordFormConversionUtilsTest, BasicFormAttributes) {
144 PasswordFormBuilder builder(kTestFormActionURL);
145 builder.AddUsernameField("username", "johnsmith", NULL);
146 builder.AddSubmitButton("inactive_submit", false);
147 builder.AddSubmitButton("active_submit", true);
148 builder.AddSubmitButton("inactive_submit2", false);
149 builder.AddPasswordField("password", "secret", NULL);
150 std::string html = builder.ProduceHTML();
152 scoped_ptr<PasswordForm> password_form;
153 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
154 ASSERT_TRUE(password_form);
156 EXPECT_EQ("data:", password_form->signon_realm);
157 EXPECT_EQ(GURL(kTestFormActionURL), password_form->action);
158 EXPECT_EQ(base::UTF8ToUTF16("active_submit"), password_form->submit_element);
159 EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
160 EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
161 EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
162 EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
163 EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form->scheme);
164 EXPECT_FALSE(password_form->ssl_valid);
165 EXPECT_FALSE(password_form->preferred);
166 EXPECT_FALSE(password_form->blacklisted_by_user);
167 EXPECT_EQ(PasswordForm::TYPE_MANUAL, password_form->type);
170 TEST_F(PasswordFormConversionUtilsTest, DisabledFieldsAreIgnored) {
171 PasswordFormBuilder builder(kTestFormActionURL);
172 builder.AddUsernameField("username", "johnsmith", NULL);
173 builder.AddDisabledUsernameField();
174 builder.AddDisabledPasswordField();
175 builder.AddPasswordField("password", "secret", NULL);
176 builder.AddSubmitButton("submit", true);
177 std::string html = builder.ProduceHTML();
179 scoped_ptr<PasswordForm> password_form;
180 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
181 ASSERT_TRUE(password_form);
182 EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
183 EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
184 EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
185 EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
188 TEST_F(PasswordFormConversionUtilsTest, IdentifyingUsernameFields) {
189 // Each test case consists of a set of parameters to be plugged into the
190 // PasswordFormBuilder below, plus the corresponding expectations.
191 struct TestCase {
192 const char* autocomplete[3];
193 const char* expected_username_element;
194 const char* expected_username_value;
195 const char* expected_other_possible_usernames;
196 } cases[] = {
197 // When no elements are marked with autocomplete='username', the text-type
198 // input field before the first password element should get selected as
199 // the username, and the rest should be marked as alternatives.
200 {{NULL, NULL, NULL}, "username2", "William", "John+Smith"},
201 // When a sole element is marked with autocomplete='username', it should
202 // be treated as the username for sure, with no other_possible_usernames.
203 {{"username", NULL, NULL}, "username1", "John", ""},
204 {{NULL, "username", NULL}, "username2", "William", ""},
205 {{NULL, NULL, "username"}, "username3", "Smith", ""},
206 // When >=2 elements have the attribute, the first should be selected as
207 // the username, and the rest should go to other_possible_usernames.
208 {{"username", "username", NULL}, "username1", "John", "William"},
209 {{NULL, "username", "username"}, "username2", "William", "Smith"},
210 {{"username", NULL, "username"}, "username1", "John", "Smith"},
211 {{"username", "username", "username"}, "username1", "John",
212 "William+Smith"},
213 // When there is an empty autocomplete attribute (i.e. autocomplete=""),
214 // it should have the same effect as having no attribute whatsoever.
215 {{"", "", ""}, "username2", "William", "John+Smith"},
216 {{"", "", "username"}, "username3", "Smith", ""},
217 {{"username", "", "username"}, "username1", "John", "Smith"},
218 // It should not matter if attribute values are upper or mixed case.
219 {{"USERNAME", NULL, "uSeRNaMe"}, "username1", "John", "Smith"},
220 {{"uSeRNaMe", NULL, "USERNAME"}, "username1", "John", "Smith"}};
222 for (size_t i = 0; i < arraysize(cases); ++i) {
223 for (size_t nonempty_username_fields = 0; nonempty_username_fields < 2;
224 ++nonempty_username_fields) {
225 SCOPED_TRACE(testing::Message()
226 << "Iteration " << i << " "
227 << (nonempty_username_fields ? "nonempty" : "empty"));
229 // Repeat each test once with empty, and once with non-empty usernames.
230 // In the former case, no empty other_possible_usernames should be saved.
231 const char* names[3];
232 if (nonempty_username_fields) {
233 names[0] = "John";
234 names[1] = "William";
235 names[2] = "Smith";
236 } else {
237 names[0] = names[1] = names[2] = "";
240 PasswordFormBuilder builder(kTestFormActionURL);
241 builder.AddUsernameField("username1", names[0], cases[i].autocomplete[0]);
242 builder.AddUsernameField("username2", names[1], cases[i].autocomplete[1]);
243 builder.AddPasswordField("password", "secret", NULL);
244 builder.AddUsernameField("username3", names[2], cases[i].autocomplete[2]);
245 builder.AddPasswordField("password2", "othersecret", NULL);
246 builder.AddSubmitButton("submit", true);
247 std::string html = builder.ProduceHTML();
249 scoped_ptr<PasswordForm> password_form;
250 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
251 ASSERT_TRUE(password_form);
253 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element),
254 password_form->username_element);
256 if (nonempty_username_fields) {
257 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_value),
258 password_form->username_value);
259 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_other_possible_usernames),
260 JoinString(password_form->other_possible_usernames, '+'));
261 } else {
262 EXPECT_TRUE(password_form->username_value.empty());
263 EXPECT_TRUE(password_form->other_possible_usernames.empty());
266 // Do a basic sanity check that we are still having a password field.
267 EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
268 EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
273 TEST_F(PasswordFormConversionUtilsTest, IdentifyingTwoPasswordFields) {
274 // Each test case consists of a set of parameters to be plugged into the
275 // PasswordFormBuilder below, plus the corresponding expectations.
276 struct TestCase {
277 const char* password_values[2];
278 const char* expected_password_element;
279 const char* expected_password_value;
280 const char* expected_new_password_element;
281 const char* expected_new_password_value;
282 } cases[] = {
283 // Twp non-empty fields with the same value should be treated as a new
284 // password field plus a confirmation field for the new password.
285 {{"alpha", "alpha"}, "", "", "password1", "alpha"},
286 // The same goes if the fields are yet empty: we speculate that we will
287 // identify them as new password fields once they are filled out, and we
288 // want to keep our abstract interpretation of the form less flaky.
289 {{"", ""}, "", "", "password1", ""},
290 // Two different values should be treated as a password change form, one
291 // that also asks for the current password, but only once for the new.
292 {{"alpha", ""}, "password1", "alpha", "password2", ""},
293 {{"", "beta"}, "password1", "", "password2", "beta"},
294 {{"alpha", "beta"}, "password1", "alpha", "password2", "beta"}};
296 for (size_t i = 0; i < arraysize(cases); ++i) {
297 SCOPED_TRACE(testing::Message() << "Iteration " << i);
299 PasswordFormBuilder builder(kTestFormActionURL);
300 builder.AddPasswordField("password1", cases[i].password_values[0], NULL);
301 builder.AddUsernameField("username1", "William", NULL);
302 builder.AddPasswordField("password2", cases[i].password_values[1], NULL);
303 builder.AddUsernameField("username2", "Smith", NULL);
304 builder.AddSubmitButton("submit", true);
305 std::string html = builder.ProduceHTML();
307 scoped_ptr<PasswordForm> password_form;
308 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
309 ASSERT_TRUE(password_form);
311 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element),
312 password_form->password_element);
313 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value),
314 password_form->password_value);
315 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element),
316 password_form->new_password_element);
317 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value),
318 password_form->new_password_value);
320 // Do a basic sanity check that we are still selecting the right username.
321 EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element);
322 EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value);
323 EXPECT_THAT(password_form->other_possible_usernames,
324 testing::ElementsAre(base::UTF8ToUTF16("Smith")));
328 TEST_F(PasswordFormConversionUtilsTest, IdentifyingThreePasswordFields) {
329 // Each test case consists of a set of parameters to be plugged into the
330 // PasswordFormBuilder below, plus the corresponding expectations.
331 struct TestCase {
332 const char* password_values[3];
333 const char* expected_password_element;
334 const char* expected_password_value;
335 const char* expected_new_password_element;
336 const char* expected_new_password_value;
337 } cases[] = {
338 // Two fields with the same value, and one different: we should treat this
339 // as a password change form with confirmation for the new password. Note
340 // that we only recognize (current + new + new) and (new + new + current)
341 // without autocomplete attributes.
342 {{"alpha", "", ""}, "password1", "alpha", "password2", ""},
343 {{"", "beta", "beta"}, "password1", "", "password2", "beta"},
344 {{"alpha", "beta", "beta"}, "password1", "alpha", "password2", "beta"},
345 {{"beta", "beta", "alpha"}, "password3", "alpha", "password1", "beta"},
346 // If the fields are yet empty, we speculate that we will identify them as
347 // (current + new + new) once they are filled out, so we should classify
348 // them the same for now to keep our abstract interpretation less flaky.
349 {{"", "", ""}, "password1", "", "password2", ""}};
350 // Note: In all other cases, we give up and consider the form invalid.
351 // This is tested in InvalidFormDueToConfusingPasswordFields.
353 for (size_t i = 0; i < arraysize(cases); ++i) {
354 SCOPED_TRACE(testing::Message() << "Iteration " << i);
356 PasswordFormBuilder builder(kTestFormActionURL);
357 builder.AddPasswordField("password1", cases[i].password_values[0], NULL);
358 builder.AddUsernameField("username1", "William", NULL);
359 builder.AddPasswordField("password2", cases[i].password_values[1], NULL);
360 builder.AddUsernameField("username2", "Smith", NULL);
361 builder.AddPasswordField("password3", cases[i].password_values[2], NULL);
362 builder.AddSubmitButton("submit", true);
363 std::string html = builder.ProduceHTML();
365 scoped_ptr<PasswordForm> password_form;
366 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
367 ASSERT_TRUE(password_form);
369 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element),
370 password_form->password_element);
371 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value),
372 password_form->password_value);
373 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element),
374 password_form->new_password_element);
375 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value),
376 password_form->new_password_value);
378 // Do a basic sanity check that we are still selecting the right username.
379 EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element);
380 EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value);
381 EXPECT_THAT(password_form->other_possible_usernames,
382 testing::ElementsAre(base::UTF8ToUTF16("Smith")));
386 TEST_F(PasswordFormConversionUtilsTest,
387 IdentifyingPasswordFieldsWithAutocompleteAttributes) {
388 // Each test case consists of a set of parameters to be plugged into the
389 // PasswordFormBuilder below, plus the corresponding expectations.
390 struct TestCase {
391 const char* autocomplete[3];
392 const char* expected_password_element;
393 const char* expected_password_value;
394 const char* expected_new_password_element;
395 const char* expected_new_password_value;
396 } cases[] = {
397 // When there are elements marked with autocomplete='current-password',
398 // but no elements with 'new-password', we should treat the first of the
399 // former kind as the current password, and ignore all other password
400 // fields, assuming they are not intentionally not marked. They might be
401 // for other purposes, such as PINs, OTPs, and the like. Actual values in
402 // the password fields should be ignored in all cases below.
403 {{"current-password", NULL, NULL},
404 "password1", "alpha", "", ""},
405 {{NULL, "current-password", NULL},
406 "password2", "beta", "", ""},
407 {{NULL, NULL, "current-password"},
408 "password3", "gamma", "", ""},
409 {{NULL, "current-password", "current-password"},
410 "password2", "beta", "", ""},
411 {{"current-password", NULL, "current-password"},
412 "password1", "alpha", "", ""},
413 {{"current-password", "current-password", NULL},
414 "password1", "alpha", "", ""},
415 {{"current-password", "current-password", "current-password"},
416 "password1", "alpha", "", ""},
417 // The same goes vice versa for autocomplete='new-password'.
418 {{"new-password", NULL, NULL},
419 "", "", "password1", "alpha"},
420 {{NULL, "new-password", NULL},
421 "", "", "password2", "beta"},
422 {{NULL, NULL, "new-password"},
423 "", "", "password3", "gamma"},
424 {{NULL, "new-password", "new-password"},
425 "", "", "password2", "beta"},
426 {{"new-password", NULL, "new-password"},
427 "", "", "password1", "alpha"},
428 {{"new-password", "new-password", NULL},
429 "", "", "password1", "alpha"},
430 {{"new-password", "new-password", "new-password"},
431 "", "", "password1", "alpha"},
432 // When there is one element marked with autocomplete='current-password',
433 // and one with 'new-password', just comply, regardless of their order.
434 // Ignore the unmarked password field(s) for the same reason as above.
435 {{"current-password", "new-password", NULL},
436 "password1", "alpha", "password2", "beta"},
437 {{"current-password", NULL, "new-password"},
438 "password1", "alpha", "password3", "gamma"},
439 {{NULL, "current-password", "new-password"},
440 "password2", "beta", "password3", "gamma"},
441 {{"new-password", "current-password", NULL},
442 "password2", "beta", "password1", "alpha"},
443 {{"new-password", NULL, "current-password"},
444 "password3", "gamma", "password1", "alpha"},
445 {{NULL, "new-password", "current-password"},
446 "password3", "gamma", "password2", "beta"},
447 // In case of duplicated elements of either kind, go with the first one of
448 // its kind.
449 {{"current-password", "current-password", "new-password"},
450 "password1", "alpha", "password3", "gamma"},
451 {{"current-password", "new-password", "current-password"},
452 "password1", "alpha", "password2", "beta"},
453 {{"new-password", "current-password", "current-password"},
454 "password2", "beta", "password1", "alpha"},
455 {{"current-password", "new-password", "new-password"},
456 "password1", "alpha", "password2", "beta"},
457 {{"new-password", "current-password", "new-password"},
458 "password2", "beta", "password1", "alpha"},
459 {{"new-password", "new-password", "current-password"},
460 "password3", "gamma", "password1", "alpha"},
461 // When there is an empty autocomplete attribute (i.e. autocomplete=""),
462 // it should have the same effect as having no attribute whatsoever.
463 {{"current-password", "", ""},
464 "password1", "alpha", "", ""},
465 {{"", "", "new-password"},
466 "", "", "password3", "gamma"},
467 {{"", "new-password", ""},
468 "", "", "password2", "beta"},
469 {{"", "current-password", "current-password"},
470 "password2", "beta", "", ""},
471 {{"new-password", "", "new-password"},
472 "", "", "password1", "alpha"},
473 {{"new-password", "", "current-password"},
474 "password3", "gamma", "password1", "alpha"},
475 // It should not matter if attribute values are upper or mixed case.
476 {{NULL, "current-password", NULL},
477 "password2", "beta", "", ""},
478 {{NULL, "CURRENT-PASSWORD", NULL},
479 "password2", "beta", "", ""},
480 {{NULL, "new-password", NULL},
481 "", "", "password2", "beta"},
482 {{NULL, "nEw-PaSsWoRd", NULL},
483 "", "", "password2", "beta"}};
485 for (size_t i = 0; i < arraysize(cases); ++i) {
486 SCOPED_TRACE(testing::Message() << "Iteration " << i);
488 PasswordFormBuilder builder(kTestFormActionURL);
489 builder.AddPasswordField("pin1", "123456", NULL);
490 builder.AddPasswordField("pin2", "789101", NULL);
491 builder.AddPasswordField("password1", "alpha", cases[i].autocomplete[0]);
492 builder.AddUsernameField("username1", "William", NULL);
493 builder.AddPasswordField("password2", "beta", cases[i].autocomplete[1]);
494 builder.AddUsernameField("username2", "Smith", NULL);
495 builder.AddPasswordField("password3", "gamma", cases[i].autocomplete[2]);
496 builder.AddSubmitButton("submit", true);
497 std::string html = builder.ProduceHTML();
499 scoped_ptr<PasswordForm> password_form;
500 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
501 ASSERT_TRUE(password_form);
503 // In the absence of username autocomplete attributes, the username should
504 // be the text input field before the first password element.
505 // No constellation of password autocomplete attributes should change that.
506 EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element);
507 EXPECT_EQ(base::UTF8ToUTF16("William"), password_form->username_value);
508 EXPECT_THAT(password_form->other_possible_usernames,
509 testing::ElementsAre(base::UTF8ToUTF16("Smith")));
510 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element),
511 password_form->password_element);
512 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value),
513 password_form->password_value);
514 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_element),
515 password_form->new_password_element);
516 EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value),
517 password_form->new_password_value);
521 TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToBadActionURL) {
522 PasswordFormBuilder builder("invalid_target");
523 builder.AddUsernameField("username", "JohnSmith", NULL);
524 builder.AddSubmitButton("submit", true);
525 builder.AddPasswordField("password", "secret", NULL);
526 std::string html = builder.ProduceHTML();
528 scoped_ptr<PasswordForm> password_form;
529 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
530 EXPECT_FALSE(password_form);
533 TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToNoPasswordFields) {
534 PasswordFormBuilder builder(kTestFormActionURL);
535 builder.AddUsernameField("username1", "John", NULL);
536 builder.AddUsernameField("username2", "Smith", NULL);
537 builder.AddSubmitButton("submit", true);
538 std::string html = builder.ProduceHTML();
540 scoped_ptr<PasswordForm> password_form;
541 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
542 EXPECT_FALSE(password_form);
545 TEST_F(PasswordFormConversionUtilsTest,
546 InvalidFormsDueToConfusingPasswordFields) {
547 // Each test case consists of a set of parameters to be plugged into the
548 // PasswordFormBuilder below.
549 const char* cases[][3] = {
550 // No autocomplete attributes to guide us, and we see:
551 // * three password values that are all different,
552 // * three password values that are all the same;
553 // * three password values with the first and last matching.
554 // In any case, we should just give up on this form.
555 {"alpha", "beta", "gamma"},
556 {"alpha", "alpha", "alpha"},
557 {"alpha", "beta", "alpha"}};
559 for (size_t i = 0; i < arraysize(cases); ++i) {
560 SCOPED_TRACE(testing::Message() << "Iteration " << i);
562 PasswordFormBuilder builder(kTestFormActionURL);
563 builder.AddUsernameField("username1", "John", NULL);
564 builder.AddPasswordField("password1", cases[i][0], NULL);
565 builder.AddPasswordField("password2", cases[i][1], NULL);
566 builder.AddPasswordField("password3", cases[i][2], NULL);
567 builder.AddSubmitButton("submit", true);
568 std::string html = builder.ProduceHTML();
570 scoped_ptr<PasswordForm> password_form;
571 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
572 EXPECT_FALSE(password_form);
576 TEST_F(PasswordFormConversionUtilsTest,
577 InvalidFormDueToTooManyPasswordFieldsWithoutAutocompleteAttributes) {
578 PasswordFormBuilder builder(kTestFormActionURL);
579 builder.AddUsernameField("username1", "John", NULL);
580 builder.AddPasswordField("password1", "alpha", NULL);
581 builder.AddPasswordField("password2", "alpha", NULL);
582 builder.AddPasswordField("password3", "alpha", NULL);
583 builder.AddPasswordField("password4", "alpha", NULL);
584 builder.AddSubmitButton("submit", true);
585 std::string html = builder.ProduceHTML();
587 scoped_ptr<PasswordForm> password_form;
588 ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
589 EXPECT_FALSE(password_form);
592 } // namespace autofill