Index: chrome/renderer/autofill/form_autocomplete_browsertest.cc |
diff --git a/chrome/renderer/autofill/form_autocomplete_browsertest.cc b/chrome/renderer/autofill/form_autocomplete_browsertest.cc |
index 1527bd28de9cdc9b12dbb52526f73d871c9b3d14..b4f52c95f79c1600d52a2ede8d1d3b761d1f280c 100644 |
--- a/chrome/renderer/autofill/form_autocomplete_browsertest.cc |
+++ b/chrome/renderer/autofill/form_autocomplete_browsertest.cc |
@@ -11,7 +11,10 @@ |
#include "components/autofill/content/common/autofill_messages.h" |
#include "components/autofill/content/renderer/autofill_agent.h" |
#include "components/autofill/core/common/form_data.h" |
-#include "content/public/test/mock_render_thread.h" |
+#include "content/public/renderer/render_frame.h" |
+#include "content/public/renderer/render_view.h" |
+#include "mojo/public/cpp/bindings/binding_set.h" |
+#include "services/shell/public/cpp/interface_provider.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "third_party/WebKit/public/web/WebDocument.h" |
#include "third_party/WebKit/public/web/WebElement.h" |
@@ -24,72 +27,124 @@ using blink::WebElement; |
using blink::WebInputElement; |
using blink::WebString; |
-typedef ChromeRenderViewTest FormAutocompleteTest; |
- |
namespace autofill { |
namespace { |
+class FakeContentAutofillDriver : public mojom::AutofillDriver { |
+ public: |
+ FakeContentAutofillDriver() : called_nofocus_(false) {} |
+ |
+ ~FakeContentAutofillDriver() override {} |
+ |
+ void BindRequest(mojom::AutofillDriverRequest request) { |
+ bindings_.AddBinding(this, std::move(request)); |
+ } |
+ |
+ bool GetCalledNoFocus() const { return called_nofocus_; } |
+ |
+ const FormData* GetFormWillSubmit() const { return form_willsubmit_.get(); } |
+ |
+ const FormData* GetFormSubmitted() const { return form_submitted_.get(); } |
+ |
+ private: |
+ // mojom::AutofillDriver: |
+ void FirstUserGestureObserved() override {} |
+ |
+ void FormsSeen(mojo::Array<FormData> forms, |
+ const base::TimeTicks& timestamp) override {} |
+ |
+ void WillSubmitForm(const FormData& form, |
+ const base::TimeTicks& timestamp) override { |
+ form_willsubmit_.reset(new FormData(form)); |
+ } |
+ |
+ void FormSubmitted(const FormData& form) override { |
+ form_submitted_.reset(new FormData(form)); |
+ } |
+ |
+ void TextFieldDidChange(const FormData& form, |
+ const FormFieldData& field, |
+ const base::TimeTicks& timestamp) override {} |
+ |
+ void QueryFormFieldAutofill(int32_t id, |
+ const FormData& form, |
+ const FormFieldData& field, |
+ const gfx::RectF& bounding_box) override {} |
+ |
+ void HidePopup() override {} |
+ |
+ void PingAck() override {} |
+ |
+ void FocusNoLongerOnForm() override { called_nofocus_ = true; } |
+ |
+ void DidFillAutofillFormData(const FormData& form, |
+ const base::TimeTicks& timestamp) override {} |
+ |
+ void DidPreviewAutofillFormData() override {} |
+ |
+ void DidEndTextFieldEditing() override {} |
+ |
+ void SetDataList(mojo::Array<mojo::String> values, |
+ mojo::Array<mojo::String> labels) override {} |
+ |
+ // Records whether FocusNoLongerOnForm() get called. |
+ bool called_nofocus_; |
+ // Records the form data received via WillSubmitForm() call. |
+ std::unique_ptr<FormData> form_willsubmit_; |
+ // Records the form data received via FormSubmitted() call. |
+ std::unique_ptr<FormData> form_submitted_; |
+ |
+ mojo::BindingSet<mojom::AutofillDriver> bindings_; |
+}; |
+ |
// Helper function to verify the form-related messages received from the |
// renderer. The same data is expected in both messages. Depending on |
// |expect_submitted_message|, will verify presence of FormSubmitted message. |
-void VerifyReceivedRendererMessages(content::MockRenderThread* render_thread, |
- const std::string& fname, |
- const std::string& lname, |
- bool expect_submitted_message) { |
- const IPC::Message* will_submit_message = |
- render_thread->sink().GetFirstMessageMatching( |
- AutofillHostMsg_WillSubmitForm::ID); |
- const IPC::Message* submitted_message = |
- render_thread->sink().GetFirstMessageMatching( |
- AutofillHostMsg_FormSubmitted::ID); |
- ASSERT_TRUE(will_submit_message != NULL); |
- ASSERT_EQ(expect_submitted_message, submitted_message != NULL); |
+void VerifyReceivedRendererMessages( |
+ const FakeContentAutofillDriver& fake_driver, |
+ const std::string& fname, |
+ const std::string& lname, |
+ bool expect_submitted_message) { |
+ ASSERT_TRUE(fake_driver.GetFormWillSubmit()); |
+ ASSERT_EQ(expect_submitted_message, |
+ fake_driver.GetFormSubmitted() != nullptr); |
// The tuple also includes a timestamp, which is ignored. |
- std::tuple<FormData, base::TimeTicks> will_submit_forms; |
- AutofillHostMsg_WillSubmitForm::Read(will_submit_message, &will_submit_forms); |
- ASSERT_LE(2U, std::get<0>(will_submit_forms).fields.size()); |
- |
- FormFieldData& will_submit_form_field = |
- std::get<0>(will_submit_forms).fields[0]; |
- EXPECT_EQ(WebString("fname"), will_submit_form_field.name); |
- EXPECT_EQ(WebString(base::UTF8ToUTF16(fname)), will_submit_form_field.value); |
- will_submit_form_field = std::get<0>(will_submit_forms).fields[1]; |
- EXPECT_EQ(WebString("lname"), will_submit_form_field.name); |
- EXPECT_EQ(WebString(base::UTF8ToUTF16(lname)), will_submit_form_field.value); |
+ const FormData& will_submit_form = *(fake_driver.GetFormWillSubmit()); |
+ ASSERT_LE(2U, will_submit_form.fields.size()); |
+ |
+ EXPECT_EQ(WebString("fname"), will_submit_form.fields[0].name); |
+ EXPECT_EQ(WebString(base::UTF8ToUTF16(fname)), |
+ will_submit_form.fields[0].value); |
+ EXPECT_EQ(WebString("lname"), will_submit_form.fields[1].name); |
+ EXPECT_EQ(WebString(base::UTF8ToUTF16(lname)), |
+ will_submit_form.fields[1].value); |
if (expect_submitted_message) { |
- std::tuple<FormData> submitted_forms; |
- AutofillHostMsg_FormSubmitted::Read(submitted_message, &submitted_forms); |
- ASSERT_LE(2U, std::get<0>(submitted_forms).fields.size()); |
- |
- FormFieldData& submitted_field = std::get<0>(submitted_forms).fields[0]; |
- EXPECT_EQ(WebString("fname"), submitted_field.name); |
- EXPECT_EQ(WebString(base::UTF8ToUTF16(fname)), submitted_field.value); |
- submitted_field = std::get<0>(submitted_forms).fields[1]; |
- EXPECT_EQ(WebString("lname"), submitted_field.name); |
- EXPECT_EQ(WebString(base::UTF8ToUTF16(lname)), submitted_field.value); |
+ const FormData& submitted_form = *(fake_driver.GetFormSubmitted()); |
+ ASSERT_LE(2U, submitted_form.fields.size()); |
+ |
+ EXPECT_EQ(WebString("fname"), submitted_form.fields[0].name); |
+ EXPECT_EQ(WebString(base::UTF8ToUTF16(fname)), |
+ submitted_form.fields[0].value); |
+ EXPECT_EQ(WebString("lname"), submitted_form.fields[1].name); |
+ EXPECT_EQ(WebString(base::UTF8ToUTF16(lname)), |
+ submitted_form.fields[1].value); |
} |
} |
// Helper function to verify that NO form-related messages are received from the |
// renderer. |
-void VerifyNoSubmitMessagesReceived(content::MockRenderThread* render_thread) { |
+void VerifyNoSubmitMessagesReceived( |
+ const FakeContentAutofillDriver& fake_driver) { |
// No submission messages sent. |
- const IPC::Message* will_submit_message = |
- render_thread->sink().GetFirstMessageMatching( |
- AutofillHostMsg_WillSubmitForm::ID); |
- const IPC::Message* submitted_message = |
- render_thread->sink().GetFirstMessageMatching( |
- AutofillHostMsg_FormSubmitted::ID); |
- EXPECT_EQ(NULL, will_submit_message); |
- EXPECT_EQ(NULL, submitted_message); |
+ EXPECT_EQ(nullptr, fake_driver.GetFormWillSubmit()); |
+ EXPECT_EQ(nullptr, fake_driver.GetFormSubmitted()); |
} |
// Simulates receiving a message from the browser to fill a form. |
-void SimulateOnFillForm(content::MockRenderThread* render_thread, |
- autofill::AutofillAgent* autofill_agent, |
+void SimulateOnFillForm(autofill::AutofillAgent* autofill_agent, |
blink::WebFrame* main_frame) { |
WebDocument document = main_frame->document(); |
WebElement element = |
@@ -98,7 +153,6 @@ void SimulateOnFillForm(content::MockRenderThread* render_thread, |
// This call is necessary to setup the autofill agent appropriate for the |
// user selection; simulates the menu actually popping up. |
- render_thread->sink().ClearMessages(); |
static_cast<autofill::PageClickListener*>(autofill_agent) |
->FormControlElementClicked(element.to<WebInputElement>(), false); |
@@ -119,13 +173,42 @@ void SimulateOnFillForm(content::MockRenderThread* render_thread, |
field_data.is_autofilled = true; |
data.fields.push_back(field_data); |
- AutofillMsg_FillForm msg(0, 0, data); |
- static_cast<content::RenderFrameObserver*>(autofill_agent) |
- ->OnMessageReceived(msg); |
+ autofill_agent->FillForm(0, data); |
} |
} // end namespace |
+class FormAutocompleteTest : public ChromeRenderViewTest { |
+ public: |
+ FormAutocompleteTest() {} |
+ ~FormAutocompleteTest() override {} |
+ |
+ protected: |
+ void SetUp() override { |
+ ChromeRenderViewTest::SetUp(); |
+ |
+ // We only use the fake driver for main frame |
+ // because our test cases only involve the main frame. |
+ shell::InterfaceProvider* remote_interfaces = |
+ view_->GetMainRenderFrame()->GetRemoteInterfaces(); |
+ shell::InterfaceProvider::TestApi test_api(remote_interfaces); |
+ test_api.SetBinderForName( |
+ mojom::AutofillDriver::Name_, |
+ base::Bind(&FormAutocompleteTest::BindAutofillDriver, |
+ base::Unretained(this))); |
+ } |
+ |
+ void BindAutofillDriver(mojo::ScopedMessagePipeHandle handle) { |
+ fake_driver_.BindRequest( |
+ mojo::MakeRequest<mojom::AutofillDriver>(std::move(handle))); |
+ } |
+ |
+ FakeContentAutofillDriver fake_driver_; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(FormAutocompleteTest); |
+}; |
+ |
// Tests that submitting a form generates WillSubmitForm and FormSubmitted |
// messages with the form fields. |
TEST_F(FormAutocompleteTest, NormalFormSubmit) { |
@@ -137,7 +220,7 @@ TEST_F(FormAutocompleteTest, NormalFormSubmit) { |
ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", |
+ VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
true /* expect_submitted_message */); |
} |
@@ -157,7 +240,7 @@ TEST_F(FormAutocompleteTest, SubmitEventPrevented) { |
"document.querySelector('input[type=submit]').click();"); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", |
+ VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
false /* expect_submitted_message */); |
} |
@@ -186,7 +269,7 @@ TEST_F(FormAutocompleteTest, AjaxSucceeded_NoLongerVisible) { |
static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", |
+ VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
true /* expect_submitted_message */); |
} |
@@ -220,7 +303,7 @@ TEST_F(FormAutocompleteTest, |
static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", |
+ VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
true /* expect_submitted_message */); |
} |
@@ -261,7 +344,7 @@ TEST_F(FormAutocompleteTest, MAYBE_NoLongerVisibleBothNoActions) { |
static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", |
+ VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
true /* expect_submitted_message */); |
} |
@@ -290,7 +373,7 @@ TEST_F(FormAutocompleteTest, AjaxSucceeded_NoLongerVisible_NoAction) { |
static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", |
+ VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
true /* expect_submitted_message */); |
} |
@@ -316,7 +399,7 @@ TEST_F(FormAutocompleteTest, AjaxSucceeded_StillVisible) { |
ProcessPendingMessages(); |
// No submission messages sent. |
- VerifyNoSubmitMessagesReceived(render_thread_.get()); |
+ VerifyNoSubmitMessagesReceived(fake_driver_); |
} |
// Tests that completing an Ajax request without any prior form interaction |
@@ -339,7 +422,7 @@ TEST_F(FormAutocompleteTest, AjaxSucceeded_NoFormInteractionInvisible) { |
ProcessPendingMessages(); |
// No submission messages sent. |
- VerifyNoSubmitMessagesReceived(render_thread_.get()); |
+ VerifyNoSubmitMessagesReceived(fake_driver_); |
} |
// Tests that completing an Ajax request after having autofilled a form, |
@@ -353,7 +436,7 @@ TEST_F(FormAutocompleteTest, AjaxSucceeded_FilledFormIsInvisible) { |
"<input name='lname'/></form></html>"); |
// Simulate filling a form using Autofill. |
- SimulateOnFillForm(render_thread_.get(), autofill_agent_, GetMainFrame()); |
+ SimulateOnFillForm(autofill_agent_, GetMainFrame()); |
// Simulate removing the form just before the ajax request completes. |
ExecuteJavaScriptForTests("var element = document.getElementById('myForm');" |
@@ -363,7 +446,7 @@ TEST_F(FormAutocompleteTest, AjaxSucceeded_FilledFormIsInvisible) { |
static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "John", "Smith", |
+ VerifyReceivedRendererMessages(fake_driver_, "John", "Smith", |
true /* expect_submitted_message */); |
} |
@@ -378,7 +461,7 @@ TEST_F(FormAutocompleteTest, AjaxSucceeded_FilledFormStillVisible) { |
"<input name='lname' value='Deckard'/></form></html>"); |
// Simulate filling a form using Autofill. |
- SimulateOnFillForm(render_thread_.get(), autofill_agent_, GetMainFrame()); |
+ SimulateOnFillForm(autofill_agent_, GetMainFrame()); |
// Form still visible. |
@@ -387,7 +470,7 @@ TEST_F(FormAutocompleteTest, AjaxSucceeded_FilledFormStillVisible) { |
ProcessPendingMessages(); |
// No submission messages sent. |
- VerifyNoSubmitMessagesReceived(render_thread_.get()); |
+ VerifyNoSubmitMessagesReceived(fake_driver_); |
} |
// Tests that completing an Ajax request without a form present will still |
@@ -417,7 +500,7 @@ TEST_F(FormAutocompleteTest, AjaxSucceeded_FormlessElements) { |
static_cast<blink::WebAutofillClient*>(autofill_agent_)->ajaxSucceeded(); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "Kirby", "Puckett", |
+ VerifyReceivedRendererMessages(fake_driver_, "Kirby", "Puckett", |
/* expect_submitted_message = */ true); |
} |
@@ -465,15 +548,17 @@ TEST_F(FormAutocompleteTest, |
WebInputElement fname_element = element.to<WebInputElement>(); |
SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); |
+ ASSERT_FALSE(fake_driver_.GetCalledNoFocus()); |
+ |
// Change focus to a different node outside the form. |
WebElement different = |
document.getElementById(WebString::fromUTF8("different")); |
SetFocused(different); |
- ProcessPendingMessages(); |
+ base::RunLoop run_loop; |
+ run_loop.RunUntilIdle(); |
- EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( |
- AutofillHostMsg_FocusNoLongerOnForm::ID) != nullptr); |
+ EXPECT_TRUE(fake_driver_.GetCalledNoFocus()); |
} |
// Test that a FocusNoLongerOnForm message is sent if focus goes from one |
@@ -495,6 +580,8 @@ TEST_F(FormAutocompleteTest, InteractingInDifferentForms_FocusNoLongerOnForm) { |
WebInputElement fname_element = element.to<WebInputElement>(); |
SimulateUserInputChangeForElement(&fname_element, std::string("Rick")); |
+ ASSERT_FALSE(fake_driver_.GetCalledNoFocus()); |
+ |
// Simulate user input in the second form so that a "no longer focused" |
// message is sent for the first form. |
document = GetMainFrame()->document(); |
@@ -503,10 +590,10 @@ TEST_F(FormAutocompleteTest, InteractingInDifferentForms_FocusNoLongerOnForm) { |
fname_element = element.to<WebInputElement>(); |
SimulateUserInputChangeForElement(&fname_element, std::string("John")); |
- ProcessPendingMessages(); |
+ base::RunLoop run_loop; |
+ run_loop.RunUntilIdle(); |
- EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( |
- AutofillHostMsg_FocusNoLongerOnForm::ID) != nullptr); |
+ EXPECT_TRUE(fake_driver_.GetCalledNoFocus()); |
} |
// Tests that submitting a form that has autocomplete="off" generates |
@@ -522,7 +609,7 @@ TEST_F(FormAutocompleteTest, AutoCompleteOffFormSubmit) { |
ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", |
+ VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
true /* expect_submitted_message */); |
} |
@@ -538,7 +625,7 @@ TEST_F(FormAutocompleteTest, AutoCompleteOffInputSubmit) { |
ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", |
+ VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
true /* expect_submitted_message */); |
} |
@@ -566,7 +653,7 @@ TEST_F(FormAutocompleteTest, DynamicAutoCompleteOffFormSubmit) { |
ExecuteJavaScriptForTests("document.getElementById('myForm').submit();"); |
ProcessPendingMessages(); |
- VerifyReceivedRendererMessages(render_thread_.get(), "Rick", "Deckard", |
+ VerifyReceivedRendererMessages(fake_driver_, "Rick", "Deckard", |
true /* expect_submitted_message */); |
} |