| 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 a7e31dcf5e23fd3c827d2cbbc564863ce8e4d723..af70d2258c7e783fbc751450f9d8cc4ae5708311 100644
|
| --- a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
|
| +++ b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
|
| @@ -9,14 +9,19 @@
|
| #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"
|
| +#include "third_party/WebKit/public/web/WebFormControlElement.h"
|
| #include "third_party/WebKit/public/web/WebFormElement.h"
|
| +#include "third_party/WebKit/public/web/WebInputElement.h"
|
| #include "third_party/WebKit/public/web/WebLocalFrame.h"
|
|
|
| +using blink::WebFormControlElement;
|
| using blink::WebFormElement;
|
| using blink::WebFrame;
|
| +using blink::WebInputElement;
|
| using blink::WebVector;
|
|
|
| namespace autofill {
|
| @@ -65,9 +70,24 @@ class PasswordFormBuilder {
|
| name_and_id, name_and_id, value, autocomplete_attribute.c_str());
|
| }
|
|
|
| - // Appends a new submit-type field at the end of the form.
|
| - void AddSubmitButton() {
|
| - html_ += "<INPUT type=\"submit\" name=\"submit\" value=\"Submit\"/>";
|
| + // Appends a disabled text-type field at the end of the form.
|
| + void AddDisabledUsernameField() {
|
| + html_ += "<INPUT type=\"text\" disabled/>";
|
| + }
|
| +
|
| + // Appends a disabled password-type field at the end of the form.
|
| + void AddDisabledPasswordField() {
|
| + html_ += "<INPUT type=\"password\" disabled/>";
|
| + }
|
| +
|
| + // Appends a new submit-type field at the end of the form with the specified
|
| + // |name|. If |activated| is true, the test will emulate as if this button
|
| + // were used to submit the form.
|
| + void AddSubmitButton(const char* name, bool activated) {
|
| + base::StringAppendF(
|
| + &html_,
|
| + "<INPUT type=\"submit\" name=\"%s\" value=\"Submit\" %s/>",
|
| + name, activated ? "set-activated-submit" : "");
|
| }
|
|
|
| // Returns the HTML code for the form containing the fields that have been
|
| @@ -103,6 +123,14 @@ class PasswordFormConversionUtilsTest : public content::RenderViewTest {
|
| frame->document().forms(forms);
|
| ASSERT_EQ(1U, forms.size());
|
|
|
| + WebVector<WebFormControlElement> control_elements;
|
| + forms[0].getFormControlElements(control_elements);
|
| + for (size_t i = 0; i < control_elements.size(); ++i) {
|
| + WebInputElement* input_element = toWebInputElement(&control_elements[i]);
|
| + if (input_element->hasAttribute("set-activated-submit"))
|
| + input_element->setActivatedSubmit(true);
|
| + }
|
| +
|
| *password_form = CreatePasswordForm(forms[0]);
|
| }
|
|
|
| @@ -112,19 +140,22 @@ class PasswordFormConversionUtilsTest : public content::RenderViewTest {
|
|
|
| } // namespace
|
|
|
| -TEST_F(PasswordFormConversionUtilsTest, ValidWebFormElementToPasswordForm) {
|
| +TEST_F(PasswordFormConversionUtilsTest, BasicFormAttributes) {
|
| PasswordFormBuilder builder(kTestFormActionURL);
|
| builder.AddUsernameField("username", "johnsmith", NULL);
|
| - builder.AddSubmitButton();
|
| + builder.AddSubmitButton("inactive_submit", false);
|
| + builder.AddSubmitButton("active_submit", true);
|
| + builder.AddSubmitButton("inactive_submit2", false);
|
| builder.AddPasswordField("password", "secret", NULL);
|
| 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());
|
| + ASSERT_TRUE(password_form);
|
|
|
| EXPECT_EQ("data:", password_form->signon_realm);
|
| EXPECT_EQ(GURL(kTestFormActionURL), password_form->action);
|
| + EXPECT_EQ(base::UTF8ToUTF16("active_submit"), password_form->submit_element);
|
| EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
|
| EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
|
| EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
|
| @@ -134,75 +165,28 @@ TEST_F(PasswordFormConversionUtilsTest, ValidWebFormElementToPasswordForm) {
|
| EXPECT_FALSE(password_form->preferred);
|
| EXPECT_FALSE(password_form->blacklisted_by_user);
|
| EXPECT_EQ(PasswordForm::TYPE_MANUAL, password_form->type);
|
| + EXPECT_FALSE(password_form->use_additional_authentication);
|
| }
|
|
|
| -TEST_F(PasswordFormConversionUtilsTest, InvalidWebFormElementToPasswordForm) {
|
| - PasswordFormBuilder builder("invalid_target");
|
| +TEST_F(PasswordFormConversionUtilsTest, DisabledFieldsAreIgnored) {
|
| + PasswordFormBuilder builder(kTestFormActionURL);
|
| builder.AddUsernameField("username", "johnsmith", NULL);
|
| - builder.AddSubmitButton();
|
| + builder.AddDisabledUsernameField();
|
| + builder.AddDisabledPasswordField();
|
| builder.AddPasswordField("password", "secret", NULL);
|
| + builder.AddSubmitButton("submit", true);
|
| 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) {
|
| - 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());
|
| + ASSERT_TRUE(password_form);
|
| + EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
|
| + EXPECT_EQ(base::UTF8ToUTF16("johnsmith"), password_form->username_value);
|
| + EXPECT_EQ(base::UTF8ToUTF16("password"), password_form->password_element);
|
| + EXPECT_EQ(base::UTF8ToUTF16("secret"), password_form->password_value);
|
| }
|
|
|
| -TEST_F(PasswordFormConversionUtilsTest,
|
| - UsernameFieldsWithAutocompleteAttributes) {
|
| +TEST_F(PasswordFormConversionUtilsTest, 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 +195,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", ""},
|
| @@ -233,33 +221,171 @@ TEST_F(PasswordFormConversionUtilsTest,
|
| {{"uSeRNaMe", NULL, "USERNAME"}, "username1", "John", "Smith"}};
|
|
|
| for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
|
| + for (size_t nonempty_username_fields = 0; nonempty_username_fields < 2;
|
| + ++nonempty_username_fields) {
|
| + SCOPED_TRACE(testing::Message()
|
| + << "Iteration " << i << " "
|
| + << (nonempty_username_fields ? "nonempty" : "empty"));
|
| +
|
| + // Repeat each test once with empty, and once with non-empty usernames.
|
| + // In the former case, no empty other_possible_usernames should be saved.
|
| + const char* names[3];
|
| + if (nonempty_username_fields) {
|
| + names[0] = "John";
|
| + names[1] = "William";
|
| + names[2] = "Smith";
|
| + } else {
|
| + names[0] = names[1] = names[2] = "";
|
| + }
|
| +
|
| + PasswordFormBuilder builder(kTestFormActionURL);
|
| + builder.AddUsernameField("username1", names[0], cases[i].autocomplete[0]);
|
| + builder.AddUsernameField("username2", names[1], cases[i].autocomplete[1]);
|
| + builder.AddPasswordField("password", "secret", NULL);
|
| + builder.AddUsernameField("username3", names[2], cases[i].autocomplete[2]);
|
| + builder.AddPasswordField("password2", "othersecret", NULL);
|
| + builder.AddSubmitButton("submit", true);
|
| + 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_username_element),
|
| + password_form->username_element);
|
| +
|
| + if (nonempty_username_fields) {
|
| + EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_value),
|
| + password_form->username_value);
|
| + EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_other_possible_usernames),
|
| + JoinString(password_form->other_possible_usernames, '+'));
|
| + } else {
|
| + EXPECT_TRUE(password_form->username_value.empty());
|
| + EXPECT_TRUE(password_form->other_possible_usernames.empty());
|
| + }
|
| +
|
| + // 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("submit", true);
|
| + 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.AddUsernameField("username1", "John", cases[i].autocomplete[0]);
|
| - builder.AddUsernameField("username2", "William", cases[i].autocomplete[1]);
|
| - builder.AddPasswordField("password", "secret", NULL);
|
| - builder.AddUsernameField("username3", "Smith", cases[i].autocomplete[2]);
|
| - builder.AddSubmitButton();
|
| + 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("submit", true);
|
| 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(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, '+'));
|
| + 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,23 +487,27 @@ TEST_F(PasswordFormConversionUtilsTest,
|
| SCOPED_TRACE(testing::Message() << "Iteration " << i);
|
|
|
| PasswordFormBuilder builder(kTestFormActionURL);
|
| + builder.AddPasswordField("pin1", "123456", NULL);
|
| + builder.AddPasswordField("pin2", "789101", NULL);
|
| builder.AddPasswordField("password1", "alpha", cases[i].autocomplete[0]);
|
| builder.AddUsernameField("username1", "William", NULL);
|
| builder.AddPasswordField("password2", "beta", cases[i].autocomplete[1]);
|
| builder.AddUsernameField("username2", "Smith", NULL);
|
| builder.AddPasswordField("password3", "gamma", cases[i].autocomplete[2]);
|
| - builder.AddSubmitButton();
|
| + builder.AddSubmitButton("submit", true);
|
| 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());
|
| + 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.
|
| + // In the absence of username autocomplete attributes, the username should
|
| + // be the text input field before the first password element.
|
| + // No constellation of password autocomplete attributes should change that.
|
| 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")));
|
| EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_element),
|
| password_form->password_element);
|
| EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_password_value),
|
| @@ -386,10 +516,78 @@ 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]);
|
| }
|
| }
|
|
|
| +TEST_F(PasswordFormConversionUtilsTest, InvalidFormDueToBadActionURL) {
|
| + PasswordFormBuilder builder("invalid_target");
|
| + builder.AddUsernameField("username", "JohnSmith", NULL);
|
| + builder.AddSubmitButton("submit", true);
|
| + 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("submit", true);
|
| + 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,
|
| + InvalidFormsDueToConfusingPasswordFields) {
|
| + // 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 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("submit", true);
|
| + 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,
|
| + InvalidFormDueToTooManyPasswordFieldsWithoutAutocompleteAttributes) {
|
| + PasswordFormBuilder builder(kTestFormActionURL);
|
| + builder.AddUsernameField("username1", "John", NULL);
|
| + builder.AddPasswordField("password1", "alpha", NULL);
|
| + builder.AddPasswordField("password2", "alpha", NULL);
|
| + builder.AddPasswordField("password3", "alpha", NULL);
|
| + builder.AddPasswordField("password4", "alpha", NULL);
|
| + builder.AddSubmitButton("submit", true);
|
| + std::string html = builder.ProduceHTML();
|
| +
|
| + scoped_ptr<PasswordForm> password_form;
|
| + ASSERT_NO_FATAL_FAILURE(LoadHTMLAndConvertForm(html, &password_form));
|
| + EXPECT_FALSE(password_form);
|
| +}
|
| +
|
| } // namespace autofill
|
|
|