Unregister from GCM when the only GCM app is removed
[chromium-blink-merge.git] / chrome / renderer / autofill / autofill_renderer_browsertest.cc
blob49a836650042d691f806b7f5a4ac62ecccb835db
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,
40 autofill::FormData,
41 autofill::FormFieldData,
42 gfx::RectF,
43 bool> AutofillQueryParam;
45 class AutofillRendererTest : public ChromeRenderViewTest {
46 public:
47 AutofillRendererTest() {}
48 ~AutofillRendererTest() override {}
50 protected:
51 void SetUp() override {
52 ChromeRenderViewTest::SetUp();
54 // Don't want any delay for form state sync changes. This will still post a
55 // message so updates will get coalesced, but as soon as we spin the message
56 // loop, it will generate an update.
57 SendContentStateImmediately();
60 void SimulateRequestAutocompleteResult(
61 blink::WebFrame* invoking_frame,
62 const blink::WebFormElement::AutocompleteResult& result,
63 const base::string16& message) {
64 AutofillMsg_RequestAutocompleteResult msg(0, result, message, FormData());
65 content::RenderFrame::FromWebFrame(invoking_frame)->OnMessageReceived(msg);
68 private:
69 DISALLOW_COPY_AND_ASSIGN(AutofillRendererTest);
72 TEST_F(AutofillRendererTest, SendForms) {
73 LoadHTML("<form method='POST'>"
74 " <input type='text' id='firstname'/>"
75 " <input type='text' id='middlename'/>"
76 " <input type='text' id='lastname' autoComplete='off'/>"
77 " <input type='hidden' id='email'/>"
78 " <select id='state'/>"
79 " <option>?</option>"
80 " <option>California</option>"
81 " <option>Texas</option>"
82 " </select>"
83 "</form>");
85 // Verify that "FormsSeen" sends the expected number of fields.
86 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
87 AutofillHostMsg_FormsSeen::ID);
88 ASSERT_NE(nullptr, message);
89 AutofillHostMsg_FormsSeen::Param params;
90 AutofillHostMsg_FormsSeen::Read(message, &params);
91 std::vector<FormData> forms = get<0>(params);
92 ASSERT_EQ(1UL, forms.size());
93 ASSERT_EQ(4UL, forms[0].fields.size());
95 FormFieldData expected;
97 expected.name = ASCIIToUTF16("firstname");
98 expected.value = base::string16();
99 expected.form_control_type = "text";
100 expected.max_length = WebInputElement::defaultMaxLength();
101 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[0]);
103 expected.name = ASCIIToUTF16("middlename");
104 expected.value = base::string16();
105 expected.form_control_type = "text";
106 expected.max_length = WebInputElement::defaultMaxLength();
107 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[1]);
109 expected.name = ASCIIToUTF16("lastname");
110 expected.value = base::string16();
111 expected.form_control_type = "text";
112 expected.autocomplete_attribute = "off";
113 expected.max_length = WebInputElement::defaultMaxLength();
114 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[2]);
115 expected.autocomplete_attribute = std::string(); // reset
117 expected.name = ASCIIToUTF16("state");
118 expected.value = ASCIIToUTF16("?");
119 expected.form_control_type = "select-one";
120 expected.max_length = 0;
121 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[3]);
123 render_thread_->sink().ClearMessages();
125 // Dynamically create a new form. A new message should be sent for it, but
126 // not for the previous form.
127 ExecuteJavaScript(
128 "var newForm=document.createElement('form');"
129 "newForm.id='new_testform';"
130 "newForm.action='http://google.com';"
131 "newForm.method='post';"
132 "var newFirstname=document.createElement('input');"
133 "newFirstname.setAttribute('type', 'text');"
134 "newFirstname.setAttribute('id', 'second_firstname');"
135 "newFirstname.value = 'Bob';"
136 "var newLastname=document.createElement('input');"
137 "newLastname.setAttribute('type', 'text');"
138 "newLastname.setAttribute('id', 'second_lastname');"
139 "newLastname.value = 'Hope';"
140 "var newEmail=document.createElement('input');"
141 "newEmail.setAttribute('type', 'text');"
142 "newEmail.setAttribute('id', 'second_email');"
143 "newEmail.value = 'bobhope@example.com';"
144 "newForm.appendChild(newFirstname);"
145 "newForm.appendChild(newLastname);"
146 "newForm.appendChild(newEmail);"
147 "document.body.appendChild(newForm);");
148 msg_loop_.RunUntilIdle();
150 message = render_thread_->sink().GetFirstMessageMatching(
151 AutofillHostMsg_FormsSeen::ID);
152 ASSERT_NE(nullptr, message);
153 AutofillHostMsg_FormsSeen::Read(message, &params);
154 forms = get<0>(params);
155 ASSERT_EQ(1UL, forms.size());
156 ASSERT_EQ(3UL, forms[0].fields.size());
158 expected.form_control_type = "text";
159 expected.max_length = WebInputElement::defaultMaxLength();
161 expected.name = ASCIIToUTF16("second_firstname");
162 expected.value = ASCIIToUTF16("Bob");
163 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[0]);
165 expected.name = ASCIIToUTF16("second_lastname");
166 expected.value = ASCIIToUTF16("Hope");
167 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[1]);
169 expected.name = ASCIIToUTF16("second_email");
170 expected.value = ASCIIToUTF16("bobhope@example.com");
171 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[2]);
174 TEST_F(AutofillRendererTest, EnsureNoFormSeenIfTooFewFields) {
175 LoadHTML("<form method='POST'>"
176 " <input type='text' id='firstname'/>"
177 " <input type='text' id='middlename'/>"
178 "</form>");
180 // Verify that "FormsSeen" isn't sent, as there are too few fields.
181 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
182 AutofillHostMsg_FormsSeen::ID);
183 ASSERT_NE(nullptr, message);
184 AutofillHostMsg_FormsSeen::Param params;
185 AutofillHostMsg_FormsSeen::Read(message, &params);
186 const std::vector<FormData>& forms = get<0>(params);
187 ASSERT_EQ(0UL, forms.size());
190 TEST_F(AutofillRendererTest, ShowAutofillWarning) {
191 LoadHTML("<form method='POST' autocomplete='Off'>"
192 " <input id='firstname' autocomplete='OFF'/>"
193 " <input id='middlename'/>"
194 " <input id='lastname'/>"
195 "</form>");
197 // Verify that "QueryFormFieldAutofill" isn't sent prior to a user
198 // interaction.
199 const IPC::Message* message0 = render_thread_->sink().GetFirstMessageMatching(
200 AutofillHostMsg_QueryFormFieldAutofill::ID);
201 EXPECT_EQ(nullptr, message0);
203 WebFrame* web_frame = GetMainFrame();
204 WebDocument document = web_frame->document();
205 WebInputElement firstname =
206 document.getElementById("firstname").to<WebInputElement>();
207 WebInputElement middlename =
208 document.getElementById("middlename").to<WebInputElement>();
210 // Simulate attempting to Autofill the form from the first element, which
211 // specifies autocomplete="off". This should still trigger an IPC which
212 // shouldn't display warnings.
213 static_cast<PageClickListener*>(autofill_agent_)
214 ->FormControlElementClicked(firstname, true);
215 const IPC::Message* message1 = render_thread_->sink().GetFirstMessageMatching(
216 AutofillHostMsg_QueryFormFieldAutofill::ID);
217 EXPECT_NE(nullptr, message1);
219 AutofillQueryParam query_param;
220 AutofillHostMsg_QueryFormFieldAutofill::Read(message1, &query_param);
221 EXPECT_FALSE(get<4>(query_param));
222 render_thread_->sink().ClearMessages();
224 // Simulate attempting to Autofill the form from the second element, which
225 // does not specify autocomplete="off". This should trigger an IPC that will
226 // show warnings, as we *do* show warnings for elements that don't themselves
227 // set autocomplete="off", but for which the form does.
228 static_cast<PageClickListener*>(autofill_agent_)
229 ->FormControlElementClicked(middlename, true);
230 const IPC::Message* message2 = render_thread_->sink().GetFirstMessageMatching(
231 AutofillHostMsg_QueryFormFieldAutofill::ID);
232 ASSERT_NE(nullptr, message2);
234 AutofillHostMsg_QueryFormFieldAutofill::Read(message2, &query_param);
235 EXPECT_TRUE(get<4>(query_param));
238 // Regression test for [ http://crbug.com/346010 ].
239 TEST_F(AutofillRendererTest, DontCrashWhileAssociatingForms) {
240 LoadHTML("<form id='form'>"
241 "<foo id='foo'>"
242 "<script id='script'>"
243 "document.documentElement.appendChild(foo);"
244 "newDoc = document.implementation.createDocument("
245 " 'http://www.w3.org/1999/xhtml', 'html');"
246 "foo.insertBefore(form, script);"
247 "newDoc.adoptNode(foo);"
248 "</script>");
250 // Shouldn't crash.
253 TEST_F(AutofillRendererTest, DynamicallyAddedUnownedFormElements) {
254 std::string html_data;
255 base::FilePath test_path = ui_test_utils::GetTestFilePath(
256 base::FilePath(FILE_PATH_LITERAL("autofill")),
257 base::FilePath(FILE_PATH_LITERAL("autofill_noform_dynamic.html")));
258 ASSERT_TRUE(base::ReadFileToString(test_path, &html_data));
259 LoadHTML(html_data.c_str());
261 // Verify that "FormsSeen" sends the expected number of fields.
262 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
263 AutofillHostMsg_FormsSeen::ID);
264 ASSERT_NE(nullptr, message);
265 AutofillHostMsg_FormsSeen::Param params;
266 AutofillHostMsg_FormsSeen::Read(message, &params);
267 std::vector<FormData> forms = get<0>(params);
268 ASSERT_EQ(1UL, forms.size());
269 ASSERT_EQ(7UL, forms[0].fields.size());
271 render_thread_->sink().ClearMessages();
273 ExecuteJavaScript("AddFields()");
274 msg_loop_.RunUntilIdle();
276 message = render_thread_->sink().GetFirstMessageMatching(
277 AutofillHostMsg_FormsSeen::ID);
278 ASSERT_NE(nullptr, message);
279 AutofillHostMsg_FormsSeen::Read(message, &params);
280 forms = get<0>(params);
281 ASSERT_EQ(1UL, forms.size());
282 ASSERT_EQ(9UL, forms[0].fields.size());
284 FormFieldData expected;
286 expected.name = ASCIIToUTF16("EMAIL_ADDRESS");
287 expected.value.clear();
288 expected.form_control_type = "text";
289 expected.max_length = WebInputElement::defaultMaxLength();
290 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[7]);
292 expected.name = ASCIIToUTF16("PHONE_HOME_WHOLE_NUMBER");
293 expected.value.clear();
294 expected.form_control_type = "text";
295 expected.max_length = WebInputElement::defaultMaxLength();
296 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[8]);
299 class RequestAutocompleteRendererTest : public AutofillRendererTest {
300 public:
301 RequestAutocompleteRendererTest()
302 : invoking_frame_(NULL), sibling_frame_(NULL) {}
303 ~RequestAutocompleteRendererTest() override {}
305 protected:
306 void SetUp() override {
307 AutofillRendererTest::SetUp();
309 // Bypass the HTTPS-only restriction to show requestAutocomplete.
310 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
311 command_line->AppendSwitch(::switches::kReduceSecurityForTesting);
313 GURL url("data:text/html;charset=utf-8,"
314 "<form><input autocomplete=cc-number></form>");
315 const char kDoubleIframeHtml[] = "<iframe id=subframe src='%s'></iframe>"
316 "<iframe id=sibling></iframe>";
317 LoadHTML(base::StringPrintf(kDoubleIframeHtml, url.spec().c_str()).c_str());
319 WebElement subframe = GetMainFrame()->document().getElementById("subframe");
320 ASSERT_FALSE(subframe.isNull());
321 invoking_frame_ = WebLocalFrame::fromFrameOwnerElement(subframe);
322 ASSERT_TRUE(invoking_frame());
323 ASSERT_EQ(GetMainFrame(), invoking_frame()->parent());
325 WebElement sibling = GetMainFrame()->document().getElementById("sibling");
326 ASSERT_FALSE(sibling.isNull());
327 sibling_frame_ = WebLocalFrame::fromFrameOwnerElement(sibling);
328 ASSERT_TRUE(sibling_frame());
330 WebVector<WebFormElement> forms;
331 invoking_frame()->document().forms(forms);
332 ASSERT_EQ(1U, forms.size());
333 invoking_form_ = forms[0];
334 ASSERT_FALSE(invoking_form().isNull());
336 render_thread_->sink().ClearMessages();
338 // Invoke requestAutocomplete to show the dialog.
339 invoking_frame_->autofillClient()->didRequestAutocomplete(invoking_form());
340 ASSERT_TRUE(render_thread_->sink().GetFirstMessageMatching(
341 AutofillHostMsg_RequestAutocomplete::ID));
343 render_thread_->sink().ClearMessages();
346 void TearDown() override {
347 invoking_form_.reset();
348 AutofillRendererTest::TearDown();
351 void NavigateFrame(WebFrame* frame) {
352 frame->loadRequest(WebURLRequest(GURL("about:blank")));
353 ProcessPendingMessages();
356 const WebFormElement& invoking_form() const { return invoking_form_; }
357 WebLocalFrame* invoking_frame() { return invoking_frame_; }
358 WebFrame* sibling_frame() { return sibling_frame_; }
360 protected:
361 WebFormElement invoking_form_;
362 WebLocalFrame* invoking_frame_;
363 WebFrame* sibling_frame_;
365 private:
366 DISALLOW_COPY_AND_ASSIGN(RequestAutocompleteRendererTest);
369 TEST_F(RequestAutocompleteRendererTest, InvokingTwiceOnlyShowsOnce) {
370 // Attempting to show the requestAutocomplete dialog again should be ignored.
371 invoking_frame_->autofillClient()->didRequestAutocomplete(invoking_form());
372 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
373 AutofillHostMsg_RequestAutocomplete::ID));
376 } // namespace autofill