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/compiler_specific.h"
8 #include "base/strings/string16.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
11 #include "chrome/test/base/testing_profile.h"
12 #include "components/autofill/core/browser/autofill_manager.h"
13 #include "components/autofill/core/browser/test_autofill_driver.h"
14 #include "components/autofill/core/browser/test_autofill_external_delegate.h"
15 #include "components/autofill/core/browser/test_autofill_manager_delegate.h"
16 #include "components/autofill/core/common/form_data.h"
17 #include "components/autofill/core/common/form_field_data.h"
18 #include "components/autofill/core/common/password_form_fill_data.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "third_party/WebKit/public/web/WebAutofillClient.h"
22 #include "ui/gfx/rect.h"
25 using WebKit::WebAutofillClient;
31 // A constant value to use as the Autofill query ID.
32 const int kQueryId = 5;
34 // A constant value to use as an Autofill profile ID.
35 const int kAutofillProfileId = 1;
37 class MockAutofillDriver : public TestAutofillDriver {
39 explicit MockAutofillDriver(content::WebContents* web_contents)
40 : TestAutofillDriver(web_contents) {}
42 // Mock methods to enable testability.
43 MOCK_METHOD1(SetRendererActionOnFormDataReception,
44 void(RendererFormDataAction action));
45 MOCK_METHOD0(RendererShouldClearFilledForm, void());
46 MOCK_METHOD0(RendererShouldClearPreviewedForm, void());
49 DISALLOW_COPY_AND_ASSIGN(MockAutofillDriver);
52 class MockAutofillManagerDelegate
53 : public autofill::TestAutofillManagerDelegate {
55 MockAutofillManagerDelegate() {}
57 MOCK_METHOD7(ShowAutofillPopup,
58 void(const gfx::RectF& element_bounds,
59 base::i18n::TextDirection text_direction,
60 const std::vector<base::string16>& values,
61 const std::vector<base::string16>& labels,
62 const std::vector<base::string16>& icons,
63 const std::vector<int>& identifiers,
64 base::WeakPtr<AutofillPopupDelegate> delegate));
66 MOCK_METHOD2(UpdateAutofillPopupDataListValues,
67 void(const std::vector<base::string16>& values,
68 const std::vector<base::string16>& lables));
70 MOCK_METHOD0(HideAutofillPopup, void());
73 DISALLOW_COPY_AND_ASSIGN(MockAutofillManagerDelegate);
76 class MockAutofillManager : public AutofillManager {
78 MockAutofillManager(AutofillDriver* driver,
79 MockAutofillManagerDelegate* delegate)
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, delegate, NULL) {
84 virtual ~MockAutofillManager() {}
86 MOCK_METHOD4(OnFillAutofillFormData,
89 const FormFieldData& field,
93 DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
98 class AutofillExternalDelegateUnitTest
99 : public ChromeRenderViewHostTestHarness {
101 virtual void SetUp() OVERRIDE {
102 ChromeRenderViewHostTestHarness::SetUp();
103 autofill_driver_.reset(new MockAutofillDriver(web_contents()));
104 autofill_manager_.reset(
105 new MockAutofillManager(autofill_driver_.get(),
106 &manager_delegate_));
107 external_delegate_.reset(
108 new AutofillExternalDelegate(
110 autofill_manager_.get(), autofill_driver_.get()));
113 virtual void TearDown() OVERRIDE {
114 // Order of destruction is important as AutofillManager relies on
115 // PersonalDataManager to be around when it gets destroyed. Also, a real
116 // AutofillManager is tied to the lifetime of the WebContents, so it must
117 // be destroyed at the destruction of the WebContents.
118 autofill_manager_.reset();
119 external_delegate_.reset();
120 autofill_driver_.reset();
121 ChromeRenderViewHostTestHarness::TearDown();
124 // Issue an OnQuery call with the given |query_id|.
125 void IssueOnQuery(int query_id) {
128 field.is_focusable = true;
129 field.should_autocomplete = true;
130 const gfx::RectF element_bounds;
132 external_delegate_->OnQuery(query_id, form, field, element_bounds, true);
135 MockAutofillManagerDelegate manager_delegate_;
136 scoped_ptr<MockAutofillDriver> autofill_driver_;
137 scoped_ptr<MockAutofillManager> autofill_manager_;
138 scoped_ptr<AutofillExternalDelegate> external_delegate_;
141 // Test that our external delegate called the virtual methods at the right time.
142 TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) {
143 IssueOnQuery(kQueryId);
145 // The enums must be cast to ints to prevent compile errors on linux_rel.
146 EXPECT_CALL(manager_delegate_,
149 testing::ElementsAre(
151 static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
153 WebAutofillClient::MenuItemIDAutofillOptions)),
156 // This should call ShowAutofillPopup.
157 std::vector<base::string16> autofill_item;
158 autofill_item.push_back(base::string16());
159 std::vector<int> autofill_ids;
160 autofill_ids.push_back(kAutofillProfileId);
161 external_delegate_->OnSuggestionsReturned(kQueryId,
167 // Called by DidAutofillSuggestions, add expectation to remove warning.
168 EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _));
170 EXPECT_CALL(*autofill_driver_, SetRendererActionOnFormDataReception(
171 AutofillDriver::FORM_DATA_ACTION_FILL));
173 EXPECT_CALL(manager_delegate_, HideAutofillPopup());
175 // This should trigger a call to hide the popup since we've selected an
177 external_delegate_->DidAcceptSuggestion(autofill_item[0], autofill_ids[0]);
180 // Test that data list elements for a node will appear in the Autofill popup.
181 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateDataList) {
182 IssueOnQuery(kQueryId);
184 std::vector<base::string16> data_list_items;
185 data_list_items.push_back(base::string16());
187 external_delegate_->SetCurrentDataListValues(data_list_items,
190 // The enums must be cast to ints to prevent compile errors on linux_rel.
191 EXPECT_CALL(manager_delegate_,
194 testing::ElementsAre(
196 WebAutofillClient::MenuItemIDDataListEntry),
197 static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
199 static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
201 WebAutofillClient::MenuItemIDAutofillOptions)),
204 // This should call ShowAutofillPopup.
205 std::vector<base::string16> autofill_item;
206 autofill_item.push_back(base::string16());
207 std::vector<int> autofill_ids;
208 autofill_ids.push_back(kAutofillProfileId);
209 external_delegate_->OnSuggestionsReturned(kQueryId,
215 // Try calling OnSuggestionsReturned with no Autofill values and ensure
216 // the datalist items are still shown.
217 // The enum must be cast to an int to prevent compile errors on linux_rel.
218 EXPECT_CALL(manager_delegate_,
221 testing::ElementsAre(
223 WebAutofillClient::MenuItemIDDataListEntry)),
226 autofill_item = std::vector<base::string16>();
227 autofill_ids = std::vector<int>();
228 external_delegate_->OnSuggestionsReturned(kQueryId,
235 // Test that datalist values can get updated while a popup is showing.
236 TEST_F(AutofillExternalDelegateUnitTest, UpdateDataListWhileShowingPopup) {
237 IssueOnQuery(kQueryId);
239 EXPECT_CALL(manager_delegate_,
240 ShowAutofillPopup(_, _, _, _, _, _, _)).Times(0);
242 // Make sure just setting the data list values doesn't cause the popup to
244 std::vector<base::string16> data_list_items;
245 data_list_items.push_back(base::string16());
247 external_delegate_->SetCurrentDataListValues(data_list_items,
250 // The enums must be cast to ints to prevent compile errors on linux_rel.
251 EXPECT_CALL(manager_delegate_,
254 testing::ElementsAre(
256 WebAutofillClient::MenuItemIDDataListEntry),
257 static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
259 static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
261 WebAutofillClient::MenuItemIDAutofillOptions)),
264 // Ensure the popup is displayed.
265 std::vector<base::string16> autofill_item;
266 autofill_item.push_back(base::string16());
267 std::vector<int> autofill_ids;
268 autofill_ids.push_back(kAutofillProfileId);
269 external_delegate_->OnSuggestionsReturned(kQueryId,
275 // This would normally get called from ShowAutofillPopup, but it is mocked so
276 // we need to call OnPopupShown ourselves.
277 external_delegate_->OnPopupShown();
279 // Update the current data list and ensure the popup is updated.
280 data_list_items.push_back(base::string16());
282 // The enums must be cast to ints to prevent compile errors on linux_rel.
283 EXPECT_CALL(manager_delegate_,
284 UpdateAutofillPopupDataListValues(data_list_items,
287 external_delegate_->SetCurrentDataListValues(data_list_items,
291 // Test that the Autofill popup is able to display warnings explaining why
292 // Autofill is disabled for a website.
293 // Regression test for http://crbug.com/247880
294 TEST_F(AutofillExternalDelegateUnitTest, AutofillWarnings) {
295 IssueOnQuery(kQueryId);
297 // The enums must be cast to ints to prevent compile errors on linux_rel.
298 EXPECT_CALL(manager_delegate_,
301 testing::ElementsAre(
303 WebAutofillClient::MenuItemIDWarningMessage)),
306 // This should call ShowAutofillPopup.
307 std::vector<base::string16> autofill_item;
308 autofill_item.push_back(base::string16());
309 std::vector<int> autofill_ids;
310 autofill_ids.push_back(WebAutofillClient::MenuItemIDWarningMessage);
311 external_delegate_->OnSuggestionsReturned(kQueryId,
318 // Test that the Autofill popup doesn't display a warning explaining why
319 // Autofill is disabled for a website when there are no Autofill suggestions.
320 // Regression test for http://crbug.com/105636
321 TEST_F(AutofillExternalDelegateUnitTest, NoAutofillWarningsWithoutSuggestions) {
324 field.is_focusable = true;
325 field.should_autocomplete = false;
326 const gfx::RectF element_bounds;
328 external_delegate_->OnQuery(kQueryId, form, field, element_bounds, true);
330 EXPECT_CALL(manager_delegate_,
331 ShowAutofillPopup(_, _, _, _, _, _, _)).Times(0);
332 EXPECT_CALL(manager_delegate_, HideAutofillPopup()).Times(1);
334 // This should not call ShowAutofillPopup.
335 std::vector<base::string16> autofill_item;
336 autofill_item.push_back(base::string16());
337 std::vector<int> autofill_ids;
338 autofill_ids.push_back(WebAutofillClient::MenuItemIDAutocompleteEntry);
339 external_delegate_->OnSuggestionsReturned(kQueryId,
346 // Test that the Autofill delegate doesn't try and fill a form with a
347 // negative unique id.
348 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateInvalidUniqueId) {
349 // Ensure it doesn't try to preview the negative id.
350 EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _)).Times(0);
351 EXPECT_CALL(*autofill_driver_,
352 SetRendererActionOnFormDataReception(_)).Times(0);
353 EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm()).Times(1);
354 external_delegate_->DidSelectSuggestion(-1);
356 // Ensure it doesn't try to fill the form in with the negative id.
357 EXPECT_CALL(manager_delegate_, HideAutofillPopup());
358 EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _)).Times(0);
359 EXPECT_CALL(*autofill_driver_,
360 SetRendererActionOnFormDataReception(_)).Times(0);
361 external_delegate_->DidAcceptSuggestion(base::string16(), -1);
364 // Test that the ClearPreview call is only sent if the form was being previewed
365 // (i.e. it isn't autofilling a password).
366 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearPreviewedForm) {
367 // Called by DidSelectSuggestion, add expectation to remove warning.
368 EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _));
370 // Ensure selecting a new password entries or Autofill entries will
371 // cause any previews to get cleared.
372 EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm()).Times(1);
373 external_delegate_->DidSelectSuggestion(
374 WebAutofillClient::MenuItemIDPasswordEntry);
376 EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm()).Times(1);
377 EXPECT_CALL(*autofill_driver_, SetRendererActionOnFormDataReception(
378 AutofillDriver::FORM_DATA_ACTION_PREVIEW));
379 external_delegate_->DidSelectSuggestion(1);
382 // Test that the popup is hidden once we are done editing the autofill field.
383 TEST_F(AutofillExternalDelegateUnitTest,
384 ExternalDelegateHidePopupAfterEditing) {
385 EXPECT_CALL(manager_delegate_, ShowAutofillPopup(_, _, _, _, _, _, _));
386 autofill::GenerateTestAutofillPopup(external_delegate_.get());
388 EXPECT_CALL(manager_delegate_, HideAutofillPopup());
389 external_delegate_->DidEndTextFieldEditing();
392 // Test that the popup is marked as visible after recieving password
394 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegatePasswordSuggestions) {
395 static const base::string16 kUsername = ASCIIToUTF16("username");
396 static const base::string16 kSignonRealm = ASCIIToUTF16("http://foo.com/");
397 std::vector<base::string16> suggestions;
398 suggestions.push_back(kUsername);
399 std::vector<base::string16> realms;
400 realms.push_back(kSignonRealm);
403 field.is_focusable = true;
404 field.should_autocomplete = true;
405 const gfx::RectF element_bounds;
407 FormFieldData username_field_data;
408 username_field_data.value = kUsername;
409 PasswordFormFillData password_form_fill_data;
410 password_form_fill_data.basic_data.fields.push_back(username_field_data);
411 external_delegate_->AddPasswordFormMapping(field, password_form_fill_data);
413 // The enums must be cast to ints to prevent compile errors on linux_rel.
414 EXPECT_CALL(manager_delegate_,
417 testing::ElementsAre(
419 WebAutofillClient::MenuItemIDPasswordEntry)),
422 external_delegate_->OnShowPasswordSuggestions(suggestions,
427 EXPECT_CALL(manager_delegate_, HideAutofillPopup());
429 // This should trigger a call to hide the popup since
430 // we've selected an option.
431 external_delegate_->DidAcceptSuggestion(
433 WebAutofillClient::MenuItemIDPasswordEntry);
436 // Test that the driver is directed to clear the form after being notified that
437 // the user accepted the suggestion to clear the form.
438 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearForm) {
439 EXPECT_CALL(manager_delegate_, HideAutofillPopup());
440 EXPECT_CALL(*autofill_driver_, RendererShouldClearFilledForm());
442 external_delegate_->DidAcceptSuggestion(
444 WebAutofillClient::MenuItemIDClearForm);
447 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateHideWarning) {
448 // Set up a field that shouldn't get autocompleted or display warnings.
451 field.is_focusable = true;
452 field.should_autocomplete = false;
453 const gfx::RectF element_bounds;
455 external_delegate_->OnQuery(kQueryId, form, field, element_bounds, false);
457 std::vector<base::string16> autofill_items;
458 autofill_items.push_back(base::string16());
459 std::vector<int> autofill_ids;
460 autofill_ids.push_back(WebAutofillClient::MenuItemIDAutocompleteEntry);
462 // Ensure the popup tries to hide itself, since it is not allowed to show
464 EXPECT_CALL(manager_delegate_, HideAutofillPopup());
466 external_delegate_->OnSuggestionsReturned(kQueryId,
473 } // namespace autofill