- add sources.
[platform/framework/web/crosswalk.git] / src / components / autofill / core / browser / autofill_external_delegate_unittest.cc
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.
4
5 #include <vector>
6
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"
23
24 using testing::_;
25 using WebKit::WebAutofillClient;
26
27 namespace autofill {
28
29 namespace {
30
31 // A constant value to use as the Autofill query ID.
32 const int kQueryId = 5;
33
34 // A constant value to use as an Autofill profile ID.
35 const int kAutofillProfileId = 1;
36
37 class MockAutofillDriver : public TestAutofillDriver {
38  public:
39   explicit MockAutofillDriver(content::WebContents* web_contents)
40       : TestAutofillDriver(web_contents) {}
41
42   // Mock methods to enable testability.
43   MOCK_METHOD1(SetRendererActionOnFormDataReception,
44                void(RendererFormDataAction action));
45   MOCK_METHOD0(RendererShouldClearFilledForm, void());
46   MOCK_METHOD0(RendererShouldClearPreviewedForm, void());
47
48  private:
49   DISALLOW_COPY_AND_ASSIGN(MockAutofillDriver);
50 };
51
52 class MockAutofillManagerDelegate
53     : public autofill::TestAutofillManagerDelegate {
54  public:
55   MockAutofillManagerDelegate() {}
56
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));
65
66   MOCK_METHOD2(UpdateAutofillPopupDataListValues,
67                void(const std::vector<base::string16>& values,
68                     const std::vector<base::string16>& lables));
69
70   MOCK_METHOD0(HideAutofillPopup, void());
71
72  private:
73   DISALLOW_COPY_AND_ASSIGN(MockAutofillManagerDelegate);
74 };
75
76 class MockAutofillManager : public AutofillManager {
77  public:
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) {
83   }
84   virtual ~MockAutofillManager() {}
85
86   MOCK_METHOD4(OnFillAutofillFormData,
87                void(int query_id,
88                     const FormData& form,
89                     const FormFieldData& field,
90                     int unique_id));
91
92  private:
93   DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
94 };
95
96 }  // namespace
97
98 class AutofillExternalDelegateUnitTest
99     : public ChromeRenderViewHostTestHarness {
100  protected:
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(
109             web_contents(),
110             autofill_manager_.get(), autofill_driver_.get()));
111   }
112
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();
122   }
123
124   // Issue an OnQuery call with the given |query_id|.
125   void IssueOnQuery(int query_id) {
126     const FormData form;
127     FormFieldData field;
128     field.is_focusable = true;
129     field.should_autocomplete = true;
130     const gfx::RectF element_bounds;
131
132     external_delegate_->OnQuery(query_id, form, field, element_bounds, true);
133   }
134
135   MockAutofillManagerDelegate manager_delegate_;
136   scoped_ptr<MockAutofillDriver> autofill_driver_;
137   scoped_ptr<MockAutofillManager> autofill_manager_;
138   scoped_ptr<AutofillExternalDelegate> external_delegate_;
139 };
140
141 // Test that our external delegate called the virtual methods at the right time.
142 TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) {
143   IssueOnQuery(kQueryId);
144
145   // The enums must be cast to ints to prevent compile errors on linux_rel.
146   EXPECT_CALL(manager_delegate_,
147               ShowAutofillPopup(
148                   _, _, _, _, _,
149                   testing::ElementsAre(
150                       kAutofillProfileId,
151                       static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
152                       static_cast<int>(
153                           WebAutofillClient::MenuItemIDAutofillOptions)),
154                   _));
155
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,
162                                             autofill_item,
163                                             autofill_item,
164                                             autofill_item,
165                                             autofill_ids);
166
167   // Called by DidAutofillSuggestions, add expectation to remove warning.
168   EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _));
169
170   EXPECT_CALL(*autofill_driver_, SetRendererActionOnFormDataReception(
171       AutofillDriver::FORM_DATA_ACTION_FILL));
172
173   EXPECT_CALL(manager_delegate_, HideAutofillPopup());
174
175   // This should trigger a call to hide the popup since we've selected an
176   // option.
177   external_delegate_->DidAcceptSuggestion(autofill_item[0], autofill_ids[0]);
178 }
179
180 // Test that data list elements for a node will appear in the Autofill popup.
181 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateDataList) {
182   IssueOnQuery(kQueryId);
183
184   std::vector<base::string16> data_list_items;
185   data_list_items.push_back(base::string16());
186
187   external_delegate_->SetCurrentDataListValues(data_list_items,
188                                                data_list_items);
189
190   // The enums must be cast to ints to prevent compile errors on linux_rel.
191   EXPECT_CALL(manager_delegate_,
192               ShowAutofillPopup(
193                   _, _, _, _, _,
194                   testing::ElementsAre(
195                       static_cast<int>(
196                           WebAutofillClient::MenuItemIDDataListEntry),
197                       static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
198                       kAutofillProfileId,
199                       static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
200                       static_cast<int>(
201                           WebAutofillClient::MenuItemIDAutofillOptions)),
202                   _));
203
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,
210                                             autofill_item,
211                                             autofill_item,
212                                             autofill_item,
213                                             autofill_ids);
214
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_,
219               ShowAutofillPopup(
220                   _, _, _, _, _,
221                   testing::ElementsAre(
222                       static_cast<int>(
223                           WebAutofillClient::MenuItemIDDataListEntry)),
224                   _));
225
226   autofill_item = std::vector<base::string16>();
227   autofill_ids = std::vector<int>();
228   external_delegate_->OnSuggestionsReturned(kQueryId,
229                                             autofill_item,
230                                             autofill_item,
231                                             autofill_item,
232                                             autofill_ids);
233 }
234
235 // Test that datalist values can get updated while a popup is showing.
236 TEST_F(AutofillExternalDelegateUnitTest, UpdateDataListWhileShowingPopup) {
237   IssueOnQuery(kQueryId);
238
239   EXPECT_CALL(manager_delegate_,
240               ShowAutofillPopup(_, _, _, _, _, _, _)).Times(0);
241
242   // Make sure just setting the data list values doesn't cause the popup to
243   // appear.
244   std::vector<base::string16> data_list_items;
245   data_list_items.push_back(base::string16());
246
247   external_delegate_->SetCurrentDataListValues(data_list_items,
248                                                data_list_items);
249
250   // The enums must be cast to ints to prevent compile errors on linux_rel.
251   EXPECT_CALL(manager_delegate_,
252               ShowAutofillPopup(
253                   _, _, _, _, _,
254                   testing::ElementsAre(
255                       static_cast<int>(
256                           WebAutofillClient::MenuItemIDDataListEntry),
257                       static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
258                       kAutofillProfileId,
259                       static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
260                       static_cast<int>(
261                           WebAutofillClient::MenuItemIDAutofillOptions)),
262                   _));
263
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,
270                                             autofill_item,
271                                             autofill_item,
272                                             autofill_item,
273                                             autofill_ids);
274
275   // This would normally get called from ShowAutofillPopup, but it is mocked so
276   // we need to call OnPopupShown ourselves.
277   external_delegate_->OnPopupShown();
278
279   // Update the current data list and ensure the popup is updated.
280   data_list_items.push_back(base::string16());
281
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,
285                                                 data_list_items));
286
287   external_delegate_->SetCurrentDataListValues(data_list_items,
288                                                data_list_items);
289 }
290
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);
296
297   // The enums must be cast to ints to prevent compile errors on linux_rel.
298   EXPECT_CALL(manager_delegate_,
299               ShowAutofillPopup(
300                   _, _, _, _, _,
301                   testing::ElementsAre(
302                       static_cast<int>(
303                           WebAutofillClient::MenuItemIDWarningMessage)),
304                   _));
305
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,
312                                             autofill_item,
313                                             autofill_item,
314                                             autofill_item,
315                                             autofill_ids);
316 }
317
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) {
322   const FormData form;
323   FormFieldData field;
324   field.is_focusable = true;
325   field.should_autocomplete = false;
326   const gfx::RectF element_bounds;
327
328   external_delegate_->OnQuery(kQueryId, form, field, element_bounds, true);
329
330   EXPECT_CALL(manager_delegate_,
331               ShowAutofillPopup(_, _, _, _, _, _, _)).Times(0);
332   EXPECT_CALL(manager_delegate_, HideAutofillPopup()).Times(1);
333
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,
340                                             autofill_item,
341                                             autofill_item,
342                                             autofill_item,
343                                             autofill_ids);
344 }
345
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);
355
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);
362 }
363
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(_, _, _, _));
369
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);
375
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);
380 }
381
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());
387
388   EXPECT_CALL(manager_delegate_, HideAutofillPopup());
389   external_delegate_->DidEndTextFieldEditing();
390 }
391
392 // Test that the popup is marked as visible after recieving password
393 // suggestions.
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);
401
402   FormFieldData field;
403   field.is_focusable = true;
404   field.should_autocomplete = true;
405   const gfx::RectF element_bounds;
406
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);
412
413   // The enums must be cast to ints to prevent compile errors on linux_rel.
414   EXPECT_CALL(manager_delegate_,
415               ShowAutofillPopup(
416                   _, _, _, _, _,
417                   testing::ElementsAre(
418                       static_cast<int>(
419                            WebAutofillClient::MenuItemIDPasswordEntry)),
420                   _));
421
422   external_delegate_->OnShowPasswordSuggestions(suggestions,
423                                                 realms,
424                                                 field,
425                                                 element_bounds);
426
427   EXPECT_CALL(manager_delegate_, HideAutofillPopup());
428
429   // This should trigger a call to hide the popup since
430   // we've selected an option.
431   external_delegate_->DidAcceptSuggestion(
432       suggestions[0],
433       WebAutofillClient::MenuItemIDPasswordEntry);
434 }
435
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());
441
442   external_delegate_->DidAcceptSuggestion(
443       base::string16(),
444       WebAutofillClient::MenuItemIDClearForm);
445 }
446
447 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateHideWarning) {
448   // Set up a field that shouldn't get autocompleted or display warnings.
449   const FormData form;
450   FormFieldData field;
451   field.is_focusable = true;
452   field.should_autocomplete = false;
453   const gfx::RectF element_bounds;
454
455   external_delegate_->OnQuery(kQueryId, form, field, element_bounds, false);
456
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);
461
462   // Ensure the popup tries to hide itself, since it is not allowed to show
463   // anything.
464   EXPECT_CALL(manager_delegate_, HideAutofillPopup());
465
466   external_delegate_->OnSuggestionsReturned(kQueryId,
467                                             autofill_items,
468                                             autofill_items,
469                                             autofill_items,
470                                             autofill_ids);
471 }
472
473 }  // namespace autofill