Skip to content

Commit

Permalink
ash: Show channel name on login screen
Browse files Browse the repository at this point in the history
Channel indicator shows the full name of the release track when
displayed in the login screen, just the icon afterwards.

Screenshots:

https://screenshot.googleplex.com/3LoPYQ3WVTxoNXw.png
https://screenshot.googleplex.com/5DtRUz6EMDASpk3.png

Bug: 1343938
Change-Id: I961051f1f4d3d48b7b53400af4a2ed9707fe1c3c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3759959
Reviewed-by: Alex Newcomer <newcomer@chromium.org>
Commit-Queue: Roger Tinkoff <rtinkoff@google.com>
Reviewed-by: Ahmed Mehfooz <amehfooz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1030085}
  • Loading branch information
rogertinkoff authored and Chromium LUCI CQ committed Jul 31, 2022
1 parent 509df95 commit 88fa024
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 65 deletions.
161 changes: 114 additions & 47 deletions ash/system/channel_indicator/channel_indicator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,49 @@
#include "ash/system/channel_indicator/channel_indicator.h"

#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/system/channel_indicator/channel_indicator_utils.h"
#include "ash/system/tray/tray_constants.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/strcat.h"
#include "components/session_manager/session_manager_types.h"
#include "components/version_info/channel.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"

