app_shell: Add version number in user agent
[chromium-blink-merge.git] / chrome / browser / ui / passwords / manage_passwords_ui_controller_unittest.cc
blob0aa2a1e2fc0fa75e8a741e856ef7cd18f27813e6
1 // Copyright 2014 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.
5 #include "base/prefs/pref_service.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "base/time/time.h"
8 #include "chrome/browser/ui/passwords/manage_passwords_bubble.h"
9 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
10 #include "chrome/browser/ui/passwords/manage_passwords_icon.h"
11 #include "chrome/browser/ui/passwords/manage_passwords_icon_mock.h"
12 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h"
13 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "components/autofill/core/common/password_form.h"
16 #include "components/password_manager/core/browser/password_form_manager.h"
17 #include "components/password_manager/core/browser/stub_password_manager_client.h"
18 #include "components/password_manager/core/browser/stub_password_manager_driver.h"
19 #include "components/password_manager/core/common/password_manager_ui.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "content/public/test/web_contents_tester.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 namespace {
27 const int64 kSlowNavigationDelayInMS = 2000;
28 const int64 kQuickNavigationDelayInMS = 500;
30 class MockElapsedTimer : public base::ElapsedTimer {
31 public:
32 MockElapsedTimer() {}
33 virtual base::TimeDelta Elapsed() const OVERRIDE { return delta_; }
35 void Advance(int64 ms) { delta_ = base::TimeDelta::FromMilliseconds(ms); }
37 private:
38 base::TimeDelta delta_;
40 DISALLOW_COPY_AND_ASSIGN(MockElapsedTimer);
43 } // namespace
45 class ManagePasswordsUIControllerTest : public ChromeRenderViewHostTestHarness {
46 public:
47 ManagePasswordsUIControllerTest() {}
49 virtual void SetUp() OVERRIDE {
50 ChromeRenderViewHostTestHarness::SetUp();
52 // Create the test UIController here so that it's bound to
53 // |test_web_contents_|, and will be retrieved correctly via
54 // ManagePasswordsUIController::FromWebContents in |controller()|.
55 new ManagePasswordsUIControllerMock(web_contents());
57 test_form_.origin = GURL("http://example.com");
59 // We need to be on a "webby" URL for most tests.
60 content::WebContentsTester::For(web_contents())
61 ->NavigateAndCommit(GURL("http://example.com"));
64 autofill::PasswordForm& test_form() { return test_form_; }
66 ManagePasswordsUIControllerMock* controller() {
67 return static_cast<ManagePasswordsUIControllerMock*>(
68 ManagePasswordsUIController::FromWebContents(web_contents()));
71 private:
72 autofill::PasswordForm test_form_;
75 TEST_F(ManagePasswordsUIControllerTest, DefaultState) {
76 EXPECT_EQ(password_manager::ui::INACTIVE_STATE, controller()->state());
77 EXPECT_FALSE(controller()->PasswordPendingUserDecision());
78 EXPECT_EQ(GURL::EmptyGURL(), controller()->origin());
80 ManagePasswordsIconMock mock;
81 controller()->UpdateIconAndBubbleState(&mock);
82 EXPECT_EQ(password_manager::ui::INACTIVE_STATE, mock.state());
85 TEST_F(ManagePasswordsUIControllerTest, PasswordAutofilled) {
86 base::string16 kTestUsername = base::ASCIIToUTF16("test_username");
87 autofill::PasswordFormMap map;
88 map[kTestUsername] = &test_form();
89 controller()->OnPasswordAutofilled(map);
91 EXPECT_EQ(password_manager::ui::MANAGE_STATE, controller()->state());
92 EXPECT_FALSE(controller()->PasswordPendingUserDecision());
93 EXPECT_EQ(test_form().origin, controller()->origin());
94 EXPECT_EQ(1u, controller()->best_matches().size());
95 ASSERT_EQ(1u, controller()->best_matches().count(kTestUsername));
97 // Controller should store a separate copy of the form as it doesn't own it.
98 EXPECT_NE(&test_form(),
99 controller()->best_matches().find(kTestUsername)->second);
101 ManagePasswordsIconMock mock;
102 controller()->UpdateIconAndBubbleState(&mock);
103 EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state());
106 TEST_F(ManagePasswordsUIControllerTest, PasswordSubmitted) {
107 password_manager::StubPasswordManagerClient client;
108 password_manager::StubPasswordManagerDriver driver;
109 scoped_ptr<password_manager::PasswordFormManager> test_form_manager(
110 new password_manager::PasswordFormManager(
111 NULL, &client, &driver, test_form(), false));
112 controller()->OnPasswordSubmitted(test_form_manager.Pass());
113 EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_AND_BUBBLE_STATE,
114 controller()->state());
115 EXPECT_TRUE(controller()->PasswordPendingUserDecision());
117 // TODO(mkwst): This should be the value of test_form().origin, but
118 // it's being masked by the stub implementation of
119 // ManagePasswordsUIControllerMock::PendingCredentials.
120 EXPECT_EQ(GURL::EmptyGURL(), controller()->origin());
122 ManagePasswordsIconMock mock;
123 controller()->UpdateIconAndBubbleState(&mock);
124 EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE,
125 mock.state());
128 TEST_F(ManagePasswordsUIControllerTest, PasswordSaved) {
129 password_manager::StubPasswordManagerClient client;
130 password_manager::StubPasswordManagerDriver driver;
131 scoped_ptr<password_manager::PasswordFormManager> test_form_manager(
132 new password_manager::PasswordFormManager(
133 NULL, &client, &driver, test_form(), false));
134 controller()->OnPasswordSubmitted(test_form_manager.Pass());
136 ManagePasswordsIconMock mock;
137 controller()->UpdateIconAndBubbleState(&mock);
138 controller()->SavePassword();
139 controller()->UpdateIconAndBubbleState(&mock);
140 EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state());
143 TEST_F(ManagePasswordsUIControllerTest, PasswordBlacklisted) {
144 password_manager::StubPasswordManagerClient client;
145 password_manager::StubPasswordManagerDriver driver;
146 scoped_ptr<password_manager::PasswordFormManager> test_form_manager(
147 new password_manager::PasswordFormManager(
148 NULL, &client, &driver, test_form(), false));
149 controller()->OnPasswordSubmitted(test_form_manager.Pass());
151 ManagePasswordsIconMock mock;
152 controller()->UpdateIconAndBubbleState(&mock);
153 controller()->NeverSavePassword();
154 controller()->UpdateIconAndBubbleState(&mock);
155 EXPECT_EQ(password_manager::ui::BLACKLIST_STATE, mock.state());
158 TEST_F(ManagePasswordsUIControllerTest, QuickNavigations) {
159 password_manager::StubPasswordManagerClient client;
160 password_manager::StubPasswordManagerDriver driver;
161 scoped_ptr<password_manager::PasswordFormManager> test_form_manager(
162 new password_manager::PasswordFormManager(
163 NULL, &client, &driver, test_form(), false));
164 controller()->OnPasswordSubmitted(test_form_manager.Pass());
165 ManagePasswordsIconMock mock;
166 controller()->UpdateIconAndBubbleState(&mock);
167 EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE,
168 mock.state());
170 // Fake-navigate within a second. We expect the bubble's state to persist
171 // if a navigation occurs too quickly for a user to reasonably have been
172 // able to interact with the bubble. This happens on `accounts.google.com`,
173 // for instance.
174 scoped_ptr<MockElapsedTimer> timer(new MockElapsedTimer());
175 timer->Advance(kQuickNavigationDelayInMS);
176 controller()->SetTimer(timer.release());
177 controller()->DidNavigateMainFrame(content::LoadCommittedDetails(),
178 content::FrameNavigateParams());
179 controller()->UpdateIconAndBubbleState(&mock);
181 EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE,
182 mock.state());
185 TEST_F(ManagePasswordsUIControllerTest, SlowNavigations) {
186 password_manager::StubPasswordManagerClient client;
187 password_manager::StubPasswordManagerDriver driver;
188 scoped_ptr<password_manager::PasswordFormManager> test_form_manager(
189 new password_manager::PasswordFormManager(
190 NULL, &client, &driver, test_form(), false));
191 controller()->OnPasswordSubmitted(test_form_manager.Pass());
192 ManagePasswordsIconMock mock;
193 controller()->UpdateIconAndBubbleState(&mock);
194 EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE,
195 mock.state());
197 // Fake-navigate after a second. We expect the bubble's state to be reset
198 // if a navigation occurs after this limit.
199 scoped_ptr<MockElapsedTimer> timer(new MockElapsedTimer());
200 timer->Advance(kSlowNavigationDelayInMS);
201 controller()->SetTimer(timer.release());
202 controller()->DidNavigateMainFrame(content::LoadCommittedDetails(),
203 content::FrameNavigateParams());
204 controller()->UpdateIconAndBubbleState(&mock);
206 EXPECT_EQ(password_manager::ui::INACTIVE_STATE, mock.state());
209 TEST_F(ManagePasswordsUIControllerTest, PasswordSubmittedToNonWebbyURL) {
210 // Navigate to a non-webby URL, then see what happens!
211 content::WebContentsTester::For(web_contents())
212 ->NavigateAndCommit(GURL("chrome://sign-in"));
214 password_manager::StubPasswordManagerClient client;
215 password_manager::StubPasswordManagerDriver driver;
216 scoped_ptr<password_manager::PasswordFormManager> test_form_manager(
217 new password_manager::PasswordFormManager(
218 NULL, &client, &driver, test_form(), false));
219 controller()->OnPasswordSubmitted(test_form_manager.Pass());
220 EXPECT_EQ(password_manager::ui::INACTIVE_STATE, controller()->state());
221 EXPECT_FALSE(controller()->PasswordPendingUserDecision());
223 // TODO(mkwst): This should be the value of test_form().origin, but
224 // it's being masked by the stub implementation of
225 // ManagePasswordsUIControllerMock::PendingCredentials.
226 EXPECT_EQ(GURL::EmptyGURL(), controller()->origin());
228 ManagePasswordsIconMock mock;
229 controller()->UpdateIconAndBubbleState(&mock);
230 EXPECT_EQ(password_manager::ui::INACTIVE_STATE, mock.state());
233 TEST_F(ManagePasswordsUIControllerTest, BlacklistBlockedAutofill) {
234 test_form().blacklisted_by_user = true;
235 base::string16 kTestUsername = base::ASCIIToUTF16("test_username");
236 autofill::PasswordFormMap map;
237 map[kTestUsername] = &test_form();
238 controller()->OnBlacklistBlockedAutofill(map);
240 EXPECT_EQ(password_manager::ui::BLACKLIST_STATE, controller()->state());
241 EXPECT_FALSE(controller()->PasswordPendingUserDecision());
242 EXPECT_EQ(test_form().origin, controller()->origin());
243 EXPECT_EQ(1u, controller()->best_matches().size());
244 ASSERT_EQ(1u, controller()->best_matches().count(kTestUsername));
246 // Controller should store a separate copy of the form as it doesn't own it.
247 EXPECT_NE(&test_form(),
248 controller()->best_matches().find(kTestUsername)->second);
250 ManagePasswordsIconMock mock;
251 controller()->UpdateIconAndBubbleState(&mock);
252 EXPECT_EQ(password_manager::ui::BLACKLIST_STATE, mock.state());
255 TEST_F(ManagePasswordsUIControllerTest, ClickedUnblacklist) {
256 base::string16 kTestUsername = base::ASCIIToUTF16("test_username");
257 autofill::PasswordFormMap map;
258 map[kTestUsername] = &test_form();
259 controller()->OnBlacklistBlockedAutofill(map);
260 controller()->UnblacklistSite();
262 EXPECT_EQ(password_manager::ui::MANAGE_STATE, controller()->state());
263 EXPECT_FALSE(controller()->PasswordPendingUserDecision());
264 EXPECT_EQ(test_form().origin, controller()->origin());
266 ManagePasswordsIconMock mock;
267 controller()->UpdateIconAndBubbleState(&mock);
268 EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state());
271 TEST_F(ManagePasswordsUIControllerTest, UnblacklistedElsewhere) {
272 test_form().blacklisted_by_user = true;
273 base::string16 kTestUsername = base::ASCIIToUTF16("test_username");
274 autofill::PasswordFormMap map;
275 map[kTestUsername] = &test_form();
276 controller()->OnBlacklistBlockedAutofill(map);
278 password_manager::PasswordStoreChange change(
279 password_manager::PasswordStoreChange::REMOVE, test_form());
280 password_manager::PasswordStoreChangeList list(1, change);
281 controller()->OnLoginsChanged(list);
283 EXPECT_EQ(password_manager::ui::MANAGE_STATE, controller()->state());
284 EXPECT_FALSE(controller()->PasswordPendingUserDecision());
285 EXPECT_EQ(test_form().origin, controller()->origin());
287 ManagePasswordsIconMock mock;
288 controller()->UpdateIconAndBubbleState(&mock);
289 EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state());
292 TEST_F(ManagePasswordsUIControllerTest, BlacklistedElsewhere) {
293 base::string16 kTestUsername = base::ASCIIToUTF16("test_username");
294 autofill::PasswordFormMap map;
295 map[kTestUsername] = &test_form();
296 controller()->OnPasswordAutofilled(map);
298 test_form().blacklisted_by_user = true;
299 password_manager::PasswordStoreChange change(
300 password_manager::PasswordStoreChange::ADD, test_form());
301 password_manager::PasswordStoreChangeList list(1, change);
302 controller()->OnLoginsChanged(list);
304 EXPECT_EQ(password_manager::ui::BLACKLIST_STATE, controller()->state());
305 EXPECT_FALSE(controller()->PasswordPendingUserDecision());
306 EXPECT_EQ(test_form().origin, controller()->origin());
308 ManagePasswordsIconMock mock;
309 controller()->UpdateIconAndBubbleState(&mock);
310 EXPECT_EQ(password_manager::ui::BLACKLIST_STATE, mock.state());
313 TEST_F(ManagePasswordsUIControllerTest, AutomaticPasswordSave) {
314 password_manager::StubPasswordManagerClient client;
315 password_manager::StubPasswordManagerDriver driver;
316 scoped_ptr<password_manager::PasswordFormManager> test_form_manager(
317 new password_manager::PasswordFormManager(
318 NULL, &client, &driver, test_form(), false));
320 controller()->OnAutomaticPasswordSave(test_form_manager.Pass());
321 EXPECT_EQ(password_manager::ui::CONFIRMATION_STATE, controller()->state());
323 ManagePasswordsIconMock mock;
324 controller()->UpdateIconAndBubbleState(&mock);
325 EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state());