Index: chrome/renderer/autofill/form_classifier_browsertest.cc |
diff --git a/chrome/renderer/autofill/form_classifier_browsertest.cc b/chrome/renderer/autofill/form_classifier_browsertest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..615b61f24a888a03e6781148ceb5db9c2d57b0b7 |
--- /dev/null |
+++ b/chrome/renderer/autofill/form_classifier_browsertest.cc |
@@ -0,0 +1,236 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/macros.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "chrome/test/base/chrome_render_view_test.h" |
+#include "components/autofill/content/renderer/form_classifier.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/WebKit/public/web/WebDocument.h" |
+#include "third_party/WebKit/public/web/WebFormElement.h" |
+#include "third_party/WebKit/public/web/WebLocalFrame.h" |
+ |
+namespace autofill { |
+ |
+class FormClassifierTest : public ChromeRenderViewTest { |
+ public: |
+ FormClassifierTest() {} |
+ |
+ void TearDown() override { |
+ LoadHTML(""); |
+ ChromeRenderViewTest::TearDown(); |
+ } |
+ |
+ bool GetGenerationField(std::string* generation_field) { |
+ blink::WebDocument document = GetMainFrame()->document(); |
+ blink::WebFormElement form = |
+ document.getElementById("test_form").to<blink::WebFormElement>(); |
+ base::string16 generation_field16; |
+ bool generation_availalbe = |
+ ClassifyFormAndFindGenerationField(form, &generation_field16); |
+ *generation_field = base::UTF16ToUTF8(generation_field16); |
+ return generation_availalbe; |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(FormClassifierTest); |
+}; |
+ |
+const char kSigninFormHTML[] = |
+ "<FORM id = 'test_form'> " |
+ " <SELECT id='account_type'>" |
+ " <OPTION value = 'personal'>" |
+ " <OPTION value = 'corporate'>" |
+ " </SELECT>" |
+ " <INPUT type = 'text' id = 'username'/>" |
+ " <INPUT type = 'password' id = 'password'/>" |
+ " <INPUT type = 'checkbox' id = 'remember_me'/>" |
+ " <INPUT type = 'checkbox' id = 'secure_login'/>" |
+ " <INPUT type = 'submit' id = 'signin' />" |
+ " <INPUT type = 'hidden' id = 'ignore_this' />" |
+ " <INPUT type = 'hidden' id = 'ignore_this_too' />" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+const char kSignupFormWithSeveralTextFieldsFormHTML[] = |
+ "<FORM id = 'test_form'> " |
+ " <INPUT type = 'text' id = 'full_name'/>" |
+ " <INPUT type = 'text' id = 'username'/>" |
+ " <INPUT type = 'password' id = 'password'/>" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+const char kSignupFormWithSeveralPasswordFieldsHTML[] = |
+ "<FORM id = 'test_form'> " |
+ " <INPUT type = 'text' id = 'username'/>" |
+ " <INPUT type = 'password' id = 'password'/>" |
+ " <INPUT type = 'password' id = 'confirm_password'/>" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+const char kSignupFormWithManyCheckboxesHTML[] = |
+ "<FORM id = 'test_form'> " |
+ " </SELECT>" |
+ " <INPUT type = 'text' id = 'username' />" |
+ " <INPUT type = 'password' id = 'password' />" |
+ " <INPUT type = 'checkbox' id = 'subscribe_science' />" |
+ " <INPUT type = 'checkbox' id = 'subscribe_music' />" |
+ " <INPUT type = 'checkbox' id = 'subscribe_sport' />" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+const char kSignupFormWithOtherFieldsHTML[] = |
+ "<FORM id = 'test_form'> " |
+ " <INPUT type = 'text' id = 'username' />" |
+ " <INPUT type = 'password' id = 'password' />" |
+ " <INPUT type = 'color' id = 'account_color' />" |
+ " <INPUT type = 'date' id = 'date_of_birth' />" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+const char kSignupFormWithTextFeatureInInputElementHTML[] = |
+ "<FORM id = 'test_form'> " |
+ " <INPUT type = 'text' id = 'username' class = 'sign-up_field' />" |
+ " <INPUT type = 'password' id = 'password' class = 'sign-up_field' />" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+const char kSignupFormWithTextFeatureInFormTagHTML[] = |
+ "<FORM id = 'test_form' some_attribute='sign_up_form' > " |
+ " <INPUT type = 'text' id = 'username' />" |
+ " <INPUT type = 'password' id = 'password' />" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+const char kSigninFormWithInvisibleFieldsHTML[] = |
+ "<FORM id = 'test_form'> " |
+ " <INPUT type = 'text' id = 'username' />" |
+ " <INPUT type = 'password' id = 'password' />" |
+ " <INPUT type = 'input' hidden id = 'hidden_field1' />" |
+ " <INPUT type = 'password' hidden id = 'hidden_field2'/>" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+const char kSignupFormWithSigninButtonHTML[] = |
+ "<FORM id = 'test_form' >" |
+ " <INPUT type = 'text' id = 'username' />" |
+ " <INPUT type = 'password' id = 'password' />" |
+ " <INPUT type = 'password' id = 'confirm_password' />" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ " <INPUT type = 'button' id = 'goto_signin_form' />" |
+ " <INPUT type = 'image' id = 'goto_auth_form' />" |
+ "</FORM>"; |
+ |
+const char kSomeFormWithoutPasswordFields[] = |
+ "<FORM id = 'test_form' >" |
+ " <INPUT type = 'text' id = 'username' />" |
+ " <INPUT type = 'text' id = 'fullname' />" |
+ " <INPUT type = 'text' id = 'address' />" |
+ " <INPUT type = 'text' id = 'phone' />" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+const char kSignupFormWithSigninTextFeatureAndManyFieldsHTML[] = |
+ "<FORM id = 'test_form' class = 'log-on_container'> " |
+ " <INPUT type = 'text' id = 'fullname' />" |
+ " <INPUT type = 'text' id = 'username' />" |
+ " <INPUT type = 'password' id = 'password' />" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+const char kChangeFormWithTreePasswordFieldsHTML[] = |
+ "<FORM id = 'test_form' >" |
+ " <INPUT type = 'password' id = 'old_password' />" |
+ " <INPUT type = 'password' id = 'password' />" |
+ " <INPUT type = 'password' id = 'confirm_password' />" |
+ " <INPUT type = 'submit' id = 'submit' />" |
+ "</FORM>"; |
+ |
+TEST_F(FormClassifierTest, SigninForm) { |
+ // Signin form with as many as possible visible elements, |
+ // i.e. if one more text/password/checkbox/other field is added, the form |
+ // will be recognized as a signup form. |
+ LoadHTML(kSigninFormHTML); |
+ std::string generation_field; |
+ EXPECT_FALSE(GetGenerationField(&generation_field)); |
+} |
+ |
+TEST_F(FormClassifierTest, SignupFormWithSeveralTextFields) { |
+ LoadHTML(kSignupFormWithSeveralTextFieldsFormHTML); |
+ std::string generation_field; |
+ EXPECT_TRUE(GetGenerationField(&generation_field)); |
+ EXPECT_EQ("password", generation_field); |
+} |
+ |
+TEST_F(FormClassifierTest, SignupFormWithSeveralPasswordFieldsHTML) { |
+ LoadHTML(kSignupFormWithSeveralPasswordFieldsHTML); |
+ std::string generation_field; |
+ EXPECT_TRUE(GetGenerationField(&generation_field)); |
+ EXPECT_EQ("password", generation_field); |
+} |
+ |
+TEST_F(FormClassifierTest, SignupFormWithManyCheckboxesHTML) { |
+ LoadHTML(kSignupFormWithManyCheckboxesHTML); |
+ std::string generation_field; |
+ EXPECT_TRUE(GetGenerationField(&generation_field)); |
+ EXPECT_EQ("password", generation_field); |
+} |
+ |
+TEST_F(FormClassifierTest, SignupFormWithOtherFieldsHTML) { |
+ LoadHTML(kSignupFormWithOtherFieldsHTML); |
+ std::string generation_field; |
+ EXPECT_TRUE(GetGenerationField(&generation_field)); |
+ EXPECT_EQ("password", generation_field); |
+} |
+ |
+TEST_F(FormClassifierTest, SignupFormWithTextFeatureInInputElementHTML) { |
+ LoadHTML(kSignupFormWithTextFeatureInInputElementHTML); |
+ std::string generation_field; |
+ EXPECT_TRUE(GetGenerationField(&generation_field)); |
+ EXPECT_EQ("password", generation_field); |
+} |
+ |
+TEST_F(FormClassifierTest, SigninFormWithTextFeatureInFormTagHTML) { |
+ LoadHTML(kSignupFormWithTextFeatureInFormTagHTML); |
+ std::string generation_field; |
+ EXPECT_TRUE(GetGenerationField(&generation_field)); |
+ EXPECT_EQ("password", generation_field); |
+} |
+ |
+TEST_F(FormClassifierTest, SigninFormWithInvisibleFieldsHTML) { |
+ LoadHTML(kSigninFormWithInvisibleFieldsHTML); |
+ std::string generation_field; |
+ EXPECT_FALSE(GetGenerationField(&generation_field)); |
+} |
+ |
+TEST_F(FormClassifierTest, SignupFormWithSigninButtonHTML) { |
+ LoadHTML(kSignupFormWithSigninButtonHTML); |
+ std::string generation_field; |
+ EXPECT_TRUE(GetGenerationField(&generation_field)); |
+ EXPECT_EQ("password", generation_field); |
+} |
+ |
+TEST_F(FormClassifierTest, SomeFormWithoutPasswordFields) { |
+ LoadHTML(kSomeFormWithoutPasswordFields); |
+ std::string generation_field; |
+ EXPECT_FALSE(GetGenerationField(&generation_field)); |
+} |
+ |
+TEST_F(FormClassifierTest, SignupFormWithSigninTextFeatureAndManyFieldsHTML) { |
+ // Even if there is signin text feature, the number of fields is more reliable |
+ // signal of signup form. So, this form should be classified as signup. |
+ LoadHTML(kSignupFormWithSigninTextFeatureAndManyFieldsHTML); |
+ std::string generation_field; |
+ EXPECT_TRUE(GetGenerationField(&generation_field)); |
+ EXPECT_EQ("password", generation_field); |
+} |
+ |
+TEST_F(FormClassifierTest, kChangeFormWithTreePasswordFieldsHTML) { |
+ LoadHTML(kChangeFormWithTreePasswordFieldsHTML); |
+ std::string generation_field; |
+ EXPECT_TRUE(GetGenerationField(&generation_field)); |
+ EXPECT_EQ("password", generation_field); |
+} |
+ |
+} // namespace autofill |