Update CrOS OOBE throbber to MD throbber; delete old asset
[chromium-blink-merge.git] / chrome / renderer / autofill / autofill_renderer_browsertest.cc
blobf8bde26ba9b7d1514928dc59a4669bc956190c1a
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"
25 #include "third_party/WebKit/public/web/WebView.h"
27 using base::ASCIIToUTF16;
28 using blink::WebDocument;
29 using blink::WebElement;
30 using blink::WebFormElement;
31 using blink::WebFrame;
32 using blink::WebLocalFrame;
33 using blink::WebInputElement;
34 using blink::WebString;
35 using blink::WebURLRequest;
36 using blink::WebVector;
38 namespace autofill {
40 typedef base::Tuple<int, autofill::FormData, autofill::FormFieldData,
41 gfx::RectF> AutofillQueryParam;
43 class AutofillRendererTest : public ChromeRenderViewTest {
44 public:
45 AutofillRendererTest() {}
46 ~AutofillRendererTest() override {}
48 protected:
49 void SetUp() override {
50 ChromeRenderViewTest::SetUp();
52 // Don't want any delay for form state sync changes. This will still post a
53 // message so updates will get coalesced, but as soon as we spin the message
54 // loop, it will generate an update.
55 SendContentStateImmediately();
58 void SimulateRequestAutocompleteResult(
59 blink::WebFrame* invoking_frame,
60 const blink::WebFormElement::AutocompleteResult& result,
61 const base::string16& message) {
62 AutofillMsg_RequestAutocompleteResult msg(0, result, message, FormData());
63 content::RenderFrame::FromWebFrame(invoking_frame)->OnMessageReceived(msg);
66 private:
67 DISALLOW_COPY_AND_ASSIGN(AutofillRendererTest);
70 TEST_F(AutofillRendererTest, SendForms) {
71 LoadHTML("<form method='POST'>"
72 " <input type='text' id='firstname'/>"
73 " <input type='text' id='middlename'/>"
74 " <input type='text' id='lastname' autoComplete='off'/>"
75 " <input type='hidden' id='email'/>"
76 " <select id='state'/>"
77 " <option>?</option>"
78 " <option>California</option>"
79 " <option>Texas</option>"
80 " </select>"
81 "</form>");
83 // Verify that "FormsSeen" sends the expected number of fields.
84 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
85 AutofillHostMsg_FormsSeen::ID);
86 ASSERT_NE(nullptr, message);
87 AutofillHostMsg_FormsSeen::Param params;
88 AutofillHostMsg_FormsSeen::Read(message, &params);
89 std::vector<FormData> forms = base::get<0>(params);
90 ASSERT_EQ(1UL, forms.size());
91 ASSERT_EQ(4UL, forms[0].fields.size());
93 FormFieldData expected;
95 expected.name = ASCIIToUTF16("firstname");
96 expected.value = base::string16();
97 expected.form_control_type = "text";
98 expected.max_length = WebInputElement::defaultMaxLength();
99 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[0]);
101 expected.name = ASCIIToUTF16("middlename");
102 expected.value = base::string16();
103 expected.form_control_type = "text";
104 expected.max_length = WebInputElement::defaultMaxLength();
105 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[1]);
107 expected.name = ASCIIToUTF16("lastname");
108 expected.value = base::string16();
109 expected.form_control_type = "text";
110 expected.autocomplete_attribute = "off";
111 expected.max_length = WebInputElement::defaultMaxLength();
112 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[2]);
113 expected.autocomplete_attribute = std::string(); // reset
115 expected.name = ASCIIToUTF16("state");
116 expected.value = ASCIIToUTF16("?");
117 expected.form_control_type = "select-one";
118 expected.max_length = 0;
119 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[3]);
121 render_thread_->sink().ClearMessages();
123 // Dynamically create a new form. A new message should be sent for it, but
124 // not for the previous form.
125 ExecuteJavaScriptForTests(
126 "var newForm=document.createElement('form');"
127 "newForm.id='new_testform';"
128 "newForm.action='http://google.com';"
129 "newForm.method='post';"
130 "var newFirstname=document.createElement('input');"
131 "newFirstname.setAttribute('type', 'text');"
132 "newFirstname.setAttribute('id', 'second_firstname');"
133 "newFirstname.value = 'Bob';"
134 "var newLastname=document.createElement('input');"
135 "newLastname.setAttribute('type', 'text');"
136 "newLastname.setAttribute('id', 'second_lastname');"
137 "newLastname.value = 'Hope';"
138 "var newEmail=document.createElement('input');"
139 "newEmail.setAttribute('type', 'text');"
140 "newEmail.setAttribute('id', 'second_email');"
141 "newEmail.value = 'bobhope@example.com';"
142 "newForm.appendChild(newFirstname);"
143 "newForm.appendChild(newLastname);"
144 "newForm.appendChild(newEmail);"
145 "document.body.appendChild(newForm);");
146 msg_loop_.RunUntilIdle();
148 message = render_thread_->sink().GetFirstMessageMatching(
149 AutofillHostMsg_FormsSeen::ID);
150 ASSERT_NE(nullptr, message);
151 AutofillHostMsg_FormsSeen::Read(message, &params);
152 forms = base::get<0>(params);
153 ASSERT_EQ(1UL, forms.size());
154 ASSERT_EQ(3UL, forms[0].fields.size());
156 expected.form_control_type = "text";
157 expected.max_length = WebInputElement::defaultMaxLength();
159 expected.name = ASCIIToUTF16("second_firstname");
160 expected.value = ASCIIToUTF16("Bob");
161 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[0]);
163 expected.name = ASCIIToUTF16("second_lastname");
164 expected.value = ASCIIToUTF16("Hope");
165 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[1]);
167 expected.name = ASCIIToUTF16("second_email");
168 expected.value = ASCIIToUTF16("bobhope@example.com");
169 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[2]);
172 TEST_F(AutofillRendererTest, EnsureNoFormSeenIfTooFewFields) {
173 LoadHTML("<form method='POST'>"
174 " <input type='text' id='firstname'/>"
175 " <input type='text' id='middlename'/>"
176 "</form>");
178 // Verify that "FormsSeen" isn't sent, as there are too few fields.
179 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
180 AutofillHostMsg_FormsSeen::ID);
181 ASSERT_NE(nullptr, message);
182 AutofillHostMsg_FormsSeen::Param params;
183 AutofillHostMsg_FormsSeen::Read(message, &params);
184 const std::vector<FormData>& forms = base::get<0>(params);
185 ASSERT_EQ(0UL, forms.size());
188 // Regression test for [ http://crbug.com/346010 ].
189 TEST_F(AutofillRendererTest, DontCrashWhileAssociatingForms) {
190 LoadHTML("<form id='form'>"
191 "<foo id='foo'>"
192 "<script id='script'>"
193 "document.documentElement.appendChild(foo);"
194 "newDoc = document.implementation.createDocument("
195 " 'http://www.w3.org/1999/xhtml', 'html');"
196 "foo.insertBefore(form, script);"
197 "newDoc.adoptNode(foo);"
198 "</script>");
200 // Shouldn't crash.
203 TEST_F(AutofillRendererTest, DynamicallyAddedUnownedFormElements) {
204 std::string html_data;
205 base::FilePath test_path = ui_test_utils::GetTestFilePath(
206 base::FilePath(FILE_PATH_LITERAL("autofill")),
207 base::FilePath(FILE_PATH_LITERAL("autofill_noform_dynamic.html")));
208 ASSERT_TRUE(base::ReadFileToString(test_path, &html_data));
209 LoadHTML(html_data.c_str());
211 // Verify that "FormsSeen" sends the expected number of fields.
212 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
213 AutofillHostMsg_FormsSeen::ID);
214 ASSERT_NE(nullptr, message);
215 AutofillHostMsg_FormsSeen::Param params;
216 AutofillHostMsg_FormsSeen::Read(message, &params);
217 std::vector<FormData> forms = base::get<0>(params);
218 ASSERT_EQ(1UL, forms.size());
219 ASSERT_EQ(7UL, forms[0].fields.size());
221 render_thread_->sink().ClearMessages();
223 ExecuteJavaScriptForTests("AddFields()");
224 msg_loop_.RunUntilIdle();
226 message = render_thread_->sink().GetFirstMessageMatching(
227 AutofillHostMsg_FormsSeen::ID);
228 ASSERT_NE(nullptr, message);
229 AutofillHostMsg_FormsSeen::Read(message, &params);
230 forms = base::get<0>(params);
231 ASSERT_EQ(1UL, forms.size());
232 ASSERT_EQ(9UL, forms[0].fields.size());
234 FormFieldData expected;
236 expected.name = ASCIIToUTF16("EMAIL_ADDRESS");
237 expected.value.clear();
238 expected.form_control_type = "text";
239 expected.max_length = WebInputElement::defaultMaxLength();
240 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[7]);
242 expected.name = ASCIIToUTF16("PHONE_HOME_WHOLE_NUMBER");
243 expected.value.clear();
244 expected.form_control_type = "text";
245 expected.max_length = WebInputElement::defaultMaxLength();
246 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[8]);
249 TEST_F(AutofillRendererTest, IgnoreNonUserGestureTextFieldChanges) {
250 LoadHTML("<form method='post'>"
251 " <input type='text' id='full_name'/>"
252 "</form>");
254 blink::WebInputElement full_name =
255 GetMainFrame()->document().getElementById("full_name")
256 .to<blink::WebInputElement>();
257 while (!full_name.focused())
258 GetMainFrame()->view()->advanceFocus(false);
260 // Not a user gesture, so no IPC message to browser.
261 DisableUserGestureSimulationForAutofill();
262 full_name.setValue("Alice", true);
263 GetMainFrame()->toWebLocalFrame()->autofillClient()->textFieldDidChange(
264 full_name);
265 base::MessageLoop::current()->RunUntilIdle();
266 ASSERT_EQ(nullptr, render_thread_->sink().GetFirstMessageMatching(
267 AutofillHostMsg_TextFieldDidChange::ID));
269 // A user gesture will send a message to the browser.
270 EnableUserGestureSimulationForAutofill();
271 SimulateUserInputChangeForElement(&full_name, "Alice");
272 ASSERT_NE(nullptr, render_thread_->sink().GetFirstMessageMatching(
273 AutofillHostMsg_TextFieldDidChange::ID));
276 class RequestAutocompleteRendererTest : public AutofillRendererTest {
277 public:
278 RequestAutocompleteRendererTest()
279 : invoking_frame_(NULL), sibling_frame_(NULL) {}
280 ~RequestAutocompleteRendererTest() override {}
282 protected:
283 void SetUp() override {
284 AutofillRendererTest::SetUp();
286 // Bypass the HTTPS-only restriction to show requestAutocomplete.
287 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
288 command_line->AppendSwitch(::switches::kReduceSecurityForTesting);
290 GURL url("data:text/html;charset=utf-8,"
291 "<form><input autocomplete=cc-number></form>");
292 const char kDoubleIframeHtml[] = "<iframe id=subframe src='%s'></iframe>"
293 "<iframe id=sibling></iframe>";
294 LoadHTML(base::StringPrintf(kDoubleIframeHtml, url.spec().c_str()).c_str());
296 WebElement subframe = GetMainFrame()->document().getElementById("subframe");
297 ASSERT_FALSE(subframe.isNull());
298 invoking_frame_ = WebLocalFrame::fromFrameOwnerElement(subframe);
299 ASSERT_TRUE(invoking_frame());
300 ASSERT_EQ(GetMainFrame(), invoking_frame()->parent());
302 WebElement sibling = GetMainFrame()->document().getElementById("sibling");
303 ASSERT_FALSE(sibling.isNull());
304 sibling_frame_ = WebLocalFrame::fromFrameOwnerElement(sibling);
305 ASSERT_TRUE(sibling_frame());
307 WebVector<WebFormElement> forms;
308 invoking_frame()->document().forms(forms);
309 ASSERT_EQ(1U, forms.size());
310 invoking_form_ = forms[0];
311 ASSERT_FALSE(invoking_form().isNull());
313 render_thread_->sink().ClearMessages();
315 // Invoke requestAutocomplete to show the dialog.
316 invoking_frame_->autofillClient()->didRequestAutocomplete(invoking_form());
317 ASSERT_TRUE(render_thread_->sink().GetFirstMessageMatching(
318 AutofillHostMsg_RequestAutocomplete::ID));
320 render_thread_->sink().ClearMessages();
323 void TearDown() override {
324 invoking_form_.reset();
325 AutofillRendererTest::TearDown();
328 void NavigateFrame(WebFrame* frame) {
329 frame->loadRequest(WebURLRequest(GURL("about:blank")));
330 ProcessPendingMessages();
333 const WebFormElement& invoking_form() const { return invoking_form_; }
334 WebLocalFrame* invoking_frame() { return invoking_frame_; }
335 WebFrame* sibling_frame() { return sibling_frame_; }
337 protected:
338 WebFormElement invoking_form_;
339 WebLocalFrame* invoking_frame_;
340 WebFrame* sibling_frame_;
342 private:
343 DISALLOW_COPY_AND_ASSIGN(RequestAutocompleteRendererTest);
346 TEST_F(RequestAutocompleteRendererTest, InvokingTwiceOnlyShowsOnce) {
347 // Attempting to show the requestAutocomplete dialog again should be ignored.
348 invoking_frame_->autofillClient()->didRequestAutocomplete(invoking_form());
349 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
350 AutofillHostMsg_RequestAutocomplete::ID));
353 } // namespace autofill