OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/browser/autofill_manager.h" | |
13 #include "components/autofill/browser/test_autofill_driver.h" | |
14 #include "components/autofill/browser/test_autofill_external_delegate.h" | |
15 #include "components/autofill/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/Source/WebKit/chromium/public/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 MockAutofillExternalDelegate : public AutofillExternalDelegate { | |
38 public: | |
39 MockAutofillExternalDelegate(content::WebContents* web_contents, | |
40 AutofillManager* autofill_manger) | |
41 : AutofillExternalDelegate(web_contents, autofill_manger) {} | |
42 | |
43 ~MockAutofillExternalDelegate() {} | |
44 | |
45 MOCK_METHOD0(ClearPreviewedForm, void()); | |
46 | |
47 private: | |
48 DISALLOW_COPY_AND_ASSIGN(MockAutofillExternalDelegate); | |
49 }; | |
50 | |
51 class MockAutofillManagerDelegate | |
52 : public autofill::TestAutofillManagerDelegate { | |
53 public: | |
54 MockAutofillManagerDelegate() {} | |
55 | |
56 MOCK_METHOD7(ShowAutofillPopup, | |
57 void(const gfx::RectF& element_bounds, | |
58 base::i18n::TextDirection text_direction, | |
59 const std::vector<base::string16>& values, | |
60 const std::vector<base::string16>& labels, | |
61 const std::vector<base::string16>& icons, | |
62 const std::vector<int>& identifiers, | |
63 base::WeakPtr<AutofillPopupDelegate> delegate)); | |
64 | |
65 MOCK_METHOD0(HideAutofillPopup, void()); | |
66 | |
67 private: | |
68 DISALLOW_COPY_AND_ASSIGN(MockAutofillManagerDelegate); | |
69 }; | |
70 | |
71 class MockAutofillManager : public AutofillManager { | |
72 public: | |
73 MockAutofillManager(AutofillDriver* driver, | |
74 MockAutofillManagerDelegate* delegate) | |
75 // Force to use the constructor designated for unit test, but we don't | |
76 // really need personal_data in this test so we pass a NULL pointer. | |
77 : AutofillManager(driver, delegate, NULL) { | |
78 } | |
79 virtual ~MockAutofillManager() {} | |
80 | |
81 MOCK_METHOD4(OnFillAutofillFormData, | |
82 void(int query_id, | |
83 const FormData& form, | |
84 const FormFieldData& field, | |
85 int unique_id)); | |
86 | |
87 private: | |
88 DISALLOW_COPY_AND_ASSIGN(MockAutofillManager); | |
89 }; | |
90 | |
91 } // namespace | |
92 | |
93 class AutofillExternalDelegateUnitTest | |
94 : public ChromeRenderViewHostTestHarness { | |
95 protected: | |
96 virtual void SetUp() OVERRIDE { | |
97 ChromeRenderViewHostTestHarness::SetUp(); | |
98 autofill_driver_.reset(new TestAutofillDriver(web_contents())); | |
99 autofill_manager_.reset( | |
100 new MockAutofillManager(autofill_driver_.get(), | |
101 &manager_delegate_)); | |
102 external_delegate_.reset( | |
103 new testing::NiceMock<MockAutofillExternalDelegate>( | |
104 web_contents(), | |
105 autofill_manager_.get())); | |
106 } | |
107 | |
108 virtual void TearDown() OVERRIDE { | |
109 // Order of destruction is important as AutofillManager relies on | |
110 // PersonalDataManager to be around when it gets destroyed. Also, a real | |
111 // AutofillManager is tied to the lifetime of the WebContents, so it must | |
112 // be destroyed at the destruction of the WebContents. | |
113 autofill_manager_.reset(); | |
114 external_delegate_.reset(); | |
115 autofill_driver_.reset(); | |
116 ChromeRenderViewHostTestHarness::TearDown(); | |
117 } | |
118 | |
119 // Issue an OnQuery call with the given |query_id|. | |
120 void IssueOnQuery(int query_id) { | |
121 const FormData form; | |
122 FormFieldData field; | |
123 field.is_focusable = true; | |
124 field.should_autocomplete = true; | |
125 const gfx::RectF element_bounds; | |
126 | |
127 external_delegate_->OnQuery(query_id, form, field, element_bounds, true); | |
128 } | |
129 | |
130 MockAutofillManagerDelegate manager_delegate_; | |
131 scoped_ptr<AutofillDriver> autofill_driver_; | |
132 scoped_ptr<MockAutofillManager> autofill_manager_; | |
133 scoped_ptr<testing::NiceMock<MockAutofillExternalDelegate> > | |
134 external_delegate_; | |
135 }; | |
136 | |
137 // Test that our external delegate called the virtual methods at the right time. | |
138 TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) { | |
139 IssueOnQuery(kQueryId); | |
140 | |
141 // The enums must be cast to ints to prevent compile errors on linux_rel. | |
142 EXPECT_CALL(manager_delegate_, | |
143 ShowAutofillPopup( | |
144 _, _, _, _, _, | |
145 testing::ElementsAre( | |
146 kAutofillProfileId, | |
147 static_cast<int>(WebAutofillClient::MenuItemIDSeparator), | |
148 static_cast<int>( | |
149 WebAutofillClient::MenuItemIDAutofillOptions)), | |
150 _)); | |
151 | |
152 // This should call ShowAutofillPopup. | |
153 std::vector<base::string16> autofill_item; | |
154 autofill_item.push_back(base::string16()); | |
155 std::vector<int> autofill_ids; | |
156 autofill_ids.push_back(kAutofillProfileId); | |
157 external_delegate_->OnSuggestionsReturned(kQueryId, | |
158 autofill_item, | |
159 autofill_item, | |
160 autofill_item, | |
161 autofill_ids); | |
162 | |
163 // Called by DidAutofillSuggestions, add expectation to remove warning. | |
164 EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _)); | |
165 | |
166 EXPECT_CALL(manager_delegate_, HideAutofillPopup()); | |
167 | |
168 // This should trigger a call to hide the popup since we've selected an | |
169 // option. | |
170 external_delegate_->DidAcceptSuggestion(autofill_item[0], autofill_ids[0]); | |
171 } | |
172 | |
173 // Test that data list elements for a node will appear in the Autofill popup. | |
174 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateDataList) { | |
175 IssueOnQuery(kQueryId); | |
176 | |
177 std::vector<base::string16> data_list_items; | |
178 data_list_items.push_back(base::string16()); | |
179 std::vector<int> data_list_ids; | |
180 data_list_ids.push_back(WebAutofillClient::MenuItemIDDataListEntry); | |
181 | |
182 external_delegate_->SetCurrentDataListValues(data_list_items, | |
183 data_list_items, | |
184 data_list_items, | |
185 data_list_ids); | |
186 | |
187 // The enums must be cast to ints to prevent compile errors on linux_rel. | |
188 EXPECT_CALL(manager_delegate_, | |
189 ShowAutofillPopup( | |
190 _, _, _, _, _, | |
191 testing::ElementsAre( | |
192 static_cast<int>( | |
193 WebAutofillClient::MenuItemIDDataListEntry), | |
194 static_cast<int>(WebAutofillClient::MenuItemIDSeparator), | |
195 kAutofillProfileId, | |
196 static_cast<int>(WebAutofillClient::MenuItemIDSeparator), | |
197 static_cast<int>( | |
198 WebAutofillClient::MenuItemIDAutofillOptions)), | |
199 _)); | |
200 | |
201 // This should call ShowAutofillPopup. | |
202 std::vector<base::string16> autofill_item; | |
203 autofill_item.push_back(base::string16()); | |
204 std::vector<int> autofill_ids; | |
205 autofill_ids.push_back(kAutofillProfileId); | |
206 external_delegate_->OnSuggestionsReturned(kQueryId, | |
207 autofill_item, | |
208 autofill_item, | |
209 autofill_item, | |
210 autofill_ids); | |
211 | |
212 // Try calling OnSuggestionsReturned with no Autofill values and ensure | |
213 // the datalist items are still shown. | |
214 // The enum must be cast to an int to prevent compile errors on linux_rel. | |
215 EXPECT_CALL(manager_delegate_, | |
216 ShowAutofillPopup( | |
217 _, _, _, _, _, | |
218 testing::ElementsAre( | |
219 static_cast<int>( | |
220 WebAutofillClient::MenuItemIDDataListEntry)), | |
221 _)); | |
222 | |
223 autofill_item = std::vector<base::string16>(); | |
224 autofill_ids = std::vector<int>(); | |
225 external_delegate_->OnSuggestionsReturned(kQueryId, | |
226 autofill_item, | |
227 autofill_item, | |
228 autofill_item, | |
229 autofill_ids); | |
230 } | |
231 | |
232 // Test that the Autofill popup is able to display warnings explaining why | |
233 // Autofill is disabled for a website. | |
234 // Regression test for http://crbug.com/247880 | |
235 TEST_F(AutofillExternalDelegateUnitTest, AutofillWarnings) { | |
236 IssueOnQuery(kQueryId); | |
237 | |
238 // The enums must be cast to ints to prevent compile errors on linux_rel. | |
239 EXPECT_CALL(manager_delegate_, | |
240 ShowAutofillPopup( | |
241 _, _, _, _, _, | |
242 testing::ElementsAre( | |
243 static_cast<int>( | |
244 WebAutofillClient::MenuItemIDWarningMessage)), | |
245 _)); | |
246 | |
247 // This should call ShowAutofillPopup. | |
248 std::vector<base::string16> autofill_item; | |
249 autofill_item.push_back(base::string16()); | |
250 std::vector<int> autofill_ids; | |
251 autofill_ids.push_back(WebAutofillClient::MenuItemIDWarningMessage); | |
252 external_delegate_->OnSuggestionsReturned(kQueryId, | |
253 autofill_item, | |
254 autofill_item, | |
255 autofill_item, | |
256 autofill_ids); | |
257 } | |
258 | |
259 // Test that the Autofill delegate doesn't try and fill a form with a | |
260 // negative unique id. | |
261 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateInvalidUniqueId) { | |
262 // Ensure it doesn't try to preview the negative id. | |
263 EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _)).Times(0); | |
264 EXPECT_CALL(*external_delegate_, ClearPreviewedForm()).Times(1); | |
265 external_delegate_->DidSelectSuggestion(-1); | |
266 | |
267 // Ensure it doesn't try to fill the form in with the negative id. | |
268 EXPECT_CALL(manager_delegate_, HideAutofillPopup()); | |
269 EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _)).Times(0); | |
270 external_delegate_->DidAcceptSuggestion(base::string16(), -1); | |
271 } | |
272 | |
273 // Test that the ClearPreview IPC is only sent the form was being previewed | |
274 // (i.e. it isn't autofilling a password). | |
275 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearPreviewedForm) { | |
276 // Called by DidSelectSuggestion, add expectation to remove warning. | |
277 EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _)); | |
278 | |
279 // Ensure selecting a new password entries or Autofill entries will | |
280 // cause any previews to get cleared. | |
281 EXPECT_CALL(*external_delegate_, ClearPreviewedForm()).Times(1); | |
282 external_delegate_->DidSelectSuggestion( | |
283 WebAutofillClient::MenuItemIDPasswordEntry); | |
284 | |
285 EXPECT_CALL(*external_delegate_, ClearPreviewedForm()).Times(1); | |
286 external_delegate_->DidSelectSuggestion(1); | |
287 } | |
288 | |
289 // Test that the popup is hidden once we are done editing the autofill field. | |
290 TEST_F(AutofillExternalDelegateUnitTest, | |
291 ExternalDelegateHidePopupAfterEditing) { | |
292 EXPECT_CALL(manager_delegate_, ShowAutofillPopup(_, _, _, _, _, _, _)); | |
293 autofill::GenerateTestAutofillPopup(external_delegate_.get()); | |
294 | |
295 EXPECT_CALL(manager_delegate_, HideAutofillPopup()); | |
296 external_delegate_->DidEndTextFieldEditing(); | |
297 } | |
298 | |
299 // Test that the popup is marked as visible after recieving password | |
300 // suggestions. | |
301 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegatePasswordSuggestions) { | |
302 static const base::string16 kUsername = ASCIIToUTF16("username"); | |
303 std::vector<base::string16> suggestions; | |
304 suggestions.push_back(kUsername); | |
305 | |
306 FormFieldData field; | |
307 field.is_focusable = true; | |
308 field.should_autocomplete = true; | |
309 const gfx::RectF element_bounds; | |
310 | |
311 FormFieldData username_field_data; | |
312 username_field_data.value = kUsername; | |
313 PasswordFormFillData password_form_fill_data; | |
314 password_form_fill_data.basic_data.fields.push_back(username_field_data); | |
315 external_delegate_->AddPasswordFormMapping(field, password_form_fill_data); | |
316 | |
317 // The enums must be cast to ints to prevent compile errors on linux_rel. | |
318 EXPECT_CALL(manager_delegate_, | |
319 ShowAutofillPopup( | |
320 _, _, _, _, _, | |
321 testing::ElementsAre( | |
322 static_cast<int>( | |
323 WebAutofillClient::MenuItemIDPasswordEntry)), | |
324 _)); | |
325 | |
326 external_delegate_->OnShowPasswordSuggestions(suggestions, | |
327 field, | |
328 element_bounds); | |
329 | |
330 EXPECT_CALL(manager_delegate_, HideAutofillPopup()); | |
331 | |
332 // This should trigger a call to hide the popup since | |
333 // we've selected an option. | |
334 external_delegate_->DidAcceptSuggestion( | |
335 suggestions[0], | |
336 WebAutofillClient::MenuItemIDPasswordEntry); | |
337 } | |
338 | |
339 TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateHideWarning) { | |
340 // Set up a field that shouldn't get autocompleted or display warnings. | |
341 const FormData form; | |
342 FormFieldData field; | |
343 field.is_focusable = true; | |
344 field.should_autocomplete = false; | |
345 const gfx::RectF element_bounds; | |
346 | |
347 external_delegate_->OnQuery(kQueryId, form, field, element_bounds, false); | |
348 | |
349 std::vector<base::string16> autofill_items; | |
350 autofill_items.push_back(base::string16()); | |
351 std::vector<int> autofill_ids; | |
352 autofill_ids.push_back(WebAutofillClient::MenuItemIDAutocompleteEntry); | |
353 | |
354 // Ensure the popup tries to hide itself, since it is not allowed to show | |
355 // anything. | |
356 EXPECT_CALL(manager_delegate_, HideAutofillPopup()); | |
357 | |
358 external_delegate_->OnSuggestionsReturned(kQueryId, | |
359 autofill_items, | |
360 autofill_items, | |
361 autofill_items, | |
362 autofill_ids); | |
363 } | |
364 | |
365 } // namespace autofill | |
OLD | NEW |