Commit 7c23ff27 authored by Xiaodan Zhu's avatar Xiaodan Zhu Committed by Commit Bot

Add alert for fullscreen window to prevent fake login.

This CL implements an alert bubble to prevent fake login.

When a device returns from sleep or low brightness and the active
window is fullscreen. Others can utilize the fullscreen window
to imitate the lock/login screen to steal user's password.

To prevent this, we generate an alert bubble to remind the user
to exit fullscreen before entering the password. The users can
also use the button in the bubble to exit fullscreen.

Bug: 1107185
Change-Id: I181f1173777ada1ec45fe7148e7dc889668d6753
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2505335
Commit-Queue: Xiaodan Zhu <zxdan@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#822564}
parent 4febb4d4
......@@ -731,6 +731,8 @@ component("ash") {
"screen_util.cc",
"screen_util.h",
"screenshot_delegate.h",
"session/fullscreen_alert_bubble.h",
"session/fullscreen_alert_bubble.cc",
"session/fullscreen_controller.cc",
"session/fullscreen_controller.h",
"session/multiprofiles_intro_dialog.cc",
......
......@@ -2155,6 +2155,17 @@ This file contains the strings for ash.
Full-screen Magnifier enabled. Press Ctrl+Search+M again to toggle it off.
</message>
<!-- Alert bubble that when the device returns from sleep or display off without a lock screen and an active window is in fullscreen mode -->
<message name="IDS_FULLSCREEN_ALERT" desc="Text on an alert bubble to tell users that the active window is in fullscreen mode and recommend to exit fullscreen before entering password.">
Your current app is full screen. If the app asks for your password exit full screen first.
</message>
<message name="IDS_EXIT_FULLSCREEN_BUTTON" desc="Text on the exit fullscreen button.">
Exit fullscreen
</message>
<message name="IDS_DISMISS_BUTTON" desc="Text on the dismiss button.">
Dismiss
</message>
<!-- Tray scale strings -->
<message name="IDS_ASH_STATUS_TRAY_SCALE" desc="The label used in scale setting detailed page of ash tray popup.">
Display scale settings
......
dd2b362e5c00cff4e1abf64f65305d4ce77ae9e1
\ No newline at end of file
dd2b362e5c00cff4e1abf64f65305d4ce77ae9e1
\ No newline at end of file
dd2b362e5c00cff4e1abf64f65305d4ce77ae9e1
\ No newline at end of file
// Copyright 2018 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/session/fullscreen_alert_bubble.h"
#include <memory>
#include "ash/login/ui/system_label_button.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/session/fullscreen_controller.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/wm/work_area_insets.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/time/time.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/events/event.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/view.h"
#include "ui/wm/core/visibility_controller.h"
#include "ui/wm/core/window_animations.h"
namespace ash {
namespace {
constexpr int kAlertBubbleWidthDp = 384;
constexpr int kBubblePaddingDp = 16;
constexpr int kBubbleBetweenChildSpacingDp = 16;
constexpr int kBubbleBorderRadius = 8;
constexpr int kButtonPaddingDp = 8;
constexpr int kOffsetFromEdge = 32;
constexpr base::TimeDelta kAlertDuration = base::TimeDelta::FromSeconds(4);
constexpr base::TimeDelta kBubbleAnimationDuration =
base::TimeDelta::FromMilliseconds(300);
constexpr SkColor kAlertTextColor =
SkColorSetA(gfx::kGoogleGrey200, SK_AlphaOPAQUE);
} // namespace
class FullscreenAlertBubbleView : public views::View {
public:
METADATA_HEADER(FullscreenAlertBubbleView);
FullscreenAlertBubbleView(views::Button::PressedCallback on_dismiss,
views::Button::PressedCallback on_exit_fullscreen) {
SetPaintToLayer();
SkColor background_color = AshColorProvider::Get()->GetBaseLayerColor(
AshColorProvider::BaseLayerType::kTransparent80);
layer()->SetBackgroundBlur(
static_cast<float>(AshColorProvider::LayerBlurSigma::kBlurDefault));
SetBackground(views::CreateRoundedRectBackground(background_color,
kBubbleBorderRadius));
layer()->SetFillsBoundsOpaquely(false);
auto* main_layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, gfx::Insets(kBubblePaddingDp),
kBubbleBetweenChildSpacingDp));
main_layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter);
alert_text_ = AddChildView(std::make_unique<views::Label>(
l10n_util::GetStringUTF16(IDS_FULLSCREEN_ALERT)));
alert_text_->SetEnabledColor(kAlertTextColor);
alert_text_->SetAutoColorReadabilityEnabled(false);
alert_text_->SetMultiLine(true);
auto* button_container = AddChildView(std::make_unique<views::View>());
auto* button_layout =
button_container->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
kButtonPaddingDp));
button_layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter);
auto* dismiss =
button_container->AddChildView(std::make_unique<SystemLabelButton>(
nullptr, l10n_util::GetStringUTF16(IDS_DISMISS_BUTTON),
SystemLabelButton::DisplayType::DEFAULT));
dismiss->SetCallback(on_dismiss);
auto* exit_fullscreen =
button_container->AddChildView(std::make_unique<SystemLabelButton>(
nullptr, l10n_util::GetStringUTF16(IDS_EXIT_FULLSCREEN_BUTTON),
SystemLabelButton::DisplayType::ALERT_NO_ICON));
exit_fullscreen->SetCallback(on_exit_fullscreen);
}
// views::View:
gfx::Size CalculatePreferredSize() const override {
gfx::Size size;
size.set_width(kAlertBubbleWidthDp);
size.set_height(GetHeightForWidth(kAlertBubbleWidthDp));
return size;
}
void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
node_data->role = ax::mojom::Role::kAlertDialog;
node_data->SetName(alert_text_->GetText());
}
private:
views::Label* alert_text_ = nullptr;
};
BEGIN_METADATA(FullscreenAlertBubbleView, views::View)
END_METADATA
FullscreenAlertBubble::FullscreenAlertBubble()
: bubble_widget_(std::make_unique<views::Widget>()),
timer_(std::make_unique<base::OneShotTimer>()) {
bubble_view_ = std::make_unique<FullscreenAlertBubbleView>(
views::Button::PressedCallback(base::BindRepeating(
&FullscreenAlertBubble::Dismiss, base::Unretained(this))),
views::Button::PressedCallback(base::BindRepeating(
&FullscreenAlertBubble::ExitFullscreen, base::Unretained(this))));
views::Widget::InitParams params;
params.type = views::Widget::InitParams::TYPE_POPUP;
params.name = "FullscreenAlertBubble";
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.z_order = ui::ZOrderLevel::kFloatingUIElement;
params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
params.parent = Shell::GetPrimaryRootWindow()->GetChildById(
kShellWindowId_SettingBubbleContainer);
params.bounds = CalculateBubbleBounds();
bubble_widget_->Init(std::move(params));
bubble_view_->set_owned_by_client();
bubble_widget_->SetContentsView(bubble_view_.get());
bubble_widget_->SetVisibilityChangedAnimationsEnabled(true);
aura::Window* native_window = bubble_widget_->GetNativeWindow();
wm::SetWindowVisibilityChangesAnimated(native_window);
wm::SetWindowVisibilityAnimationType(
native_window, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
wm::SetWindowVisibilityAnimationDuration(native_window,
kBubbleAnimationDuration);
}
FullscreenAlertBubble::~FullscreenAlertBubble() = default;
void FullscreenAlertBubble::Show() {
bubble_widget_->Show();
timer_->Start(FROM_HERE, kAlertDuration,
base::BindOnce(&FullscreenAlertBubble::Hide,
weak_ptr_factory_.GetWeakPtr()));
}
void FullscreenAlertBubble::Hide() {
bubble_widget_->Hide();
}
void FullscreenAlertBubble::Dismiss(const ui::Event& event) {
Hide();
}
void FullscreenAlertBubble::ExitFullscreen(const ui::Event& event) {
FullscreenController::MaybeExitFullscreen();
Hide();
}
gfx::Rect FullscreenAlertBubble::CalculateBubbleBounds() {
gfx::Rect work_area = WorkAreaInsets::ForWindow(Shell::GetPrimaryRootWindow())
->user_work_area_bounds();
int x = work_area.x() + (work_area.width() - kAlertBubbleWidthDp) / 2;
int y = work_area.y() + kOffsetFromEdge;
return gfx::Rect(gfx::Point(x, y), bubble_view_->CalculatePreferredSize());
}
} // namespace ash
// Copyright 2018 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.
#ifndef ASH_FULLSCREEN_ALERT_BUBBLE_H_
#define ASH_FULLSCREEN_ALERT_BUBBLE_H_
#include <memory>
#include "ash/ash_export.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/widget/widget.h"
namespace views {
class Button;
class Widget;
} // namespace views
namespace gfx {
class Rect;
}
namespace base {
class OneShotTimer;
}
namespace ash {
class FullscreenAlertBubbleView;
// When the device returns back from sleep or low brightness without a lock
// screen, remind the user to exit fullscreen before entering password.
class ASH_EXPORT FullscreenAlertBubble {
public:
FullscreenAlertBubble();
~FullscreenAlertBubble();
FullscreenAlertBubble(const FullscreenAlertBubble&) = delete;
FullscreenAlertBubble& operator=(const FullscreenAlertBubble&) = delete;
void Show();
void Hide();
void Dismiss(const ui::Event& event);
void ExitFullscreen(const ui::Event& event);
private:
gfx::Rect CalculateBubbleBounds();
std::unique_ptr<FullscreenAlertBubbleView> bubble_view_;
std::unique_ptr<views::Widget> bubble_widget_;
std::unique_ptr<base::OneShotTimer> timer_;
base::WeakPtrFactory<FullscreenAlertBubble> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_FULLSCREEN_ALERT_BUBBLE_H_
......@@ -4,10 +4,15 @@
#include "ash/session/fullscreen_controller.h"
#include <limits>
#include "ash/login/ui/lock_screen.h"
#include "ash/session/fullscreen_alert_bubble.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shelf/shelf.h"
#include "ash/wm/window_state.h"
#include "ash/wm/wm_event.h"
#include "chromeos/dbus/power_manager/backlight.pb.h"
#include "chromeos/dbus/power_manager/idle.pb.h"
namespace ash {
......@@ -50,6 +55,30 @@ void FullscreenController::MaybeExitFullscreen() {
active_window_state->OnWMEvent(&event);
}
void FullscreenController::MaybeShowAlert() {
// 1. Check if there is a lock/login screen showing up.
if (LockScreen::HasInstance())
return;
// 2. Check if the activate window is fullscreen.
WindowState* active_window_state = WindowState::ForActiveWindow();
if (!active_window_state || !active_window_state->IsFullscreen())
return;
// 3. Check if the shelf is visible.
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;
if (!bubble_)
bubble_ = std::make_unique<FullscreenAlertBubble>();
bubble_->Show();
}
void FullscreenController::SuspendImminent(
power_manager::SuspendImminent::Reason reason) {
if (session_controller_->login_status() != LoginStatus::GUEST)
......@@ -67,4 +96,30 @@ void FullscreenController::ScreenIdleStateChanged(
MaybeExitFullscreen();
}
void FullscreenController::ScreenBrightnessChanged(
const power_manager::BacklightBrightnessChange& change) {
// Show alert when the device returns from low (epsilon) brightness which
// covers three cases.
// 1. The device returns from sleep.
// 2. The device lid is opended (with sleep on).
// 3. The device returns from low display brightness.
double epsilon = std::numeric_limits<double>::epsilon();
if (change.percent() <= epsilon) {
device_in_dark_ = true;
} else {
if (device_in_dark_)
MaybeShowAlert();
device_in_dark_ = false;
}
}
void FullscreenController::LidEventReceived(
chromeos::PowerManagerClient::LidState state,
const base::TimeTicks& timestamp) {
// Show alert when the lid is opened. This also covers the case when the user
// turn off "Sleep when cover is closed".
if (state == chromeos::PowerManagerClient::LidState::OPEN)
MaybeShowAlert();
}
} // namespace ash
......@@ -5,11 +5,15 @@
#ifndef ASH_SESSION_FULLSCREEN_CONTROLLER_H_
#define ASH_SESSION_FULLSCREEN_CONTROLLER_H_
#include <memory>
#include "base/time/time.h"
#include "chromeos/dbus/power/power_manager_client.h"
namespace ash {
class SessionControllerImpl;
class FullscreenAlertBubble;
class FullscreenController : public chromeos::PowerManagerClient::Observer {
public:
......@@ -21,13 +25,24 @@ class FullscreenController : public chromeos::PowerManagerClient::Observer {
static void MaybeExitFullscreen();
void MaybeShowAlert();
private:
// chromeos::PowerManagerClient::Observer:
void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
void ScreenIdleStateChanged(
const power_manager::ScreenIdleState& proto) override;
void ScreenBrightnessChanged(
const power_manager::BacklightBrightnessChange& change) override;
void LidEventReceived(chromeos::PowerManagerClient::LidState state,
const base::TimeTicks& timestamp) override;
const SessionControllerImpl* const session_controller_;
std::unique_ptr<FullscreenAlertBubble> bubble_;
// Whether the screen brightness is low enough to make display dark.
bool device_in_dark_ = false;
};
} // namespace ash
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment