123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/system/session/logout_confirmation_controller.h"
- #include "ash/constants/ash_pref_names.h"
- #include "ash/session/session_controller_impl.h"
- #include "ash/session/test_session_controller_client.h"
- #include "ash/shell.h"
- #include "ash/test/ash_test_base.h"
- #include "ash/test/test_window_builder.h"
- #include "ash/wm/desks/desks_util.h"
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/memory/ref_counted.h"
- #include "base/test/test_mock_time_task_runner.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "base/time/tick_clock.h"
- #include "components/prefs/pref_service.h"
- #include "components/session_manager/session_manager_types.h"
- #include "components/user_manager/user_type.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "ui/aura/window.h"
- #include "ui/views/widget/widget.h"
- namespace ash {
- constexpr char kUserEmail[] = "user1@test.com";
- class LogoutConfirmationControllerTest : public testing::Test {
- public:
- LogoutConfirmationControllerTest(const LogoutConfirmationControllerTest&) =
- delete;
- LogoutConfirmationControllerTest& operator=(
- const LogoutConfirmationControllerTest&) = delete;
- protected:
- LogoutConfirmationControllerTest();
- ~LogoutConfirmationControllerTest() override;
- void LogOut(LogoutConfirmationController::Source source);
- bool log_out_called_;
- scoped_refptr<base::TestMockTimeTaskRunner> runner_;
- base::ThreadTaskRunnerHandle runner_handle_;
- LogoutConfirmationController controller_;
- };
- LogoutConfirmationControllerTest::LogoutConfirmationControllerTest()
- : log_out_called_(false),
- runner_(new base::TestMockTimeTaskRunner),
- runner_handle_(runner_) {
- controller_.SetClockForTesting(runner_->GetMockTickClock());
- controller_.SetLogoutCallbackForTesting(base::BindRepeating(
- &LogoutConfirmationControllerTest::LogOut, base::Unretained(this)));
- }
- LogoutConfirmationControllerTest::~LogoutConfirmationControllerTest() = default;
- void LogoutConfirmationControllerTest::LogOut(
- LogoutConfirmationController::Source source) {
- log_out_called_ = true;
- }
- // Verifies that the user is logged out immediately if logout confirmation with
- // a zero-length countdown is requested.
- TEST_F(LogoutConfirmationControllerTest, ZeroDuration) {
- controller_.ConfirmLogout(
- runner_->NowTicks(),
- LogoutConfirmationController::Source::kShelfExitButton);
- EXPECT_FALSE(log_out_called_);
- runner_->FastForwardBy(base::TimeDelta());
- EXPECT_TRUE(log_out_called_);
- }
- // Verifies that the user is logged out when the countdown expires.
- TEST_F(LogoutConfirmationControllerTest, DurationExpired) {
- controller_.ConfirmLogout(
- runner_->NowTicks() + base::Seconds(10),
- LogoutConfirmationController::Source::kShelfExitButton);
- EXPECT_FALSE(log_out_called_);
- runner_->FastForwardBy(base::Seconds(9));
- EXPECT_FALSE(log_out_called_);
- runner_->FastForwardBy(base::Seconds(2));
- EXPECT_TRUE(log_out_called_);
- }
- // Verifies that when a second request to confirm logout is made and the second
- // request's countdown ends before the original request's, the user is logged
- // out when the new countdown expires.
- TEST_F(LogoutConfirmationControllerTest, DurationShortened) {
- controller_.ConfirmLogout(
- runner_->NowTicks() + base::Seconds(30),
- LogoutConfirmationController::Source::kShelfExitButton);
- EXPECT_FALSE(log_out_called_);
- runner_->FastForwardBy(base::Seconds(9));
- EXPECT_FALSE(log_out_called_);
- controller_.ConfirmLogout(
- runner_->NowTicks() + base::Seconds(10),
- LogoutConfirmationController::Source::kShelfExitButton);
- runner_->FastForwardBy(base::Seconds(9));
- EXPECT_FALSE(log_out_called_);
- runner_->FastForwardBy(base::Seconds(2));
- EXPECT_TRUE(log_out_called_);
- }
- // Verifies that when a second request to confirm logout is made and the second
- // request's countdown ends after the original request's, the user is logged
- // out when the original countdown expires.
- TEST_F(LogoutConfirmationControllerTest, DurationExtended) {
- controller_.ConfirmLogout(
- runner_->NowTicks() + base::Seconds(10),
- LogoutConfirmationController::Source::kShelfExitButton);
- EXPECT_FALSE(log_out_called_);
- runner_->FastForwardBy(base::Seconds(9));
- EXPECT_FALSE(log_out_called_);
- controller_.ConfirmLogout(
- runner_->NowTicks() + base::Seconds(10),
- LogoutConfirmationController::Source::kShelfExitButton);
- runner_->FastForwardBy(base::Seconds(2));
- EXPECT_TRUE(log_out_called_);
- }
- // Verifies that when the screen is locked while the countdown is running, the
- // user is not logged out, even when the original countdown expires.
- TEST_F(LogoutConfirmationControllerTest, Lock) {
- controller_.ConfirmLogout(
- runner_->NowTicks() + base::Seconds(10),
- LogoutConfirmationController::Source::kShelfExitButton);
- EXPECT_FALSE(log_out_called_);
- controller_.OnLockStateChanged(true);
- runner_->FastForwardUntilNoTasksRemain();
- EXPECT_FALSE(log_out_called_);
- }
- // Verifies that when the user confirms the logout request, the user is logged
- // out immediately.
- TEST_F(LogoutConfirmationControllerTest, UserAccepted) {
- controller_.ConfirmLogout(
- runner_->NowTicks() + base::Seconds(10),
- LogoutConfirmationController::Source::kShelfExitButton);
- EXPECT_FALSE(log_out_called_);
- controller_.OnLogoutConfirmed();
- EXPECT_TRUE(log_out_called_);
- }
- // Verifies that when the user denies the logout request, the user is not logged
- // out, even when the original countdown expires.
- TEST_F(LogoutConfirmationControllerTest, UserDenied) {
- controller_.ConfirmLogout(
- runner_->NowTicks() + base::Seconds(10),
- LogoutConfirmationController::Source::kShelfExitButton);
- EXPECT_FALSE(log_out_called_);
- controller_.OnDialogClosed();
- runner_->FastForwardUntilNoTasksRemain();
- EXPECT_FALSE(log_out_called_);
- }
- // Verifies that after the user has denied a logout request, a subsequent logout
- // request is handled correctly and the user is logged out when the countdown
- // expires.
- TEST_F(LogoutConfirmationControllerTest, DurationExpiredAfterDeniedRequest) {
- controller_.ConfirmLogout(
- runner_->NowTicks() + base::Seconds(10),
- LogoutConfirmationController::Source::kShelfExitButton);
- EXPECT_FALSE(log_out_called_);
- controller_.OnDialogClosed();
- runner_->FastForwardUntilNoTasksRemain();
- EXPECT_FALSE(log_out_called_);
- controller_.ConfirmLogout(
- runner_->NowTicks() + base::Seconds(10),
- LogoutConfirmationController::Source::kShelfExitButton);
- EXPECT_FALSE(log_out_called_);
- runner_->FastForwardBy(base::Seconds(9));
- EXPECT_FALSE(log_out_called_);
- runner_->FastForwardBy(base::Seconds(2));
- EXPECT_TRUE(log_out_called_);
- }
- class LastWindowClosedTest : public NoSessionAshTestBase {
- public:
- LastWindowClosedTest() = default;
- LastWindowClosedTest(const LastWindowClosedTest&) = delete;
- LastWindowClosedTest& operator=(const LastWindowClosedTest&) = delete;
- ~LastWindowClosedTest() override = default;
- // Simulate a managed guest session (non-demo session) login.
- void StartManagedGuestSession() {
- TestSessionControllerClient* session = GetSessionControllerClient();
- session->Reset();
- session->AddUserSession(kUserEmail, user_manager::USER_TYPE_PUBLIC_ACCOUNT);
- session->SetSessionState(session_manager::SessionState::ACTIVE);
- }
- // Simulate a demo session signing in.
- void StartDemoSession() {
- GetSessionControllerClient()->SetIsDemoSession();
- // Demo session is implemented as a managed guest session.
- StartManagedGuestSession();
- }
- // PrefService for the managed guest session started by
- // StartManagedGuestSession().
- PrefService* pref_service() {
- return Shell::Get()->session_controller()->GetUserPrefServiceForUser(
- AccountId::FromUserEmail(kUserEmail));
- }
- };
- TEST_F(LastWindowClosedTest, RegularSession) {
- // Dialog is not visible at startup.
- LogoutConfirmationController* controller =
- Shell::Get()->logout_confirmation_controller();
- EXPECT_FALSE(controller->dialog_for_testing());
- // Dialog is not visible after login.
- CreateUserSessions(1);
- EXPECT_FALSE(controller->dialog_for_testing());
- // Creating and closing a window does not show the dialog because this is not
- // a managed guest session.
- std::unique_ptr<aura::Window> window = CreateToplevelTestWindow();
- EXPECT_FALSE(controller->dialog_for_testing());
- window.reset();
- EXPECT_FALSE(controller->dialog_for_testing());
- }
- TEST_F(LastWindowClosedTest, DemoSession) {
- // Dialog is not visible at startup.
- LogoutConfirmationController* controller =
- Shell::Get()->logout_confirmation_controller();
- EXPECT_FALSE(controller->dialog_for_testing());
- // Dialog is not visible after demo session starts.
- StartDemoSession();
- EXPECT_FALSE(controller->dialog_for_testing());
- // Creating and closing a window does not show the dialog.
- std::unique_ptr<aura::Window> window = CreateToplevelTestWindow();
- EXPECT_FALSE(controller->dialog_for_testing());
- window.reset();
- EXPECT_FALSE(controller->dialog_for_testing());
- }
- TEST_F(LastWindowClosedTest, ManagedGuestSession) {
- LogoutConfirmationController* controller =
- Shell::Get()->logout_confirmation_controller();
- // Dialog is not visible after managed guest session login.
- StartManagedGuestSession();
- EXPECT_FALSE(controller->dialog_for_testing());
- // Opening windows does not show the dialog.
- std::unique_ptr<views::Widget> widget1 = CreateTestWidget();
- std::unique_ptr<views::Widget> widget2 = CreateTestWidget();
- EXPECT_FALSE(controller->dialog_for_testing());
- // Closing the last window shows the dialog.
- widget1.reset();
- EXPECT_FALSE(controller->dialog_for_testing());
- widget2.reset();
- EXPECT_TRUE(controller->dialog_for_testing());
- }
- TEST_F(LastWindowClosedTest, SuggestLogoutAfterClosingLastWindowPolicy) {
- LogoutConfirmationController* controller =
- Shell::Get()->logout_confirmation_controller();
- // Dialog is not visible after managed guest session login.
- StartManagedGuestSession();
- pref_service()->SetBoolean(prefs::kSuggestLogoutAfterClosingLastWindow,
- false);
- EXPECT_FALSE(controller->dialog_for_testing());
- // Opening windows does not show the dialog.
- std::unique_ptr<views::Widget> widget1 = CreateTestWidget();
- std::unique_ptr<views::Widget> widget2 = CreateTestWidget();
- EXPECT_FALSE(controller->dialog_for_testing());
- // Closing the last window does not show the dialog because the
- // kSuggestLogoutAfterClosingLastWindow is set to false.
- widget1.reset();
- EXPECT_FALSE(controller->dialog_for_testing());
- widget2.reset();
- EXPECT_FALSE(controller->dialog_for_testing());
- }
- // Test ARC++ window hierarchy where window minimize, restore and go in/out full
- // screen causes a window removing deep inside the top window hierarchy. Actions
- // above should no cause logout timer and only closing the last top window
- // triggers the logout timer.
- TEST_F(LastWindowClosedTest, ManagedGuestSessionComplexHierarchy) {
- LogoutConfirmationController* controller =
- Shell::Get()->logout_confirmation_controller();
- StartManagedGuestSession();
- EXPECT_FALSE(controller->dialog_for_testing());
- std::unique_ptr<aura::Window> window = CreateToplevelTestWindow();
- EXPECT_FALSE(controller->dialog_for_testing());
- std::unique_ptr<aura::Window> window_child =
- ChildTestWindowBuilder(window.get()).Build();
- EXPECT_FALSE(controller->dialog_for_testing());
- window_child.reset();
- EXPECT_FALSE(controller->dialog_for_testing());
- window.reset();
- EXPECT_TRUE(controller->dialog_for_testing());
- }
- TEST_F(LastWindowClosedTest, AlwaysOnTop) {
- LogoutConfirmationController* controller =
- Shell::Get()->logout_confirmation_controller();
- StartManagedGuestSession();
- // The new widget starts in the default window container.
- std::unique_ptr<views::Widget> widget = CreateTestWidget();
- // Moving the widget to the always-on-top container does not trigger the
- // dialog because the window didn't close.
- widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
- EXPECT_FALSE(controller->dialog_for_testing());
- // Closing the window triggers the dialog.
- widget.reset();
- EXPECT_TRUE(controller->dialog_for_testing());
- }
- TEST_F(LastWindowClosedTest, MultipleContainers) {
- LogoutConfirmationController* controller =
- Shell::Get()->logout_confirmation_controller();
- StartManagedGuestSession();
- // Create two windows in different containers.
- std::unique_ptr<views::Widget> normal_widget = CreateTestWidget();
- std::unique_ptr<views::Widget> always_on_top_widget = CreateTestWidget();
- always_on_top_widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
- // Closing the last window shows the dialog.
- always_on_top_widget.reset();
- EXPECT_FALSE(controller->dialog_for_testing());
- normal_widget.reset();
- EXPECT_TRUE(controller->dialog_for_testing());
- }
- TEST_F(LastWindowClosedTest, MultipleDisplays) {
- LogoutConfirmationController* controller =
- Shell::Get()->logout_confirmation_controller();
- StartManagedGuestSession();
- // Create two displays, each with a window.
- UpdateDisplay("1024x768,800x600");
- std::unique_ptr<aura::Window> window1 =
- ChildTestWindowBuilder(Shell::GetAllRootWindows()[0]->GetChildById(
- desks_util::GetActiveDeskContainerId()))
- .Build();
- std::unique_ptr<aura::Window> window2 =
- ChildTestWindowBuilder(Shell::GetAllRootWindows()[1]->GetChildById(
- desks_util::GetActiveDeskContainerId()))
- .Build();
- // Closing the last window shows the dialog.
- window1.reset();
- EXPECT_FALSE(controller->dialog_for_testing());
- window2.reset();
- EXPECT_TRUE(controller->dialog_for_testing());
- }
- } // namespace ash
|