blob: 23ba4d58f15a1be617183b25f5d4f0f8aaaa93f6 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/session/fullscreen_controller.h"
#include <memory>
#include "ash/constants/app_types.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test_shell_delegate.h"
#include "ash/wm/window_state.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "chromeos/ui/base/window_properties.h"
#include "chromeos/ui/wm/fullscreen/pref_names.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
namespace ash {
namespace {
const GURL kActiveUrl = GURL("https://wwww.test.com");
const GURL kEmptyUrl;
constexpr char kNonMatchingPattern[] = "google.com";
constexpr char kMatchingPattern[] = "test.com";
constexpr char kWildcardPattern[] = "*";
bool IsOfficialBuildWithoutDcheck() {
#if defined(OFFICIAL_BUILD) && !DCHECK_IS_ON()
return true;
#else
return false;
#endif
}
class FullscreenControllerTestBase : public AshTestBase {
public:
FullscreenControllerTestBase() = default;
FullscreenControllerTestBase(const FullscreenControllerTestBase&) = delete;
FullscreenControllerTestBase& operator=(const FullscreenControllerTestBase&) =
delete;
~FullscreenControllerTestBase() override = default;
// AshTestBase:
void SetUp() override {
// Create a test shell delegate which can return fake responses.
auto test_shell_delegate = std::make_unique<TestShellDelegate>();
test_shell_delegate_ = test_shell_delegate.get();
AshTestBase::SetUp(std::move(test_shell_delegate));
CreateFullscreenWindow();
}
void TearDown() override {
window_.reset();
AshTestBase::TearDown();
}
protected:
void CreateFullscreenWindow() {
window_ = CreateTestWindow();
window_->SetProperty(aura::client::kShowStateKey,
ui::SHOW_STATE_FULLSCREEN);
SetPropertiesForNewFullscreenWindow(window_.get());
window_state_ = WindowState::Get(window_.get());
}
virtual void SetPropertiesForNewFullscreenWindow(aura::Window* window) {}
void SetKeepFullscreenWithoutNotificationAllowList(
const std::string& pattern) {
base::Value::List list;
list.Append(pattern);
Shell::Get()->session_controller()->GetPrimaryUserPrefService()->SetList(
chromeos::prefs::kKeepFullscreenWithoutNotificationUrlAllowList,
std::move(list));
}
std::unique_ptr<aura::Window> window_;
raw_ptr<WindowState, DanglingUntriaged> window_state_ = nullptr;
raw_ptr<TestShellDelegate, DanglingUntriaged> test_shell_delegate_ = nullptr;
};
class FullscreenControllerTest : public FullscreenControllerTestBase,
public testing::WithParamInterface<bool> {
protected:
void SetPropertiesForNewFullscreenWindow(aura::Window* window) override {
if (is_lacros_window_) {
window->SetProperty(aura::client::kAppType,
static_cast<int>(AppType::LACROS));
}
}
void SetUpShellDelegate(bool should_exit_fullscreen, GURL url = kActiveUrl) {
// The shell delegate will only retrieve the active URL for ash-chrome
// windows and return the empty URL for lacros-chrome windows.
if (is_lacros_window_) {
test_shell_delegate_->SetLastCommittedURLForWindow(kEmptyUrl);
test_shell_delegate_->SetShouldExitFullscreenBeforeLock(
should_exit_fullscreen);
} else {
test_shell_delegate_->SetLastCommittedURLForWindow(url);
}
}
bool is_lacros_window_ = GetParam();
};
// Test that full screen is exited after session unlock if the allow list pref
// is unset.
TEST_P(FullscreenControllerTest, ExitFullscreenIfUnsetPref) {
EXPECT_TRUE(window_state_->IsFullscreen());
base::RunLoop run_loop;
Shell::Get()->session_controller()->PrepareForLock(run_loop.QuitClosure());
GetSessionControllerClient()->LockScreen();
GetSessionControllerClient()->UnlockScreen();
run_loop.Run();
EXPECT_FALSE(window_state_->IsFullscreen());
}
// Test that full screen is exited after session unlock if the URL of the active
// window does not match any patterns from the allow list.
TEST_P(FullscreenControllerTest, ExitFullscreenIfNonMatchingPref) {
bool should_exit_fullscreen = true;
SetUpShellDelegate(should_exit_fullscreen);
SetKeepFullscreenWithoutNotificationAllowList(kNonMatchingPattern);
EXPECT_TRUE(window_state_->IsFullscreen());
base::RunLoop run_loop;
Shell::Get()->session_controller()->PrepareForLock(run_loop.QuitClosure());
GetSessionControllerClient()->LockScreen();
GetSessionControllerClient()->UnlockScreen();
run_loop.Run();
EXPECT_EQ(window_state_->IsFullscreen(), !should_exit_fullscreen);
}
// Test that full screen is not exited after session unlock if the URL of the
// active window matches a pattern from the allow list.
TEST_P(FullscreenControllerTest, KeepFullscreenIfMatchingPref) {
bool should_exit_fullscreen = false;
SetUpShellDelegate(should_exit_fullscreen);
// Set up the URL exempt list with one matching and one non-matching pattern.
base::Value::List list;
list.Append(kNonMatchingPattern);
list.Append(kMatchingPattern);
Shell::Get()->session_controller()->GetPrimaryUserPrefService()->SetList(
chromeos::prefs::kKeepFullscreenWithoutNotificationUrlAllowList,
std::move(list));
EXPECT_TRUE(window_state_->IsFullscreen());
base::RunLoop run_loop;
Shell::Get()->session_controller()->PrepareForLock(run_loop.QuitClosure());
GetSessionControllerClient()->LockScreen();
GetSessionControllerClient()->UnlockScreen();
run_loop.Run();
EXPECT_EQ(window_state_->IsFullscreen(), !should_exit_fullscreen);
}
// Test that full screen is not exited after session unlock if the allow list
// includes the wildcard character.
TEST_P(FullscreenControllerTest, KeepFullscreenIfWildcardPref) {
bool should_exit_fullscreen = false;
SetUpShellDelegate(should_exit_fullscreen);
SetKeepFullscreenWithoutNotificationAllowList(kWildcardPattern);
EXPECT_TRUE(window_state_->IsFullscreen());
base::RunLoop run_loop;
Shell::Get()->session_controller()->PrepareForLock(run_loop.QuitClosure());
GetSessionControllerClient()->LockScreen();
GetSessionControllerClient()->UnlockScreen();
run_loop.Run();
EXPECT_EQ(window_state_->IsFullscreen(), !should_exit_fullscreen);
}
// Test that full screen is exited after session unlock if the URL is not
// available.
TEST_P(FullscreenControllerTest, ExitFullscreenIfUnsetUrlUnsetPref) {
bool should_exit_fullscreen = true;
SetUpShellDelegate(should_exit_fullscreen, kEmptyUrl);
EXPECT_TRUE(window_state_->IsFullscreen());
base::RunLoop run_loop;
Shell::Get()->session_controller()->PrepareForLock(run_loop.QuitClosure());
GetSessionControllerClient()->LockScreen();
GetSessionControllerClient()->UnlockScreen();
run_loop.Run();
EXPECT_EQ(window_state_->IsFullscreen(), !should_exit_fullscreen);
}
// Test that full screen is not exited after session unlock if the allow list
// includes the wildcard character and the URL is not available.
TEST_P(FullscreenControllerTest, KeepFullscreenIfUnsetUrlWildcardPref) {
bool should_exit_fullscreen = false;
SetUpShellDelegate(should_exit_fullscreen, kEmptyUrl);
SetKeepFullscreenWithoutNotificationAllowList(kWildcardPattern);
EXPECT_TRUE(window_state_->IsFullscreen());
base::RunLoop run_loop;
Shell::Get()->session_controller()->PrepareForLock(run_loop.QuitClosure());
GetSessionControllerClient()->LockScreen();
GetSessionControllerClient()->UnlockScreen();
run_loop.Run();
EXPECT_EQ(window_state_->IsFullscreen(), !should_exit_fullscreen);
}
INSTANTIATE_TEST_SUITE_P(All, FullscreenControllerTest, testing::Bool());
using FullscreenControllerNotLacrosRelatedTest = FullscreenControllerTestBase;
TEST_F(FullscreenControllerNotLacrosRelatedTest,
KeepFullscreenIfNoExitPropertySet) {
window_->SetProperty(chromeos::kUseOverviewToExitFullscreen, true);
window_->SetProperty(chromeos::kNoExitFullscreenOnLock, true);
window_->SetProperty(aura::client::kAppType,
static_cast<int>(AppType::CROSTINI_APP));
ASSERT_TRUE(window_state_->IsFullscreen());
base::RunLoop run_loop;
Shell::Get()->session_controller()->PrepareForLock(run_loop.QuitClosure());
GetSessionControllerClient()->LockScreen();
EXPECT_TRUE(window_state_->IsFullscreen());
GetSessionControllerClient()->UnlockScreen();
run_loop.Run();
EXPECT_TRUE(window_state_->IsFullscreen());
}
TEST_F(FullscreenControllerNotLacrosRelatedTest,
NoExitPropertyNotAllowedIfOverviewPropertyIsNotSet) {
// CHECK macro discards error message for the official build with
// dcheck=false. See the definition in base/check.h for details.
std::string expected_error_message =
IsOfficialBuildWithoutDcheck() ? "" : "Property combination not allowed";
EXPECT_DEATH(
{
window_->SetProperty(chromeos::kUseOverviewToExitFullscreen, false);
window_->SetProperty(chromeos::kNoExitFullscreenOnLock, true);
ASSERT_TRUE(window_state_->IsFullscreen());
base::RunLoop run_loop;
Shell::Get()->session_controller()->PrepareForLock(
run_loop.QuitClosure());
GetSessionControllerClient()->LockScreen();
},
expected_error_message);
}
} // namespace
} // namespace ash