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