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 "base/compiler_specific.h" 6#include "base/message_loop/message_loop.h" 7#include "base/strings/utf_string_conversions.h" 8#include "components/autofill/core/browser/popup_item_ids.h" 9#include "components/autofill/core/browser/test_autofill_client.h" 10#include "components/autofill/core/browser/test_autofill_driver.h" 11#include "components/password_manager/core/browser/password_autofill_manager.h" 12#include "components/password_manager/core/browser/stub_password_manager_client.h" 13#include "components/password_manager/core/browser/stub_password_manager_driver.h" 14#include "testing/gmock/include/gmock/gmock.h" 15#include "testing/gtest/include/gtest/gtest.h" 16#include "ui/gfx/geometry/rect_f.h" 17 18// The name of the username/password element in the form. 19const char kUsernameName[] = "username"; 20const char kInvalidUsername[] = "no-username"; 21const char kPasswordName[] = "password"; 22 23const char kAliceUsername[] = "alice"; 24const char kAlicePassword[] = "password"; 25 26using testing::_; 27 28namespace autofill { 29class AutofillPopupDelegate; 30} 31 32namespace password_manager { 33 34namespace { 35 36class MockPasswordManagerDriver : public StubPasswordManagerDriver { 37 public: 38 MOCK_METHOD2(FillSuggestion, 39 void(const base::string16&, const base::string16&)); 40 MOCK_METHOD2(PreviewSuggestion, 41 void(const base::string16&, const base::string16&)); 42}; 43 44class TestPasswordManagerClient : public StubPasswordManagerClient { 45 public: 46 virtual PasswordManagerDriver* GetDriver() OVERRIDE { return &driver_; } 47 48 MockPasswordManagerDriver* mock_driver() { return &driver_; } 49 50 private: 51 MockPasswordManagerDriver driver_; 52}; 53 54class MockAutofillClient : public autofill::TestAutofillClient { 55 public: 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<autofill::AutofillPopupDelegate> delegate)); 64 MOCK_METHOD0(HideAutofillPopup, void()); 65}; 66 67} // namespace 68 69class PasswordAutofillManagerTest : public testing::Test { 70 protected: 71 PasswordAutofillManagerTest() 72 : test_username_(base::ASCIIToUTF16(kAliceUsername)), 73 test_password_(base::ASCIIToUTF16(kAlicePassword)) {} 74 75 virtual void SetUp() OVERRIDE { 76 // Add a preferred login and an additional login to the FillData. 77 username_field_.name = base::ASCIIToUTF16(kUsernameName); 78 username_field_.value = test_username_; 79 fill_data_.basic_data.fields.push_back(username_field_); 80 81 autofill::FormFieldData password_field; 82 password_field.name = base::ASCIIToUTF16(kPasswordName); 83 password_field.value = test_password_; 84 fill_data_.basic_data.fields.push_back(password_field); 85 } 86 87 void InitializePasswordAutofillManager( 88 PasswordManagerClient* client, 89 autofill::AutofillClient* autofill_client) { 90 password_autofill_manager_.reset( 91 new PasswordAutofillManager(client, autofill_client)); 92 password_autofill_manager_->OnAddPasswordFormMapping(username_field_, 93 fill_data_); 94 } 95 96 protected: 97 scoped_ptr<PasswordAutofillManager> password_autofill_manager_; 98 99 autofill::FormFieldData username_field_; 100 base::string16 test_username_; 101 base::string16 test_password_; 102 103 private: 104 autofill::PasswordFormFillData fill_data_; 105 106 // The TestAutofillDriver uses a SequencedWorkerPool which expects the 107 // existence of a MessageLoop. 108 base::MessageLoop message_loop_; 109}; 110 111TEST_F(PasswordAutofillManagerTest, FillSuggestion) { 112 scoped_ptr<TestPasswordManagerClient> client(new TestPasswordManagerClient); 113 InitializePasswordAutofillManager(client.get(), NULL); 114 115 EXPECT_CALL(*client->mock_driver(), 116 FillSuggestion(test_username_, test_password_)); 117 EXPECT_TRUE(password_autofill_manager_->FillSuggestionForTest( 118 username_field_, test_username_)); 119 testing::Mock::VerifyAndClearExpectations(client->mock_driver()); 120 121 EXPECT_CALL(*client->mock_driver(), 122 FillSuggestion(_, _)).Times(0); 123 EXPECT_FALSE(password_autofill_manager_->FillSuggestionForTest( 124 username_field_, base::ASCIIToUTF16(kInvalidUsername))); 125 126 autofill::FormFieldData invalid_username_field; 127 invalid_username_field.name = base::ASCIIToUTF16(kInvalidUsername); 128 129 EXPECT_FALSE(password_autofill_manager_->FillSuggestionForTest( 130 invalid_username_field, test_username_)); 131 132 password_autofill_manager_->Reset(); 133 EXPECT_FALSE(password_autofill_manager_->FillSuggestionForTest( 134 username_field_, test_username_)); 135} 136 137TEST_F(PasswordAutofillManagerTest, PreviewSuggestion) { 138 scoped_ptr<TestPasswordManagerClient> client(new TestPasswordManagerClient); 139 InitializePasswordAutofillManager(client.get(), NULL); 140 141 EXPECT_CALL(*client->mock_driver(), 142 PreviewSuggestion(test_username_, test_password_)); 143 EXPECT_TRUE(password_autofill_manager_->PreviewSuggestionForTest( 144 username_field_, test_username_)); 145 testing::Mock::VerifyAndClearExpectations(client->mock_driver()); 146 147 EXPECT_CALL(*client->mock_driver(), PreviewSuggestion(_, _)).Times(0); 148 EXPECT_FALSE(password_autofill_manager_->PreviewSuggestionForTest( 149 username_field_, base::ASCIIToUTF16(kInvalidUsername))); 150 151 autofill::FormFieldData invalid_username_field; 152 invalid_username_field.name = base::ASCIIToUTF16(kInvalidUsername); 153 154 EXPECT_FALSE(password_autofill_manager_->PreviewSuggestionForTest( 155 invalid_username_field, test_username_)); 156 157 password_autofill_manager_->Reset(); 158 EXPECT_FALSE(password_autofill_manager_->PreviewSuggestionForTest( 159 username_field_, test_username_)); 160} 161 162// Test that the popup is marked as visible after recieving password 163// suggestions. 164TEST_F(PasswordAutofillManagerTest, ExternalDelegatePasswordSuggestions) { 165 scoped_ptr<TestPasswordManagerClient> client(new TestPasswordManagerClient); 166 scoped_ptr<MockAutofillClient> autofill_client(new MockAutofillClient); 167 InitializePasswordAutofillManager(client.get(), autofill_client.get()); 168 169 gfx::RectF element_bounds; 170 std::vector<base::string16> suggestions; 171 suggestions.push_back(test_username_); 172 std::vector<base::string16> realms; 173 realms.push_back(base::ASCIIToUTF16("http://foo.com/")); 174 175 // The enums must be cast to ints to prevent compile errors on linux_rel. 176 EXPECT_CALL(*autofill_client, 177 ShowAutofillPopup( 178 _, 179 _, 180 _, 181 _, 182 _, 183 testing::ElementsAre(autofill::POPUP_ITEM_ID_PASSWORD_ENTRY), 184 _)); 185 password_autofill_manager_->OnShowPasswordSuggestions( 186 username_field_, element_bounds, suggestions, realms); 187 188 // Accepting a suggestion should trigger a call to hide the popup. 189 EXPECT_CALL(*autofill_client, HideAutofillPopup()); 190 password_autofill_manager_->DidAcceptSuggestion( 191 suggestions[0], autofill::POPUP_ITEM_ID_PASSWORD_ENTRY); 192} 193 194} // namespace password_manager 195