1 // Copyright 2013 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.
7 #include "base/command_line.h"
8 #include "base/compiler_specific.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "components/autofill/core/browser/autofill_manager.h"
13 #include "components/autofill/core/browser/popup_item_ids.h"
14 #include "components/autofill/core/browser/test_autofill_client.h"
15 #include "components/autofill/core/browser/test_autofill_driver.h"
16 #include "components/autofill/core/browser/test_autofill_external_delegate.h"
17 #include "components/autofill/core/common/autofill_switches.h"
18 #include "components/autofill/core/common/form_data.h"
19 #include "components/autofill/core/common/form_field_data.h"
20 #include "components/autofill/core/common/password_form_fill_data.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/gfx/rect.h"
25 using base::ASCIIToUTF16;
32 // A constant value to use as the Autofill query ID.
33 const int kQueryId = 5;
35 // A constant value to use as an Autofill profile ID.
36 const int kAutofillProfileId = 1;
38 class MockAutofillDriver : public TestAutofillDriver {
40 MockAutofillDriver() {}
41 // Mock methods to enable testability.
42 MOCK_METHOD1(RendererShouldAcceptDataListSuggestion,
43 void(const base::string16&));
44 MOCK_METHOD0(RendererShouldClearFilledForm, void());
45 MOCK_METHOD0(RendererShouldClearPreviewedForm, void());
46 MOCK_METHOD1(RendererShouldFillFieldWithValue, void(const base::string16&));
47 MOCK_METHOD1(RendererShouldPreviewFieldWithValue,
48 void(const base::string16&));
51 DISALLOW_COPY_AND_ASSIGN(MockAutofillDriver);
54 class MockAutofillClient : public autofill::TestAutofillClient {
56 MockAutofillClient() {}
58 MOCK_METHOD7(ShowAutofillPopup,
59 void(const gfx::RectF& element_bounds,
60 base::i18n::TextDirection text_direction,
61 const std::vector<base::string16>& values,
62 const std::vector<base::string16>& labels,
63 const std::vector<base::string16>& icons,
64 const std::vector<int>& identifiers,
65 base::WeakPtr<AutofillPopupDelegate> delegate));
67 MOCK_METHOD2(UpdateAutofillPopupDataListValues,
68 void(const std::vector<base::string16>& values,
69 const std::vector<base::string16>& lables));
71 MOCK_METHOD0(HideAutofillPopup, void());
74 DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
77 class MockAutofillManager : public AutofillManager {
79 MockAutofillManager(AutofillDriver* driver, MockAutofillClient* client)
80 // Force to use the constructor designated for unit test, but we don't
81 // really need personal_data in this test so we pass a NULL pointer.
82 : AutofillManager(driver, client, NULL) {}
83 virtual ~MockAutofillManager() {}
85 MOCK_METHOD5(FillOrPreviewForm,
86 void(AutofillDriver::RendererFormDataAction action,
89 const FormFieldData& field,
93 DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
98 class AutofillExternalDelegateUnitTest : public testing::Test {
100 void SetUp() override {
101 autofill_driver_.reset(new MockAutofillDriver());
102 autofill_manager_.reset(
103 new MockAutofillManager(autofill_driver_.get(), &autofill_client_));
104 external_delegate_.reset(
105 new AutofillExternalDelegate(
106 autofill_manager_.get(), autofill_driver_.get()));
109 void TearDown() override {
110 // Order of destruction is important as AutofillManager relies on
111 // PersonalDataManager to be around when it gets destroyed.
112 autofill_manager_.reset();
113 external_delegate_.reset();
114 autofill_driver_.reset();
117 // Issue an OnQuery call with the given |query_id|.
118 void IssueOnQuery(int query_id) {
121 field.is_focusable = true;
122 field.should_autocomplete = true;
123 const gfx::RectF element_bounds;
125 external_delegate_->OnQuery(query_id, form, field, element_bounds, true);
128 MockAutofillClient autofill_client_;
129 scoped_ptr<MockAutofillDriver> autofill_driver_;
130 scoped_ptr<MockAutofillManager> autofill_manager_;
131 scoped_ptr<AutofillExternalDelegate> external_delegate_;
133 base::MessageLoop message_loop_;
136 // Test that our external delegate called the virtual methods at the right time.
137 TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) {
138 IssueOnQuery(kQueryId);
140 // The enums must be cast to ints to prevent compile errors on linux_rel.
148 testing::ElementsAre(
150 static_cast<int>(POPUP_ITEM_ID_SEPARATOR),
151 static_cast<int>(POPUP_ITEM_ID_AUTOFILL_OPTIONS)),
154 // This should call ShowAutofillPopup.
155 std::vector<base::string16> autofill_item;
156 autofill_item.push_back(base::string16());
157 std::vector<int> autofill_ids;
158 autofill_ids.push_back(kAutofillProfileId);
159 external_delegate_->OnSuggestionsReturned(kQueryId,
165 EXPECT_CALL(*autofill_manager_,
167 AutofillDriver::FORM_DATA_ACTION_FILL, _, _, _, _));
168 EXPECT_CALL(autofill_client_, HideAutofillPopup());
170 // This should trigger a call to hide the popup since we've selected an
172 external_delegate_->DidAcceptSuggestion(autofill_item[0], autofill_ids[0]);
175 // Test that data list elements for a node will appear in the Autofill popup.
176 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateDataList) {
177 IssueOnQuery(kQueryId);
179 std::vector<base::string16> data_list_items;
180 data_list_items.push_back(base::string16());
184 UpdateAutofillPopupDataListValues(data_list_items, data_list_items));
186 external_delegate_->SetCurrentDataListValues(data_list_items,
189 // The enums must be cast to ints to prevent compile errors on linux_rel.
197 testing::ElementsAre(
198 static_cast<int>(POPUP_ITEM_ID_DATALIST_ENTRY),
199 static_cast<int>(POPUP_ITEM_ID_SEPARATOR),
201 static_cast<int>(POPUP_ITEM_ID_SEPARATOR),
202 static_cast<int>(POPUP_ITEM_ID_AUTOFILL_OPTIONS)),
205 // This should call ShowAutofillPopup.
206 std::vector<base::string16> autofill_item;
207 autofill_item.push_back(base::string16());
208 std::vector<int> autofill_ids;
209 autofill_ids.push_back(kAutofillProfileId);
210 external_delegate_->OnSuggestionsReturned(kQueryId,
216 // Try calling OnSuggestionsReturned with no Autofill values and ensure
217 // the datalist items are still shown.
218 // The enum must be cast to an int to prevent compile errors on linux_rel.
227 testing::ElementsAre(static_cast<int>(POPUP_ITEM_ID_DATALIST_ENTRY)),
230 autofill_item = std::vector<base::string16>();
231 autofill_ids = std::vector<int>();
232 external_delegate_->OnSuggestionsReturned(kQueryId,
239 // Test that datalist values can get updated while a popup is showing.
240 TEST_F(AutofillExternalDelegateUnitTest, UpdateDataListWhileShowingPopup) {
241 IssueOnQuery(kQueryId);
243 EXPECT_CALL(autofill_client_, ShowAutofillPopup(_, _, _, _, _, _, _))
246 // Make sure just setting the data list values doesn't cause the popup to
248 std::vector<base::string16> data_list_items;
249 data_list_items.push_back(base::string16());
253 UpdateAutofillPopupDataListValues(data_list_items, data_list_items));
255 external_delegate_->SetCurrentDataListValues(data_list_items,
258 // The enums must be cast to ints to prevent compile errors on linux_rel.
266 testing::ElementsAre(
267 static_cast<int>(POPUP_ITEM_ID_DATALIST_ENTRY),
268 static_cast<int>(POPUP_ITEM_ID_SEPARATOR),
270 static_cast<int>(POPUP_ITEM_ID_SEPARATOR),
271 static_cast<int>(POPUP_ITEM_ID_AUTOFILL_OPTIONS)),
274 // Ensure the popup is displayed.
275 std::vector<base::string16> autofill_item;
276 autofill_item.push_back(base::string16());
277 std::vector<int> autofill_ids;
278 autofill_ids.push_back(kAutofillProfileId);
279 external_delegate_->OnSuggestionsReturned(kQueryId,
285 // This would normally get called from ShowAutofillPopup, but it is mocked so
286 // we need to call OnPopupShown ourselves.
287 external_delegate_->OnPopupShown();
289 // Update the current data list and ensure the popup is updated.
290 data_list_items.push_back(base::string16());
292 // The enums must be cast to ints to prevent compile errors on linux_rel.
295 UpdateAutofillPopupDataListValues(data_list_items, data_list_items));
297 external_delegate_->SetCurrentDataListValues(data_list_items,
301 // Test that the Autofill popup is able to display warnings explaining why
302 // Autofill is disabled for a website.
303 // Regression test for http://crbug.com/247880
304 TEST_F(AutofillExternalDelegateUnitTest, AutofillWarnings) {
305 IssueOnQuery(kQueryId);
307 // The enums must be cast to ints to prevent compile errors on linux_rel.
316 testing::ElementsAre(static_cast<int>(POPUP_ITEM_ID_WARNING_MESSAGE)),
319 // This should call ShowAutofillPopup.
320 std::vector<base::string16> autofill_item;
321 autofill_item.push_back(base::string16());
322 std::vector<int> autofill_ids;
323 autofill_ids.push_back(POPUP_ITEM_ID_WARNING_MESSAGE);
324 external_delegate_->OnSuggestionsReturned(kQueryId,
331 // Test that the Autofill popup doesn't display a warning explaining why
332 // Autofill is disabled for a website when there are no Autofill suggestions.
333 // Regression test for http://crbug.com/105636
334 TEST_F(AutofillExternalDelegateUnitTest, NoAutofillWarningsWithoutSuggestions) {
337 field.is_focusable = true;
338 field.should_autocomplete = false;
339 const gfx::RectF element_bounds;
341 external_delegate_->OnQuery(kQueryId, form, field, element_bounds, true);
343 EXPECT_CALL(autofill_client_, ShowAutofillPopup(_, _, _, _, _, _, _))
345 EXPECT_CALL(autofill_client_, HideAutofillPopup()).Times(1);
347 // This should not call ShowAutofillPopup.
348 std::vector<base::string16> autofill_item;
349 autofill_item.push_back(base::string16());
350 std::vector<int> autofill_ids;
351 autofill_ids.push_back(POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY);
352 external_delegate_->OnSuggestionsReturned(kQueryId,
359 // Test that the Autofill delegate doesn't try and fill a form with a
360 // negative unique id.
361 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateInvalidUniqueId) {
362 // Ensure it doesn't try to preview the negative id.
363 EXPECT_CALL(*autofill_manager_, FillOrPreviewForm(_, _, _, _, _)).Times(0);
364 EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm()).Times(1);
365 external_delegate_->DidSelectSuggestion(base::string16(), -1);
367 // Ensure it doesn't try to fill the form in with the negative id.
368 EXPECT_CALL(autofill_client_, HideAutofillPopup());
369 EXPECT_CALL(*autofill_manager_, FillOrPreviewForm(_, _, _, _, _)).Times(0);
370 external_delegate_->DidAcceptSuggestion(base::string16(), -1);
373 // Test that the ClearPreview call is only sent if the form was being previewed
374 // (i.e. it isn't autofilling a password).
375 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearPreviewedForm) {
376 // Ensure selecting a new password entries or Autofill entries will
377 // cause any previews to get cleared.
378 EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm()).Times(1);
379 external_delegate_->DidSelectSuggestion(ASCIIToUTF16("baz foo"),
380 POPUP_ITEM_ID_PASSWORD_ENTRY);
381 EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm()).Times(1);
382 EXPECT_CALL(*autofill_manager_,
384 AutofillDriver::FORM_DATA_ACTION_PREVIEW, _, _, _, _));
385 external_delegate_->DidSelectSuggestion(ASCIIToUTF16("baz foo"), 1);
387 // Ensure selecting an autocomplete entry will cause any previews to
389 EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm()).Times(1);
390 EXPECT_CALL(*autofill_driver_, RendererShouldPreviewFieldWithValue(
391 ASCIIToUTF16("baz foo")));
392 external_delegate_->DidSelectSuggestion(ASCIIToUTF16("baz foo"),
393 POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY);
396 // Test that the popup is hidden once we are done editing the autofill field.
397 TEST_F(AutofillExternalDelegateUnitTest,
398 ExternalDelegateHidePopupAfterEditing) {
399 EXPECT_CALL(autofill_client_, ShowAutofillPopup(_, _, _, _, _, _, _));
400 autofill::GenerateTestAutofillPopup(external_delegate_.get());
402 EXPECT_CALL(autofill_client_, HideAutofillPopup());
403 external_delegate_->DidEndTextFieldEditing();
406 // Test that the driver is directed to accept the data list after being notified
407 // that the user accepted the data list suggestion.
408 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateAcceptSuggestion) {
409 EXPECT_CALL(autofill_client_, HideAutofillPopup());
410 base::string16 dummy_string(ASCIIToUTF16("baz qux"));
411 EXPECT_CALL(*autofill_driver_,
412 RendererShouldAcceptDataListSuggestion(dummy_string));
413 external_delegate_->DidAcceptSuggestion(dummy_string,
414 POPUP_ITEM_ID_DATALIST_ENTRY);
417 // Test that the driver is directed to clear the form after being notified that
418 // the user accepted the suggestion to clear the form.
419 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearForm) {
420 EXPECT_CALL(autofill_client_, HideAutofillPopup());
421 EXPECT_CALL(*autofill_driver_, RendererShouldClearFilledForm());
423 external_delegate_->DidAcceptSuggestion(base::string16(),
424 POPUP_ITEM_ID_CLEAR_FORM);
427 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateHideWarning) {
428 // Set up a field that shouldn't get autocompleted or display warnings.
431 field.is_focusable = true;
432 field.should_autocomplete = false;
433 const gfx::RectF element_bounds;
435 external_delegate_->OnQuery(kQueryId, form, field, element_bounds, false);
437 std::vector<base::string16> autofill_items;
438 autofill_items.push_back(base::string16());
439 std::vector<int> autofill_ids;
440 autofill_ids.push_back(POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY);
442 // Ensure the popup tries to hide itself, since it is not allowed to show
444 EXPECT_CALL(autofill_client_, HideAutofillPopup());
446 external_delegate_->OnSuggestionsReturned(kQueryId,
453 TEST_F(AutofillExternalDelegateUnitTest, IgnoreAutocompleteOffForAutofill) {
454 CommandLine::ForCurrentProcess()->AppendSwitch(
455 switches::kIgnoreAutocompleteOffForAutofill);
459 field.is_focusable = true;
460 field.should_autocomplete = false;
461 const gfx::RectF element_bounds;
463 external_delegate_->OnQuery(kQueryId, form, field, element_bounds, false);
465 std::vector<base::string16> autofill_items;
466 autofill_items.push_back(base::string16());
467 std::vector<int> autofill_ids;
468 autofill_ids.push_back(POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY);
470 // Ensure the popup tries to show itself, despite autocomplete="off".
471 EXPECT_CALL(autofill_client_, ShowAutofillPopup(_, _, _, _, _, _, _));
472 EXPECT_CALL(autofill_client_, HideAutofillPopup()).Times(0);
474 external_delegate_->OnSuggestionsReturned(kQueryId,
481 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateFillFieldWithValue) {
482 EXPECT_CALL(autofill_client_, HideAutofillPopup());
483 base::string16 dummy_string(ASCIIToUTF16("baz foo"));
484 EXPECT_CALL(*autofill_driver_,
485 RendererShouldFillFieldWithValue(dummy_string));
486 external_delegate_->DidAcceptSuggestion(dummy_string,
487 POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY);
490 } // namespace autofill