OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <tuple> | 5 #include <tuple> |
6 | 6 |
7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
8 #include "base/time/time.h" | 8 #include "base/time/time.h" |
9 #include "build/build_config.h" | 9 #include "build/build_config.h" |
10 #include "chrome/test/base/chrome_render_view_test.h" | 10 #include "chrome/test/base/chrome_render_view_test.h" |
11 #include "components/autofill/content/common/autofill_messages.h" | 11 #include "components/autofill/content/common/autofill_messages.h" |
12 #include "components/autofill/content/renderer/autofill_agent.h" | 12 #include "components/autofill/content/renderer/autofill_agent.h" |
13 #include "components/autofill/core/common/form_data.h" | 13 #include "components/autofill/core/common/form_data.h" |
14 #include "content/public/test/mock_render_thread.h" | 14 #include "content/public/renderer/render_frame.h" |
15 #include "content/public/renderer/render_view.h" | |
16 #include "mojo/public/cpp/bindings/binding_set.h" | |
17 #include "services/shell/public/cpp/interface_provider.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
16 #include "third_party/WebKit/public/web/WebDocument.h" | 19 #include "third_party/WebKit/public/web/WebDocument.h" |
17 #include "third_party/WebKit/public/web/WebElement.h" | 20 #include "third_party/WebKit/public/web/WebElement.h" |
18 #include "third_party/WebKit/public/web/WebFormElement.h" | 21 #include "third_party/WebKit/public/web/WebFormElement.h" |
19 #include "third_party/WebKit/public/web/WebInputElement.h" | 22 #include "third_party/WebKit/public/web/WebInputElement.h" |
20 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 23 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
21 | 24 |
22 using blink::WebDocument; | 25 using blink::WebDocument; |
23 using blink::WebElement; | 26 using blink::WebElement; |
24 using blink::WebInputElement; | 27 using blink::WebInputElement; |
25 using blink::WebString; | 28 using blink::WebString; |
26 | 29 |
27 typedef ChromeRenderViewTest FormAutocompleteTest; | |
28 | |
29 namespace autofill { | 30 namespace autofill { |
30 | 31 |
31 namespace { | 32 namespace { |
32 | 33 |
34 class FakeContentAutofillDriver : public mojom::AutofillDriver { | |
35 public: | |
36 FakeContentAutofillDriver() : called_nofocus_(false) {} | |
37 ~FakeContentAutofillDriver() override {} | |
38 | |
39 void BindRequest(mojom::AutofillDriverRequest request) { | |
40 bindings_.AddBinding(this, std::move(request)); | |
41 } | |
42 | |
43 void Reset() { called_nofocus_ = false; } | |
44 | |
45 // Records whether FocusNoLongerOnForm() get called. | |
46 bool called_nofocus_; | |
47 // Records the form data received via WillSubmitForm() call. | |
48 std::unique_ptr<FormData> form_willsubmit_; | |
49 // Records the form data received via FormSubmitted() call. | |
50 std::unique_ptr<FormData> form_submitted_; | |
51 | |
52 private: | |
53 // mojom::AutofillDriver: | |
54 void FirstUserGestureObserved() override {} | |
55 void FormsSeen(mojo::Array<FormData> forms, | |
56 const base::TimeTicks& timestamp) override {} | |
57 void WillSubmitForm(const FormData& form, | |
58 const base::TimeTicks& timestamp) override { | |
59 form_willsubmit_.reset(new FormData(form)); | |
60 } | |
61 void FormSubmitted(const FormData& form) override { | |
62 form_submitted_.reset(new FormData(form)); | |
63 } | |
64 void TextFieldDidChange(const FormData& form, | |
65 const FormFieldData& field, | |
66 const base::TimeTicks& timestamp) override {} | |
67 void QueryFormFieldAutofill(int32_t id, | |
68 const FormData& form, | |
69 const FormFieldData& field, | |
70 const gfx::RectF& bounding_box) override {} | |
71 void HidePopup() override {} | |
72 void PingAck() override {} | |
73 void FocusNoLongerOnForm() override { called_nofocus_ = true; } | |
74 void DidFillAutofillFormData(const FormData& form, | |
75 const base::TimeTicks& timestamp) override {} | |
76 void DidPreviewAutofillFormData() override {} | |
77 void DidEndTextFieldEditing() override {} | |
78 void SetDataList(mojo::Array<mojo::String> values, | |
79 mojo::Array<mojo::String> labels) override {} | |
80 | |
81 mojo::BindingSet<mojom::AutofillDriver> bindings_; | |
82 }; | |
83 | |
33 // Helper function to verify the form-related messages received from the | 84 // Helper function to verify the form-related messages received from the |
34 // renderer. The same data is expected in both messages. Depending on | 85 // renderer. The same data is expected in both messages. Depending on |
35 // |expect_submitted_message|, will verify presence of FormSubmitted message. | 86 // |expect_submitted_message|, will verify presence of FormSubmitted message. |
36 void VerifyReceivedRendererMessages(content::MockRenderThread* render_thread, | 87 void VerifyReceivedRendererMessages( |
37 const std::string& fname, | 88 const FakeContentAutofillDriver& fake_driver, |
38 const std::string& lname, | 89 const std::string& fname, |
39 bool expect_submitted_message) { | 90 const std::string& lname, |
40 const IPC::Message* will_submit_message = | 91 bool expect_submitted_message) { |
41 render_thread->sink().GetFirstMessageMatching( | 92 ASSERT_NE(nullptr, fake_driver.form_willsubmit_); |
vabr (Chromium)
2016/06/23 14:21:21
ASSERT_TRUE(fake_driver.form_willsubmit_);
(Also
leonhsl(Using Gerrit)
2016/06/24 15:44:31
Done.
| |
42 AutofillHostMsg_WillSubmitForm::ID); | 93 ASSERT_EQ(expect_submitted_message, fake_driver.form_submitted_ != nullptr); |
43 const IPC::Message* submitted_message = | |
44 render_thread->sink().GetFirstMessageMatching( | |
45 AutofillHostMsg_FormSubmitted::ID); | |
46 ASSERT_TRUE(will_submit_message != NULL); | |
47 ASSERT_EQ(expect_submitted_message, submitted_message != NULL); | |
48 | 94 |
49 // The tuple also includes a timestamp, which is ignored. | 95 // The tuple also includes a timestamp, which is ignored. |
50 std::tuple<FormData, base::TimeTicks> will_submit_forms; | 96 FormData& will_submit_form = *(fake_driver.form_willsubmit_.get()); |
51 AutofillHostMsg_WillSubmitForm::Read(will_submit_message, &will_submit_forms); | 97 ASSERT_EQ(2U, will_submit_form.fields.size()); |
52 ASSERT_EQ(2U, std::get<0>(will_submit_forms).fields.size()); | |
53 | 98 |
54 FormFieldData& will_submit_form_field = | 99 FormFieldData& will_submit_form_field = will_submit_form.fields[0]; |
55 std::get<0>(will_submit_forms).fields[0]; | |
56 EXPECT_EQ(WebString("fname"), will_submit_form_field.name); | 100 EXPECT_EQ(WebString("fname"), will_submit_form_field.name); |
57 EXPECT_EQ(WebString(base::UTF8ToUTF16(fname)), will_submit_form_field.value); | 101 EXPECT_EQ(WebString(base::UTF8ToUTF16(fname)), will_submit_form_field.value); |
58 will_submit_form_field = std::get<0>(will_submit_forms).fields[1]; | 102 will_submit_form_field = will_submit_form.fields[1]; |
59 EXPECT_EQ(WebString("lname"), will_submit_form_field.name); | 103 EXPECT_EQ(WebString("lname"), will_submit_form_field.name); |
60 EXPECT_EQ(WebString(base::UTF8ToUTF16(lname)), will_submit_form_field.value); | 104 EXPECT_EQ(WebString(base::UTF8ToUTF16(lname)), will_submit_form_field.value); |
61 | 105 |
62 if (expect_submitted_message) { | 106 if (expect_submitted_message) { |
63 std::tuple<FormData> submitted_forms; | 107 FormData& submitted_form = *(fake_driver.form_submitted_.get()); |
64 AutofillHostMsg_FormSubmitted::Read(submitted_message, &submitted_forms); | |
65 ASSERT_EQ(2U, std::get<0>(submitted_forms).fields.size()); | |
66 | 108 |
67 FormFieldData& submitted_field = std::get<0>(submitted_forms).fields[0]; | 109 ASSERT_EQ(2U, submitted_form.fields.size()); |
110 | |
111 FormFieldData& submitted_field = submitted_form.fields[0]; | |
68 EXPECT_EQ(WebString("fname"), submitted_field.name); | 112 EXPECT_EQ(WebString("fname"), submitted_field.name); |
69 EXPECT_EQ(WebString(base::UTF8ToUTF16(fname)), submitted_field.value); | 113 EXPECT_EQ(WebString(base::UTF8ToUTF16(fname)), submitted_field.value); |
70 submitted_field = std::get<0>(submitted_forms).fields[1]; | 114 submitted_field = submitted_form.fields[1]; |
71 EXPECT_EQ(WebString("lname"), submitted_field.name); | 115 EXPECT_EQ(WebString("lname"), submitted_field.name); |
72 EXPECT_EQ(WebString(base::UTF8ToUTF16(lname)), submitted_field.value); | 116 EXPECT_EQ(WebString(base::UTF8ToUTF16(lname)), submitted_field.value); |
73 } | 117 } |
74 } | 118 } |
75 | 119 |
76 // Helper function to verify that NO form-related messages are received from the | 120 // Helper function to verify that NO form-related messages are received from the |
77 // renderer. | 121 // renderer. |
78 void VerifyNoSubmitMessagesReceived(content::MockRenderThread* render_thread) { | 122 void VerifyNoSubmitMessagesReceived( |
123 const FakeContentAutofillDriver& fake_driver) { | |
79 // No submission messages sent. | 124 // No submission messages sent. |
80 const IPC::Message* will_submit_message = | 125 EXPECT_EQ(nullptr, fake_driver.form_willsubmit_); |
81 render_thread->sink().GetFirstMessageMatching( | 126 EXPECT_EQ(nullptr, fake_driver.form_submitted_); |
82 AutofillHostMsg_WillSubmitForm::ID); | |
83 const IPC::Message* submitted_message = | |
84 render_thread->sink().GetFirstMessageMatching( | |
85 AutofillHostMsg_FormSubmitted::ID); | |
86 EXPECT_EQ(NULL, will_submit_message); | |
87 EXPECT_EQ(NULL, submitted_message); | |
88 } | 127 } |
89 | 128 |
90 // Simulates receiving a message from the browser to fill a form. | 129 // Simulates receiving a message from the browser to fill a form. |
91 void SimulateOnFillForm(content::MockRenderThread* render_thread, | 130 void SimulateOnFillForm(autofill::AutofillAgent* autofill_agent, |
92 autofill::AutofillAgent* autofill_agent, | |
93 blink::WebFrame* main_frame) { | 131 blink::WebFrame* main_frame) { |
94 WebDocument document = main_frame->document(); | 132 WebDocument document = main_frame->document(); |
95 WebElement element = | 133 WebElement element = |
96 document.getElementById(WebString::fromUTF8("fname")); | 134 document.getElementById(WebString::fromUTF8("fname")); |
97 ASSERT_FALSE(element.isNull()); | 135 ASSERT_FALSE(element.isNull()); |
98 | 136 |
99 // This call is necessary to setup the autofill agent appropriate for the | 137 // This call is necessary to setup the autofill agent appropriate for the |
100 // user selection; simulates the menu actually popping up. | 138 // user selection; simulates the menu actually popping up. |
101 render_thread->sink().ClearMessages(); | |
102 static_cast<autofill::PageClickListener*>(autofill_agent) | 139 static_cast<autofill::PageClickListener*>(autofill_agent) |
103 ->FormControlElementClicked(element.to<WebInputElement>(), false); | 140 ->FormControlElementClicked(element.to<WebInputElement>(), false); |
104 | 141 |
105 FormData data; | 142 FormData data; |
106 data.name = base::ASCIIToUTF16("name"); | 143 data.name = base::ASCIIToUTF16("name"); |
107 data.origin = GURL("http://example.com/"); | 144 data.origin = GURL("http://example.com/"); |
108 data.action = GURL("http://example.com/blade.php"); | 145 data.action = GURL("http://example.com/blade.php"); |
109 data.is_form_tag = true; // Default value. | 146 data.is_form_tag = true; // Default value. |
110 | 147 |
111 FormFieldData field_data; | 148 FormFieldData field_data; |
112 field_data.name = base::ASCIIToUTF16("fname"); | 149 field_data.name = base::ASCIIToUTF16("fname"); |
113 field_data.value = base::ASCIIToUTF16("John"); | 150 field_data.value = base::ASCIIToUTF16("John"); |
114 field_data.is_autofilled = true; | 151 field_data.is_autofilled = true; |
115 data.fields.push_back(field_data); | 152 data.fields.push_back(field_data); |
116 | 153 |
117 field_data.name = base::ASCIIToUTF16("lname"); | 154 field_data.name = base::ASCIIToUTF16("lname"); |
118 field_data.value = base::ASCIIToUTF16("Smith"); | 155 field_data.value = base::ASCIIToUTF16("Smith"); |
119 field_data.is_autofilled = true; | 156 field_data.is_autofilled = true; |
120 data.fields.push_back(field_data); | 157 data.fields.push_back(field_data); |
121 | 158 |
122 AutofillMsg_FillForm msg(0, 0, data); | 159 autofill_agent->FillForm(0, data); |
123 static_cast<content::RenderFrameObserver*>(autofill_agent) | |
124 ->OnMessageReceived(msg); | |
125 } | 160 } |
126 | 161 |
127 } // end namespace | 162 } // end namespace |
128 | 163 |
164 class FormAutocompleteTest : public ChromeRenderViewTest { | |
165 public: | |
166 FormAutocompleteTest() {} | |
167 ~FormAutocompleteTest() override {} | |
168 | |
169 protected: | |
170 void SetUp() override { | |
171 ChromeRenderViewTest::SetUp(); | |
172 | |
173 // We only use the fake driver for main frame | |
vabr (Chromium)
2016/06/23 14:21:22
If possible, please move the SetUp code to the con
leonhsl(Using Gerrit)
2016/06/24 15:44:31
As our codes depend on ChromeRenderViewTest::SetUp
| |
174 // because our test cases only involve the main frame. | |
175 shell::InterfaceProvider* remote_interfaces = | |
176 view_->GetMainRenderFrame()->GetRemoteInterfaces(); | |
177 shell::InterfaceProvider::TestApi test_api(remote_interfaces); | |
178 test_api.SetBinderForName( | |
179 mojom::AutofillDriver::Name_, | |
180 base::Bind(&FormAutocompleteTest::BindAutofillDriver, | |
181 base::Unretained(this))); | |
182 } | |
183 | |
184 void BindAutofillDriver(mojo::ScopedMessagePipeHandle handle) { | |
185 fake_driver_.BindRequest( | |
186 mojo::MakeRequest<mojom::AutofillDriver>(std::move(handle))); | |
187 } | |
188 | |
189 FakeContentAutofillDriver fake_driver_; | |
190 | |
191 private: | |
192 DISALLOW_COPY_AND_ASSIGN(FormAutocompleteTest); | |
193 }; | |
194 | |
129 // Tests that submitting a form generates WillSubmitForm and FormSubmitted | 195 // Tests that submitting a form generates WillSubmitForm and FormSubmitted |
130 // messages with the form fields. | 196 // messages with the form fields. |
131 TEST_F(FormAutocompleteTest, NormalFormSubmit) { | 197 TEST_F(FormAutocompleteTest, NormalFormSubmit) { |
132 // Load a form. | 198 // Load a form. |
133 LoadHTML("<html><form id='myForm'><input name='fname' value='Rick'/>" | 199 LoadHTML("<html><form id='myForm'><input name='fname' value='Rick'/>" |
134 "<input name='lname' value='Deckard'/></form></html>"); | 200 "<input name='lname' value='Deckard'/></form></html>"); |
135 | 201 |
136 // Submit the form. | 202 // Submit the form. |
137 ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); | 203 ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); |
138 ProcessPendingMessages(); | 204 ProcessPendingMessages(); |
139 | 205 |
140 VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", | 206 VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
141 true /* expect_submitted_message */); | 207 true /* expect_submitted_message */); |
142 } | 208 } |
143 | 209 |
144 // Tests that submitting a form that prevents the submit event from propagating | 210 // Tests that submitting a form that prevents the submit event from propagating |
145 // will only send the WillSubmitForm message. | 211 // will only send the WillSubmitForm message. |
146 TEST_F(FormAutocompleteTest, SubmitEventPrevented) { | 212 TEST_F(FormAutocompleteTest, SubmitEventPrevented) { |
147 // Load a form. | 213 // Load a form. |
148 LoadHTML( | 214 LoadHTML( |
149 "<html><form id='myForm'><input name='fname' value='Rick'/>" | 215 "<html><form id='myForm'><input name='fname' value='Rick'/>" |
150 "<input name='lname' value='Deckard'/><input type=submit></form>" | 216 "<input name='lname' value='Deckard'/><input type=submit></form>" |
151 "</html>"); | 217 "</html>"); |
152 | 218 |
153 // Submit the form. | 219 // Submit the form. |
154 ExecuteJavaScriptForTests( | 220 ExecuteJavaScriptForTests( |
155 "var form = document.forms[0];" | 221 "var form = document.forms[0];" |
156 "form.onsubmit = function(event) { event.preventDefault(); };" | 222 "form.onsubmit = function(event) { event.preventDefault(); };" |
157 "document.querySelector('input[type=submit]').click();"); | 223 "document.querySelector('input[type=submit]').click();"); |
158 ProcessPendingMessages(); | 224 ProcessPendingMessages(); |
159 | 225 |
160 VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", | 226 VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
161 false /* expect_submitted_message */); | 227 false /* expect_submitted_message */); |
162 } | 228 } |
163 | 229 |
164 // Tests that completing an Ajax request and having the form disappear will | 230 // Tests that completing an Ajax request and having the form disappear will |
165 // trigger submission from Autofill's point of view. | 231 // trigger submission from Autofill's point of view. |
166 TEST_F(FormAutocompleteTest, AjaxSucceeded_NoLongerVisible) { | 232 TEST_F(FormAutocompleteTest, AjaxSucceeded_NoLongerVisible) { |
167 // Load a form. | 233 // Load a form. |
168 LoadHTML( | 234 LoadHTML( |
169 "<html><form id='myForm' action='http://example.com/blade.php'>" | 235 "<html><form id='myForm' action='http://example.com/blade.php'>" |
170 "<input name='fname' id='fname' value='Bob'/>" | 236 "<input name='fname' id='fname' value='Bob'/>" |
171 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); | 237 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); |
172 | 238 |
173 // Simulate user input so that the form is "remembered". | 239 // Simulate user input so that the form is "remembered". |
174 WebDocument document = GetMainFrame()->document(); | 240 WebDocument document = GetMainFrame()->document(); |
175 WebElement element = document.getElementById(WebString::fromUTF8("fname")); | 241 WebElement element = document.getElementById(WebString::fromUTF8("fname")); |
176 ASSERT_FALSE(element.isNull()); | 242 ASSERT_FALSE(element.isNull()); |
177 WebInputElement fname_element = element.to<WebInputElement>(); | 243 WebInputElement fname_element = element.to<WebInputElement>(); |
178 SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); | 244 SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); |
179 | 245 |
180 // Simulate removing the form just before the ajax request completes. | 246 // Simulate removing the form just before the ajax request completes. |
181 ExecuteJavaScriptForTests( | 247 ExecuteJavaScriptForTests( |
182 "var element = document.getElementById('myForm');" | 248 "var element = document.getElementById('myForm');" |
183 "element.parentNode.removeChild(element);"); | 249 "element.parentNode.removeChild(element);"); |
184 | 250 |
185 // Simulate an Ajax request completing. | 251 // Simulate an Ajax request completing. |
186 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); | 252 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
187 ProcessPendingMessages(); | 253 ProcessPendingMessages(); |
188 | 254 |
189 VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", | 255 VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
190 true /* expect_submitted_message */); | 256 true /* expect_submitted_message */); |
191 } | 257 } |
192 | 258 |
193 // Tests that completing an Ajax request and having the form with a specific | 259 // Tests that completing an Ajax request and having the form with a specific |
194 // action disappear will trigger submission from Autofill's point of view, even | 260 // action disappear will trigger submission from Autofill's point of view, even |
195 // if there is another form with the same data but different action on the page. | 261 // if there is another form with the same data but different action on the page. |
196 TEST_F(FormAutocompleteTest, | 262 TEST_F(FormAutocompleteTest, |
197 AjaxSucceeded_NoLongerVisible_DifferentActionsSameData) { | 263 AjaxSucceeded_NoLongerVisible_DifferentActionsSameData) { |
198 // Load a form. | 264 // Load a form. |
199 LoadHTML( | 265 LoadHTML( |
(...skipping 13 matching lines...) Expand all Loading... | |
213 | 279 |
214 // Simulate removing the form just before the ajax request completes. | 280 // Simulate removing the form just before the ajax request completes. |
215 ExecuteJavaScriptForTests( | 281 ExecuteJavaScriptForTests( |
216 "var element = document.getElementById('myForm');" | 282 "var element = document.getElementById('myForm');" |
217 "element.parentNode.removeChild(element);"); | 283 "element.parentNode.removeChild(element);"); |
218 | 284 |
219 // Simulate an Ajax request completing. | 285 // Simulate an Ajax request completing. |
220 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); | 286 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
221 ProcessPendingMessages(); | 287 ProcessPendingMessages(); |
222 | 288 |
223 VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", | 289 VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
224 true /* expect_submitted_message */); | 290 true /* expect_submitted_message */); |
225 } | 291 } |
226 | 292 |
227 // Tests that completing an Ajax request and having the form with no action | 293 // Tests that completing an Ajax request and having the form with no action |
228 // specified disappear will trigger submission from Autofill's point of view, | 294 // specified disappear will trigger submission from Autofill's point of view, |
229 // even if there is still another form with no action in the page. It will | 295 // even if there is still another form with no action in the page. It will |
230 // compare field data within the forms. | 296 // compare field data within the forms. |
231 // TODO(kolos) Re-enable when the implementation of IsFormVisible is on-par | 297 // TODO(kolos) Re-enable when the implementation of IsFormVisible is on-par |
232 // for these platforms. | 298 // for these platforms. |
233 #if defined(OS_MACOSX) || defined(OS_ANDROID) | 299 #if defined(OS_MACOSX) || defined(OS_ANDROID) |
(...skipping 20 matching lines...) Expand all Loading... | |
254 | 320 |
255 // Simulate removing the form just before the ajax request completes. | 321 // Simulate removing the form just before the ajax request completes. |
256 ExecuteJavaScriptForTests( | 322 ExecuteJavaScriptForTests( |
257 "var element = document.getElementById('myForm');" | 323 "var element = document.getElementById('myForm');" |
258 "element.parentNode.removeChild(element);"); | 324 "element.parentNode.removeChild(element);"); |
259 | 325 |
260 // Simulate an Ajax request completing. | 326 // Simulate an Ajax request completing. |
261 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); | 327 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
262 ProcessPendingMessages(); | 328 ProcessPendingMessages(); |
263 | 329 |
264 VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", | 330 VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
265 true /* expect_submitted_message */); | 331 true /* expect_submitted_message */); |
266 } | 332 } |
267 | 333 |
268 // Tests that completing an Ajax request and having the form with no action | 334 // Tests that completing an Ajax request and having the form with no action |
269 // specified disappear will trigger submission from Autofill's point of view. | 335 // specified disappear will trigger submission from Autofill's point of view. |
270 TEST_F(FormAutocompleteTest, AjaxSucceeded_NoLongerVisible_NoAction) { | 336 TEST_F(FormAutocompleteTest, AjaxSucceeded_NoLongerVisible_NoAction) { |
271 // Load a form. | 337 // Load a form. |
272 LoadHTML( | 338 LoadHTML( |
273 "<html><form id='myForm'>" | 339 "<html><form id='myForm'>" |
274 "<input name='fname' id='fname' value='Bob'/>" | 340 "<input name='fname' id='fname' value='Bob'/>" |
275 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); | 341 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); |
276 | 342 |
277 // Simulate user input so that the form is "remembered". | 343 // Simulate user input so that the form is "remembered". |
278 WebDocument document = GetMainFrame()->document(); | 344 WebDocument document = GetMainFrame()->document(); |
279 WebElement element = | 345 WebElement element = |
280 document.getElementById(WebString::fromUTF8("fname")); | 346 document.getElementById(WebString::fromUTF8("fname")); |
281 ASSERT_FALSE(element.isNull()); | 347 ASSERT_FALSE(element.isNull()); |
282 WebInputElement fname_element = element.to<WebInputElement>(); | 348 WebInputElement fname_element = element.to<WebInputElement>(); |
283 SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); | 349 SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); |
284 | 350 |
285 // Simulate removing the form just before the ajax request completes. | 351 // Simulate removing the form just before the ajax request completes. |
286 ExecuteJavaScriptForTests("var element = document.getElementById('myForm');" | 352 ExecuteJavaScriptForTests("var element = document.getElementById('myForm');" |
287 "element.parentNode.removeChild(element);"); | 353 "element.parentNode.removeChild(element);"); |
288 | 354 |
289 // Simulate an Ajax request completing. | 355 // Simulate an Ajax request completing. |
290 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); | 356 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
291 ProcessPendingMessages(); | 357 ProcessPendingMessages(); |
292 | 358 |
293 VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", | 359 VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
294 true /* expect_submitted_message */); | 360 true /* expect_submitted_message */); |
295 } | 361 } |
296 | 362 |
297 // Tests that completing an Ajax request but leaving a form visible will not | 363 // Tests that completing an Ajax request but leaving a form visible will not |
298 // trigger submission from Autofill's point of view. | 364 // trigger submission from Autofill's point of view. |
299 TEST_F(FormAutocompleteTest, AjaxSucceeded_StillVisible) { | 365 TEST_F(FormAutocompleteTest, AjaxSucceeded_StillVisible) { |
300 // Load a form. | 366 // Load a form. |
301 LoadHTML( | 367 LoadHTML( |
302 "<html><form id='myForm' action='http://example.com/blade.php'>" | 368 "<html><form id='myForm' action='http://example.com/blade.php'>" |
303 "<input name='fname' id='fname' value='Bob'/>" | 369 "<input name='fname' id='fname' value='Bob'/>" |
304 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); | 370 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); |
305 | 371 |
306 // Simulate user input so that the form is "remembered". | 372 // Simulate user input so that the form is "remembered". |
307 WebDocument document = GetMainFrame()->document(); | 373 WebDocument document = GetMainFrame()->document(); |
308 WebElement element = | 374 WebElement element = |
309 document.getElementById(WebString::fromUTF8("fname")); | 375 document.getElementById(WebString::fromUTF8("fname")); |
310 ASSERT_FALSE(element.isNull()); | 376 ASSERT_FALSE(element.isNull()); |
311 WebInputElement fname_element = element.to<WebInputElement>(); | 377 WebInputElement fname_element = element.to<WebInputElement>(); |
312 SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); | 378 SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); |
313 | 379 |
314 // Simulate an Ajax request completing. | 380 // Simulate an Ajax request completing. |
315 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); | 381 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
316 ProcessPendingMessages(); | 382 ProcessPendingMessages(); |
317 | 383 |
318 // No submission messages sent. | 384 // No submission messages sent. |
319 VerifyNoSubmitMessagesReceived(render_thread_.get()); | 385 VerifyNoSubmitMessagesReceived(fake_driver_); |
320 } | 386 } |
321 | 387 |
322 // Tests that completing an Ajax request without any prior form interaction | 388 // Tests that completing an Ajax request without any prior form interaction |
323 // does not trigger form submission from Autofill's point of view. | 389 // does not trigger form submission from Autofill's point of view. |
324 TEST_F(FormAutocompleteTest, AjaxSucceeded_NoFormInteractionInvisible) { | 390 TEST_F(FormAutocompleteTest, AjaxSucceeded_NoFormInteractionInvisible) { |
325 // Load a form. | 391 // Load a form. |
326 LoadHTML( | 392 LoadHTML( |
327 "<html><form id='myForm' action='http://example.com/blade.php'>" | 393 "<html><form id='myForm' action='http://example.com/blade.php'>" |
328 "<input name='fname' id='fname' value='Bob'/>" | 394 "<input name='fname' id='fname' value='Bob'/>" |
329 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); | 395 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); |
330 | 396 |
331 // No form interaction. | 397 // No form interaction. |
332 | 398 |
333 // Simulate removing the form just before the ajax request completes. | 399 // Simulate removing the form just before the ajax request completes. |
334 ExecuteJavaScriptForTests("var element = document.getElementById('myForm');" | 400 ExecuteJavaScriptForTests("var element = document.getElementById('myForm');" |
335 "element.parentNode.removeChild(element);"); | 401 "element.parentNode.removeChild(element);"); |
336 | 402 |
337 // Simulate an Ajax request completing without prior user interaction. | 403 // Simulate an Ajax request completing without prior user interaction. |
338 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); | 404 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
339 ProcessPendingMessages(); | 405 ProcessPendingMessages(); |
340 | 406 |
341 // No submission messages sent. | 407 // No submission messages sent. |
342 VerifyNoSubmitMessagesReceived(render_thread_.get()); | 408 VerifyNoSubmitMessagesReceived(fake_driver_); |
343 } | 409 } |
344 | 410 |
345 // Tests that completing an Ajax request after having autofilled a form, | 411 // Tests that completing an Ajax request after having autofilled a form, |
346 // with the form disappearing, will trigger submission from Autofill's | 412 // with the form disappearing, will trigger submission from Autofill's |
347 // point of view. | 413 // point of view. |
348 TEST_F(FormAutocompleteTest, AjaxSucceeded_FilledFormIsInvisible) { | 414 TEST_F(FormAutocompleteTest, AjaxSucceeded_FilledFormIsInvisible) { |
349 // Load a form. | 415 // Load a form. |
350 LoadHTML( | 416 LoadHTML( |
351 "<html><form id='myForm' action='http://example.com/blade.php'>" | 417 "<html><form id='myForm' action='http://example.com/blade.php'>" |
352 "<input name='fname' id='fname'/>" | 418 "<input name='fname' id='fname'/>" |
353 "<input name='lname'/></form></html>"); | 419 "<input name='lname'/></form></html>"); |
354 | 420 |
355 // Simulate filling a form using Autofill. | 421 // Simulate filling a form using Autofill. |
356 SimulateOnFillForm(render_thread_.get(), autofill_agent_, GetMainFrame()); | 422 SimulateOnFillForm(autofill_agent_, GetMainFrame()); |
357 | 423 |
358 // Simulate removing the form just before the ajax request completes. | 424 // Simulate removing the form just before the ajax request completes. |
359 ExecuteJavaScriptForTests("var element = document.getElementById('myForm');" | 425 ExecuteJavaScriptForTests("var element = document.getElementById('myForm');" |
360 "element.parentNode.removeChild(element);"); | 426 "element.parentNode.removeChild(element);"); |
361 | 427 |
362 // Simulate an Ajax request completing. | 428 // Simulate an Ajax request completing. |
363 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); | 429 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
364 ProcessPendingMessages(); | 430 ProcessPendingMessages(); |
365 | 431 |
366 VerifyReceivedRendererMessages(render_thread_.get(), "John", "Smith", | 432 VerifyReceivedRendererMessages(fake_driver_, "John", "Smith", |
367 true /* expect_submitted_message */); | 433 true /* expect_submitted_message */); |
368 } | 434 } |
369 | 435 |
370 // Tests that completing an Ajax request after having autofilled a form, | 436 // Tests that completing an Ajax request after having autofilled a form, |
371 // without the form disappearing, will not trigger submission from Autofill's | 437 // without the form disappearing, will not trigger submission from Autofill's |
372 // point of view. | 438 // point of view. |
373 TEST_F(FormAutocompleteTest, AjaxSucceeded_FilledFormStillVisible) { | 439 TEST_F(FormAutocompleteTest, AjaxSucceeded_FilledFormStillVisible) { |
374 // Load a form. | 440 // Load a form. |
375 LoadHTML( | 441 LoadHTML( |
376 "<html><form id='myForm' action='http://example.com/blade.php'>" | 442 "<html><form id='myForm' action='http://example.com/blade.php'>" |
377 "<input name='fname' id='fname' value='Rick'/>" | 443 "<input name='fname' id='fname' value='Rick'/>" |
378 "<input name='lname' value='Deckard'/></form></html>"); | 444 "<input name='lname' value='Deckard'/></form></html>"); |
379 | 445 |
380 // Simulate filling a form using Autofill. | 446 // Simulate filling a form using Autofill. |
381 SimulateOnFillForm(render_thread_.get(), autofill_agent_, GetMainFrame()); | 447 SimulateOnFillForm(autofill_agent_, GetMainFrame()); |
382 | 448 |
383 // Form still visible. | 449 // Form still visible. |
384 | 450 |
385 // Simulate an Ajax request completing. | 451 // Simulate an Ajax request completing. |
386 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); | 452 static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
387 ProcessPendingMessages(); | 453 ProcessPendingMessages(); |
388 | 454 |
389 // No submission messages sent. | 455 // No submission messages sent. |
390 VerifyNoSubmitMessagesReceived(render_thread_.get()); | 456 VerifyNoSubmitMessagesReceived(fake_driver_); |
391 } | 457 } |
392 | 458 |
393 // Test that a FocusNoLongerOnForm message is sent if focus goes from an | 459 // Test that a FocusNoLongerOnForm message is sent if focus goes from an |
394 // interacted form to an element outside the form. | 460 // interacted form to an element outside the form. |
395 TEST_F(FormAutocompleteTest, | 461 TEST_F(FormAutocompleteTest, |
396 InteractedFormNoLongerFocused_FocusNoLongerOnForm) { | 462 InteractedFormNoLongerFocused_FocusNoLongerOnForm) { |
397 // Load a form. | 463 // Load a form. |
398 LoadHTML( | 464 LoadHTML( |
399 "<html><input type='text' id='different'/>" | 465 "<html><input type='text' id='different'/>" |
400 "<form id='myForm' action='http://example.com/blade.php'>" | 466 "<form id='myForm' action='http://example.com/blade.php'>" |
401 "<input name='fname' id='fname' value='Bob'/>" | 467 "<input name='fname' id='fname' value='Bob'/>" |
402 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); | 468 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); |
403 | 469 |
404 // Simulate user input so that the form is "remembered". | 470 // Simulate user input so that the form is "remembered". |
405 WebDocument document = GetMainFrame()->document(); | 471 WebDocument document = GetMainFrame()->document(); |
406 WebElement element = document.getElementById(WebString::fromUTF8("fname")); | 472 WebElement element = document.getElementById(WebString::fromUTF8("fname")); |
407 ASSERT_FALSE(element.isNull()); | 473 ASSERT_FALSE(element.isNull()); |
408 WebInputElement fname_element = element.to<WebInputElement>(); | 474 WebInputElement fname_element = element.to<WebInputElement>(); |
409 SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); | 475 SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); |
410 | 476 |
477 ASSERT_FALSE(fake_driver_.called_nofocus_); | |
478 | |
411 // Change focus to a different node outside the form. | 479 // Change focus to a different node outside the form. |
412 WebElement different = | 480 WebElement different = |
413 document.getElementById(WebString::fromUTF8("different")); | 481 document.getElementById(WebString::fromUTF8("different")); |
414 SetFocused(different); | 482 SetFocused(different); |
415 | 483 |
416 ProcessPendingMessages(); | 484 base::RunLoop run_loop; |
485 run_loop.RunUntilIdle(); | |
417 | 486 |
418 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( | 487 EXPECT_TRUE(fake_driver_.called_nofocus_); |
419 AutofillHostMsg_FocusNoLongerOnForm::ID) != nullptr); | |
420 } | 488 } |
421 | 489 |
422 // Test that a FocusNoLongerOnForm message is sent if focus goes from one | 490 // Test that a FocusNoLongerOnForm message is sent if focus goes from one |
423 // interacted form to another. | 491 // interacted form to another. |
424 TEST_F(FormAutocompleteTest, InteractingInDifferentForms_FocusNoLongerOnForm) { | 492 TEST_F(FormAutocompleteTest, InteractingInDifferentForms_FocusNoLongerOnForm) { |
425 // Load a form. | 493 // Load a form. |
426 LoadHTML( | 494 LoadHTML( |
427 "<html><form id='myForm' action='http://example.com/blade.php'>" | 495 "<html><form id='myForm' action='http://example.com/blade.php'>" |
428 "<input name='fname' id='fname' value='Bob'/>" | 496 "<input name='fname' id='fname' value='Bob'/>" |
429 "<input name='lname' value='Deckard'/><input type=submit></form>" | 497 "<input name='lname' value='Deckard'/><input type=submit></form>" |
430 "<form id='myForm2' action='http://example.com/runner.php'>" | 498 "<form id='myForm2' action='http://example.com/runner.php'>" |
431 "<input name='fname' id='fname2' value='Bob'/>" | 499 "<input name='fname' id='fname2' value='Bob'/>" |
432 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); | 500 "<input name='lname' value='Deckard'/><input type=submit></form></html>"); |
433 | 501 |
434 // Simulate user input in the first form so that the form is "remembered". | 502 // Simulate user input in the first form so that the form is "remembered". |
435 WebDocument document = GetMainFrame()->document(); | 503 WebDocument document = GetMainFrame()->document(); |
436 WebElement element = document.getElementById(WebString::fromUTF8("fname")); | 504 WebElement element = document.getElementById(WebString::fromUTF8("fname")); |
437 ASSERT_FALSE(element.isNull()); | 505 ASSERT_FALSE(element.isNull()); |
438 WebInputElement fname_element = element.to<WebInputElement>(); | 506 WebInputElement fname_element = element.to<WebInputElement>(); |
439 SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); | 507 SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); |
440 | 508 |
509 ASSERT_FALSE(fake_driver_.called_nofocus_); | |
510 | |
441 // Simulate user input in the second form so that a "no longer focused" | 511 // Simulate user input in the second form so that a "no longer focused" |
442 // message is sent for the first form. | 512 // message is sent for the first form. |
443 document = GetMainFrame()->document(); | 513 document = GetMainFrame()->document(); |
444 element = document.getElementById(WebString::fromUTF8("fname2")); | 514 element = document.getElementById(WebString::fromUTF8("fname2")); |
445 ASSERT_FALSE(element.isNull()); | 515 ASSERT_FALSE(element.isNull()); |
446 fname_element = element.to<WebInputElement>(); | 516 fname_element = element.to<WebInputElement>(); |
447 SimulateUserInputChangeForElement(&fname_element, std::string("John")); | 517 SimulateUserInputChangeForElement(&fname_element, std::string("John")); |
448 | 518 |
449 ProcessPendingMessages(); | 519 base::RunLoop run_loop; |
520 run_loop.RunUntilIdle(); | |
450 | 521 |
451 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( | 522 EXPECT_TRUE(fake_driver_.called_nofocus_); |
452 AutofillHostMsg_FocusNoLongerOnForm::ID) != nullptr); | |
453 } | 523 } |
454 | 524 |
455 // Tests that submitting a form that has autocomplete="off" generates | 525 // Tests that submitting a form that has autocomplete="off" generates |
456 // WillSubmitForm and FormSubmitted messages. | 526 // WillSubmitForm and FormSubmitted messages. |
457 TEST_F(FormAutocompleteTest, AutoCompleteOffFormSubmit) { | 527 TEST_F(FormAutocompleteTest, AutoCompleteOffFormSubmit) { |
458 // Load a form. | 528 // Load a form. |
459 LoadHTML("<html><form id='myForm' autocomplete='off'>" | 529 LoadHTML("<html><form id='myForm' autocomplete='off'>" |
460 "<input name='fname' value='Rick'/>" | 530 "<input name='fname' value='Rick'/>" |
461 "<input name='lname' value='Deckard'/>" | 531 "<input name='lname' value='Deckard'/>" |
462 "</form></html>"); | 532 "</form></html>"); |
463 | 533 |
464 // Submit the form. | 534 // Submit the form. |
465 ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); | 535 ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); |
466 ProcessPendingMessages(); | 536 ProcessPendingMessages(); |
467 | 537 |
468 VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", | 538 VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
469 true /* expect_submitted_message */); | 539 true /* expect_submitted_message */); |
470 } | 540 } |
471 | 541 |
472 // Tests that fields with autocomplete off are submitted. | 542 // Tests that fields with autocomplete off are submitted. |
473 TEST_F(FormAutocompleteTest, AutoCompleteOffInputSubmit) { | 543 TEST_F(FormAutocompleteTest, AutoCompleteOffInputSubmit) { |
474 // Load a form. | 544 // Load a form. |
475 LoadHTML("<html><form id='myForm'>" | 545 LoadHTML("<html><form id='myForm'>" |
476 "<input name='fname' value='Rick'/>" | 546 "<input name='fname' value='Rick'/>" |
477 "<input name='lname' value='Deckard' autocomplete='off'/>" | 547 "<input name='lname' value='Deckard' autocomplete='off'/>" |
478 "</form></html>"); | 548 "</form></html>"); |
479 | 549 |
480 // Submit the form. | 550 // Submit the form. |
481 ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); | 551 ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); |
482 ProcessPendingMessages(); | 552 ProcessPendingMessages(); |
483 | 553 |
484 VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", | 554 VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
485 true /* expect_submitted_message */); | 555 true /* expect_submitted_message */); |
486 } | 556 } |
487 | 557 |
488 // Tests that submitting a form that has been dynamically set as autocomplete | 558 // Tests that submitting a form that has been dynamically set as autocomplete |
489 // off generates WillSubmitForm and FormSubmitted messages. | 559 // off generates WillSubmitForm and FormSubmitted messages. |
490 // Note: We previously did the opposite, for bug http://crbug.com/36520 | 560 // Note: We previously did the opposite, for bug http://crbug.com/36520 |
491 TEST_F(FormAutocompleteTest, DynamicAutoCompleteOffFormSubmit) { | 561 TEST_F(FormAutocompleteTest, DynamicAutoCompleteOffFormSubmit) { |
492 LoadHTML("<html><form id='myForm'><input name='fname' value='Rick'/>" | 562 LoadHTML("<html><form id='myForm'><input name='fname' value='Rick'/>" |
493 "<input name='lname' value='Deckard'/></form></html>"); | 563 "<input name='lname' value='Deckard'/></form></html>"); |
494 | 564 |
495 WebElement element = | 565 WebElement element = |
496 GetMainFrame()->document().getElementById(blink::WebString("myForm")); | 566 GetMainFrame()->document().getElementById(blink::WebString("myForm")); |
497 ASSERT_FALSE(element.isNull()); | 567 ASSERT_FALSE(element.isNull()); |
498 blink::WebFormElement form = element.to<blink::WebFormElement>(); | 568 blink::WebFormElement form = element.to<blink::WebFormElement>(); |
499 EXPECT_TRUE(form.autoComplete()); | 569 EXPECT_TRUE(form.autoComplete()); |
500 | 570 |
501 // Dynamically mark the form as autocomplete off. | 571 // Dynamically mark the form as autocomplete off. |
502 ExecuteJavaScriptForTests( | 572 ExecuteJavaScriptForTests( |
503 "document.getElementById('myForm')." | 573 "document.getElementById('myForm')." |
504 "setAttribute('autocomplete', 'off');"); | 574 "setAttribute('autocomplete', 'off');"); |
505 ProcessPendingMessages(); | 575 ProcessPendingMessages(); |
506 EXPECT_FALSE(form.autoComplete()); | 576 EXPECT_FALSE(form.autoComplete()); |
507 | 577 |
508 // Submit the form. | 578 // Submit the form. |
509 ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); | 579 ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); |
510 ProcessPendingMessages(); | 580 ProcessPendingMessages(); |
511 | 581 |
512 VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", | 582 VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
513 true /* expect_submitted_message */); | 583 true /* expect_submitted_message */); |
514 } | 584 } |
515 | 585 |
516 } // namespace autofill | 586 } // namespace autofill |
OLD | NEW |