Skip to content

Commit

Permalink
Lacros: Support KeepFullscreenWithoutNotification policy
Browse files Browse the repository at this point in the history
This CL adds support for the KeepFullscreenWithoutNotification policy
for lacros browser and app windows. The implementation from ash is
mimicked in lacros.

- A fullscreen controller crosapi is added to allow ash to query lacros
  whether it should exit full screen before lock.
- The kKeepFullscreenWithoutNotificationUrlAllowList pref and common
  logic are moved to //chromeos/ui/wm/fullscreen which is
  accessible from //ash and //chrome/browser/lacros.
- ShouldExitFullscreenBeforeLock() in
  //ash/session/fullscreen_controller is replaced with
  MaybeExitFullscreenBeforeLock(PrepareForLockCallback) to handle the
  crosapi callback from lacros.

Bug: 1348155, b:213295466
Change-Id: Idc361f0e0e6c3fde831f9dac20e4d0bef0adfdb3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3497703
Reviewed-by: Dominic Battré <battre@chromium.org>
Reviewed-by: Erik Chen <erikchen@chromium.org>
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Reviewed-by: Alexander Hendrich <hendrich@chromium.org>
Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org>
Commit-Queue: Anina Koehler <aninak@google.com>
Cr-Commit-Position: refs/heads/main@{#1033387}
  • Loading branch information
annklr authored and Chromium LUCI CQ committed Aug 10, 2022
1 parent 27bd7b5 commit f1e29df
Show file tree
Hide file tree
Showing 42 changed files with 1,013 additions and 99 deletions.
3 changes: 3 additions & 0 deletions ash/ash_prefs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include "ash/wm/window_cycle/window_cycle_controller.h"
#include "chromeos/ash/services/assistant/public/cpp/assistant_prefs.h"
#include "chromeos/components/quick_answers/public/cpp/quick_answers_prefs.h"
#include "chromeos/ui/wm/fullscreen/pref_names.h"
#include "components/language/core/browser/pref_names.h"
#include "components/live_caption/pref_names.h"
#include "components/soda/constants.h"
Expand Down Expand Up @@ -128,6 +129,8 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry, bool for_test) {
registry->RegisterBooleanPref(chromeos::prefs::kSuggestedContentEnabled,
true);
registry->RegisterBooleanPref(::prefs::kLiveCaptionEnabled, false);
registry->RegisterListPref(
chromeos::prefs::kKeepFullscreenWithoutNotificationUrlAllowList);
registry->RegisterStringPref(::prefs::kLiveCaptionLanguageCode,
speech::kUsEnglishLocale);
registry->RegisterStringPref(language::prefs::kApplicationLocale,
Expand Down
5 changes: 0 additions & 5 deletions ash/constants/ash_pref_names.cc
Original file line number Diff line number Diff line change
Expand Up @@ -447,11 +447,6 @@ const char kAllowMGSToStoreDisplayProperties[] =
// A boolean pref that enable fullscreen alert bubble.
// TODO(zxdan): Change to an allowlist in M89.
const char kFullscreenAlertEnabled[] = "ash.fullscreen_alert_enabled";
// A list of URLs that are allowed to continue full screen mode after session
// unlock without a notification. To prevent fake login screens, the device
// normally exits full screen mode before locking a session.
const char kKeepFullscreenWithoutNotificationUrlAllowList[] =
"ash.keep_fullscreen_without_notification_url_allow_list";

// A boolean pref storing whether the gesture education notification has ever
// been shown to the user, which we use to stop showing it again.
Expand Down
2 changes: 0 additions & 2 deletions ash/constants/ash_pref_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS)
extern const char kAllowMGSToStoreDisplayProperties[];

COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kFullscreenAlertEnabled[];
COMPONENT_EXPORT(ASH_CONSTANTS)
extern const char kKeepFullscreenWithoutNotificationUrlAllowList[];

COMPONENT_EXPORT(ASH_CONSTANTS)
extern const char kGestureEducationNotificationShown[];
Expand Down
145 changes: 91 additions & 54 deletions ash/session/fullscreen_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <limits>

#include "ash/constants/app_types.h"
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/session/fullscreen_notification_bubble.h"
Expand All @@ -18,13 +19,48 @@
#include "base/check.h"
#include "chromeos/dbus/power_manager/backlight.pb.h"
#include "chromeos/dbus/power_manager/idle.pb.h"
#include "chromeos/ui/wm/fullscreen/keep_fullscreen_for_url_checker.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/url_matcher/url_matcher.h"
#include "components/url_matcher/url_util.h"
#include "ui/aura/client/aura_constants.h"
#include "url/gurl.h"

namespace ash {

namespace {

// Exits full screen to avoid the web page or app mimicking the lock screen if
// the active window is in full screen mode and the shelf is not visible. Do not
// exit fullscreen if the shelf is visible while in fullscreen because the shelf
// makes it harder for a web page or app to mimic the lock screen.
void ExitFullscreenIfActive() {
WindowState* active_window_state = WindowState::ForActiveWindow();
if (!active_window_state || !active_window_state->IsFullscreen())
return;

Shelf* shelf = Shelf::ForWindow(active_window_state->window());
const bool shelf_visible =
shelf->GetVisibilityState() == ShelfVisibilityState::SHELF_VISIBLE;

if (shelf_visible && !active_window_state->GetHideShelfWhenFullscreen())
return;

const WMEvent event(WM_EVENT_TOGGLE_FULLSCREEN);
active_window_state->OnWMEvent(&event);
}

// Receives the result from the request to Lacros and exits full screen, if
// required. |callback| will be invoked to signal readiness for session lock.
void OnShouldExitFullscreenResult(base::OnceClosure callback,
bool should_exit_fullscreen) {
if (should_exit_fullscreen)
ExitFullscreenIfActive();

std::move(callback).Run();
}

} // namespace

FullscreenController::FullscreenController(
SessionControllerImpl* session_controller)
: session_controller_(session_controller) {
Expand All @@ -43,24 +79,63 @@ FullscreenController::~FullscreenController() {
}

// static
void FullscreenController::MaybeExitFullscreen() {
// If the active window is fullscreen, exit fullscreen to avoid the web page
// or app mimicking the lock screen. Do not exit fullscreen if the shelf is
// visible while in fullscreen because the shelf makes it harder for a web
// page or app to mimic the lock screen.
void FullscreenController::RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kFullscreenAlertEnabled, true,
PrefRegistry::PUBLIC);
}

void FullscreenController::MaybeExitFullscreenBeforeLock(
base::OnceClosure callback) {
// Check whether it is allowed to keep full screen on unlock.
if (!features::IsFullscreenAfterUnlockAllowed()) {
ExitFullscreenIfActive();
std::move(callback).Run();
return;
}

// Nothing to do if the active window is not in full screen mode.
WindowState* active_window_state = WindowState::ForActiveWindow();
if (!active_window_state || !active_window_state->IsFullscreen())
if (!active_window_state || !active_window_state->IsFullscreen()) {
std::move(callback).Run();
return;
}

Shelf* shelf = Shelf::ForWindow(active_window_state->window());
const bool shelf_visible =
shelf->GetVisibilityState() == ShelfVisibilityState::SHELF_VISIBLE;
if (!keep_fullscreen_checker_) {
keep_fullscreen_checker_ =
std::make_unique<chromeos::KeepFullscreenForUrlChecker>(
Shell::Get()->session_controller()->GetPrimaryUserPrefService());
}

if (shelf_visible && !active_window_state->GetHideShelfWhenFullscreen())
// Always exit full screen if the allowlist policy is unset.
if (!keep_fullscreen_checker_
->IsKeepFullscreenWithoutNotificationPolicySet()) {
ExitFullscreenIfActive();
std::move(callback).Run();
return;
}

const WMEvent event(WM_EVENT_TOGGLE_FULLSCREEN);
active_window_state->OnWMEvent(&event);
// Try to get the URL of the active window from the shell delegate.
const GURL& url =
Shell::Get()->shell_delegate()->GetLastCommittedURLForWindowIfAny(
active_window_state->window());

// If the chrome shell delegate did not return a URL for the active window, it
// could be a Lacros window and it should check with Lacros whether the
// FullscreenController should exit full screen mode.
if (url.is_empty() &&
active_window_state->window()->GetProperty(aura::client::kAppType) ==
static_cast<int>(AppType::LACROS)) {
auto should_exit_fullscreen_callback =
base::BindOnce(&OnShouldExitFullscreenResult, std::move(callback));
Shell::Get()->shell_delegate()->ShouldExitFullscreenBeforeLock(
std::move(should_exit_fullscreen_callback));
return;
}

// Check if it is allowed by user pref to keep full screen for the window URL.
if (keep_fullscreen_checker_->ShouldExitFullscreenForUrl(url))
ExitFullscreenIfActive();
std::move(callback).Run();
}

void FullscreenController::MaybeShowNotification() {
Expand Down Expand Up @@ -99,21 +174,12 @@ void FullscreenController::MaybeShowNotification() {
bubble_->ShowForWindowState(active_window_state);
}

// static
void FullscreenController::RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kFullscreenAlertEnabled, true,
PrefRegistry::PUBLIC);
registry->RegisterListPref(
prefs::kKeepFullscreenWithoutNotificationUrlAllowList,
PrefRegistry::PUBLIC);
}

void FullscreenController::SuspendImminent(
power_manager::SuspendImminent::Reason reason) {
if (session_controller_->login_status() != LoginStatus::GUEST)
return;

MaybeExitFullscreen();
ExitFullscreenIfActive();
}

void FullscreenController::ScreenIdleStateChanged(
Expand All @@ -122,7 +188,7 @@ void FullscreenController::ScreenIdleStateChanged(
return;

if (proto.off() || proto.dimmed())
MaybeExitFullscreen();
ExitFullscreenIfActive();
}

void FullscreenController::ScreenBrightnessChanged(
Expand Down Expand Up @@ -151,33 +217,4 @@ void FullscreenController::LidEventReceived(
MaybeShowNotification();
}

// static
bool FullscreenController::ShouldExitFullscreenBeforeLock() {
// Check whether it is allowed to keep full screen on unlock.
if (!features::IsFullscreenAfterUnlockAllowed())
return true;

// Nothing to do if the active window is not in full screen mode.
WindowState* active_window_state = WindowState::ForActiveWindow();
if (!active_window_state || !active_window_state->IsFullscreen())
return false;

// Always exit full screen if the allowlist policy is unset.
auto* prefs = Shell::Get()->session_controller()->GetPrimaryUserPrefService();
const auto& url_allow_list = prefs->GetValueList(
prefs::kKeepFullscreenWithoutNotificationUrlAllowList);
if (url_allow_list.size() == 0)
return true;

// Get the URL of the active window from the shell delegate.
const GURL& url =
Shell::Get()->shell_delegate()->GetLastCommittedURLForWindowIfAny(
active_window_state->window());

// Check if it is allowed by user pref to keep full screen for the active URL.
url_matcher::URLMatcher url_matcher;
url_matcher::util::AddAllowFilters(&url_matcher, url_allow_list);
return url_matcher.MatchURL(url).empty();
}

} // namespace ash
19 changes: 14 additions & 5 deletions ash/session/fullscreen_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

class PrefRegistrySimple;

namespace chromeos {
class KeepFullscreenForUrlChecker;
} // namespace chromeos

namespace ash {

class SessionControllerImpl;
Expand All @@ -25,13 +29,17 @@ class FullscreenController : public chromeos::PowerManagerClient::Observer {

~FullscreenController() override;

static void MaybeExitFullscreen();

static void RegisterProfilePrefs(PrefRegistrySimple* registry);

static bool ShouldExitFullscreenBeforeLock();
// Checks the window state, user pref and, if required, sends a request to
// Lacros to determine whether it should exit full screen mode before the
// session is locked. |callback| will be invoked to signal readiness for
// session lock.
void MaybeExitFullscreenBeforeLock(base::OnceClosure callback);

private:
void MaybeShowNotification();

// chromeos::PowerManagerClient::Observer:
void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
void ScreenIdleStateChanged(
Expand All @@ -41,12 +49,13 @@ class FullscreenController : public chromeos::PowerManagerClient::Observer {
void LidEventReceived(chromeos::PowerManagerClient::LidState state,
base::TimeTicks timestamp) override;

void MaybeShowNotification();

const SessionControllerImpl* const session_controller_;

std::unique_ptr<FullscreenNotificationBubble> bubble_;

std::unique_ptr<chromeos::KeepFullscreenForUrlChecker>
keep_fullscreen_checker_;

// Whether the screen brightness is low enough to make display dark.
bool device_in_dark_ = false;
};
Expand Down
Loading

0 comments on commit f1e29df

Please sign in to comment.