15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be 35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file. 45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/prefs/pref_service.h" 65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/utf_string_conversions.h" 76d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/time/time.h" 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/passwords/manage_passwords_bubble.h" 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/passwords/manage_passwords_icon.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/passwords/manage_passwords_icon_mock.h" 12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/test/base/chrome_render_view_host_test_harness.h" 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/test/base/testing_profile.h" 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/autofill/core/common/password_form.h" 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/password_manager/core/browser/password_form_manager.h" 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/password_manager/core/browser/stub_password_manager_client.h" 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/password_manager/core/browser/stub_password_manager_driver.h" 19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "components/password_manager/core/common/password_manager_ui.h" 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/test/test_browser_thread_bundle.h" 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/test/web_contents_tester.h" 225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "testing/gmock/include/gmock/gmock.h" 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "testing/gtest/include/gtest/gtest.h" 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)namespace { 266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)const int64 kSlowNavigationDelayInMS = 2000; 286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)const int64 kQuickNavigationDelayInMS = 500; 296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)class MockElapsedTimer : public base::ElapsedTimer { 316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) public: 326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) MockElapsedTimer() {} 336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) virtual base::TimeDelta Elapsed() const OVERRIDE { return delta_; } 346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) void Advance(int64 ms) { delta_ = base::TimeDelta::FromMilliseconds(ms); } 366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) private: 386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) base::TimeDelta delta_; 396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockElapsedTimer); 416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}; 426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} // namespace 446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ManagePasswordsUIControllerTest : public ChromeRenderViewHostTestHarness { 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public: 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ManagePasswordsUIControllerTest() {} 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual void SetUp() OVERRIDE { 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ChromeRenderViewHostTestHarness::SetUp(); 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Create the test UIController here so that it's bound to 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // |test_web_contents_|, and will be retrieved correctly via 54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // ManagePasswordsUIController::FromWebContents in |controller()|. 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new ManagePasswordsUIControllerMock(web_contents()); 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu test_form_.origin = GURL("http://example.com"); 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // We need to be on a "webby" URL for most tests. 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::WebContentsTester::For(web_contents()) 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ->NavigateAndCommit(GURL("http://example.com")); 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu autofill::PasswordForm& test_form() { return test_form_; } 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ManagePasswordsUIControllerMock* controller() { 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return static_cast<ManagePasswordsUIControllerMock*>( 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ManagePasswordsUIController::FromWebContents(web_contents())); 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private: 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu autofill::PasswordForm test_form_; 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, DefaultState) { 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(password_manager::ui::INACTIVE_STATE, controller()->state()); 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_FALSE(controller()->PasswordPendingUserDecision()); 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(GURL::EmptyGURL(), controller()->origin()); 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ManagePasswordsIconMock mock; 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu controller()->UpdateIconAndBubbleState(&mock); 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(password_manager::ui::INACTIVE_STATE, mock.state()); 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, PasswordAutofilled) { 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::string16 kTestUsername = base::ASCIIToUTF16("test_username"); 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu autofill::PasswordFormMap map; 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu map[kTestUsername] = &test_form(); 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu controller()->OnPasswordAutofilled(map); 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(password_manager::ui::MANAGE_STATE, controller()->state()); 92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_FALSE(controller()->PasswordPendingUserDecision()); 935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(test_form().origin, controller()->origin()); 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(1u, controller()->best_matches().size()); 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ASSERT_EQ(1u, controller()->best_matches().count(kTestUsername)); 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Controller should store a separate copy of the form as it doesn't own it. 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_NE(&test_form(), 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller()->best_matches().find(kTestUsername)->second); 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ManagePasswordsIconMock mock; 1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu controller()->UpdateIconAndBubbleState(&mock); 103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state()); 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, PasswordSubmitted) { 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu password_manager::StubPasswordManagerClient client; 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) password_manager::StubPasswordManagerDriver driver; 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<password_manager::PasswordFormManager> test_form_manager( 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu new password_manager::PasswordFormManager( 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, &client, &driver, test_form(), false)); 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller()->OnPasswordSubmitted(test_form_manager.Pass()); 113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_AND_BUBBLE_STATE, 114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) controller()->state()); 115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_TRUE(controller()->PasswordPendingUserDecision()); 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // TODO(mkwst): This should be the value of test_form().origin, but 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // it's being masked by the stub implementation of 119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // ManagePasswordsUIControllerMock::PendingCredentials. 1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(GURL::EmptyGURL(), controller()->origin()); 1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ManagePasswordsIconMock mock; 1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu controller()->UpdateIconAndBubbleState(&mock); 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mock.state()); 1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 128116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(ManagePasswordsUIControllerTest, PasswordSaved) { 129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch password_manager::StubPasswordManagerClient client; 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch password_manager::StubPasswordManagerDriver driver; 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<password_manager::PasswordFormManager> test_form_manager( 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new password_manager::PasswordFormManager( 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, &client, &driver, test_form(), false)); 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller()->OnPasswordSubmitted(test_form_manager.Pass()); 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ManagePasswordsIconMock mock; 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch controller()->UpdateIconAndBubbleState(&mock); 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch controller()->SavePassword(); 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch controller()->UpdateIconAndBubbleState(&mock); 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state()); 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 143116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(ManagePasswordsUIControllerTest, PasswordBlacklisted) { 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch password_manager::StubPasswordManagerClient client; 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch password_manager::StubPasswordManagerDriver driver; 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<password_manager::PasswordFormManager> test_form_manager( 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new password_manager::PasswordFormManager( 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, &client, &driver, test_form(), false)); 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller()->OnPasswordSubmitted(test_form_manager.Pass()); 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ManagePasswordsIconMock mock; 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch controller()->UpdateIconAndBubbleState(&mock); 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch controller()->NeverSavePassword(); 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch controller()->UpdateIconAndBubbleState(&mock); 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(password_manager::ui::BLACKLIST_STATE, mock.state()); 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, QuickNavigations) { 1596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) password_manager::StubPasswordManagerClient client; 1606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) password_manager::StubPasswordManagerDriver driver; 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<password_manager::PasswordFormManager> test_form_manager( 1626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) new password_manager::PasswordFormManager( 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, &client, &driver, test_form(), false)); 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller()->OnPasswordSubmitted(test_form_manager.Pass()); 1656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ManagePasswordsIconMock mock; 1666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller()->UpdateIconAndBubbleState(&mock); 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mock.state()); 1696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Fake-navigate within a second. We expect the bubble's state to persist 1716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // if a navigation occurs too quickly for a user to reasonably have been 1726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // able to interact with the bubble. This happens on `accounts.google.com`, 1736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // for instance. 1746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) scoped_ptr<MockElapsedTimer> timer(new MockElapsedTimer()); 1756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) timer->Advance(kQuickNavigationDelayInMS); 1766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller()->SetTimer(timer.release()); 1776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller()->DidNavigateMainFrame(content::LoadCommittedDetails(), 1786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) content::FrameNavigateParams()); 1796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller()->UpdateIconAndBubbleState(&mock); 1806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mock.state()); 1836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, SlowNavigations) { 1866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) password_manager::StubPasswordManagerClient client; 1876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) password_manager::StubPasswordManagerDriver driver; 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<password_manager::PasswordFormManager> test_form_manager( 1896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) new password_manager::PasswordFormManager( 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, &client, &driver, test_form(), false)); 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller()->OnPasswordSubmitted(test_form_manager.Pass()); 1926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ManagePasswordsIconMock mock; 1936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller()->UpdateIconAndBubbleState(&mock); 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mock.state()); 1966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Fake-navigate after a second. We expect the bubble's state to be reset 1986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // if a navigation occurs after this limit. 1996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) scoped_ptr<MockElapsedTimer> timer(new MockElapsedTimer()); 2006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) timer->Advance(kSlowNavigationDelayInMS); 2016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller()->SetTimer(timer.release()); 2026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller()->DidNavigateMainFrame(content::LoadCommittedDetails(), 2036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) content::FrameNavigateParams()); 2046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) controller()->UpdateIconAndBubbleState(&mock); 2056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 2066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_EQ(password_manager::ui::INACTIVE_STATE, mock.state()); 2076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 2086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, PasswordSubmittedToNonWebbyURL) { 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Navigate to a non-webby URL, then see what happens! 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::WebContentsTester::For(web_contents()) 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ->NavigateAndCommit(GURL("chrome://sign-in")); 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password_manager::StubPasswordManagerClient client; 21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) password_manager::StubPasswordManagerDriver driver; 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<password_manager::PasswordFormManager> test_form_manager( 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new password_manager::PasswordFormManager( 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, &client, &driver, test_form(), false)); 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller()->OnPasswordSubmitted(test_form_manager.Pass()); 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(password_manager::ui::INACTIVE_STATE, controller()->state()); 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(controller()->PasswordPendingUserDecision()); 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(mkwst): This should be the value of test_form().origin, but 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // it's being masked by the stub implementation of 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ManagePasswordsUIControllerMock::PendingCredentials. 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(GURL::EmptyGURL(), controller()->origin()); 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ManagePasswordsIconMock mock; 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) controller()->UpdateIconAndBubbleState(&mock); 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(password_manager::ui::INACTIVE_STATE, mock.state()); 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, BlacklistBlockedAutofill) { 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) test_form().blacklisted_by_user = true; 235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::string16 kTestUsername = base::ASCIIToUTF16("test_username"); 236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) autofill::PasswordFormMap map; 237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) map[kTestUsername] = &test_form(); 238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) controller()->OnBlacklistBlockedAutofill(map); 239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(password_manager::ui::BLACKLIST_STATE, controller()->state()); 241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_FALSE(controller()->PasswordPendingUserDecision()); 242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(test_form().origin, controller()->origin()); 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(1u, controller()->best_matches().size()); 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ASSERT_EQ(1u, controller()->best_matches().count(kTestUsername)); 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Controller should store a separate copy of the form as it doesn't own it. 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_NE(&test_form(), 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller()->best_matches().find(kTestUsername)->second); 2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ManagePasswordsIconMock mock; 251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) controller()->UpdateIconAndBubbleState(&mock); 252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(password_manager::ui::BLACKLIST_STATE, mock.state()); 253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, ClickedUnblacklist) { 256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::string16 kTestUsername = base::ASCIIToUTF16("test_username"); 257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) autofill::PasswordFormMap map; 258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) map[kTestUsername] = &test_form(); 259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) controller()->OnBlacklistBlockedAutofill(map); 260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) controller()->UnblacklistSite(); 2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 262010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(password_manager::ui::MANAGE_STATE, controller()->state()); 263010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_FALSE(controller()->PasswordPendingUserDecision()); 264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(test_form().origin, controller()->origin()); 2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ManagePasswordsIconMock mock; 2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu controller()->UpdateIconAndBubbleState(&mock); 268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state()); 2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, UnblacklistedElsewhere) { 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) test_form().blacklisted_by_user = true; 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::string16 kTestUsername = base::ASCIIToUTF16("test_username"); 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) autofill::PasswordFormMap map; 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) map[kTestUsername] = &test_form(); 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) controller()->OnBlacklistBlockedAutofill(map); 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password_manager::PasswordStoreChange change( 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password_manager::PasswordStoreChange::REMOVE, test_form()); 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password_manager::PasswordStoreChangeList list(1, change); 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) controller()->OnLoginsChanged(list); 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(password_manager::ui::MANAGE_STATE, controller()->state()); 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(controller()->PasswordPendingUserDecision()); 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(test_form().origin, controller()->origin()); 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ManagePasswordsIconMock mock; 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) controller()->UpdateIconAndBubbleState(&mock); 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state()); 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, BlacklistedElsewhere) { 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::string16 kTestUsername = base::ASCIIToUTF16("test_username"); 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) autofill::PasswordFormMap map; 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) map[kTestUsername] = &test_form(); 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) controller()->OnPasswordAutofilled(map); 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) test_form().blacklisted_by_user = true; 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password_manager::PasswordStoreChange change( 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password_manager::PasswordStoreChange::ADD, test_form()); 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password_manager::PasswordStoreChangeList list(1, change); 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) controller()->OnLoginsChanged(list); 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(password_manager::ui::BLACKLIST_STATE, controller()->state()); 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(controller()->PasswordPendingUserDecision()); 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(test_form().origin, controller()->origin()); 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ManagePasswordsIconMock mock; 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) controller()->UpdateIconAndBubbleState(&mock); 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(password_manager::ui::BLACKLIST_STATE, mock.state()); 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(ManagePasswordsUIControllerTest, AutomaticPasswordSave) { 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) password_manager::StubPasswordManagerClient client; 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) password_manager::StubPasswordManagerDriver driver; 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<password_manager::PasswordFormManager> test_form_manager( 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new password_manager::PasswordFormManager( 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, &client, &driver, test_form(), false)); 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller()->OnAutomaticPasswordSave(test_form_manager.Pass()); 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(password_manager::ui::CONFIRMATION_STATE, controller()->state()); 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ManagePasswordsIconMock mock; 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller()->UpdateIconAndBubbleState(&mock); 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state()); 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 327