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 |