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 "chrome/browser/chromeos/login/lock/screen_locker.h"
6 
7 #include <memory>
8 
9 #include "ash/wm/window_state.h"
10 #include "base/bind.h"
11 #include "base/macros.h"
12 #include "base/run_loop.h"
13 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
14 #include "chrome/browser/chromeos/login/lock/screen_locker_tester.h"
15 #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
16 #include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
17 #include "chrome/browser/profiles/profile_manager.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_window.h"
20 #include "chrome/browser/ui/exclusive_access/exclusive_access_test.h"
21 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/test/base/in_process_browser_test.h"
24 #include "chromeos/dbus/biod/fake_biod_client.h"
25 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
26 #include "components/prefs/pref_service.h"
27 #include "components/session_manager/core/session_manager.h"
28 #include "components/user_manager/user_names.h"
29 #include "content/public/test/browser_test.h"
30 #include "content/public/test/test_utils.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
33 
34 namespace chromeos {
35 namespace {
36 
37 constexpr char kFingerprint[] = "pinky";
38 
39 class ScreenLockerTest : public InProcessBrowserTest {
40  public:
41   ScreenLockerTest() = default;
42   ~ScreenLockerTest() override = default;
43 
session_manager_client()44   FakeSessionManagerClient* session_manager_client() {
45     return FakeSessionManagerClient::Get();
46   }
47 
48   // InProcessBrowserTest:
SetUpInProcessBrowserTestFixture()49   void SetUpInProcessBrowserTestFixture() override {
50     zero_duration_mode_ =
51         std::make_unique<ui::ScopedAnimationDurationScaleMode>(
52             ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
53   }
54 
TearDown()55   void TearDown() override { quick_unlock::EnabledForTesting(false); }
56 
EnrollFingerprint()57   void EnrollFingerprint() {
58     quick_unlock::EnabledForTesting(true);
59 
60     FakeBiodClient::Get()->StartEnrollSession(
61         "test-user", std::string(),
62         base::BindOnce(&ScreenLockerTest::OnStartSession,
63                        base::Unretained(this)));
64     base::RunLoop().RunUntilIdle();
65 
66     FakeBiodClient::Get()->SendEnrollScanDone(
67         kFingerprint, biod::SCAN_RESULT_SUCCESS, true /* is_complete */,
68         -1 /* percent_complete */);
69     base::RunLoop().RunUntilIdle();
70 
71     ProfileManager::GetActiveUserProfile()->GetPrefs()->SetInteger(
72         prefs::kQuickUnlockFingerprintRecord, 1);
73   }
74 
AuthenticateWithFingerprint()75   void AuthenticateWithFingerprint() {
76     FakeBiodClient::Get()->SendAuthScanDone(kFingerprint,
77                                             biod::SCAN_RESULT_SUCCESS);
78     base::RunLoop().RunUntilIdle();
79   }
80 
81  private:
OnStartSession(const dbus::ObjectPath & path)82   void OnStartSession(const dbus::ObjectPath& path) {}
83 
84   std::unique_ptr<ui::ScopedAnimationDurationScaleMode> zero_duration_mode_;
85 
86   DISALLOW_COPY_AND_ASSIGN(ScreenLockerTest);
87 };
88 
89 }  // namespace
90 
IN_PROC_BROWSER_TEST_F(ScreenLockerTest,TestBadThenGoodPassword)91 IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestBadThenGoodPassword) {
92   ScreenLockerTester tester;
93   tester.Lock();
94 
95   tester.SetUnlockPassword(user_manager::StubAccountId(), "pass");
96 
97   // Submit a bad password.
98   tester.UnlockWithPassword(user_manager::StubAccountId(), "fail");
99   EXPECT_TRUE(tester.IsLocked());
100 
101   // Submit the correct password. Successful authentication clears the lock
102   // screen and tells the SessionManager to announce this over DBus.
103   tester.UnlockWithPassword(user_manager::StubAccountId(), "pass");
104   EXPECT_FALSE(tester.IsLocked());
105   EXPECT_EQ(1, session_manager_client()->notify_lock_screen_shown_call_count());
106   EXPECT_EQ(session_manager::SessionState::ACTIVE,
107             session_manager::SessionManager::Get()->session_state());
108   EXPECT_EQ(
109       1, session_manager_client()->notify_lock_screen_dismissed_call_count());
110 }
111 
112 // Test how locking the screen affects an active fullscreen window.
IN_PROC_BROWSER_TEST_F(ScreenLockerTest,TestFullscreenExit)113 IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestFullscreenExit) {
114   // 1) If the active browser window is in fullscreen and the fullscreen window
115   // does not have all the pixels (e.g. the shelf is auto hidden instead of
116   // hidden), locking the screen should exit fullscreen. The shelf is
117   // auto hidden when in immersive fullscreen.
118   ScreenLockerTester tester;
119   BrowserWindow* browser_window = browser()->window();
120   ash::WindowState* window_state =
121       ash::WindowState::Get(browser_window->GetNativeWindow());
122   {
123     FullscreenNotificationObserver fullscreen_waiter(browser());
124     browser()
125         ->exclusive_access_manager()
126         ->fullscreen_controller()
127         ->ToggleBrowserFullscreenMode();
128     fullscreen_waiter.Wait();
129     EXPECT_TRUE(browser_window->IsFullscreen());
130     EXPECT_FALSE(window_state->GetHideShelfWhenFullscreen());
131     EXPECT_FALSE(tester.IsLocked());
132   }
133   {
134     tester.Lock();
135     EXPECT_FALSE(browser_window->IsFullscreen());
136     EXPECT_TRUE(window_state->GetHideShelfWhenFullscreen());
137     EXPECT_TRUE(tester.IsLocked());
138   }
139   tester.SetUnlockPassword(user_manager::StubAccountId(), "pass");
140   tester.UnlockWithPassword(user_manager::StubAccountId(), "pass");
141   EXPECT_FALSE(tester.IsLocked());
142   EXPECT_FALSE(browser_window->IsFullscreen());
143 
144   // Browser window should be activated after screen locker is gone. Otherwise,
145   // the rest of the test would fail.
146   ASSERT_EQ(window_state, ash::WindowState::ForActiveWindow());
147 
148   // 2) Similar to 1) if the active browser window is in fullscreen and the
149   // fullscreen window has all of the pixels, locking the screen should exit
150   // fullscreen. The fullscreen window has all of the pixels when in tab
151   // fullscreen.
152   {
153     FullscreenNotificationObserver fullscreen_waiter(browser());
154     content::WebContents* web_contents =
155         browser()->tab_strip_model()->GetActiveWebContents();
156     browser()
157         ->exclusive_access_manager()
158         ->fullscreen_controller()
159         ->EnterFullscreenModeForTab(web_contents->GetMainFrame());
160     fullscreen_waiter.Wait();
161     EXPECT_TRUE(browser_window->IsFullscreen());
162     EXPECT_TRUE(window_state->GetHideShelfWhenFullscreen());
163     EXPECT_FALSE(tester.IsLocked());
164   }
165   {
166     tester.Lock();
167     EXPECT_FALSE(browser_window->IsFullscreen());
168     EXPECT_TRUE(tester.IsLocked());
169   }
170 
171   tester.SetUnlockPassword(user_manager::StubAccountId(), "pass");
172   tester.UnlockWithPassword(user_manager::StubAccountId(), "pass");
173   EXPECT_FALSE(tester.IsLocked());
174 
175   EXPECT_EQ(2, session_manager_client()->notify_lock_screen_shown_call_count());
176   EXPECT_EQ(
177       2, session_manager_client()->notify_lock_screen_dismissed_call_count());
178 }
179 
IN_PROC_BROWSER_TEST_F(ScreenLockerTest,TestShowTwice)180 IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestShowTwice) {
181   ScreenLockerTester tester;
182   tester.Lock();
183 
184   // Calling Show again simply send LockCompleted signal.
185   ScreenLocker::Show();
186   EXPECT_TRUE(tester.IsLocked());
187   EXPECT_EQ(2, session_manager_client()->notify_lock_screen_shown_call_count());
188 
189   // Close the locker to match expectations.
190   ScreenLocker::Hide();
191   base::RunLoop().RunUntilIdle();
192   EXPECT_FALSE(tester.IsLocked());
193   EXPECT_EQ(
194       1, session_manager_client()->notify_lock_screen_dismissed_call_count());
195 }
196 
IN_PROC_BROWSER_TEST_F(ScreenLockerTest,PasswordAuthWhenAuthDisabled)197 IN_PROC_BROWSER_TEST_F(ScreenLockerTest, PasswordAuthWhenAuthDisabled) {
198   // Show lock screen and wait until it is shown.
199   ScreenLockerTester tester;
200   tester.Lock();
201 
202   // Inject fake authentication credentials.
203   const std::string kPassword = "pass";
204   tester.SetUnlockPassword(user_manager::StubAccountId(), kPassword);
205   EXPECT_TRUE(tester.IsLocked());
206 
207   // Disable authentication for user.
208   ScreenLocker::default_screen_locker()->DisableAuthForUser(
209       user_manager::StubAccountId(),
210       ash::AuthDisabledData(ash::AuthDisabledReason::kTimeWindowLimit,
211                             base::Time::Now() + base::TimeDelta::FromHours(1),
212                             base::TimeDelta::FromHours(1),
213                             true /*disable_lock_screen_media*/));
214 
215   // Try to authenticate with password.
216   tester.ForceSubmitPassword(user_manager::StubAccountId(), kPassword);
217   EXPECT_TRUE(tester.IsLocked());
218 
219   // Re-enable authentication for user.
220   ScreenLocker::default_screen_locker()->EnableAuthForUser(
221       user_manager::StubAccountId());
222 
223   // Try to authenticate with password.
224   tester.UnlockWithPassword(user_manager::StubAccountId(), kPassword);
225   base::RunLoop().RunUntilIdle();
226   EXPECT_FALSE(tester.IsLocked());
227   EXPECT_EQ(1, session_manager_client()->notify_lock_screen_shown_call_count());
228   EXPECT_EQ(session_manager::SessionState::ACTIVE,
229             session_manager::SessionManager::Get()->session_state());
230   EXPECT_EQ(
231       1, session_manager_client()->notify_lock_screen_dismissed_call_count());
232 }
233 
IN_PROC_BROWSER_TEST_F(ScreenLockerTest,FingerprintAuthWhenAuthDisabled)234 IN_PROC_BROWSER_TEST_F(ScreenLockerTest, FingerprintAuthWhenAuthDisabled) {
235   EnrollFingerprint();
236 
237   // Show lock screen and wait until it is shown.
238   ScreenLockerTester tester;
239   tester.Lock();
240 
241   const std::string kPassword = "pass";
242   tester.SetUnlockPassword(user_manager::StubAccountId(), kPassword);
243   EXPECT_TRUE(tester.IsLocked());
244 
245   // Disable authentication for user.
246   ScreenLocker::default_screen_locker()->DisableAuthForUser(
247       user_manager::StubAccountId(),
248       ash::AuthDisabledData(ash::AuthDisabledReason::kTimeUsageLimit,
249                             base::Time::Now() + base::TimeDelta::FromHours(1),
250                             base::TimeDelta::FromHours(3),
251                             true /*disable_lock_screen_media*/));
252 
253   // Try to authenticate with fingerprint.
254   AuthenticateWithFingerprint();
255   EXPECT_TRUE(tester.IsLocked());
256 
257   // Re-enable authentication for user.
258   ScreenLocker::default_screen_locker()->EnableAuthForUser(
259       user_manager::StubAccountId());
260 
261   // Try to authenticate with fingerprint.
262   AuthenticateWithFingerprint();
263   EXPECT_FALSE(tester.IsLocked());
264   EXPECT_EQ(1, session_manager_client()->notify_lock_screen_shown_call_count());
265   EXPECT_EQ(session_manager::SessionState::ACTIVE,
266             session_manager::SessionManager::Get()->session_state());
267   EXPECT_EQ(
268       1, session_manager_client()->notify_lock_screen_dismissed_call_count());
269 }
270 
271 }  // namespace chromeos
272