PrivacyIndicators: Add screen share icon to privacy indicators view
Add a screen share indicator to PrivacyIndicatorsTrayItemView, as well as update it accordingly when screen sharing status changes. We also change ScreenSecurityNotificationController to be ScreenSecurityController since this class now also handles non-notification related logic. Bug: 1357853 Change-Id: Iab7c402a14db68c8d3310c1e2324057c907d2ec2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3933380 Reviewed-by: Alex Newcomer <newcomer@chromium.org> Commit-Queue: Andre Le <leandre@chromium.org> Cr-Commit-Position: refs/heads/main@{#1055885}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
539d25dc3e
commit
619585281e
ash
BUILD.gnash_strings.grd
ash_strings_grd
system
privacy
privacy_indicators_controller.ccprivacy_indicators_controller.hprivacy_indicators_tray_item_view.ccprivacy_indicators_tray_item_view.hprivacy_indicators_tray_item_view_unittest.ccscreen_security_controller.ccscreen_security_controller.hscreen_security_controller_unittest.ccscreen_security_notification_controller_unittest.cc
system_notification_controller.ccsystem_notification_controller.h@ -1618,8 +1618,8 @@ component("ash") {
|
||||
"system/privacy/privacy_indicators_tray_item_view.cc",
|
||||
"system/privacy/privacy_indicators_tray_item_view.h",
|
||||
"system/privacy/screen_capture_observer.h",
|
||||
"system/privacy/screen_security_notification_controller.cc",
|
||||
"system/privacy/screen_security_notification_controller.h",
|
||||
"system/privacy/screen_security_controller.cc",
|
||||
"system/privacy/screen_security_controller.h",
|
||||
"system/privacy/screen_share_observer.h",
|
||||
"system/privacy/screen_switch_check_controller.cc",
|
||||
"system/privacy/screen_switch_check_controller.h",
|
||||
@ -2968,7 +2968,7 @@ test("ash_unittests") {
|
||||
"system/power/video_activity_notifier_unittest.cc",
|
||||
"system/privacy/privacy_indicators_controller_unittest.cc",
|
||||
"system/privacy/privacy_indicators_tray_item_view_unittest.cc",
|
||||
"system/privacy/screen_security_notification_controller_unittest.cc",
|
||||
"system/privacy/screen_security_controller_unittest.cc",
|
||||
"system/privacy_hub/camera_privacy_switch_controller_unittest.cc",
|
||||
"system/privacy_hub/microphone_privacy_switch_controller_unittest.cc",
|
||||
"system/progress_indicator/progress_indicator_animation_registry_unittest.cc",
|
||||
|
@ -3988,6 +3988,10 @@ Here are some things you can try to get started.
|
||||
<message name="IDS_PRIVACY_NOTIFICATION_BUTTON_APP_SETTINGS" desc="Title for the launch app button of the notification shown when an app is using the camera/microphone.">
|
||||
App settings
|
||||
</message>
|
||||
<message name="IDS_PRIVACY_INDICATORS_VIEW_TOOLTIP" desc="Tooltip for the privacy indicators view in the status area.">
|
||||
<ph name="CAMERA_AND_MICROPHONE_ACCESS_STATUS">$1<ex>You're sharing your screen</ex></ph>,
|
||||
<ph name="SCREEN_SHARE_STATUS">$2<ex>Camera in use</ex></ph>
|
||||
</message>
|
||||
|
||||
<!-- Strings for camera privacy hub switch notifications -->
|
||||
<message name="IDS_PRIVACY_HUB_WANT_TO_TURN_OFF_CAMERA_NOTIFICATION_TITLE" desc="Title for a notification shown to the users when they disable camera via the hardware switch.">
|
||||
|
@ -0,0 +1 @@
|
||||
6bd63e24804bc33446d2edcdda57a66c5a89a096
|
@ -7,11 +7,13 @@
|
||||
#include <string>
|
||||
|
||||
#include "ash/constants/ash_constants.h"
|
||||
#include "ash/constants/ash_features.h"
|
||||
#include "ash/public/cpp/notification_utils.h"
|
||||
#include "ash/resources/vector_icons/vector_icons.h"
|
||||
#include "ash/root_window_controller.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/system/privacy/privacy_indicators_tray_item_view.h"
|
||||
#include "ash/system/status_area_widget.h"
|
||||
#include "ash/system/unified/unified_system_tray.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
@ -154,4 +156,21 @@ void UpdatePrivacyIndicatorsView(bool is_camera_used, bool is_microphone_used) {
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePrivacyIndicatorsScreenShareStatus(bool is_screen_sharing) {
|
||||
if (!features::IsPrivacyIndicatorsEnabled())
|
||||
return;
|
||||
|
||||
DCHECK(ash::Shell::HasInstance());
|
||||
for (auto* root_window_controller :
|
||||
ash::Shell::Get()->GetAllRootWindowControllers()) {
|
||||
DCHECK(root_window_controller);
|
||||
DCHECK(root_window_controller->GetStatusAreaWidget());
|
||||
|
||||
root_window_controller->GetStatusAreaWidget()
|
||||
->unified_system_tray()
|
||||
->privacy_indicators_view()
|
||||
->UpdateScreenShareStatus(is_screen_sharing);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -69,6 +69,11 @@ void ASH_EXPORT ModifyPrivacyIndicatorsNotification(
|
||||
void ASH_EXPORT UpdatePrivacyIndicatorsView(bool is_camera_used,
|
||||
bool is_microphone_used);
|
||||
|
||||
// Update `PrivacyIndicatorsTrayItemView` screen share status across all status
|
||||
// area widgets.
|
||||
void ASH_EXPORT
|
||||
UpdatePrivacyIndicatorsScreenShareStatus(bool is_screen_sharing);
|
||||
|
||||
} // namespace ash
|
||||
|
||||
#endif // ASH_SYSTEM_PRIVACY_PRIVACY_INDICATORS_CONTROLLER_H_
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/style/ash_color_provider.h"
|
||||
#include "ash/system/tray/tray_item_view.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/metrics/histogram_functions.h"
|
||||
#include "base/time/time.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
@ -41,6 +40,7 @@ const int kPrivacyIndicatorsViewSpacing = 2;
|
||||
const int kPrivacyIndicatorsIconSize = 16;
|
||||
const int kPrivacyIndicatorsViewExpandedShorterSideSize = 24;
|
||||
const int kPrivacyIndicatorsViewExpandedLongerSideSize = 50;
|
||||
const int kPrivacyIndicatorsViewExpandedWithScreenShareSize = 68;
|
||||
const int kPrivacyIndicatorsViewSize = 8;
|
||||
|
||||
constexpr auto kDwellInExpandDuration = base::Milliseconds(1000);
|
||||
@ -108,19 +108,22 @@ PrivacyIndicatorsTrayItemView::PrivacyIndicatorsTrayItemView(Shelf* shelf)
|
||||
layer()->SetRoundedCornerRadius(
|
||||
gfx::RoundedCornersF{kPrivacyIndicatorsViewExpandedShorterSideSize / 2});
|
||||
|
||||
auto camera_icon = std::make_unique<views::ImageView>();
|
||||
camera_icon->SetPaintToLayer();
|
||||
camera_icon->layer()->SetFillsBoundsOpaquely(false);
|
||||
camera_icon_ = container_view->AddChildView(std::move(camera_icon));
|
||||
auto add_icon_to_container = [&container_view]() {
|
||||
auto icon = std::make_unique<views::ImageView>();
|
||||
icon->SetPaintToLayer();
|
||||
icon->layer()->SetFillsBoundsOpaquely(false);
|
||||
icon->SetVisible(false);
|
||||
return container_view->AddChildView(std::move(icon));
|
||||
};
|
||||
|
||||
auto microphone_icon = std::make_unique<views::ImageView>();
|
||||
microphone_icon->SetPaintToLayer();
|
||||
microphone_icon->layer()->SetFillsBoundsOpaquely(false);
|
||||
microphone_icon_ = container_view->AddChildView(std::move(microphone_icon));
|
||||
camera_icon_ = add_icon_to_container();
|
||||
microphone_icon_ = add_icon_to_container();
|
||||
screen_share_icon_ = add_icon_to_container();
|
||||
|
||||
AddChildView(std::move(container_view));
|
||||
|
||||
UpdateIcons();
|
||||
TooltipTextChanged();
|
||||
}
|
||||
|
||||
PrivacyIndicatorsTrayItemView::~PrivacyIndicatorsTrayItemView() = default;
|
||||
@ -134,13 +137,23 @@ void PrivacyIndicatorsTrayItemView::Update(bool camera_is_used,
|
||||
camera_is_used_ = camera_is_used;
|
||||
microphone_is_used_ = microphone_is_used;
|
||||
|
||||
SetVisible(camera_is_used_ || microphone_is_used_);
|
||||
SetVisible(camera_is_used_ || microphone_is_used_ || is_screen_sharing_);
|
||||
if (!GetVisible())
|
||||
return;
|
||||
|
||||
camera_icon_->SetVisible(camera_is_used);
|
||||
microphone_icon_->SetVisible(microphone_is_used);
|
||||
TooltipTextChanged();
|
||||
}
|
||||
|
||||
void PrivacyIndicatorsTrayItemView::UpdateScreenShareStatus(
|
||||
bool is_screen_sharing) {
|
||||
if (is_screen_sharing_ == is_screen_sharing)
|
||||
return;
|
||||
is_screen_sharing_ = is_screen_sharing;
|
||||
|
||||
SetVisible(camera_is_used_ || microphone_is_used_ || is_screen_sharing_);
|
||||
screen_share_icon_->SetVisible(is_screen_sharing_);
|
||||
TooltipTextChanged();
|
||||
}
|
||||
|
||||
@ -153,18 +166,32 @@ void PrivacyIndicatorsTrayItemView::UpdateAlignmentForShelf(Shelf* shelf) {
|
||||
|
||||
std::u16string PrivacyIndicatorsTrayItemView::GetTooltipText(
|
||||
const gfx::Point& point) const {
|
||||
auto cam_and_mic_status = std::u16string();
|
||||
if (camera_is_used_ && microphone_is_used_) {
|
||||
return l10n_util::GetStringUTF16(
|
||||
cam_and_mic_status = l10n_util::GetStringUTF16(
|
||||
IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA_AND_MIC);
|
||||
} else if (camera_is_used_) {
|
||||
cam_and_mic_status =
|
||||
l10n_util::GetStringUTF16(IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA);
|
||||
} else if (microphone_is_used_) {
|
||||
cam_and_mic_status =
|
||||
l10n_util::GetStringUTF16(IDS_PRIVACY_NOTIFICATION_TITLE_MIC);
|
||||
}
|
||||
|
||||
if (camera_is_used_)
|
||||
return l10n_util::GetStringUTF16(IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA);
|
||||
auto screen_share_status =
|
||||
is_screen_sharing_
|
||||
? l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SCREEN_SHARE_TITLE)
|
||||
: std::u16string();
|
||||
|
||||
if (microphone_is_used_)
|
||||
return l10n_util::GetStringUTF16(IDS_PRIVACY_NOTIFICATION_TITLE_MIC);
|
||||
if (cam_and_mic_status.empty())
|
||||
return screen_share_status;
|
||||
|
||||
return std::u16string();
|
||||
if (screen_share_status.empty())
|
||||
return cam_and_mic_status;
|
||||
|
||||
return l10n_util::GetStringFUTF16(IDS_PRIVACY_INDICATORS_VIEW_TOOLTIP,
|
||||
{cam_and_mic_status, screen_share_status},
|
||||
/*offsets=*/nullptr);
|
||||
}
|
||||
|
||||
void PrivacyIndicatorsTrayItemView::PerformVisibilityAnimation(bool visible) {
|
||||
@ -197,13 +224,13 @@ gfx::Size PrivacyIndicatorsTrayItemView::CalculatePreferredSize() const {
|
||||
case AnimationState::kExpand:
|
||||
shorter_side = kPrivacyIndicatorsViewExpandedShorterSideSize;
|
||||
longer_side =
|
||||
kPrivacyIndicatorsViewExpandedLongerSideSize *
|
||||
GetLongerSideLengthInExpandedMode() *
|
||||
gfx::Tween::CalculateValue(gfx::Tween::ACCEL_20_DECEL_100,
|
||||
expand_animation_->GetCurrentValue());
|
||||
break;
|
||||
case AnimationState::kDwellInExpand:
|
||||
shorter_side = kPrivacyIndicatorsViewExpandedShorterSideSize;
|
||||
longer_side = kPrivacyIndicatorsViewExpandedLongerSideSize;
|
||||
longer_side = GetLongerSideLengthInExpandedMode();
|
||||
break;
|
||||
case AnimationState::kOnlyLongerSideShrink:
|
||||
shorter_side = kPrivacyIndicatorsViewExpandedShorterSideSize;
|
||||
@ -309,6 +336,9 @@ void PrivacyIndicatorsTrayItemView::UpdateIcons() {
|
||||
microphone_icon_->SetImage(
|
||||
gfx::CreateVectorIcon(kPrivacyIndicatorsMicrophoneIcon,
|
||||
kPrivacyIndicatorsIconSize, icon_color));
|
||||
screen_share_icon_->SetImage(
|
||||
gfx::CreateVectorIcon(kPrivacyIndicatorsScreenShareIcon,
|
||||
kPrivacyIndicatorsIconSize, icon_color));
|
||||
}
|
||||
|
||||
void PrivacyIndicatorsTrayItemView::UpdateBoundsInset() {
|
||||
@ -337,7 +367,7 @@ int PrivacyIndicatorsTrayItemView::CalculateSizeDuringShrinkAnimation(
|
||||
double animation_value = gfx::Tween::CalculateValue(
|
||||
gfx::Tween::ACCEL_20_DECEL_100, animation->GetCurrentValue());
|
||||
int begin_size = for_longer_side
|
||||
? kPrivacyIndicatorsViewExpandedLongerSideSize
|
||||
? GetLongerSideLengthInExpandedMode()
|
||||
: kPrivacyIndicatorsViewExpandedShorterSideSize;
|
||||
|
||||
// The size shrink from `begin_size` to kPrivacyIndicatorsViewSize when
|
||||
@ -346,6 +376,13 @@ int PrivacyIndicatorsTrayItemView::CalculateSizeDuringShrinkAnimation(
|
||||
(begin_size - kPrivacyIndicatorsViewSize) * animation_value;
|
||||
}
|
||||
|
||||
int PrivacyIndicatorsTrayItemView::GetLongerSideLengthInExpandedMode() const {
|
||||
// If all three icons are visible, the view should be longer.
|
||||
return camera_is_used_ && microphone_is_used_ && is_screen_sharing_
|
||||
? kPrivacyIndicatorsViewExpandedWithScreenShareSize
|
||||
: kPrivacyIndicatorsViewExpandedLongerSideSize;
|
||||
}
|
||||
|
||||
void PrivacyIndicatorsTrayItemView::EndAllAnimations() {
|
||||
shorter_side_shrink_animation_->End();
|
||||
longer_side_shrink_animation_->End();
|
||||
|
@ -58,6 +58,9 @@ class ASH_EXPORT PrivacyIndicatorsTrayItemView : public TrayItemView {
|
||||
// Update the view according to the state of camara/microphone access.
|
||||
void Update(bool camera_is_used, bool microphone_is_used);
|
||||
|
||||
// Update the view according to the state of screen sharing.
|
||||
void UpdateScreenShareStatus(bool is_screen_sharing);
|
||||
|
||||
// Update the view according to the shelf alignment.
|
||||
void UpdateAlignmentForShelf(Shelf* shelf);
|
||||
|
||||
@ -90,6 +93,9 @@ class ASH_EXPORT PrivacyIndicatorsTrayItemView : public TrayItemView {
|
||||
// shorter side.
|
||||
int CalculateSizeDuringShrinkAnimation(bool for_longer_side) const;
|
||||
|
||||
// Calculate the length of the longer size, based on `is_screen_sharing_`.
|
||||
int GetLongerSideLengthInExpandedMode() const;
|
||||
|
||||
// End all 3 animations contained in this class.
|
||||
void EndAllAnimations();
|
||||
|
||||
@ -98,9 +104,11 @@ class ASH_EXPORT PrivacyIndicatorsTrayItemView : public TrayItemView {
|
||||
// Owned by the views hierarchy.
|
||||
views::ImageView* camera_icon_ = nullptr;
|
||||
views::ImageView* microphone_icon_ = nullptr;
|
||||
views::ImageView* screen_share_icon_ = nullptr;
|
||||
|
||||
bool camera_is_used_ = false;
|
||||
bool microphone_is_used_ = false;
|
||||
bool is_screen_sharing_ = false;
|
||||
|
||||
// Keep track the current animation state during the multi-part animation.
|
||||
AnimationState animation_state_ = kIdle;
|
||||
|
@ -40,6 +40,21 @@ int GetExpectedSizeInShrinkAnimation(bool for_longer_side, double progress) {
|
||||
(begin_size - kPrivacyIndicatorsViewSize) * animation_value;
|
||||
}
|
||||
|
||||
// Get the expected tooltip text, given the string for camera/mic access and
|
||||
// screen share.
|
||||
std::u16string GetExpectedTooltipText(std::u16string cam_mic_status,
|
||||
std::u16string screen_share_status) {
|
||||
if (cam_mic_status.empty())
|
||||
return screen_share_status;
|
||||
|
||||
if (screen_share_status.empty())
|
||||
return cam_mic_status;
|
||||
|
||||
return l10n_util::GetStringFUTF16(IDS_PRIVACY_INDICATORS_VIEW_TOOLTIP,
|
||||
{cam_mic_status, screen_share_status},
|
||||
/*offsets=*/nullptr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace ash {
|
||||
@ -94,6 +109,9 @@ class PrivacyIndicatorsTrayItemViewTest : public AshTestBase {
|
||||
views::ImageView* microphone_icon() {
|
||||
return privacy_indicators_view_->microphone_icon_;
|
||||
}
|
||||
views::ImageView* screen_share_icon() {
|
||||
return privacy_indicators_view_->screen_share_icon_;
|
||||
}
|
||||
|
||||
gfx::LinearAnimation* expand_animation() {
|
||||
return privacy_indicators_view_->expand_animation_.get();
|
||||
@ -143,28 +161,78 @@ TEST_F(PrivacyIndicatorsTrayItemViewTest, IconsVisibility) {
|
||||
EXPECT_FALSE(privacy_indicators_view()->GetVisible());
|
||||
}
|
||||
|
||||
TEST_F(PrivacyIndicatorsTrayItemViewTest, ScreenShareIconsVisibility) {
|
||||
EXPECT_FALSE(privacy_indicators_view()->GetVisible());
|
||||
|
||||
privacy_indicators_view()->UpdateScreenShareStatus(
|
||||
/*is_screen_sharing=*/true);
|
||||
EXPECT_TRUE(privacy_indicators_view()->GetVisible());
|
||||
EXPECT_TRUE(screen_share_icon()->GetVisible());
|
||||
EXPECT_FALSE(camera_icon()->GetVisible());
|
||||
EXPECT_FALSE(microphone_icon()->GetVisible());
|
||||
|
||||
privacy_indicators_view()->UpdateScreenShareStatus(
|
||||
/*is_screen_sharing=*/false);
|
||||
EXPECT_FALSE(privacy_indicators_view()->GetVisible());
|
||||
|
||||
// Test screen share showing up with other icons.
|
||||
privacy_indicators_view()->Update(/*camera_is_used=*/false,
|
||||
/*microphone_is_used=*/true);
|
||||
privacy_indicators_view()->UpdateScreenShareStatus(
|
||||
/*is_screen_sharing=*/true);
|
||||
EXPECT_TRUE(privacy_indicators_view()->GetVisible());
|
||||
EXPECT_FALSE(camera_icon()->GetVisible());
|
||||
EXPECT_TRUE(microphone_icon()->GetVisible());
|
||||
EXPECT_TRUE(screen_share_icon()->GetVisible());
|
||||
|
||||
privacy_indicators_view()->UpdateScreenShareStatus(
|
||||
/*is_screen_sharing=*/false);
|
||||
EXPECT_TRUE(privacy_indicators_view()->GetVisible());
|
||||
EXPECT_FALSE(camera_icon()->GetVisible());
|
||||
EXPECT_TRUE(microphone_icon()->GetVisible());
|
||||
EXPECT_FALSE(screen_share_icon()->GetVisible());
|
||||
}
|
||||
|
||||
TEST_F(PrivacyIndicatorsTrayItemViewTest, TooltipText) {
|
||||
EXPECT_EQ(std::u16string(), GetTooltipText());
|
||||
EXPECT_EQ(GetExpectedTooltipText(/*cam_mic_status=*/std::u16string(),
|
||||
/*screen_share_status=*/std::u16string()),
|
||||
GetTooltipText());
|
||||
|
||||
privacy_indicators_view()->Update(/*camera_is_used=*/true,
|
||||
/*microphone_is_used=*/false);
|
||||
EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA),
|
||||
EXPECT_EQ(GetExpectedTooltipText(/*cam_mic_status=*/l10n_util::GetStringUTF16(
|
||||
IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA),
|
||||
/*screen_share_status=*/std::u16string()),
|
||||
GetTooltipText());
|
||||
|
||||
privacy_indicators_view()->Update(/*camera_is_used=*/false,
|
||||
/*microphone_is_used=*/true);
|
||||
EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PRIVACY_NOTIFICATION_TITLE_MIC),
|
||||
EXPECT_EQ(GetExpectedTooltipText(/*cam_mic_status=*/l10n_util::GetStringUTF16(
|
||||
IDS_PRIVACY_NOTIFICATION_TITLE_MIC),
|
||||
/*screen_share_status=*/std::u16string()),
|
||||
GetTooltipText());
|
||||
|
||||
privacy_indicators_view()->Update(/*camera_is_used=*/true,
|
||||
/*microphone_is_used=*/true);
|
||||
EXPECT_EQ(
|
||||
l10n_util::GetStringUTF16(IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA_AND_MIC),
|
||||
GetExpectedTooltipText(/*cam_mic_status=*/l10n_util::GetStringUTF16(
|
||||
IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA_AND_MIC),
|
||||
/*screen_share_status=*/std::u16string()),
|
||||
GetTooltipText());
|
||||
|
||||
privacy_indicators_view()->Update(/*camera_is_used=*/false,
|
||||
/*microphone_is_used=*/false);
|
||||
EXPECT_EQ(std::u16string(), GetTooltipText());
|
||||
EXPECT_EQ(GetExpectedTooltipText(/*cam_mic_status=*/std::u16string(),
|
||||
/*screen_share_status=*/std::u16string()),
|
||||
GetTooltipText());
|
||||
|
||||
privacy_indicators_view()->UpdateScreenShareStatus(
|
||||
/*is_screen_sharing=*/true);
|
||||
EXPECT_EQ(GetExpectedTooltipText(
|
||||
/*cam_mic_status=*/std::u16string(),
|
||||
/*screen_share_status=*/l10n_util::GetStringUTF16(
|
||||
IDS_ASH_STATUS_TRAY_SCREEN_SHARE_TITLE)),
|
||||
GetTooltipText());
|
||||
}
|
||||
|
||||
TEST_F(PrivacyIndicatorsTrayItemViewTest, ShelfAlignmentChanged) {
|
||||
@ -322,4 +390,36 @@ TEST_F(PrivacyIndicatorsTrayItemViewTest, SideShelfVisibilityAnimation) {
|
||||
privacy_indicators_view()->GetPreferredSize().height());
|
||||
}
|
||||
|
||||
TEST_F(PrivacyIndicatorsTrayItemViewTest, StateChangeDuringAnimation) {
|
||||
SetViewVisibleWithAnimation();
|
||||
double progress = 0.5;
|
||||
|
||||
// Firstly, expand animation will be performed.
|
||||
AnimateToValue(expand_animation(), progress);
|
||||
|
||||
// Update state in mid animation, shouldn't crash anything.
|
||||
privacy_indicators_view()->Update(/*camera_is_used=*/true,
|
||||
/*microphone_is_used=*/false);
|
||||
|
||||
expand_animation()->End();
|
||||
|
||||
// After that shrink animations will be started.
|
||||
longer_side_shrink_animation()->Start();
|
||||
AnimateToValue(longer_side_shrink_animation(), progress);
|
||||
|
||||
// Update the state again, no crash expected.
|
||||
privacy_indicators_view()->UpdateScreenShareStatus(
|
||||
/*is_screen_sharing=*/true);
|
||||
|
||||
shorter_side_shrink_animation()->Start();
|
||||
AnimateToValue(shorter_side_shrink_animation(), progress);
|
||||
|
||||
// The view should become invisible immediately after setting these states.
|
||||
privacy_indicators_view()->Update(/*camera_is_used=*/false,
|
||||
/*microphone_is_used=*/false);
|
||||
privacy_indicators_view()->UpdateScreenShareStatus(
|
||||
/*is_screen_sharing=*/false);
|
||||
EXPECT_FALSE(privacy_indicators_view()->GetVisible());
|
||||
}
|
||||
|
||||
} // namespace ash
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/privacy/screen_security_notification_controller.h"
|
||||
#include "ash/system/privacy/screen_security_controller.h"
|
||||
|
||||
#include "ash/constants/ash_constants.h"
|
||||
#include "ash/constants/ash_features.h"
|
||||
@ -11,6 +11,7 @@
|
||||
#include "ash/resources/vector_icons/vector_icons.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/system/privacy/privacy_indicators_controller.h"
|
||||
#include "ash/system/tray/system_tray_notifier.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/metrics/user_metrics.h"
|
||||
@ -32,21 +33,20 @@ const char kScreenShareNotificationId[] = "chrome://screen/share";
|
||||
const char kNotifierScreenCapture[] = "ash.screen-capture";
|
||||
const char kNotifierScreenShare[] = "ash.screen-share";
|
||||
|
||||
ScreenSecurityNotificationController::ScreenSecurityNotificationController() {
|
||||
ScreenSecurityController::ScreenSecurityController() {
|
||||
Shell::Get()->AddShellObserver(this);
|
||||
Shell::Get()->system_tray_notifier()->AddScreenCaptureObserver(this);
|
||||
Shell::Get()->system_tray_notifier()->AddScreenShareObserver(this);
|
||||
}
|
||||
|
||||
ScreenSecurityNotificationController::~ScreenSecurityNotificationController() {
|
||||
ScreenSecurityController::~ScreenSecurityController() {
|
||||
Shell::Get()->system_tray_notifier()->RemoveScreenShareObserver(this);
|
||||
Shell::Get()->system_tray_notifier()->RemoveScreenCaptureObserver(this);
|
||||
Shell::Get()->RemoveShellObserver(this);
|
||||
}
|
||||
|
||||
void ScreenSecurityNotificationController::CreateNotification(
|
||||
const std::u16string& message,
|
||||
bool is_capture) {
|
||||
void ScreenSecurityController::CreateNotification(const std::u16string& message,
|
||||
bool is_capture) {
|
||||
message_center::RichNotificationData data;
|
||||
data.buttons.push_back(message_center::ButtonInfo(l10n_util::GetStringUTF16(
|
||||
is_capture ? IDS_ASH_STATUS_TRAY_SCREEN_CAPTURE_STOP
|
||||
@ -62,7 +62,7 @@ void ScreenSecurityNotificationController::CreateNotification(
|
||||
auto delegate =
|
||||
base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
|
||||
base::BindRepeating(
|
||||
[](base::WeakPtr<ScreenSecurityNotificationController> controller,
|
||||
[](base::WeakPtr<ScreenSecurityController> controller,
|
||||
bool is_capture, absl::optional<int> button_index) {
|
||||
if (!button_index)
|
||||
return;
|
||||
@ -125,7 +125,7 @@ void ScreenSecurityNotificationController::CreateNotification(
|
||||
std::move(notification));
|
||||
}
|
||||
|
||||
void ScreenSecurityNotificationController::StopAllSessions(bool is_capture) {
|
||||
void ScreenSecurityController::StopAllSessions(bool is_capture) {
|
||||
message_center::MessageCenter::Get()->RemoveNotification(
|
||||
is_capture ? kScreenCaptureNotificationId : kScreenShareNotificationId,
|
||||
false /* by_user */);
|
||||
@ -141,12 +141,12 @@ void ScreenSecurityNotificationController::StopAllSessions(bool is_capture) {
|
||||
change_source_callback_.Reset();
|
||||
}
|
||||
|
||||
void ScreenSecurityNotificationController::ChangeSource() {
|
||||
void ScreenSecurityController::ChangeSource() {
|
||||
if (change_source_callback_ && capture_stop_callbacks_.size() == 1)
|
||||
change_source_callback_.Run();
|
||||
}
|
||||
|
||||
void ScreenSecurityNotificationController::OnScreenCaptureStart(
|
||||
void ScreenSecurityController::OnScreenCaptureStart(
|
||||
const base::RepeatingClosure& stop_callback,
|
||||
const base::RepeatingClosure& source_callback,
|
||||
const std::u16string& screen_capture_status) {
|
||||
@ -166,11 +166,11 @@ void ScreenSecurityNotificationController::OnScreenCaptureStart(
|
||||
CreateNotification(screen_capture_status, true /* is_capture */);
|
||||
}
|
||||
|
||||
void ScreenSecurityNotificationController::OnScreenCaptureStop() {
|
||||
void ScreenSecurityController::OnScreenCaptureStop() {
|
||||
StopAllSessions(true /* is_capture */);
|
||||
}
|
||||
|
||||
void ScreenSecurityNotificationController::OnScreenShareStart(
|
||||
void ScreenSecurityController::OnScreenShareStart(
|
||||
const base::RepeatingClosure& stop_callback,
|
||||
const std::u16string& helper_name) {
|
||||
share_stop_callbacks_.emplace_back(std::move(stop_callback));
|
||||
@ -185,14 +185,19 @@ void ScreenSecurityNotificationController::OnScreenShareStart(
|
||||
}
|
||||
|
||||
CreateNotification(help_label_text, false /* is_capture */);
|
||||
|
||||
if (features::IsPrivacyIndicatorsEnabled())
|
||||
UpdatePrivacyIndicatorsScreenShareStatus(/*is_screen_sharing=*/true);
|
||||
}
|
||||
|
||||
void ScreenSecurityNotificationController::OnScreenShareStop() {
|
||||
void ScreenSecurityController::OnScreenShareStop() {
|
||||
StopAllSessions(false /* is_capture */);
|
||||
|
||||
if (features::IsPrivacyIndicatorsEnabled())
|
||||
UpdatePrivacyIndicatorsScreenShareStatus(/*is_screen_sharing=*/false);
|
||||
}
|
||||
|
||||
void ScreenSecurityNotificationController::OnCastingSessionStartedOrStopped(
|
||||
bool started) {
|
||||
void ScreenSecurityController::OnCastingSessionStartedOrStopped(bool started) {
|
||||
is_casting_ = started;
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ASH_SYSTEM_PRIVACY_SCREEN_SECURITY_NOTIFICATION_CONTROLLER_H_
|
||||
#define ASH_SYSTEM_PRIVACY_SCREEN_SECURITY_NOTIFICATION_CONTROLLER_H_
|
||||
#ifndef ASH_SYSTEM_PRIVACY_SCREEN_SECURITY_CONTROLLER_H_
|
||||
#define ASH_SYSTEM_PRIVACY_SCREEN_SECURITY_CONTROLLER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -21,19 +21,16 @@ extern ASH_EXPORT const char kNotifierScreenCapture[];
|
||||
extern ASH_EXPORT const char kNotifierScreenShare[];
|
||||
|
||||
// Controller class to manage screen security notifications.
|
||||
class ASH_EXPORT ScreenSecurityNotificationController
|
||||
: public ScreenCaptureObserver,
|
||||
public ScreenShareObserver,
|
||||
public ShellObserver {
|
||||
class ASH_EXPORT ScreenSecurityController : public ScreenCaptureObserver,
|
||||
public ScreenShareObserver,
|
||||
public ShellObserver {
|
||||
public:
|
||||
ScreenSecurityNotificationController();
|
||||
ScreenSecurityController();
|
||||
|
||||
ScreenSecurityNotificationController(
|
||||
const ScreenSecurityNotificationController&) = delete;
|
||||
ScreenSecurityNotificationController& operator=(
|
||||
const ScreenSecurityNotificationController&) = delete;
|
||||
ScreenSecurityController(const ScreenSecurityController&) = delete;
|
||||
ScreenSecurityController& operator=(const ScreenSecurityController&) = delete;
|
||||
|
||||
~ScreenSecurityNotificationController() override;
|
||||
~ScreenSecurityController() override;
|
||||
|
||||
private:
|
||||
void CreateNotification(const std::u16string& message, bool is_capture);
|
||||
@ -69,10 +66,9 @@ class ASH_EXPORT ScreenSecurityNotificationController
|
||||
std::vector<base::OnceClosure> share_stop_callbacks_;
|
||||
base::RepeatingClosure change_source_callback_;
|
||||
|
||||
base::WeakPtrFactory<ScreenSecurityNotificationController> weak_ptr_factory_{
|
||||
this};
|
||||
base::WeakPtrFactory<ScreenSecurityController> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
||||
#endif // ASH_SYSTEM_PRIVACY_SCREEN_SECURITY_NOTIFICATION_CONTROLLER_H_
|
||||
#endif // ASH_SYSTEM_PRIVACY_SCREEN_SECURITY_CONTROLLER_H_
|
150
ash/system/privacy/screen_security_controller_unittest.cc
Normal file
150
ash/system/privacy/screen_security_controller_unittest.cc
Normal file
@ -0,0 +1,150 @@
|
||||
// Copyright 2018 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/system/privacy/screen_security_controller.h"
|
||||
|
||||
#include "ash/constants/ash_constants.h"
|
||||
#include "ash/constants/ash_features.h"
|
||||
#include "ash/root_window_controller.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/system/privacy/privacy_indicators_tray_item_view.h"
|
||||
#include "ash/system/status_area_widget.h"
|
||||
#include "ash/system/tray/system_tray_notifier.h"
|
||||
#include "ash/system/unified/unified_system_tray.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/callback_helpers.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "ui/color/color_id.h"
|
||||
#include "ui/message_center/message_center.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
namespace {
|
||||
|
||||
message_center::Notification* FindNotification(const std::string& id) {
|
||||
return message_center::MessageCenter::Get()->FindVisibleNotificationById(id);
|
||||
}
|
||||
|
||||
// Check the visibility of privacy indicators in all displays.
|
||||
void ExpectPrivacyIndicatorsVisible(bool visible) {
|
||||
for (ash::RootWindowController* root_window_controller :
|
||||
ash::Shell::Get()->GetAllRootWindowControllers()) {
|
||||
EXPECT_EQ(root_window_controller->GetStatusAreaWidget()
|
||||
->unified_system_tray()
|
||||
->privacy_indicators_view()
|
||||
->GetVisible(),
|
||||
visible);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class ScreenSecurityControllerTest : public AshTestBase,
|
||||
public testing::WithParamInterface<bool> {
|
||||
public:
|
||||
ScreenSecurityControllerTest() = default;
|
||||
ScreenSecurityControllerTest(const ScreenSecurityControllerTest&) = delete;
|
||||
ScreenSecurityControllerTest& operator=(const ScreenSecurityControllerTest&) =
|
||||
delete;
|
||||
~ScreenSecurityControllerTest() override = default;
|
||||
|
||||
// AppAccessNotifierBaseTest:
|
||||
void SetUp() override {
|
||||
scoped_feature_list_.InitWithFeatureState(
|
||||
features::kPrivacyIndicators, IsPrivacyIndicatorsFeatureEnabled());
|
||||
AshTestBase::SetUp();
|
||||
}
|
||||
|
||||
bool IsPrivacyIndicatorsFeatureEnabled() const { return GetParam(); }
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
All,
|
||||
ScreenSecurityControllerTest,
|
||||
/*IsPrivacyIndicatorsFeatureEnabled()=*/::testing::Bool());
|
||||
|
||||
TEST_P(ScreenSecurityControllerTest, ShowScreenCaptureNotification) {
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
|
||||
base::DoNothing(), base::RepeatingClosure(), std::u16string());
|
||||
EXPECT_TRUE(FindNotification(kScreenCaptureNotificationId));
|
||||
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
|
||||
EXPECT_FALSE(FindNotification(kScreenCaptureNotificationId));
|
||||
}
|
||||
|
||||
TEST_P(ScreenSecurityControllerTest, ShowScreenShareNotification) {
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenShareStart(
|
||||
base::DoNothing(), std::u16string());
|
||||
EXPECT_TRUE(FindNotification(kScreenShareNotificationId));
|
||||
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenShareStop();
|
||||
EXPECT_FALSE(FindNotification(kScreenShareNotificationId));
|
||||
}
|
||||
|
||||
TEST_P(ScreenSecurityControllerTest,
|
||||
DoNotShowScreenCaptureNotificationWhenCasting) {
|
||||
Shell::Get()->OnCastingSessionStartedOrStopped(true /* started */);
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
|
||||
base::DoNothing(), base::RepeatingClosure(), std::u16string());
|
||||
EXPECT_FALSE(FindNotification(kScreenCaptureNotificationId));
|
||||
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
|
||||
Shell::Get()->OnCastingSessionStartedOrStopped(false /* started */);
|
||||
EXPECT_FALSE(FindNotification(kScreenCaptureNotificationId));
|
||||
}
|
||||
|
||||
class PrivacyIndicatorsScreenSecurityTest : public AshTestBase {
|
||||
public:
|
||||
PrivacyIndicatorsScreenSecurityTest() = default;
|
||||
PrivacyIndicatorsScreenSecurityTest(
|
||||
const PrivacyIndicatorsScreenSecurityTest&) = delete;
|
||||
PrivacyIndicatorsScreenSecurityTest& operator=(
|
||||
const PrivacyIndicatorsScreenSecurityTest&) = delete;
|
||||
~PrivacyIndicatorsScreenSecurityTest() override = default;
|
||||
|
||||
// AshTestBase:
|
||||
void SetUp() override {
|
||||
scoped_feature_list_.InitAndEnableFeature(features::kPrivacyIndicators);
|
||||
|
||||
AshTestBase::SetUp();
|
||||
}
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
};
|
||||
|
||||
TEST_F(PrivacyIndicatorsScreenSecurityTest, ScreenShareNotification) {
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenShareStart(
|
||||
base::DoNothing(), std::u16string());
|
||||
|
||||
auto* notification = FindNotification(kScreenShareNotificationId);
|
||||
EXPECT_TRUE(notification);
|
||||
|
||||
// Notification should have the correct notifier id so that it will be grouped
|
||||
// with other privacy indicators notification.
|
||||
EXPECT_EQ(kPrivacyIndicatorsNotifierId, notification->notifier_id().id);
|
||||
|
||||
EXPECT_EQ(ui::kColorAshPrivacyIndicatorsBackground,
|
||||
notification->accent_color_id());
|
||||
}
|
||||
|
||||
TEST_F(PrivacyIndicatorsScreenSecurityTest, TrayItemIndicator) {
|
||||
// Make sure the indicator shows up on multiple displays.
|
||||
UpdateDisplay("400x300,400x300,400x300,400x300");
|
||||
|
||||
ExpectPrivacyIndicatorsVisible(/*visible=*/false);
|
||||
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenShareStart(
|
||||
base::DoNothing(), std::u16string());
|
||||
ExpectPrivacyIndicatorsVisible(/*visible=*/true);
|
||||
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenShareStop();
|
||||
ExpectPrivacyIndicatorsVisible(/*visible=*/false);
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -1,54 +0,0 @@
|
||||
// Copyright 2018 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/system/privacy/screen_security_notification_controller.h"
|
||||
|
||||
#include "ash/shell.h"
|
||||
#include "ash/system/tray/system_tray_notifier.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/callback_helpers.h"
|
||||
#include "ui/message_center/message_center.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
using ScreenSecurityNotificationControllerTest = AshTestBase;
|
||||
|
||||
namespace {
|
||||
|
||||
message_center::Notification* FindNotification(const std::string& id) {
|
||||
return message_center::MessageCenter::Get()->FindVisibleNotificationById(id);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_F(ScreenSecurityNotificationControllerTest,
|
||||
ShowScreenCaptureNotification) {
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
|
||||
base::DoNothing(), base::RepeatingClosure(), std::u16string());
|
||||
EXPECT_TRUE(FindNotification(kScreenCaptureNotificationId));
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
|
||||
EXPECT_FALSE(FindNotification(kScreenCaptureNotificationId));
|
||||
}
|
||||
|
||||
TEST_F(ScreenSecurityNotificationControllerTest, ShowScreenShareNotification) {
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenShareStart(
|
||||
base::DoNothing(), std::u16string());
|
||||
EXPECT_TRUE(FindNotification(kScreenShareNotificationId));
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenShareStop();
|
||||
EXPECT_FALSE(FindNotification(kScreenShareNotificationId));
|
||||
}
|
||||
|
||||
TEST_F(ScreenSecurityNotificationControllerTest,
|
||||
DoNotShowScreenCaptureNotificationWhenCasting) {
|
||||
Shell::Get()->OnCastingSessionStartedOrStopped(true /* started */);
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
|
||||
base::DoNothing(), base::RepeatingClosure(), std::u16string());
|
||||
EXPECT_FALSE(FindNotification(kScreenCaptureNotificationId));
|
||||
Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
|
||||
Shell::Get()->OnCastingSessionStartedOrStopped(false /* started */);
|
||||
EXPECT_FALSE(FindNotification(kScreenCaptureNotificationId));
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -14,7 +14,7 @@
|
||||
#include "ash/system/network/managed_sim_lock_notifier.h"
|
||||
#include "ash/system/network/wifi_toggle_notification_controller.h"
|
||||
#include "ash/system/power/power_notification_controller.h"
|
||||
#include "ash/system/privacy/screen_security_notification_controller.h"
|
||||
#include "ash/system/privacy/screen_security_controller.h"
|
||||
#include "ash/system/session/session_limit_notification_controller.h"
|
||||
#include "ash/system/tracing_notification_controller.h"
|
||||
#include "ash/system/update/update_notification_controller.h"
|
||||
@ -31,8 +31,7 @@ SystemNotificationController::SystemNotificationController()
|
||||
std::make_unique<GestureEducationNotificationController>()),
|
||||
power_(std::make_unique<PowerNotificationController>(
|
||||
message_center::MessageCenter::Get())),
|
||||
screen_security_(
|
||||
std::make_unique<ScreenSecurityNotificationController>()),
|
||||
screen_security_(std::make_unique<ScreenSecurityController>()),
|
||||
session_limit_(std::make_unique<SessionLimitNotificationController>()),
|
||||
tracing_(std::make_unique<TracingNotificationController>()),
|
||||
update_(std::make_unique<UpdateNotificationController>()),
|
||||
|
@ -18,7 +18,7 @@ class CellularSetupNotifier;
|
||||
class ManagedSimLockNotifier;
|
||||
class MicrophoneMuteNotificationController;
|
||||
class PowerNotificationController;
|
||||
class ScreenSecurityNotificationController;
|
||||
class ScreenSecurityController;
|
||||
class SessionLimitNotificationController;
|
||||
class TracingNotificationController;
|
||||
class UpdateNotificationController;
|
||||
@ -50,7 +50,7 @@ class SystemNotificationController {
|
||||
std::unique_ptr<ManagedSimLockNotifier> managed_sim_lock_notifier_;
|
||||
std::unique_ptr<MicrophoneMuteNotificationController> microphone_mute_;
|
||||
const std::unique_ptr<PowerNotificationController> power_;
|
||||
const std::unique_ptr<ScreenSecurityNotificationController> screen_security_;
|
||||
const std::unique_ptr<ScreenSecurityController> screen_security_;
|
||||
const std::unique_ptr<SessionLimitNotificationController> session_limit_;
|
||||
const std::unique_ptr<TracingNotificationController> tracing_;
|
||||
const std::unique_ptr<UpdateNotificationController> update_;
|
||||
|
Reference in New Issue
Block a user