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.
19 const char kUsernameName[] = "username";
20 const char kInvalidUsername[] = "no-username";
21 const char kPasswordName[] = "password";
22
23 const char kAliceUsername[] = "alice";
24 const char kAlicePassword[] = "password";
25
26 using testing::_;
27
28 namespace autofill {
29 class AutofillPopupDelegate;
30 }
31
32 namespace password_manager {
33
34 namespace {
35
36 class 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
44 class TestPasswordManagerClient : public StubPasswordManagerClient {
45 public:
GetDriver()46 virtual PasswordManagerDriver* GetDriver() OVERRIDE { return &driver_; }
47
mock_driver()48 MockPasswordManagerDriver* mock_driver() { return &driver_; }
49
50 private:
51 MockPasswordManagerDriver driver_;
52 };
53
54 class 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
69 class PasswordAutofillManagerTest : public testing::Test {
70 protected:
PasswordAutofillManagerTest()71 PasswordAutofillManagerTest()
72 : test_username_(base::ASCIIToUTF16(kAliceUsername)),
73 test_password_(base::ASCIIToUTF16(kAlicePassword)) {}
74
SetUp()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
InitializePasswordAutofillManager(PasswordManagerClient * client,autofill::AutofillClient * autofill_client)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
TEST_F(PasswordAutofillManagerTest,FillSuggestion)111 TEST_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
TEST_F(PasswordAutofillManagerTest,PreviewSuggestion)137 TEST_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.
TEST_F(PasswordAutofillManagerTest,ExternalDelegatePasswordSuggestions)164 TEST_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