| 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 |