namespace ash {

namespace {

// Background rounded rectangle corner radius.
constexpr int kIndicatorBgCornerRadius = 50;

// Size of vertical padding area around the icon or text.
constexpr int kIndicatorVerticalInset = 8;

} // namespace

ChannelIndicatorView::ChannelIndicatorView(Shelf* shelf,
version_info::Channel channel)
: TrayItemView(shelf), channel_(channel) {
: TrayItemView(shelf), channel_(channel), session_observer_(this) {
SetVisible(false);
CreateImageView();
Update(channel_);
SetBorder(
views::CreateEmptyBorder(gfx::Insets::VH(kIndicatorVerticalInset, 0)));
Update();
}

ChannelIndicatorView::~ChannelIndicatorView() = default;

gfx::Size ChannelIndicatorView::CalculatePreferredSize() const {
return gfx::Size(kUnifiedTrayChannelIndicatorDimension,
kUnifiedTrayChannelIndicatorDimension);
}

void ChannelIndicatorView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->SetName(accessible_name_);
}
Expand All @@ -57,63 +67,120 @@ const char* ChannelIndicatorView::GetClassName() const {

void ChannelIndicatorView::OnThemeChanged() {
TrayItemView::OnThemeChanged();
Update(channel_);

if (Shell::Get()->session_controller()->GetSessionState() ==
session_manager::SessionState::ACTIVE) {
// User is logged in, set image view colors.
if (image_view()) {
image_view()->SetBackground(views::CreateRoundedRectBackground(
channel_indicator_utils::GetBgColor(channel_),
kIndicatorBgCornerRadius));
image_view()->SetImage(gfx::CreateVectorIcon(
channel_indicator_utils::GetVectorIcon(channel_),
kUnifiedTrayChannelIndicatorDimension,
channel_indicator_utils::GetFgColor(channel_)));
}
return;
}

// User is not logged in, set label colors.
if (label()) {
label()->SetBackground(views::CreateRoundedRectBackground(
channel_indicator_utils::GetBgColor(channel_),
kIndicatorBgCornerRadius));
label()->SetEnabledColor(channel_indicator_utils::GetFgColor(channel_));
}
}

void ChannelIndicatorView::HandleLocaleChange() {
Update(channel_);
Update();
}

void ChannelIndicatorView::Update(version_info::Channel channel) {
if (!channel_indicator_utils::IsDisplayableChannel(channel))
void ChannelIndicatorView::Update() {
if (!channel_indicator_utils::IsDisplayableChannel(channel_))
return;

SetImageOrText();
SetVisible(true);
SetAccessibleName(channel);
SetTooltip(channel);
SetImage(channel);
SetAccessibleName();
SetTooltip();
}

void ChannelIndicatorView::SetImage(version_info::Channel channel) {
DCHECK(channel_indicator_utils::IsDisplayableChannel(channel));
void ChannelIndicatorView::SetImageOrText() {
DCHECK(channel_indicator_utils::IsDisplayableChannel(channel_));

if (Shell::Get()->session_controller()->GetSessionState() ==
session_manager::SessionState::ACTIVE) {
// User is logged in, show the icon.
if (image_view())
return;

DestroyLabel();
CreateImageView();
image_view()->SetBackground(views::CreateRoundedRectBackground(
channel_indicator_utils::GetBgColor(channel_),
kIndicatorBgCornerRadius));
image_view()->SetImage(
gfx::CreateVectorIcon(channel_indicator_utils::GetVectorIcon(channel_),
kUnifiedTrayChannelIndicatorDimension,
channel_indicator_utils::GetFgColor(channel_)));
PreferredSizeChanged();
return;
}

SetBorder(views::CreateEmptyBorder(
gfx::Insets::VH(kUnifiedTrayChannelIndicatorDimension / 2, 0)));
image_view()->SetBackground(views::CreateRoundedRectBackground(
channel_indicator_utils::GetBgColor(channel), kIndicatorBgCornerRadius));
// User is not logged in, show the channel name.
if (label())
return;

switch (channel) {
case version_info::Channel::BETA:
image_view()->SetImage(gfx::CreateVectorIcon(
kChannelBetaIcon, kUnifiedTrayChannelIndicatorDimension,
channel_indicator_utils::GetFgColor(channel)));
break;
case version_info::Channel::DEV:
image_view()->SetImage(gfx::CreateVectorIcon(
kChannelDevIcon, kUnifiedTrayChannelIndicatorDimension,
channel_indicator_utils::GetFgColor(channel)));
break;
case version_info::Channel::CANARY:
image_view()->SetImage(gfx::CreateVectorIcon(
kChannelCanaryIcon, kUnifiedTrayChannelIndicatorDimension,
channel_indicator_utils::GetFgColor(channel)));
break;
default:
break;
}
DestroyImageView();
CreateLabel();
label()->SetBorder(views::CreateEmptyBorder(gfx::Insets::VH(0, 6)));
label()->SetBackground(views::CreateRoundedRectBackground(
channel_indicator_utils::GetBgColor(channel_), kIndicatorBgCornerRadius));
label()->SetEnabledColor(channel_indicator_utils::GetFgColor(channel_));
label()->SetText(l10n_util::GetStringUTF16(
channel_indicator_utils::GetChannelNameStringResourceID(
channel_,
/*append_channel=*/false)));
PreferredSizeChanged();
}

void ChannelIndicatorView::SetAccessibleName(version_info::Channel channel) {
DCHECK(channel_indicator_utils::IsDisplayableChannel(channel));
void ChannelIndicatorView::SetAccessibleName() {
DCHECK(channel_indicator_utils::IsDisplayableChannel(channel_));
accessible_name_ = l10n_util::GetStringUTF16(
channel_indicator_utils::GetChannelNameStringResourceID(channel, true));
image_view()->SetAccessibleName(accessible_name_);
channel_indicator_utils::GetChannelNameStringResourceID(
channel_, /*append_channel=*/true));

// If icon is showing, set it on the image view.
if (image_view()) {
DCHECK(!label());
image_view()->SetAccessibleName(accessible_name_);
return;
}

// Otherwise set it on the label.
if (label())
label()->SetAccessibleName(accessible_name_);
}

void ChannelIndicatorView::SetTooltip(version_info::Channel channel) {
DCHECK(channel_indicator_utils::IsDisplayableChannel(channel));
void ChannelIndicatorView::SetTooltip() {
DCHECK(channel_indicator_utils::IsDisplayableChannel(channel_));
tooltip_ = l10n_util::GetStringUTF16(
channel_indicator_utils::GetChannelNameStringResourceID(channel, true));
channel_indicator_utils::GetChannelNameStringResourceID(
channel_, /*append_channel=*/true));
}

void ChannelIndicatorView::OnSessionStateChanged(
session_manager::SessionState state) {
Update();
}

bool ChannelIndicatorView::IsLabelVisibleForTesting() {
return label() && label()->GetVisible();
}

bool ChannelIndicatorView::IsImageViewVisibleForTesting() {
return image_view() && image_view()->GetVisible();
}

} // namespace ash
28 changes: 20 additions & 8 deletions ash/system/channel_indicator/channel_indicator.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
#ifndef ASH_SYSTEM_CHANNEL_INDICATOR_CHANNEL_INDICATOR_H_
#define ASH_SYSTEM_CHANNEL_INDICATOR_CHANNEL_INDICATOR_H_

#include "ash/public/cpp/session/session_observer.h"
#include "ash/system/tray/tray_item_view.h"
#include "base/memory/weak_ptr.h"
#include "components/session_manager/session_manager_types.h"
#include "components/version_info/channel.h"

namespace ash {

// A view that resides in the system tray, to make it obvious to the user when a
// device is running on a release track other than "stable."
class ChannelIndicatorView : public TrayItemView {
class ASH_EXPORT ChannelIndicatorView : public TrayItemView,
public SessionObserver {
public:
ChannelIndicatorView(Shelf* shelf, version_info::Channel channel);
ChannelIndicatorView(const ChannelIndicatorView&) = delete;
Expand All @@ -21,7 +25,6 @@ class ChannelIndicatorView : public TrayItemView {
~ChannelIndicatorView() override;

// views::View:
gfx::Size CalculatePreferredSize() const override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override;
std::u16string GetTooltipText(const gfx::Point& p) const override;
Expand All @@ -31,13 +34,18 @@ class ChannelIndicatorView : public TrayItemView {
// TrayItemView:
void HandleLocaleChange() override;

// SessionObserver:
void OnSessionStateChanged(session_manager::SessionState state) override;

// Introspection methods for testing.
bool IsLabelVisibleForTesting();
bool IsImageViewVisibleForTesting();

private:
// Functions called downstream from Update(), that make no assumptions about
// the value of the `channel_` member variable.
void Update(version_info::Channel channel);
void SetImage(version_info::Channel channel);
void SetAccessibleName(version_info::Channel channel);
void SetTooltip(version_info::Channel channel);
void Update();
void SetImageOrText();
void SetAccessibleName();
void SetTooltip();

// The localized string used to announce this view in accessibility mode.
std::u16string accessible_name_;
Expand All @@ -47,6 +55,10 @@ class ChannelIndicatorView : public TrayItemView {

// The release track on which this devices resides.
const version_info::Channel channel_;

ScopedSessionObserver session_observer_;

base::WeakPtrFactory<ChannelIndicatorView> weak_factory_{this};
};

} // namespace ash
Expand Down
45 changes: 35 additions & 10 deletions ash/system/channel_indicator/channel_indicator_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@

#include "ash/constants/ash_features.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/system/channel_indicator/channel_indicator_utils.h"
#include "ash/system/model/system_tray_model.h"
#include "ash/system/status_area_widget_test_helper.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/test/ash_test_base.h"
#include "ash/test_shell_delegate.h"
#include "base/test/scoped_feature_list.h"
#include "components/session_manager/session_manager_types.h"
#include "components/version_info/channel.h"

namespace ash {
Expand All @@ -39,6 +42,12 @@ class ChannelIndicatorViewTest
AshTestBase::SetUp(std::move(shell_delegate));
}

void SetSessionState(session_manager::SessionState state) {
SessionInfo info;
info.state = state;
Shell::Get()->session_controller()->SetSessionInfo(info);
}

private:
base::test::ScopedFeatureList feature_list_;
};
Expand All @@ -65,16 +74,32 @@ TEST_P(ChannelIndicatorViewTest, Visible) {

// The `ChannelIndicatorView` should be visible for BETA, DEV, and CANARY
// channels, not visible otherwise.
switch (shell_delegate->GetChannel()) {
case version_info::Channel::BETA:
case version_info::Channel::DEV:
case version_info::Channel::CANARY:
EXPECT_TRUE(channel_indicator_view->GetVisible());
break;
case version_info::Channel::UNKNOWN:
case version_info::Channel::STABLE:
EXPECT_FALSE(channel_indicator_view->GetVisible());
break;
EXPECT_EQ(channel_indicator_view->GetVisible(),
channel_indicator_utils::IsDisplayableChannel(
shell_delegate->GetChannel()));

// If the view is visible, verify what we display depending on the session
// state.
if (channel_indicator_view->GetVisible()) {
// User is not logged in, view should display text, no image.
SetSessionState(session_manager::SessionState::LOGIN_PRIMARY);
EXPECT_TRUE(channel_indicator_view->IsLabelVisibleForTesting());
EXPECT_FALSE(channel_indicator_view->IsImageViewVisibleForTesting());

// User is logged in, view should display image, no text.
SetSessionState(session_manager::SessionState::ACTIVE);
EXPECT_FALSE(channel_indicator_view->IsLabelVisibleForTesting());
EXPECT_TRUE(channel_indicator_view->IsImageViewVisibleForTesting());

// User locks the session, view should display text, no image.
SetSessionState(session_manager::SessionState::LOCKED);
EXPECT_TRUE(channel_indicator_view->IsLabelVisibleForTesting());
EXPECT_FALSE(channel_indicator_view->IsImageViewVisibleForTesting());

// User is logged in again, view should display image, no text.
SetSessionState(session_manager::SessionState::ACTIVE);
EXPECT_FALSE(channel_indicator_view->IsLabelVisibleForTesting());
EXPECT_TRUE(channel_indicator_view->IsImageViewVisibleForTesting());
}
}

Expand Down
18 changes: 18 additions & 0 deletions ash/system/channel_indicator/channel_indicator_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
#include <string>

#include "ash/public/cpp/style/dark_light_mode_controller.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/notreached.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
Expand Down Expand Up @@ -97,4 +99,20 @@ std::u16string GetFullReleaseTrackString(version_info::Channel channel) {
base::UTF8ToUTF16(Shell::Get()->shell_delegate()->GetVersionString())});
}

const gfx::VectorIcon& GetVectorIcon(version_info::Channel channel) {
DCHECK(IsDisplayableChannel(channel));
switch (channel) {
case version_info::Channel::BETA:
return kChannelBetaIcon;
case version_info::Channel::DEV:
return kChannelDevIcon;
case version_info::Channel::CANARY:
return kChannelCanaryIcon;
case version_info::Channel::UNKNOWN:
case version_info::Channel::STABLE:
NOTREACHED();
return kChannelCanaryIcon;
}
}

} // namespace ash::channel_indicator_utils

0 comments on commit 88fa024

Please sign in to comment.