Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / chrome / renderer / autofill / autofill_renderer_browsertest.cc
blob0ff5d278a96321e89ebb1152f26faae245971380
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/command_line.h"
6 #include "base/files/file_util.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/test/base/chrome_render_view_test.h"
10 #include "chrome/test/base/ui_test_utils.h"
11 #include "components/autofill/content/common/autofill_messages.h"
12 #include "components/autofill/content/renderer/autofill_agent.h"
13 #include "components/autofill/core/common/form_data.h"
14 #include "components/autofill/core/common/form_field_data.h"
15 #include "content/public/common/content_switches.h"
16 #include "content/public/renderer/render_frame.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/WebKit/public/platform/WebString.h"
19 #include "third_party/WebKit/public/platform/WebURLRequest.h"
20 #include "third_party/WebKit/public/platform/WebVector.h"
21 #include "third_party/WebKit/public/web/WebDocument.h"
22 #include "third_party/WebKit/public/web/WebFormElement.h"
23 #include "third_party/WebKit/public/web/WebInputElement.h"
24 #include "third_party/WebKit/public/web/WebLocalFrame.h"
26 using base::ASCIIToUTF16;
27 using blink::WebDocument;
28 using blink::WebElement;
29 using blink::WebFormElement;
30 using blink::WebFrame;
31 using blink::WebLocalFrame;
32 using blink::WebInputElement;
33 using blink::WebString;
34 using blink::WebURLRequest;
35 using blink::WebVector;
37 namespace autofill {
39 typedef Tuple<int, autofill::FormData, autofill::FormFieldData, gfx::RectF>
40 AutofillQueryParam;
42 class AutofillRendererTest : public ChromeRenderViewTest {
43 public:
44 AutofillRendererTest() {}
45 ~AutofillRendererTest() override {}
47 protected:
48 void SetUp() override {
49 ChromeRenderViewTest::SetUp();
51 // Don't want any delay for form state sync changes. This will still post a
52 // message so updates will get coalesced, but as soon as we spin the message
53 // loop, it will generate an update.
54 SendContentStateImmediately();
57 void SimulateRequestAutocompleteResult(
58 blink::WebFrame* invoking_frame,
59 const blink::WebFormElement::AutocompleteResult& result,
60 const base::string16& message) {
61 AutofillMsg_RequestAutocompleteResult msg(0, result, message, FormData());
62 content::RenderFrame::FromWebFrame(invoking_frame)->OnMessageReceived(msg);
65 private:
66 DISALLOW_COPY_AND_ASSIGN(AutofillRendererTest);
69 TEST_F(AutofillRendererTest, SendForms) {
70 LoadHTML("<form method='POST'>"
71 " <input type='text' id='firstname'/>"
72 " <input type='text' id='middlename'/>"
73 " <input type='text' id='lastname' autoComplete='off'/>"
74 " <input type='hidden' id='email'/>"
75 " <select id='state'/>"
76 " <option>?</option>"
77 " <option>California</option>"
78 " <option>Texas</option>"
79 " </select>"
80 "</form>");
82 // Verify that "FormsSeen" sends the expected number of fields.
83 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
84 AutofillHostMsg_FormsSeen::ID);
85 ASSERT_NE(nullptr, message);
86 AutofillHostMsg_FormsSeen::Param params;
87 AutofillHostMsg_FormsSeen::Read(message, &params);
88 std::vector<FormData> forms = get<0>(params);
89 ASSERT_EQ(1UL, forms.size());
90 ASSERT_EQ(4UL, forms[0].fields.size());
92 FormFieldData expected;
94 expected.name = ASCIIToUTF16("firstname");
95 expected.value = base::string16();
96 expected.form_control_type = "text";
97 expected.max_length = WebInputElement::defaultMaxLength();
98 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[0]);
100 expected.name = ASCIIToUTF16("middlename");
101 expected.value = base::string16();
102 expected.form_control_type = "text";
103 expected.max_length = WebInputElement::defaultMaxLength();
104 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[1]);
106 expected.name = ASCIIToUTF16("lastname");
107 expected.value = base::string16();
108 expected.form_control_type = "text";
109 expected.autocomplete_attribute = "off";
110 expected.max_length = WebInputElement::defaultMaxLength();
111 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[2]);
112 expected.autocomplete_attribute = std::string(); // reset
114 expected.name = ASCIIToUTF16("state");
115 expected.value = ASCIIToUTF16("?");
116 expected.form_control_type = "select-one";
117 expected.max_length = 0;
118 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[3]);
120 render_thread_->sink().ClearMessages();
122 // Dynamically create a new form. A new message should be sent for it, but
123 // not for the previous form.
124 ExecuteJavaScript(
125 "var newForm=document.createElement('form');"
126 "newForm.id='new_testform';"
127 "newForm.action='http://google.com';"
128 "newForm.method='post';"
129 "var newFirstname=document.createElement('input');"
130 "newFirstname.setAttribute('type', 'text');"
131 "newFirstname.setAttribute('id', 'second_firstname');"
132 "newFirstname.value = 'Bob';"
133 "var newLastname=document.createElement('input');"
134 "newLastname.setAttribute('type', 'text');"
135 "newLastname.setAttribute('id', 'second_lastname');"
136 "newLastname.value = 'Hope';"
137 "var newEmail=document.createElement('input');"
138 "newEmail.setAttribute('type', 'text');"
139 "newEmail.setAttribute('id', 'second_email');"
140 "newEmail.value = 'bobhope@example.com';"
141 "newForm.appendChild(newFirstname);"
142 "newForm.appendChild(newLastname);"
143 "newForm.appendChild(newEmail);"
144 "document.body.appendChild(newForm);");
145 msg_loop_.RunUntilIdle();
147 message = render_thread_->sink().GetFirstMessageMatching(
148 AutofillHostMsg_FormsSeen::ID);
149 ASSERT_NE(nullptr, message);
150 AutofillHostMsg_FormsSeen::Read(message, &params);
151 forms = get<0>(params);
152 ASSERT_EQ(1UL, forms.size());
153 ASSERT_EQ(3UL, forms[0].fields.size());
155 expected.form_control_type = "text";
156 expected.max_length = WebInputElement::defaultMaxLength();
158 expected.name = ASCIIToUTF16("second_firstname");
159 expected.value = ASCIIToUTF16("Bob");
160 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[0]);
162 expected.name = ASCIIToUTF16("second_lastname");
163 expected.value = ASCIIToUTF16("Hope");
164 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[1]);
166 expected.name = ASCIIToUTF16("second_email");
167 expected.value = ASCIIToUTF16("bobhope@example.com");
168 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[2]);
171 TEST_F(AutofillRendererTest, EnsureNoFormSeenIfTooFewFields) {
172 LoadHTML("<form method='POST'>"
173 " <input type='text' id='firstname'/>"
174 " <input type='text' id='middlename'/>"
175 "</form>");
177 // Verify that "FormsSeen" isn't sent, as there are too few fields.
178 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
179 AutofillHostMsg_FormsSeen::ID);
180 ASSERT_NE(nullptr, message);
181 AutofillHostMsg_FormsSeen::Param params;
182 AutofillHostMsg_FormsSeen::Read(message, &params);
183 const std::vector<FormData>& forms = get<0>(params);
184 ASSERT_EQ(0UL, forms.size());
187 // Regression test for [ http://crbug.com/346010 ].
188 TEST_F(AutofillRendererTest, DontCrashWhileAssociatingForms) {
189 LoadHTML("<form id='form'>"
190 "<foo id='foo'>"
191 "<script id='script'>"
192 "document.documentElement.appendChild(foo);"
193 "newDoc = document.implementation.createDocument("
194 " 'http://www.w3.org/1999/xhtml', 'html');"
195 "foo.insertBefore(form, script);"
196 "newDoc.adoptNode(foo);"
197 "</script>");
199 // Shouldn't crash.
202 TEST_F(AutofillRendererTest, DynamicallyAddedUnownedFormElements) {
203 std::string html_data;
204 base::FilePath test_path = ui_test_utils::GetTestFilePath(
205 base::FilePath(FILE_PATH_LITERAL("autofill")),
206 base::FilePath(FILE_PATH_LITERAL("autofill_noform_dynamic.html")));
207 ASSERT_TRUE(base::ReadFileToString(test_path, &html_data));
208 LoadHTML(html_data.c_str());
210 // Verify that "FormsSeen" sends the expected number of fields.
211 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
212 AutofillHostMsg_FormsSeen::ID);
213 ASSERT_NE(nullptr, message);
214 AutofillHostMsg_FormsSeen::Param params;
215 AutofillHostMsg_FormsSeen::Read(message, &params);
216 std::vector<FormData> forms = get<0>(params);
217 ASSERT_EQ(1UL, forms.size());
218 ASSERT_EQ(7UL, forms[0].fields.size());
220 render_thread_->sink().ClearMessages();
222 ExecuteJavaScript("AddFields()");
223 msg_loop_.RunUntilIdle();
225 message = render_thread_->sink().GetFirstMessageMatching(
226 AutofillHostMsg_FormsSeen::ID);
227 ASSERT_NE(nullptr, message);
228 AutofillHostMsg_FormsSeen::Read(message, &params);
229 forms = get<0>(params);
230 ASSERT_EQ(1UL, forms.size());
231 ASSERT_EQ(9UL, forms[0].fields.size());
233 FormFieldData expected;
235 expected.name = ASCIIToUTF16("EMAIL_ADDRESS");
236 expected.value.clear();
237 expected.form_control_type = "text";
238 expected.max_length = WebInputElement::defaultMaxLength();
239 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[7]);
241 expected.name = ASCIIToUTF16("PHONE_HOME_WHOLE_NUMBER");
242 expected.value.clear();
243 expected.form_control_type = "text";
244 expected.max_length = WebInputElement::defaultMaxLength();
245 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[8]);
248 class RequestAutocompleteRendererTest : public AutofillRendererTest {
249 public:
250 RequestAutocompleteRendererTest()
251 : invoking_frame_(NULL), sibling_frame_(NULL) {}
252 ~RequestAutocompleteRendererTest() override {}
254 protected:
255 void SetUp() override {
256 AutofillRendererTest::SetUp();
258 // Bypass the HTTPS-only restriction to show requestAutocomplete.
259 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
260 command_line->AppendSwitch(::switches::kReduceSecurityForTesting);
262 GURL url("data:text/html;charset=utf-8,"
263 "<form><input autocomplete=cc-number></form>");
264 const char kDoubleIframeHtml[] = "<iframe id=subframe src='%s'></iframe>"
265 "<iframe id=sibling></iframe>";
266 LoadHTML(base::StringPrintf(kDoubleIframeHtml, url.spec().c_str()).c_str());
268 WebElement subframe = GetMainFrame()->document().getElementById("subframe");
269 ASSERT_FALSE(subframe.isNull());
270 invoking_frame_ = WebLocalFrame::fromFrameOwnerElement(subframe);
271 ASSERT_TRUE(invoking_frame());
272 ASSERT_EQ(GetMainFrame(), invoking_frame()->parent());
274 WebElement sibling = GetMainFrame()->document().getElementById("sibling");
275 ASSERT_FALSE(sibling.isNull());
276 sibling_frame_ = WebLocalFrame::fromFrameOwnerElement(sibling);
277 ASSERT_TRUE(sibling_frame());
279 WebVector<WebFormElement> forms;
280 invoking_frame()->document().forms(forms);
281 ASSERT_EQ(1U, forms.size());
282 invoking_form_ = forms[0];
283 ASSERT_FALSE(invoking_form().isNull());
285 render_thread_->sink().ClearMessages();
287 // Invoke requestAutocomplete to show the dialog.
288 invoking_frame_->autofillClient()->didRequestAutocomplete(invoking_form());
289 ASSERT_TRUE(render_thread_->sink().GetFirstMessageMatching(
290 AutofillHostMsg_RequestAutocomplete::ID));
292 render_thread_->sink().ClearMessages();
295 void TearDown() override {
296 invoking_form_.reset();
297 AutofillRendererTest::TearDown();
300 void NavigateFrame(WebFrame* frame) {
301 frame->loadRequest(WebURLRequest(GURL("about:blank")));
302 ProcessPendingMessages();
305 const WebFormElement& invoking_form() const { return invoking_form_; }
306 WebLocalFrame* invoking_frame() { return invoking_frame_; }
307 WebFrame* sibling_frame() { return sibling_frame_; }
309 protected:
310 WebFormElement invoking_form_;
311 WebLocalFrame* invoking_frame_;
312 WebFrame* sibling_frame_;
314 private:
315 DISALLOW_COPY_AND_ASSIGN(RequestAutocompleteRendererTest);
318 TEST_F(RequestAutocompleteRendererTest, InvokingTwiceOnlyShowsOnce) {
319 // Attempting to show the requestAutocomplete dialog again should be ignored.
320 invoking_frame_->autofillClient()->didRequestAutocomplete(invoking_form());
321 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
322 AutofillHostMsg_RequestAutocomplete::ID));
325 } // namespace autofill