summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/autofill/form_autofill_browsertest.cc
diff options
context:
space:
mode:
authorisherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-16 00:23:54 +0000
committerisherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-16 00:23:54 +0000
commitaaa80c9edbb4234a89e05c5bbd53d9a4f790e86e (patch)
tree7f09503cc73ef9f3ed29b891fdd71e2ed09a9912 /chrome/renderer/autofill/form_autofill_browsertest.cc
parente4d9491934ef4bb70aeac5c92cbe76e0399e7367 (diff)
downloadchromium_src-aaa80c9edbb4234a89e05c5bbd53d9a4f790e86e.zip
chromium_src-aaa80c9edbb4234a89e05c5bbd53d9a4f790e86e.tar.gz
chromium_src-aaa80c9edbb4234a89e05c5bbd53d9a4f790e86e.tar.bz2
Split Autofill's FormManager into a FormCache and a collection of utility functions.
(1) Move the non-static functions from FormManager into a FormCache class. (2) Move the static functions from FormManager to a form_autofill_util file. (3) Update #includes as appropriate. (4) Remove a couple of unused options from the RequirementsMask enum. BUG=71257 TEST=compiles Review URL: http://codereview.chromium.org/7892051 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101421 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/autofill/form_autofill_browsertest.cc')
-rw-r--r--chrome/renderer/autofill/form_autofill_browsertest.cc2889
1 files changed, 2889 insertions, 0 deletions
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc
new file mode 100644
index 0000000..cd484d3
--- /dev/null
+++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -0,0 +1,2889 @@
+// Copyright (c) 2011 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 <vector>
+
+#include "base/format_macros.h"
+#include "base/string16.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/renderer/autofill/form_autofill_util.h"
+#include "chrome/renderer/autofill/form_cache.h"
+#include "chrome/test/base/render_view_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSelectElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
+#include "webkit/glue/form_data.h"
+#include "webkit/glue/web_io_operators.h"
+
+using WebKit::WebDocument;
+using WebKit::WebElement;
+using WebKit::WebFormControlElement;
+using WebKit::WebFormElement;
+using WebKit::WebFrame;
+using WebKit::WebInputElement;
+using WebKit::WebSelectElement;
+using WebKit::WebNode;
+using WebKit::WebString;
+using WebKit::WebVector;
+
+using autofill::ClearPreviewedFormWithElement;
+using autofill::FillForm;
+using autofill::FindFormAndFieldForFormControlElement;
+using autofill::FormWithElementIsAutofilled;
+using autofill::FormCache;
+using autofill::PreviewForm;
+using autofill::WebFormControlElementToFormField;
+
+using webkit_glue::FormData;
+using webkit_glue::FormField;
+
+class FormManagerTest : public RenderViewTest {
+ public:
+ FormManagerTest() : RenderViewTest() {}
+ virtual ~FormManagerTest() {}
+
+ void ExpectLabels(const char* html,
+ const std::vector<string16>& labels,
+ const std::vector<string16>& names,
+ const std::vector<string16>& values) {
+ std::vector<string16> control_types(labels.size(), ASCIIToUTF16("text"));
+ ExpectLabelsAndTypes(html, labels, names, values, control_types);
+ }
+
+ void ExpectLabelsAndTypes(const char* html,
+ const std::vector<string16>& labels,
+ const std::vector<string16>& names,
+ const std::vector<string16>& values,
+ const std::vector<string16>& control_types) {
+ ASSERT_EQ(labels.size(), names.size());
+ ASSERT_EQ(labels.size(), values.size());
+ ASSERT_EQ(labels.size(), control_types.size());
+
+ LoadHTML(html);
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ const FormData& form = forms[0];
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://cnn.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(labels.size(), fields.size());
+ for (size_t i = 0; i < labels.size(); ++i) {
+ int max_length = control_types[i] == ASCIIToUTF16("text") ?
+ WebInputElement::defaultMaxLength() : 0;
+ FormField expected;
+ expected.label = labels[i];
+ expected.name = names[i];
+ expected.value = values[i];
+ expected.form_control_type = control_types[i];
+ expected.max_length = max_length;
+ SCOPED_TRACE(StringPrintf("i: %" PRIuS, i));
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[i]);
+ }
+ }
+
+ void ExpectJohnSmithLabels(const char* html) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("First name:"));
+ names.push_back(ASCIIToUTF16("firstname"));
+ values.push_back(ASCIIToUTF16("John"));
+
+ labels.push_back(ASCIIToUTF16("Last name:"));
+ names.push_back(ASCIIToUTF16("lastname"));
+ values.push_back(ASCIIToUTF16("Smith"));
+
+ labels.push_back(ASCIIToUTF16("Email:"));
+ names.push_back(ASCIIToUTF16("email"));
+ values.push_back(ASCIIToUTF16("john@example.com"));
+
+ ExpectLabels(html, labels, names, values);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FormManagerTest);
+};
+
+// We should be able to extract a normal text field.
+TEST_F(FormManagerTest, WebFormControlElementToFormField) {
+ LoadHTML("<INPUT type=\"text\" id=\"element\" value=\"value\"/>");
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ WebElement web_element = frame->document().getElementById("element");
+ WebFormControlElement element = web_element.to<WebFormControlElement>();
+ FormField result1;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_NONE, &result1);
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("element");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, result1);
+
+ FormField result2;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result2);
+
+ expected.name = ASCIIToUTF16("element");
+ expected.value = ASCIIToUTF16("value");
+ EXPECT_FORM_FIELD_EQUALS(expected, result2);
+}
+
+// We should be able to extract a text field with autocomplete="off".
+TEST_F(FormManagerTest, WebFormControlElementToFormFieldAutocompleteOff) {
+ LoadHTML("<INPUT type=\"text\" id=\"element\" value=\"value\""
+ " autocomplete=\"off\"/>");
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ WebElement web_element = frame->document().getElementById("element");
+ WebFormControlElement element = web_element.to<WebFormControlElement>();
+ FormField result;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result);
+
+ FormField expected;
+ expected.name = ASCIIToUTF16("element");
+ expected.value = ASCIIToUTF16("value");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, result);
+}
+
+// We should be able to extract a text field with maxlength specified.
+TEST_F(FormManagerTest, WebFormControlElementToFormFieldMaxLength) {
+ LoadHTML("<INPUT type=\"text\" id=\"element\" value=\"value\""
+ " maxlength=\"5\"/>");
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ WebElement web_element = frame->document().getElementById("element");
+ WebFormControlElement element = web_element.to<WebFormControlElement>();
+ FormField result;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result);
+
+ FormField expected;
+ expected.name = ASCIIToUTF16("element");
+ expected.value = ASCIIToUTF16("value");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = 5;
+ EXPECT_FORM_FIELD_EQUALS(expected, result);
+}
+
+// We should be able to extract a text field that has been autofilled.
+TEST_F(FormManagerTest, WebFormControlElementToFormFieldAutofilled) {
+ LoadHTML("<INPUT type=\"text\" id=\"element\" value=\"value\"/>");
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ WebElement web_element = frame->document().getElementById("element");
+ WebInputElement element = web_element.to<WebInputElement>();
+ element.setAutofilled(true);
+ FormField result;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result);
+
+ FormField expected;
+ expected.name = ASCIIToUTF16("element");
+ expected.value = ASCIIToUTF16("value");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ expected.is_autofilled = true;
+ EXPECT_FORM_FIELD_EQUALS(expected, result);
+}
+
+// We should be able to extract a <select> field.
+TEST_F(FormManagerTest, WebFormControlElementToFormFieldSelect) {
+ LoadHTML("<SELECT id=\"element\"/>"
+ " <OPTION value=\"CA\">California</OPTION>"
+ " <OPTION value=\"TX\">Texas</OPTION>"
+ "</SELECT>");
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ WebElement web_element = frame->document().getElementById("element");
+ WebFormControlElement element = web_element.to<WebFormControlElement>();
+ FormField result1;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result1);
+
+ FormField expected;
+ expected.name = ASCIIToUTF16("element");
+ expected.max_length = 0;
+ expected.form_control_type = ASCIIToUTF16("select-one");
+
+ expected.value = ASCIIToUTF16("CA");
+ EXPECT_FORM_FIELD_EQUALS(expected, result1);
+
+ FormField result2;
+ WebFormControlElementToFormField(
+ element,
+ static_cast<autofill::ExtractMask>(autofill::EXTRACT_VALUE |
+ autofill::EXTRACT_OPTION_TEXT),
+ &result2);
+ expected.value = ASCIIToUTF16("California");
+ EXPECT_FORM_FIELD_EQUALS(expected, result2);
+
+ FormField result3;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_OPTIONS,
+ &result3);
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, result3);
+
+ ASSERT_EQ(2U, result3.option_values.size());
+ ASSERT_EQ(2U, result3.option_contents.size());
+ EXPECT_EQ(ASCIIToUTF16("CA"), result3.option_values[0]);
+ EXPECT_EQ(ASCIIToUTF16("California"), result3.option_contents[0]);
+ EXPECT_EQ(ASCIIToUTF16("TX"), result3.option_values[1]);
+ EXPECT_EQ(ASCIIToUTF16("Texas"), result3.option_contents[1]);
+}
+
+// We should not extract the value for non-text and non-select fields.
+TEST_F(FormManagerTest, WebFormControlElementToFormFieldInvalidType) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <INPUT type=\"hidden\" id=\"hidden\" value=\"apple\"/>"
+ " <INPUT type=\"password\" id=\"password\" value=\"secret\"/>"
+ " <INPUT type=\"checkbox\" id=\"checkbox\" value=\"mail\"/>"
+ " <INPUT type=\"radio\" id=\"radio\" value=\"male\"/>"
+ " <INPUT type=\"submit\" id=\"submit\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ WebElement web_element = frame->document().getElementById("hidden");
+ WebFormControlElement element = web_element.to<WebFormControlElement>();
+ FormField result;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result);
+
+ FormField expected;
+ expected.max_length = 0;
+
+ expected.name = ASCIIToUTF16("hidden");
+ expected.form_control_type = ASCIIToUTF16("hidden");
+ EXPECT_FORM_FIELD_EQUALS(expected, result);
+
+ web_element = frame->document().getElementById("password");
+ element = web_element.to<WebFormControlElement>();
+ WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result);
+ expected.name = ASCIIToUTF16("password");
+ expected.form_control_type = ASCIIToUTF16("password");
+ EXPECT_FORM_FIELD_EQUALS(expected, result);
+
+ web_element = frame->document().getElementById("checkbox");
+ element = web_element.to<WebFormControlElement>();
+ WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result);
+ expected.name = ASCIIToUTF16("checkbox");
+ expected.form_control_type = ASCIIToUTF16("checkbox");
+ EXPECT_FORM_FIELD_EQUALS(expected, result);
+
+ web_element = frame->document().getElementById("radio");
+ element = web_element.to<WebFormControlElement>();
+ WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result);
+ expected.name = ASCIIToUTF16("radio");
+ expected.form_control_type = ASCIIToUTF16("radio");
+ EXPECT_FORM_FIELD_EQUALS(expected, result);
+
+
+ web_element = frame->document().getElementById("submit");
+ element = web_element.to<WebFormControlElement>();
+ WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result);
+ expected.name = ASCIIToUTF16("submit");
+ expected.form_control_type = ASCIIToUTF16("submit");
+ EXPECT_FORM_FIELD_EQUALS(expected, result);
+}
+
+// We should be able to extract the autocompletetype attribute.
+TEST_F(FormManagerTest, WebFormControlElementToFormFieldAutocompletetype) {
+ std::string html =
+ "<INPUT type=\"text\" id=\"absent\"/>"
+ "<INPUT type=\"text\" id=\"empty\" x-autocompletetype=\"\"/>"
+ "<INPUT type=\"text\" id=\"whitespace\" x-autocompletetype=\" \"/>"
+ "<INPUT type=\"text\" id=\"regular\" x-autocompletetype=\"email\"/>"
+ "<INPUT type=\"text\" id=\"multi-valued\" "
+ " x-autocompletetype=\"x-confirm-email email\"/>"
+ "<INPUT type=\"text\" id=\"unprefixed\" autocompletetype=\"email\"/>"
+ "<SELECT id=\"select\" x-autocompletetype=\"state\"/>"
+ " <OPTION value=\"CA\">California</OPTION>"
+ " <OPTION value=\"TX\">Texas</OPTION>"
+ "</SELECT>";
+ html +=
+ "<INPUT type=\"text\" id=\"malicious\" x-autocompletetype=\"" +
+ std::string(10000, 'x') + "\"/>";
+ LoadHTML(html.c_str());
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ // An absent attribute is equivalent to an empty one.
+ WebElement web_element = frame->document().getElementById("absent");
+ WebFormControlElement element = web_element.to<WebFormControlElement>();
+ FormField result1;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_NONE, &result1);
+
+ FormField expected;
+ expected.name = ASCIIToUTF16("absent");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.autocomplete_type = string16();
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, result1);
+
+ web_element = frame->document().getElementById("empty");
+ element = web_element.to<WebFormControlElement>();
+ FormField result2;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_NONE, &result2);
+ expected.name = ASCIIToUTF16("empty");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.autocomplete_type = string16();
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, result2);
+
+ // The renderer should trim whitespace.
+ web_element = frame->document().getElementById("whitespace");
+ element = web_element.to<WebFormControlElement>();
+ FormField result3;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_NONE, &result3);
+ expected.name = ASCIIToUTF16("whitespace");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.autocomplete_type = string16();
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, result3);
+
+ // Common case: exactly one type specified.
+ web_element = frame->document().getElementById("regular");
+ element = web_element.to<WebFormControlElement>();
+ FormField result4;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_NONE, &result4);
+ expected.name = ASCIIToUTF16("regular");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.autocomplete_type = ASCIIToUTF16("email");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, result4);
+
+ // Verify that we correctly extract fallback types as well.
+ web_element = frame->document().getElementById("multi-valued");
+ element = web_element.to<WebFormControlElement>();
+ FormField result5;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_NONE, &result5);
+ expected.name = ASCIIToUTF16("multi-valued");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.autocomplete_type = ASCIIToUTF16("x-confirm-email email");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, result5);
+
+ // The attribute is not yet part of the HTML standard, so we only recognize
+ // the prefixed version -- 'x-autocompletetype' -- and not the unprefixed one.
+ web_element = frame->document().getElementById("unprefixed");
+ element = web_element.to<WebFormControlElement>();
+ FormField result6;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_NONE, &result6);
+ expected.name = ASCIIToUTF16("unprefixed");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.autocomplete_type = string16();
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, result6);
+
+ // <select> elements should behave no differently from text fields here.
+ web_element = frame->document().getElementById("select");
+ element = web_element.to<WebFormControlElement>();
+ FormField result7;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_NONE, &result7);
+ expected.name = ASCIIToUTF16("select");
+ expected.form_control_type = ASCIIToUTF16("select-one");
+ expected.autocomplete_type = ASCIIToUTF16("state");
+ expected.max_length = 0;
+ EXPECT_FORM_FIELD_EQUALS(expected, result7);
+
+ // Very long attribute values should be replaced by a default string, to
+ // prevent malicious websites from DOSing the browser process.
+ web_element = frame->document().getElementById("malicious");
+ element = web_element.to<WebFormControlElement>();
+ FormField result8;
+ WebFormControlElementToFormField(element, autofill::EXTRACT_NONE, &result8);
+ expected.name = ASCIIToUTF16("malicious");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.autocomplete_type = ASCIIToUTF16("x-max-data-length-exceeded");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, result8);
+}
+
+TEST_F(FormManagerTest, WebFormElementToFormData) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <LABEL for=\"firstname\">First name:</LABEL>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <LABEL for=\"lastname\">Last name:</LABEL>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <LABEL for=\"state\">State:</LABEL>"
+ " <SELECT id=\"state\"/>"
+ " <OPTION value=\"CA\">California</OPTION>"
+ " <OPTION value=\"TX\">Texas</OPTION>"
+ " </SELECT>"
+ // The below inputs should be ignored
+ " <LABEL for=\"notvisible\">Hidden:</LABEL>"
+ " <INPUT type=\"hidden\" id=\"notvisible\" value=\"apple\"/>"
+ " <LABEL for=\"password\">Password:</LABEL>"
+ " <INPUT type=\"password\" id=\"password\" value=\"secret\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ WebVector<WebFormElement> forms;
+ frame->document().forms(forms);
+ ASSERT_EQ(1U, forms.size());
+
+ WebElement element = frame->document().getElementById("firstname");
+ WebInputElement input_element = element.to<WebInputElement>();
+
+ FormData form;
+ FormField field;
+ EXPECT_TRUE(WebFormElementToFormData(forms[0],
+ input_element,
+ autofill::REQUIRE_NONE,
+ autofill::EXTRACT_VALUE,
+ &form,
+ &field));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://cnn.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+
+ FormField expected;
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("John");
+ expected.label = ASCIIToUTF16("First name:");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Smith");
+ expected.label = ASCIIToUTF16("Last name:");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("state");
+ expected.value = ASCIIToUTF16("CA");
+ expected.label = ASCIIToUTF16("State:");
+ expected.form_control_type = ASCIIToUTF16("select-one");
+ expected.max_length = 0;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+}
+
+TEST_F(FormManagerTest, ExtractForms) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " First name: <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " Last name: <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " Email: <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, ExtractMultipleForms) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>"
+ "<FORM name=\"TestForm2\" action=\"http://zoo.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"Jack\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Adams\"/>"
+ " <INPUT type=\"text\" id=\"email\" value=\"jack@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(2U, forms.size());
+
+ // First form.
+ const FormData& form = forms[0];
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://cnn.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("John");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Smith");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ expected.value = ASCIIToUTF16("john@example.com");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ // Second form.
+ const FormData& form2 = forms[1];
+ EXPECT_EQ(ASCIIToUTF16("TestForm2"), form2.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
+ EXPECT_EQ(GURL("http://zoo.com"), form2.action);
+
+ const std::vector<FormField>& fields2 = form2.fields;
+ ASSERT_EQ(3U, fields2.size());
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("Jack");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Adams");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ expected.value = ASCIIToUTF16("jack@example.com");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[2]);
+}
+
+// We should not extract a form if it has too few fillable fields.
+TEST_F(FormManagerTest, ExtractFormsTooFewFields) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ EXPECT_EQ(0U, forms.size());
+}
+
+TEST_F(FormManagerTest, WebFormElementToFormDataAutocomplete) {
+ {
+ // Form is not auto-completable due to autocomplete=off.
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\""
+ " autocomplete=off>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ WebVector<WebFormElement> web_forms;
+ web_frame->document().forms(web_forms);
+ ASSERT_EQ(1U, web_forms.size());
+ WebFormElement web_form = web_forms[0];
+
+ FormData form;
+ EXPECT_TRUE(WebFormElementToFormData(
+ web_form, WebFormControlElement(), autofill::REQUIRE_NONE,
+ autofill::EXTRACT_NONE, &form, NULL));
+ EXPECT_FALSE(WebFormElementToFormData(
+ web_form, WebFormControlElement(), autofill::REQUIRE_AUTOCOMPLETE,
+ autofill::EXTRACT_NONE, &form, NULL));
+ }
+
+ {
+ // The firstname element is not auto-completable due to autocomplete=off.
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://abc.com\" "
+ " method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\""
+ " autocomplete=off>"
+ " <INPUT type=\"text\" id=\"middlename\" value=\"Jack\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ WebVector<WebFormElement> web_forms;
+ web_frame->document().forms(web_forms);
+ ASSERT_EQ(1U, web_forms.size());
+ WebFormElement web_form = web_forms[0];
+
+ FormData form;
+ EXPECT_TRUE(WebFormElementToFormData(
+ web_form, WebFormControlElement(), autofill::REQUIRE_AUTOCOMPLETE,
+ autofill::EXTRACT_VALUE, &form, NULL));
+
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://abc.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("middlename");
+ expected.value = ASCIIToUTF16("Jack");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Smith");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ expected.value = ASCIIToUTF16("john@example.com");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+ }
+}
+
+TEST_F(FormManagerTest, FindForm) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Get the input element we want to find.
+ WebElement element = web_frame->document().getElementById("firstname");
+ WebInputElement input_element = element.to<WebInputElement>();
+
+ // Find the form and verify it's the correct form.
+ FormData form;
+ FormField field;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form,
+ &field));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("John");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+ EXPECT_FORM_FIELD_EQUALS(expected, field);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Smith");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ expected.value = ASCIIToUTF16("john@example.com");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+}
+
+TEST_F(FormManagerTest, FillForm) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"hidden\" id=\"imhidden\"/>"
+ " <INPUT type=\"text\" id=\"notempty\" value=\"Hi\"/>"
+ " <INPUT type=\"text\" autocomplete=\"off\" id=\"noautocomplete\"/>"
+ " <INPUT type=\"text\" disabled=\"disabled\" id=\"notenabled\"/>"
+ " <INPUT type=\"text\" readonly id=\"readonly\"/>"
+ " <INPUT type=\"text\" style=\"visibility: hidden\""
+ " id=\"invisible\"/>"
+ " <INPUT type=\"text\" style=\"display: none\" id=\"displaynone\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Get the input element we want to find.
+ WebElement element = web_frame->document().getElementById("firstname");
+ WebInputElement input_element = element.to<WebInputElement>();
+
+ // Find the form that contains the input element.
+ FormData form;
+ FormField field;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form,
+ &field));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(8U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("notempty");
+ expected.value = ASCIIToUTF16("Hi");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ expected.name = ASCIIToUTF16("noautocomplete");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[3]);
+
+ expected.name = ASCIIToUTF16("notenabled");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[4]);
+
+ expected.name = ASCIIToUTF16("readonly");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[5]);
+
+ expected.name = ASCIIToUTF16("invisible");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[6]);
+
+ expected.name = ASCIIToUTF16("displaynone");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[7]);
+
+ // Fill the form.
+ form.fields[0].value = ASCIIToUTF16("Wyatt");
+ form.fields[1].value = ASCIIToUTF16("Earp");
+ form.fields[2].value = ASCIIToUTF16("Alpha");
+ form.fields[3].value = ASCIIToUTF16("Beta");
+ form.fields[4].value = ASCIIToUTF16("Gamma");
+ form.fields[5].value = ASCIIToUTF16("Delta");
+ form.fields[6].value = ASCIIToUTF16("Epsilon");
+ form.fields[7].value = ASCIIToUTF16("Zeta");
+ FillForm(form, input_element);
+
+ // Verify the filled elements.
+ WebDocument document = web_frame->document();
+ WebInputElement firstname =
+ document.getElementById("firstname").to<WebInputElement>();
+ EXPECT_TRUE(firstname.isAutofilled());
+ EXPECT_EQ(ASCIIToUTF16("Wyatt"), firstname.value());
+ EXPECT_EQ(5, firstname.selectionStart());
+ EXPECT_EQ(5, firstname.selectionEnd());
+
+ WebInputElement lastname =
+ document.getElementById("lastname").to<WebInputElement>();
+ EXPECT_TRUE(lastname.isAutofilled());
+ EXPECT_EQ(ASCIIToUTF16("Earp"), lastname.value());
+
+ // Non-empty fields are not filled.
+ WebInputElement notempty =
+ document.getElementById("notempty").to<WebInputElement>();
+ EXPECT_FALSE(notempty.isAutofilled());
+ EXPECT_EQ(ASCIIToUTF16("Hi"), notempty.value());
+
+ // autocomplete=off fields are not filled.
+ WebInputElement noautocomplete =
+ document.getElementById("noautocomplete").to<WebInputElement>();
+ EXPECT_FALSE(noautocomplete.isAutofilled());
+ EXPECT_TRUE(noautocomplete.value().isEmpty());
+
+ // Disabled fields are not filled.
+ WebInputElement notenabled =
+ document.getElementById("notenabled").to<WebInputElement>();
+ EXPECT_FALSE(notenabled.isAutofilled());
+ EXPECT_TRUE(notenabled.value().isEmpty());
+
+ // Read-only fields are not filled.
+ WebInputElement readonly =
+ document.getElementById("readonly").to<WebInputElement>();
+ EXPECT_FALSE(readonly.isAutofilled());
+ EXPECT_TRUE(readonly.value().isEmpty());
+
+ // |visibility:hidden| fields are not filled.
+ WebInputElement invisible =
+ document.getElementById("invisible").to<WebInputElement>();
+ EXPECT_FALSE(invisible.isAutofilled());
+ EXPECT_TRUE(invisible.value().isEmpty());
+
+ // |display:none| fields are not filled.
+ WebInputElement display_none =
+ document.getElementById("displaynone").to<WebInputElement>();
+ EXPECT_FALSE(display_none.isAutofilled());
+ EXPECT_TRUE(display_none.value().isEmpty());
+}
+
+TEST_F(FormManagerTest, PreviewForm) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"text\" id=\"notempty\" value=\"Hi\"/>"
+ " <INPUT type=\"text\" autocomplete=\"off\" id=\"noautocomplete\"/>"
+ " <INPUT type=\"text\" disabled=\"disabled\" id=\"notenabled\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Get the input element we want to find.
+ WebElement element = web_frame->document().getElementById("firstname");
+ WebInputElement input_element = element.to<WebInputElement>();
+
+ // Find the form that contains the input element.
+ FormData form;
+ FormField field;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form,
+ &field));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(5U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("notempty");
+ expected.value = ASCIIToUTF16("Hi");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ expected.name = ASCIIToUTF16("noautocomplete");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[3]);
+
+ expected.name = ASCIIToUTF16("notenabled");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[4]);
+
+ // Preview the form.
+ form.fields[0].value = ASCIIToUTF16("Wyatt");
+ form.fields[1].value = ASCIIToUTF16("Earp");
+ form.fields[2].value = ASCIIToUTF16("Alpha");
+ form.fields[3].value = ASCIIToUTF16("Beta");
+ form.fields[4].value = ASCIIToUTF16("Gamma");
+ PreviewForm(form, input_element);
+
+ // Verify the previewed elements.
+ WebDocument document = web_frame->document();
+ WebInputElement firstname =
+ document.getElementById("firstname").to<WebInputElement>();
+ EXPECT_TRUE(firstname.isAutofilled());
+ EXPECT_EQ(ASCIIToUTF16("Wyatt"), firstname.suggestedValue());
+ EXPECT_EQ(0, firstname.selectionStart());
+ EXPECT_EQ(5, firstname.selectionEnd());
+
+ WebInputElement lastname =
+ document.getElementById("lastname").to<WebInputElement>();
+ EXPECT_TRUE(lastname.isAutofilled());
+ EXPECT_EQ(ASCIIToUTF16("Earp"), lastname.suggestedValue());
+
+ // Non-empty fields are not previewed.
+ WebInputElement notempty =
+ document.getElementById("notempty").to<WebInputElement>();
+ EXPECT_FALSE(notempty.isAutofilled());
+ EXPECT_TRUE(notempty.suggestedValue().isEmpty());
+
+ // autocomplete=off fields are not previewed.
+ WebInputElement noautocomplete =
+ document.getElementById("noautocomplete").to<WebInputElement>();
+ EXPECT_FALSE(noautocomplete.isAutofilled());
+ EXPECT_TRUE(noautocomplete.suggestedValue().isEmpty());
+
+ // Disabled fields are not previewed.
+ WebInputElement notenabled =
+ document.getElementById("notenabled").to<WebInputElement>();
+ EXPECT_FALSE(notenabled.isAutofilled());
+ EXPECT_TRUE(notenabled.suggestedValue().isEmpty());
+}
+
+TEST_F(FormManagerTest, Labels) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <LABEL for=\"firstname\"> First name: </LABEL>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <LABEL for=\"lastname\"> Last name: </LABEL>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <LABEL for=\"email\"> Email: </LABEL>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsWithSpans) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <LABEL for=\"firstname\"><span>First name: </span></LABEL>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <LABEL for=\"lastname\"><span>Last name: </span></LABEL>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <LABEL for=\"email\"><span>Email: </span></LABEL>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+// This test is different from FormManagerTest.Labels in that the label elements
+// for= attribute is set to the name of the form control element it is a label
+// for instead of the id of the form control element. This is invalid because
+// the for= attribute must be set to the id of the form control element;
+// however, current label parsing code will extract the text from the previous
+// label element and apply it to the following input field.
+TEST_F(FormManagerTest, InvalidLabels) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <LABEL for=\"firstname\"> First name: </LABEL>"
+ " <INPUT type=\"text\" name=\"firstname\" value=\"John\"/>"
+ " <LABEL for=\"lastname\"> Last name: </LABEL>"
+ " <INPUT type=\"text\" name=\"lastname\" value=\"Smith\"/>"
+ " <LABEL for=\"email\"> Email: </LABEL>"
+ " <INPUT type=\"text\" name=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+// This test has three form control elements, only one of which has a label
+// element associated with it.
+TEST_F(FormManagerTest, OneLabelElement) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " First name:"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <LABEL for=\"lastname\">Last name: </LABEL>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " Email:"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromText) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " First name:"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " Last name:"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " Email:"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromParagraph) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <P>First name:</P><INPUT type=\"text\" "
+ " id=\"firstname\" value=\"John\"/>"
+ " <P>Last name:</P>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <P>Email:</P>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromBold) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <B>First name:</B><INPUT type=\"text\" "
+ " id=\"firstname\" value=\"John\"/>"
+ " <B>Last name:</B>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <B>Email:</B>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsInferredPriorToImgOrBr) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " First name:<IMG/><INPUT type=\"text\" "
+ " id=\"firstname\" value=\"John\"/>"
+ " Last name:<IMG/>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " Email:<BR/>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromTableCell) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<TABLE>"
+ " <TR>"
+ " <TD>First name:</TD>"
+ " <TD><INPUT type=\"text\" id=\"firstname\" value=\"John\"/></TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>Last name:</TD>"
+ " <TD><INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/></TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>Email:</TD>"
+ " <TD><INPUT type=\"text\" id=\"email\""
+ " value=\"john@example.com\"/></TD>"
+ " </TR>"
+ " <TR>"
+ " <TD></TD>"
+ " <TD>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </TD>"
+ " </TR>"
+ "</TABLE>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromTableCellTH) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<TABLE>"
+ " <TR>"
+ " <TH>First name:</TH>"
+ " <TD><INPUT type=\"text\" id=\"firstname\" value=\"John\"/></TD>"
+ " </TR>"
+ " <TR>"
+ " <TH>Last name:</TH>"
+ " <TD><INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/></TD>"
+ " </TR>"
+ " <TR>"
+ " <TH>Email:</TH>"
+ " <TD><INPUT type=\"text\" id=\"email\""
+ " value=\"john@example.com\"/></TD>"
+ " </TR>"
+ " <TR>"
+ " <TD></TD>"
+ " <TD>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </TD>"
+ " </TR>"
+ "</TABLE>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromTableCellNested) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("First name: Bogus"));
+ names.push_back(ASCIIToUTF16("firstname"));
+ values.push_back(ASCIIToUTF16("John"));
+
+ labels.push_back(ASCIIToUTF16("Last name:"));
+ names.push_back(ASCIIToUTF16("lastname"));
+ values.push_back(ASCIIToUTF16("Smith"));
+
+ labels.push_back(ASCIIToUTF16("Email:"));
+ names.push_back(ASCIIToUTF16("email"));
+ values.push_back(ASCIIToUTF16("john@example.com"));
+
+ ExpectLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<TABLE>"
+ " <TR>"
+ " <TD>"
+ " <FONT>"
+ " First name:"
+ " </FONT>"
+ " <FONT>"
+ " Bogus"
+ " </FONT>"
+ " </TD>"
+ " <TD>"
+ " <FONT>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " </FONT>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <FONT>"
+ " Last name:"
+ " </FONT>"
+ " </TD>"
+ " <TD>"
+ " <FONT>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " </FONT>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <FONT>"
+ " Email:"
+ " </FONT>"
+ " </TD>"
+ " <TD>"
+ " <FONT>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " </FONT>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD></TD>"
+ " <TD>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </TD>"
+ " </TR>"
+ "</TABLE>"
+ "</FORM>",
+ labels, names, values);
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromTableEmptyTDs) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("* First Name"));
+ names.push_back(ASCIIToUTF16("firstname"));
+ values.push_back(ASCIIToUTF16("John"));
+
+ labels.push_back(ASCIIToUTF16("* Last Name"));
+ names.push_back(ASCIIToUTF16("lastname"));
+ values.push_back(ASCIIToUTF16("Smith"));
+
+ labels.push_back(ASCIIToUTF16("* Email"));
+ names.push_back(ASCIIToUTF16("email"));
+ values.push_back(ASCIIToUTF16("john@example.com"));
+
+ ExpectLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<TABLE>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN>"
+ " <B>First Name</B>"
+ " </TD>"
+ " <TD></TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN>"
+ " <B>Last Name</B>"
+ " </TD>"
+ " <TD></TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN>"
+ " <B>Email</B>"
+ " </TD>"
+ " <TD></TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD></TD>"
+ " <TD>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </TD>"
+ " </TR>"
+ "</TABLE>"
+ "</FORM>",
+ labels, names, values);
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromPreviousTD) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("* First Name"));
+ names.push_back(ASCIIToUTF16("firstname"));
+ values.push_back(ASCIIToUTF16("John"));
+
+ labels.push_back(ASCIIToUTF16("* Last Name"));
+ names.push_back(ASCIIToUTF16("lastname"));
+ values.push_back(ASCIIToUTF16("Smith"));
+
+ labels.push_back(ASCIIToUTF16("* Email"));
+ names.push_back(ASCIIToUTF16("email"));
+ values.push_back(ASCIIToUTF16("john@example.com"));
+
+ ExpectLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<TABLE>"
+ " <TR>"
+ " <TD>* First Name</TD>"
+ " <TD>"
+ " Bogus"
+ " <INPUT type=\"hidden\"/>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>* Last Name</TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>* Email</TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD></TD>"
+ " <TD>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </TD>"
+ " </TR>"
+ "</TABLE>"
+ "</FORM>",
+ labels, names, values);
+}
+
+// <script>, <noscript> and <option> tags are excluded when the labels are
+// inferred.
+// Also <!-- comment --> is excluded.
+TEST_F(FormManagerTest, LabelsInferredFromTableWithSpecialElements) {
+ std::vector<string16> labels, names, values, control_types;
+
+ labels.push_back(ASCIIToUTF16("* First Name"));
+ names.push_back(ASCIIToUTF16("firstname"));
+ values.push_back(ASCIIToUTF16("John"));
+ control_types.push_back(ASCIIToUTF16("text"));
+
+ labels.push_back(ASCIIToUTF16("* Middle Name"));
+ names.push_back(ASCIIToUTF16("middlename"));
+ values.push_back(ASCIIToUTF16("Joe"));
+ control_types.push_back(ASCIIToUTF16("text"));
+
+ labels.push_back(ASCIIToUTF16("* Last Name"));
+ names.push_back(ASCIIToUTF16("lastname"));
+ values.push_back(ASCIIToUTF16("Smith"));
+ control_types.push_back(ASCIIToUTF16("text"));
+
+ labels.push_back(ASCIIToUTF16("* Country"));
+ names.push_back(ASCIIToUTF16("country"));
+ values.push_back(ASCIIToUTF16("US"));
+ control_types.push_back(ASCIIToUTF16("select-one"));
+
+ labels.push_back(ASCIIToUTF16("* Email"));
+ names.push_back(ASCIIToUTF16("email"));
+ values.push_back(ASCIIToUTF16("john@example.com"));
+ control_types.push_back(ASCIIToUTF16("text"));
+
+ ExpectLabelsAndTypes(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<TABLE>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN>"
+ " <B>First Name</B>"
+ " </TD>"
+ " <TD>"
+ " <SCRIPT> <!-- function test() { alert('ignored as label'); } -->"
+ " </SCRIPT>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN>"
+ " <B>Middle Name</B>"
+ " </TD>"
+ " <TD>"
+ " <NOSCRIPT>"
+ " <P>Bad</P>"
+ " </NOSCRIPT>"
+ " <INPUT type=\"text\" id=\"middlename\" value=\"Joe\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN>"
+ " <B>Last Name</B>"
+ " </TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN>"
+ " <B>Country</B>"
+ " </TD>"
+ " <TD>"
+ " <SELECT id=\"country\">"
+ " <OPTION VALUE=\"US\">The value should be ignored as label."
+ " </OPTION>"
+ " <OPTION VALUE=\"JP\">JAPAN</OPTION>"
+ " </SELECT>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN>"
+ " <B>Email</B>"
+ " </TD>"
+ " <TD>"
+ " <!-- This comment should be ignored as inferred label.-->"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD></TD>"
+ " <TD>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </TD>"
+ " </TR>"
+ "</TABLE>"
+ "</FORM>",
+ labels, names, values, control_types);
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromTableLabels) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<TABLE>"
+ " <TR>"
+ " <TD>"
+ " <LABEL>First name:</LABEL>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <LABEL>Last name:</LABEL>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <LABEL>Email:</LABEL>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " </TD>"
+ " </TR>"
+ "</TABLE>"
+ "<INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromTableTDInterveningElements) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<TABLE>"
+ " <TR>"
+ " <TD>"
+ " First name:"
+ " <BR>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " Last name:"
+ " <BR>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " Email:"
+ " <BR>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " </TD>"
+ " </TR>"
+ "</TABLE>"
+ "<INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+}
+
+// Verify that we correctly infer labels when the label text spans multiple
+// adjacent HTML elements, not separated by whitespace.
+TEST_F(FormManagerTest, LabelsInferredFromTableAdjacentElements) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("*First Name"));
+ names.push_back(ASCIIToUTF16("firstname"));
+ values.push_back(ASCIIToUTF16("John"));
+
+ labels.push_back(ASCIIToUTF16("*Last Name"));
+ names.push_back(ASCIIToUTF16("lastname"));
+ values.push_back(ASCIIToUTF16("Smith"));
+
+ labels.push_back(ASCIIToUTF16("*Email"));
+ names.push_back(ASCIIToUTF16("email"));
+ values.push_back(ASCIIToUTF16("john@example.com"));
+
+ ExpectLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<TABLE>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN><B>First Name</B>"
+ " </TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN><B>Last Name</B>"
+ " </TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <SPAN>*</SPAN><B>Email</B>"
+ " </TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </TD>"
+ " </TR>"
+ "</TABLE>"
+ "</FORM>",
+ labels, names, values);
+}
+
+// Verify that we correctly infer labels when the label text resides in the
+// previous row.
+TEST_F(FormManagerTest, LabelsInferredFromTableRow) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("*First Name *Last Name *Email"));
+ names.push_back(ASCIIToUTF16("firstname"));
+ values.push_back(ASCIIToUTF16("John"));
+
+ labels.push_back(ASCIIToUTF16("*First Name *Last Name *Email"));
+ names.push_back(ASCIIToUTF16("lastname"));
+ values.push_back(ASCIIToUTF16("Smith"));
+
+ labels.push_back(ASCIIToUTF16("*First Name *Last Name *Email"));
+ names.push_back(ASCIIToUTF16("email"));
+ values.push_back(ASCIIToUTF16("john@example.com"));
+
+ ExpectLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<TABLE>"
+ " <TR>"
+ " <TD>*First Name</TD>"
+ " <TD>*Last Name</TD>"
+ " <TD>*Email</TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " </TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " </TD>"
+ " <TD>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " </TD>"
+ " </TR>"
+ " <TR>"
+ " <TD>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </TD>"
+ " </TR>"
+ "</TABLE>",
+ labels, names, values);
+}
+
+// Verify that we correctly infer labels when enclosed within a list item.
+TEST_F(FormManagerTest, LabelsInferredFromListItem) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("* Home Phone"));
+ names.push_back(ASCIIToUTF16("areacode"));
+ values.push_back(ASCIIToUTF16("415"));
+
+ labels.push_back(ASCIIToUTF16("* Home Phone"));
+ names.push_back(ASCIIToUTF16("prefix"));
+ values.push_back(ASCIIToUTF16("555"));
+
+ labels.push_back(ASCIIToUTF16("* Home Phone"));
+ names.push_back(ASCIIToUTF16("suffix"));
+ values.push_back(ASCIIToUTF16("1212"));
+
+ ExpectLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<DIV>"
+ " <LI>"
+ " <SPAN>Bogus</SPAN>"
+ " </LI>"
+ " <LI>"
+ " <LABEL><EM>*</EM> Home Phone</LABEL>"
+ " <INPUT type=\"text\" id=\"areacode\" value=\"415\"/>"
+ " <INPUT type=\"text\" id=\"prefix\" value=\"555\"/>"
+ " <INPUT type=\"text\" id=\"suffix\" value=\"1212\"/>"
+ " </LI>"
+ " <LI>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </LI>"
+ "</DIV>"
+ "</FORM>",
+ labels, names, values);
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromDefinitionList) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("* First name: Bogus"));
+ names.push_back(ASCIIToUTF16("firstname"));
+ values.push_back(ASCIIToUTF16("John"));
+
+ labels.push_back(ASCIIToUTF16("Last name:"));
+ names.push_back(ASCIIToUTF16("lastname"));
+ values.push_back(ASCIIToUTF16("Smith"));
+
+ labels.push_back(ASCIIToUTF16("Email:"));
+ names.push_back(ASCIIToUTF16("email"));
+ values.push_back(ASCIIToUTF16("john@example.com"));
+
+ ExpectLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<DL>"
+ " <DT>"
+ " <SPAN>"
+ " *"
+ " </SPAN>"
+ " <SPAN>"
+ " First name:"
+ " </SPAN>"
+ " <SPAN>"
+ " Bogus"
+ " </SPAN>"
+ " </DT>"
+ " <DD>"
+ " <FONT>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " </FONT>"
+ " </DD>"
+ " <DT>"
+ " <SPAN>"
+ " Last name:"
+ " </SPAN>"
+ " </DT>"
+ " <DD>"
+ " <FONT>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " </FONT>"
+ " </DD>"
+ " <DT>"
+ " <SPAN>"
+ " Email:"
+ " </SPAN>"
+ " </DT>"
+ " <DD>"
+ " <FONT>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " </FONT>"
+ " </DD>"
+ " <DT></DT>"
+ " <DD>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </DD>"
+ "</DL>"
+ "</FORM>",
+ labels, names, values);
+}
+
+TEST_F(FormManagerTest, LabelsInferredWithSameName) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("Address Line 1:"));
+ names.push_back(ASCIIToUTF16("Address"));
+ values.push_back(string16());
+
+ labels.push_back(ASCIIToUTF16("Address Line 2:"));
+ names.push_back(ASCIIToUTF16("Address"));
+ values.push_back(string16());
+
+ labels.push_back(ASCIIToUTF16("Address Line 3:"));
+ names.push_back(ASCIIToUTF16("Address"));
+ values.push_back(string16());
+
+ ExpectLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " Address Line 1:"
+ " <INPUT type=\"text\" name=\"Address\"/>"
+ " Address Line 2:"
+ " <INPUT type=\"text\" name=\"Address\"/>"
+ " Address Line 3:"
+ " <INPUT type=\"text\" name=\"Address\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>",
+ labels, names, values);
+}
+
+TEST_F(FormManagerTest, LabelsInferredWithImageTags) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("Phone:"));
+ names.push_back(ASCIIToUTF16("dayphone1"));
+ values.push_back(string16());
+
+ labels.push_back(ASCIIToUTF16("-"));
+ names.push_back(ASCIIToUTF16("dayphone2"));
+ values.push_back(string16());
+
+ labels.push_back(ASCIIToUTF16("-"));
+ names.push_back(ASCIIToUTF16("dayphone3"));
+ values.push_back(string16());
+
+ labels.push_back(ASCIIToUTF16("ext.:"));
+ names.push_back(ASCIIToUTF16("dayphone4"));
+ values.push_back(string16());
+
+ labels.push_back(string16());
+ names.push_back(ASCIIToUTF16("dummy"));
+ values.push_back(string16());
+
+ ExpectLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " Phone:"
+ " <input type=\"text\" name=\"dayphone1\">"
+ " <img/>"
+ " -"
+ " <img/>"
+ " <input type=\"text\" name=\"dayphone2\">"
+ " <img/>"
+ " -"
+ " <img/>"
+ " <input type=\"text\" name=\"dayphone3\">"
+ " ext.:"
+ " <input type=\"text\" name=\"dayphone4\">"
+ " <input type=\"text\" name=\"dummy\">"
+ " <input type=\"submit\" name=\"reply-send\" value=\"Send\">"
+ "</FORM>",
+ labels, names, values);
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromDivTable) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<DIV>First name:<BR>"
+ " <SPAN>"
+ " <INPUT type=\"text\" name=\"firstname\" value=\"John\">"
+ " </SPAN>"
+ "</DIV>"
+ "<DIV>Last name:<BR>"
+ " <SPAN>"
+ " <INPUT type=\"text\" name=\"lastname\" value=\"Smith\">"
+ " </SPAN>"
+ "</DIV>"
+ "<DIV>Email:<BR>"
+ " <SPAN>"
+ " <INPUT type=\"text\" name=\"email\" value=\"john@example.com\">"
+ " </SPAN>"
+ "</DIV>"
+ "<input type=\"submit\" name=\"reply-send\" value=\"Send\">"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromDivSiblingTable) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<DIV>First name:</DIV>"
+ "<DIV>"
+ " <SPAN>"
+ " <INPUT type=\"text\" name=\"firstname\" value=\"John\">"
+ " </SPAN>"
+ "</DIV>"
+ "<DIV>Last name:</DIV>"
+ "<DIV>"
+ " <SPAN>"
+ " <INPUT type=\"text\" name=\"lastname\" value=\"Smith\">"
+ " </SPAN>"
+ "</DIV>"
+ "<DIV>Email:</DIV>"
+ "<DIV>"
+ " <SPAN>"
+ " <INPUT type=\"text\" name=\"email\" value=\"john@example.com\">"
+ " </SPAN>"
+ "</DIV>"
+ "<input type=\"submit\" name=\"reply-send\" value=\"Send\">"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, LabelsInferredFromDefinitionListRatherThanDivTable) {
+ ExpectJohnSmithLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ "<DIV>This is not a label.<BR>"
+ "<DL>"
+ " <DT>"
+ " <SPAN>"
+ " First name:"
+ " </SPAN>"
+ " </DT>"
+ " <DD>"
+ " <FONT>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " </FONT>"
+ " </DD>"
+ " <DT>"
+ " <SPAN>"
+ " Last name:"
+ " </SPAN>"
+ " </DT>"
+ " <DD>"
+ " <FONT>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " </FONT>"
+ " </DD>"
+ " <DT>"
+ " <SPAN>"
+ " Email:"
+ " </SPAN>"
+ " </DT>"
+ " <DD>"
+ " <FONT>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " </FONT>"
+ " </DD>"
+ " <DT></DT>"
+ " <DD>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ " </DD>"
+ "</DL>"
+ "</DIV>"
+ "</FORM>");
+}
+
+TEST_F(FormManagerTest, FillFormMaxLength) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" maxlength=\"5\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" maxlength=\"7\"/>"
+ " <INPUT type=\"text\" id=\"email\" maxlength=\"9\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Get the input element we want to find.
+ WebElement element = web_frame->document().getElementById("firstname");
+ WebInputElement input_element = element.to<WebInputElement>();
+
+ // Find the form that contains the input element.
+ FormData form;
+ FormField field;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form,
+ &field));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.max_length = 5;
+ expected.is_autofilled = false;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.max_length = 7;
+ expected.is_autofilled = false;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ expected.max_length = 9;
+ expected.is_autofilled = false;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ // Fill the form.
+ form.fields[0].value = ASCIIToUTF16("Brother");
+ form.fields[1].value = ASCIIToUTF16("Jonathan");
+ form.fields[2].value = ASCIIToUTF16("brotherj@example.com");
+ FillForm(form, input_element);
+
+ // Find the newly-filled form that contains the input element.
+ FormData form2;
+ FormField field2;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form2,
+ &field2));
+
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form2.action);
+
+ const std::vector<FormField>& fields2 = form2.fields;
+ ASSERT_EQ(3U, fields2.size());
+
+ expected.form_control_type = ASCIIToUTF16("text");
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("Broth");
+ expected.max_length = 5;
+ expected.is_autofilled = true;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Jonatha");
+ expected.max_length = 7;
+ expected.is_autofilled = true;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ expected.value = ASCIIToUTF16("brotherj@");
+ expected.max_length = 9;
+ expected.is_autofilled = true;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[2]);
+}
+
+// This test uses negative values of the maxlength attribute for input elements.
+// In this case, the maxlength of the input elements is set to the default
+// maxlength (defined in WebKit.)
+TEST_F(FormManagerTest, FillFormNegativeMaxLength) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" maxlength=\"-1\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" maxlength=\"-10\"/>"
+ " <INPUT type=\"text\" id=\"email\" maxlength=\"-13\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Get the input element we want to find.
+ WebElement element = web_frame->document().getElementById("firstname");
+ WebInputElement input_element = element.to<WebInputElement>();
+
+ // Find the form that contains the input element.
+ FormData form;
+ FormField field;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form,
+ &field));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("firstname");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ // Fill the form.
+ form.fields[0].value = ASCIIToUTF16("Brother");
+ form.fields[1].value = ASCIIToUTF16("Jonathan");
+ form.fields[2].value = ASCIIToUTF16("brotherj@example.com");
+ FillForm(form, input_element);
+
+ // Find the newly-filled form that contains the input element.
+ FormData form2;
+ FormField field2;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form2,
+ &field2));
+
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form2.action);
+
+ const std::vector<FormField>& fields2 = form2.fields;
+ ASSERT_EQ(3U, fields2.size());
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("Brother");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Jonathan");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ expected.value = ASCIIToUTF16("brotherj@example.com");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+}
+
+TEST_F(FormManagerTest, FillFormEmptyName) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"text\" id=\"email\"/>"
+ " <INPUT type=\"submit\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Get the input element we want to find.
+ WebElement element = web_frame->document().getElementById("firstname");
+ WebInputElement input_element = element.to<WebInputElement>();
+
+ // Find the form that contains the input element.
+ FormData form;
+ FormField field;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form,
+ &field));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("firstname");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ // Fill the form.
+ form.fields[0].value = ASCIIToUTF16("Wyatt");
+ form.fields[1].value = ASCIIToUTF16("Earp");
+ form.fields[2].value = ASCIIToUTF16("wyatt@example.com");
+ FillForm(form, input_element);
+
+ // Find the newly-filled form that contains the input element.
+ FormData form2;
+ FormField field2;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form2,
+ &field2));
+
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form2.action);
+
+ const std::vector<FormField>& fields2 = form2.fields;
+ ASSERT_EQ(3U, fields2.size());
+
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("Wyatt");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Earp");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ expected.value = ASCIIToUTF16("wyatt@example.com");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+}
+
+TEST_F(FormManagerTest, FillFormEmptyFormNames) {
+ LoadHTML("<FORM action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\"/>"
+ " <INPUT type=\"text\" id=\"middlename\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"submit\" value=\"Send\"/>"
+ "</FORM>"
+ "<FORM action=\"http://abc.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"apple\"/>"
+ " <INPUT type=\"text\" id=\"banana\"/>"
+ " <INPUT type=\"text\" id=\"cantelope\"/>"
+ " <INPUT type=\"submit\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(2U, forms.size());
+
+ // Get the input element we want to find.
+ WebElement element = web_frame->document().getElementById("apple");
+ WebInputElement input_element = element.to<WebInputElement>();
+
+ // Find the form that contains the input element.
+ FormData form;
+ FormField field;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form,
+ &field));
+ EXPECT_EQ(string16(), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://abc.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("apple");
+ expected.is_autofilled = false;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("banana");
+ expected.is_autofilled = false;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("cantelope");
+ expected.is_autofilled = false;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ // Fill the form.
+ form.fields[0].value = ASCIIToUTF16("Red");
+ form.fields[1].value = ASCIIToUTF16("Yellow");
+ form.fields[2].value = ASCIIToUTF16("Also Yellow");
+ FillForm(form, input_element);
+
+ // Find the newly-filled form that contains the input element.
+ FormData form2;
+ FormField field2;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form2,
+ &field2));
+
+ EXPECT_EQ(string16(), form2.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
+ EXPECT_EQ(GURL("http://abc.com"), form2.action);
+
+ const std::vector<FormField>& fields2 = form2.fields;
+ ASSERT_EQ(3U, fields2.size());
+
+ expected.name = ASCIIToUTF16("apple");
+ expected.value = ASCIIToUTF16("Red");
+ expected.is_autofilled = true;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[0]);
+
+ expected.name = ASCIIToUTF16("banana");
+ expected.value = ASCIIToUTF16("Yellow");
+ expected.is_autofilled = true;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[1]);
+
+ expected.name = ASCIIToUTF16("cantelope");
+ expected.value = ASCIIToUTF16("Also Yellow");
+ expected.is_autofilled = true;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[2]);
+}
+
+TEST_F(FormManagerTest, ThreePartPhone) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " Phone:"
+ " <input type=\"text\" name=\"dayphone1\">"
+ " -"
+ " <input type=\"text\" name=\"dayphone2\">"
+ " -"
+ " <input type=\"text\" name=\"dayphone3\">"
+ " ext.:"
+ " <input type=\"text\" name=\"dayphone4\">"
+ " <input type=\"submit\" name=\"reply-send\" value=\"Send\">"
+ "</FORM>");
+
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ WebVector<WebFormElement> forms;
+ frame->document().forms(forms);
+ ASSERT_EQ(1U, forms.size());
+
+ FormData form;
+ EXPECT_TRUE(WebFormElementToFormData(forms[0],
+ WebFormControlElement(),
+ autofill::REQUIRE_NONE,
+ autofill::EXTRACT_VALUE,
+ &form,
+ NULL));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://cnn.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(4U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.label = ASCIIToUTF16("Phone:");
+ expected.name = ASCIIToUTF16("dayphone1");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.label = ASCIIToUTF16("-");
+ expected.name = ASCIIToUTF16("dayphone2");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.label = ASCIIToUTF16("-");
+ expected.name = ASCIIToUTF16("dayphone3");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ expected.label = ASCIIToUTF16("ext.:");
+ expected.name = ASCIIToUTF16("dayphone4");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[3]);
+}
+
+
+TEST_F(FormManagerTest, MaxLengthFields) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " Phone:"
+ " <input type=\"text\" maxlength=\"3\" name=\"dayphone1\">"
+ " -"
+ " <input type=\"text\" maxlength=\"3\" name=\"dayphone2\">"
+ " -"
+ " <input type=\"text\" maxlength=\"4\" size=\"5\""
+ " name=\"dayphone3\">"
+ " ext.:"
+ " <input type=\"text\" maxlength=\"5\" name=\"dayphone4\">"
+ " <input type=\"text\" name=\"default1\">"
+ " <input type=\"text\" maxlength=\"-1\" name=\"invalid1\">"
+ " <input type=\"submit\" name=\"reply-send\" value=\"Send\">"
+ "</FORM>");
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ WebVector<WebFormElement> forms;
+ frame->document().forms(forms);
+ ASSERT_EQ(1U, forms.size());
+
+ FormData form;
+ EXPECT_TRUE(WebFormElementToFormData(forms[0],
+ WebFormControlElement(),
+ autofill::REQUIRE_NONE,
+ autofill::EXTRACT_VALUE,
+ &form,
+ NULL));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://cnn.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(6U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+
+ expected.label = ASCIIToUTF16("Phone:");
+ expected.name = ASCIIToUTF16("dayphone1");
+ expected.max_length = 3;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.label = ASCIIToUTF16("-");
+ expected.name = ASCIIToUTF16("dayphone2");
+ expected.max_length = 3;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.label = ASCIIToUTF16("-");
+ expected.name = ASCIIToUTF16("dayphone3");
+ expected.max_length = 4;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ expected.label = ASCIIToUTF16("ext.:");
+ expected.name = ASCIIToUTF16("dayphone4");
+ expected.max_length = 5;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[3]);
+
+ // When unspecified |size|, default is returned.
+ expected.label = string16();
+ expected.name = ASCIIToUTF16("default1");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[4]);
+
+ // When invalid |size|, default is returned.
+ expected.label = string16();
+ expected.name = ASCIIToUTF16("invalid1");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[5]);
+}
+
+// This test re-creates the experience of typing in a field then selecting a
+// profile from the Autofill suggestions popup. The field that is being typed
+// into should be filled even though it's not technically empty.
+TEST_F(FormManagerTest, FillFormNonEmptyField) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"text\" id=\"email\"/>"
+ " <INPUT type=\"submit\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Get the input element we want to find.
+ WebElement element = web_frame->document().getElementById("firstname");
+ WebInputElement input_element = element.to<WebInputElement>();
+
+ // Simulate typing by modifying the field value.
+ input_element.setValue(ASCIIToUTF16("Wy"));
+
+ // Find the form that contains the input element.
+ FormData form;
+ FormField field;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form,
+ &field));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("Wy");
+ expected.is_autofilled = false;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = string16();
+ expected.is_autofilled = false;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ expected.value = string16();
+ expected.is_autofilled = false;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ // Preview the form and verify that the cursor position has been updated.
+ form.fields[0].value = ASCIIToUTF16("Wyatt");
+ form.fields[1].value = ASCIIToUTF16("Earp");
+ form.fields[2].value = ASCIIToUTF16("wyatt@example.com");
+ PreviewForm(form, input_element);
+ EXPECT_EQ(2, input_element.selectionStart());
+ EXPECT_EQ(5, input_element.selectionEnd());
+
+ // Fill the form.
+ FillForm(form, input_element);
+
+ // Find the newly-filled form that contains the input element.
+ FormData form2;
+ FormField field2;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, &form2,
+ &field2));
+
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form2.action);
+
+ const std::vector<FormField>& fields2 = form2.fields;
+ ASSERT_EQ(3U, fields2.size());
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("Wyatt");
+ expected.is_autofilled = true;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Earp");
+ expected.is_autofilled = true;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[1]);
+
+ expected.name = ASCIIToUTF16("email");
+ expected.value = ASCIIToUTF16("wyatt@example.com");
+ expected.is_autofilled = true;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[2]);
+
+ // Verify that the cursor position has been updated.
+ EXPECT_EQ(5, input_element.selectionStart());
+ EXPECT_EQ(5, input_element.selectionEnd());
+}
+
+TEST_F(FormManagerTest, ClearFormWithNode) {
+ LoadHTML(
+ "<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"Wyatt\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Earp\"/>"
+ " <INPUT type=\"text\" autocomplete=\"off\" id=\"noAC\" value=\"one\"/>"
+ " <INPUT type=\"text\" id=\"notenabled\" disabled=\"disabled\">"
+ " <INPUT type=\"submit\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Set the auto-filled attribute on the firstname element.
+ WebInputElement firstname =
+ web_frame->document().getElementById("firstname").to<WebInputElement>();
+ firstname.setAutofilled(true);
+
+ // Set the value of the disabled attribute.
+ WebInputElement notenabled =
+ web_frame->document().getElementById("notenabled").to<WebInputElement>();
+ notenabled.setValue(WebString::fromUTF8("no clear"));
+
+ // Clear the form.
+ EXPECT_TRUE(form_cache.ClearFormWithElement(firstname));
+
+ // Verify that the auto-filled attribute has been turned off.
+ EXPECT_FALSE(firstname.isAutofilled());
+
+ // Verify the form is cleared.
+ FormData form2;
+ FormField field2;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(firstname, &form2,
+ &field2));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form2.action);
+
+ const std::vector<FormField>& fields2 = form2.fields;
+ ASSERT_EQ(4U, fields2.size());
+
+ FormField expected;
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[1]);
+
+ expected.name = ASCIIToUTF16("noAC");
+ expected.value = string16();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[2]);
+
+ expected.name = ASCIIToUTF16("notenabled");
+ expected.value = ASCIIToUTF16("no clear");
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[3]);
+
+ // Verify that the cursor position has been updated.
+ EXPECT_EQ(0, firstname.selectionStart());
+ EXPECT_EQ(0, firstname.selectionEnd());
+}
+
+TEST_F(FormManagerTest, ClearFormWithNodeContainingSelectOne) {
+ LoadHTML(
+ "<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"Wyatt\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Earp\"/>"
+ " <SELECT id=\"state\" name=\"state\">"
+ " <OPTION selected>?</OPTION>"
+ " <OPTION>AA</OPTION>"
+ " <OPTION>AE</OPTION>"
+ " <OPTION>AK</OPTION>"
+ " </SELECT>"
+ " <INPUT type=\"submit\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Set the auto-filled attribute on the firstname element.
+ WebInputElement firstname =
+ web_frame->document().getElementById("firstname").to<WebInputElement>();
+ firstname.setAutofilled(true);
+
+ // Set the value of the select-one.
+ WebSelectElement select_element =
+ web_frame->document().getElementById("state").to<WebSelectElement>();
+ select_element.setValue(WebString::fromUTF8("AK"));
+
+ // Clear the form.
+ EXPECT_TRUE(form_cache.ClearFormWithElement(firstname));
+
+ // Verify that the auto-filled attribute has been turned off.
+ EXPECT_FALSE(firstname.isAutofilled());
+
+ // Verify the form is cleared.
+ FormData form2;
+ FormField field2;
+ EXPECT_TRUE(FindFormAndFieldForFormControlElement(firstname, &form2,
+ &field2));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form2.action);
+
+ const std::vector<FormField>& fields2 = form2.fields;
+ ASSERT_EQ(3U, fields2.size());
+
+ FormField expected;
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = string16();
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = string16();
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[1]);
+
+ expected.name = ASCIIToUTF16("state");
+ expected.value = ASCIIToUTF16("?");
+ expected.form_control_type = ASCIIToUTF16("select-one");
+ expected.max_length = 0;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields2[2]);
+
+ // Verify that the cursor position has been updated.
+ EXPECT_EQ(0, firstname.selectionStart());
+ EXPECT_EQ(0, firstname.selectionEnd());
+}
+
+TEST_F(FormManagerTest, ClearPreviewedFormWithElement) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"Wyatt\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"text\" id=\"email\"/>"
+ " <INPUT type=\"email\" id=\"email2\"/>"
+ " <INPUT type=\"tel\" id=\"phone\"/>"
+ " <INPUT type=\"submit\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Set the auto-filled attribute.
+ WebInputElement firstname =
+ web_frame->document().getElementById("firstname").to<WebInputElement>();
+ firstname.setAutofilled(true);
+ WebInputElement lastname =
+ web_frame->document().getElementById("lastname").to<WebInputElement>();
+ lastname.setAutofilled(true);
+ WebInputElement email =
+ web_frame->document().getElementById("email").to<WebInputElement>();
+ email.setAutofilled(true);
+ WebInputElement email2 =
+ web_frame->document().getElementById("email2").to<WebInputElement>();
+ email2.setAutofilled(true);
+ WebInputElement phone =
+ web_frame->document().getElementById("phone").to<WebInputElement>();
+ phone.setAutofilled(true);
+
+ // Set the suggested values on two of the elements.
+ lastname.setSuggestedValue(ASCIIToUTF16("Earp"));
+ email.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com"));
+ email2.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com"));
+ phone.setSuggestedValue(ASCIIToUTF16("650-777-9999"));
+
+ // Clear the previewed fields.
+ EXPECT_TRUE(ClearPreviewedFormWithElement(lastname, false));
+
+ // Fields with empty suggestions suggestions are not modified.
+ EXPECT_EQ(ASCIIToUTF16("Wyatt"), firstname.value());
+ EXPECT_TRUE(firstname.suggestedValue().isEmpty());
+ EXPECT_TRUE(firstname.isAutofilled());
+
+ // Verify the previewed fields are cleared.
+ EXPECT_TRUE(lastname.value().isEmpty());
+ EXPECT_TRUE(lastname.suggestedValue().isEmpty());
+ EXPECT_FALSE(lastname.isAutofilled());
+ EXPECT_TRUE(email.value().isEmpty());
+ EXPECT_TRUE(email.suggestedValue().isEmpty());
+ EXPECT_FALSE(email.isAutofilled());
+ EXPECT_TRUE(email2.value().isEmpty());
+ EXPECT_TRUE(email2.suggestedValue().isEmpty());
+ EXPECT_FALSE(email2.isAutofilled());
+ EXPECT_TRUE(phone.value().isEmpty());
+ EXPECT_TRUE(phone.suggestedValue().isEmpty());
+ EXPECT_FALSE(phone.isAutofilled());
+
+ // Verify that the cursor position has been updated.
+ EXPECT_EQ(0, lastname.selectionStart());
+ EXPECT_EQ(0, lastname.selectionEnd());
+}
+
+TEST_F(FormManagerTest, ClearPreviewedFormWithNonEmptyInitiatingNode) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"W\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"text\" id=\"email\"/>"
+ " <INPUT type=\"email\" id=\"email2\"/>"
+ " <INPUT type=\"tel\" id=\"phone\"/>"
+ " <INPUT type=\"submit\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Set the auto-filled attribute.
+ WebInputElement firstname =
+ web_frame->document().getElementById("firstname").to<WebInputElement>();
+ firstname.setAutofilled(true);
+ WebInputElement lastname =
+ web_frame->document().getElementById("lastname").to<WebInputElement>();
+ lastname.setAutofilled(true);
+ WebInputElement email =
+ web_frame->document().getElementById("email").to<WebInputElement>();
+ email.setAutofilled(true);
+ WebInputElement email2 =
+ web_frame->document().getElementById("email2").to<WebInputElement>();
+ email2.setAutofilled(true);
+ WebInputElement phone =
+ web_frame->document().getElementById("phone").to<WebInputElement>();
+ phone.setAutofilled(true);
+
+
+ // Set the suggested values on all of the elements.
+ firstname.setSuggestedValue(ASCIIToUTF16("Wyatt"));
+ lastname.setSuggestedValue(ASCIIToUTF16("Earp"));
+ email.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com"));
+ email2.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com"));
+ phone.setSuggestedValue(ASCIIToUTF16("650-777-9999"));
+
+ // Clear the previewed fields.
+ EXPECT_TRUE(ClearPreviewedFormWithElement(firstname, false));
+
+ // Fields with non-empty values are restored.
+ EXPECT_EQ(ASCIIToUTF16("W"), firstname.value());
+ EXPECT_TRUE(firstname.suggestedValue().isEmpty());
+ EXPECT_FALSE(firstname.isAutofilled());
+ EXPECT_EQ(1, firstname.selectionStart());
+ EXPECT_EQ(1, firstname.selectionEnd());
+
+ // Verify the previewed fields are cleared.
+ EXPECT_TRUE(lastname.value().isEmpty());
+ EXPECT_TRUE(lastname.suggestedValue().isEmpty());
+ EXPECT_FALSE(lastname.isAutofilled());
+ EXPECT_TRUE(email.value().isEmpty());
+ EXPECT_TRUE(email.suggestedValue().isEmpty());
+ EXPECT_FALSE(email.isAutofilled());
+ EXPECT_TRUE(email2.value().isEmpty());
+ EXPECT_TRUE(email2.suggestedValue().isEmpty());
+ EXPECT_FALSE(email2.isAutofilled());
+ EXPECT_TRUE(phone.value().isEmpty());
+ EXPECT_TRUE(phone.suggestedValue().isEmpty());
+ EXPECT_FALSE(phone.isAutofilled());
+}
+
+TEST_F(FormManagerTest, ClearPreviewedFormWithAutofilledInitiatingNode) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"W\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"text\" id=\"email\"/>"
+ " <INPUT type=\"email\" id=\"email2\"/>"
+ " <INPUT type=\"tel\" id=\"phone\"/>"
+ " <INPUT type=\"submit\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Set the auto-filled attribute.
+ WebInputElement firstname =
+ web_frame->document().getElementById("firstname").to<WebInputElement>();
+ firstname.setAutofilled(true);
+ WebInputElement lastname =
+ web_frame->document().getElementById("lastname").to<WebInputElement>();
+ lastname.setAutofilled(true);
+ WebInputElement email =
+ web_frame->document().getElementById("email").to<WebInputElement>();
+ email.setAutofilled(true);
+ WebInputElement email2 =
+ web_frame->document().getElementById("email2").to<WebInputElement>();
+ email2.setAutofilled(true);
+ WebInputElement phone =
+ web_frame->document().getElementById("phone").to<WebInputElement>();
+ phone.setAutofilled(true);
+
+ // Set the suggested values on all of the elements.
+ firstname.setSuggestedValue(ASCIIToUTF16("Wyatt"));
+ lastname.setSuggestedValue(ASCIIToUTF16("Earp"));
+ email.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com"));
+ email2.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com"));
+ phone.setSuggestedValue(ASCIIToUTF16("650-777-9999"));
+
+ // Clear the previewed fields.
+ EXPECT_TRUE(ClearPreviewedFormWithElement(firstname, true));
+
+ // Fields with non-empty values are restored.
+ EXPECT_EQ(ASCIIToUTF16("W"), firstname.value());
+ EXPECT_TRUE(firstname.suggestedValue().isEmpty());
+ EXPECT_TRUE(firstname.isAutofilled());
+ EXPECT_EQ(1, firstname.selectionStart());
+ EXPECT_EQ(1, firstname.selectionEnd());
+
+ // Verify the previewed fields are cleared.
+ EXPECT_TRUE(lastname.value().isEmpty());
+ EXPECT_TRUE(lastname.suggestedValue().isEmpty());
+ EXPECT_FALSE(lastname.isAutofilled());
+ EXPECT_TRUE(email.value().isEmpty());
+ EXPECT_TRUE(email.suggestedValue().isEmpty());
+ EXPECT_FALSE(email.isAutofilled());
+ EXPECT_TRUE(email2.value().isEmpty());
+ EXPECT_TRUE(email2.suggestedValue().isEmpty());
+ EXPECT_FALSE(email2.isAutofilled());
+ EXPECT_TRUE(phone.value().isEmpty());
+ EXPECT_TRUE(phone.suggestedValue().isEmpty());
+ EXPECT_FALSE(phone.isAutofilled());
+}
+
+TEST_F(FormManagerTest, FormWithNodeIsAutofilled) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"Wyatt\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"text\" id=\"email\"/>"
+ " <INPUT type=\"email\" id=\"email2\"/>"
+ " <INPUT type=\"tel\" id=\"phone\"/>"
+ " <INPUT type=\"submit\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ WebInputElement firstname =
+ web_frame->document().getElementById("firstname").to<WebInputElement>();
+
+ // Auto-filled attribute not set yet.
+ EXPECT_FALSE(FormWithElementIsAutofilled(firstname));
+
+ // Set the auto-filled attribute.
+ firstname.setAutofilled(true);
+
+ EXPECT_TRUE(FormWithElementIsAutofilled(firstname));
+}
+
+// If we have multiple labels per id, the labels concatenated into label string.
+TEST_F(FormManagerTest, MultipleLabelsPerElement) {
+ std::vector<string16> labels, names, values;
+
+ labels.push_back(ASCIIToUTF16("First Name:"));
+ names.push_back(ASCIIToUTF16("firstname"));
+ values.push_back(ASCIIToUTF16("John"));
+
+ labels.push_back(ASCIIToUTF16("Last Name:"));
+ names.push_back(ASCIIToUTF16("lastname"));
+ values.push_back(ASCIIToUTF16("Smith"));
+
+ labels.push_back(ASCIIToUTF16("Email: xxx@yyy.com"));
+ names.push_back(ASCIIToUTF16("email"));
+ values.push_back(ASCIIToUTF16("john@example.com"));
+
+ ExpectLabels(
+ "<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <LABEL for=\"firstname\"> First Name: </LABEL>"
+ " <LABEL for=\"firstname\"></LABEL>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <LABEL for=\"lastname\"></LABEL>"
+ " <LABEL for=\"lastname\"> Last Name: </LABEL>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <LABEL for=\"email\"> Email: </LABEL>"
+ " <LABEL for=\"email\"> xxx@yyy.com </LABEL>"
+ " <INPUT type=\"text\" id=\"email\" value=\"john@example.com\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>",
+ labels, names, values);
+}
+
+TEST_F(FormManagerTest, SelectOneAsText) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <SELECT id=\"country\">"
+ " <OPTION value=\"AF\">Afghanistan</OPTION>"
+ " <OPTION value=\"AL\">Albania</OPTION>"
+ " <OPTION value=\"DZ\">Algeria</OPTION>"
+ " </SELECT>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), frame);
+
+ // Set the value of the select-one.
+ WebSelectElement select_element =
+ frame->document().getElementById("country").to<WebSelectElement>();
+ select_element.setValue(WebString::fromUTF8("AL"));
+
+ WebVector<WebFormElement> forms;
+ frame->document().forms(forms);
+ ASSERT_EQ(1U, forms.size());
+
+ FormData form;
+
+ // Extract the country select-one value as text.
+ EXPECT_TRUE(WebFormElementToFormData(
+ forms[0], WebFormControlElement(), autofill::REQUIRE_NONE,
+ static_cast<autofill::ExtractMask>(
+ autofill::EXTRACT_VALUE | autofill::EXTRACT_OPTION_TEXT),
+ &form, NULL));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://cnn.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+
+ FormField expected;
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("John");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Smith");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("country");
+ expected.value = ASCIIToUTF16("Albania");
+ expected.form_control_type = ASCIIToUTF16("select-one");
+ expected.max_length = 0;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+
+ form.fields.clear();
+ // Extract the country select-one value as value.
+ EXPECT_TRUE(WebFormElementToFormData(forms[0],
+ WebFormControlElement(),
+ autofill::REQUIRE_NONE,
+ autofill::EXTRACT_VALUE,
+ &form,
+ NULL));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(frame->document().url()), form.origin);
+ EXPECT_EQ(GURL("http://cnn.com"), form.action);
+
+ ASSERT_EQ(3U, fields.size());
+
+ expected.name = ASCIIToUTF16("firstname");
+ expected.value = ASCIIToUTF16("John");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+
+ expected.name = ASCIIToUTF16("lastname");
+ expected.value = ASCIIToUTF16("Smith");
+ expected.form_control_type = ASCIIToUTF16("text");
+ expected.max_length = WebInputElement::defaultMaxLength();
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
+
+ expected.name = ASCIIToUTF16("country");
+ expected.value = ASCIIToUTF16("AL");
+ expected.form_control_type = ASCIIToUTF16("select-one");
+ expected.max_length = 0;
+ EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
+}