blob: cc4e7711eb97548e5954a55c31aac757ce3b7143 [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/system/unified/quick_settings_header.h"
#include <memory>
#include "ash/login/ui/fake_login_detachable_base_model.h"
#include "ash/login/ui/lock_contents_view_test_api.h"
#include "ash/login/ui/lock_screen.h"
#include "ash/login/ui/login_test_base.h"
#include "ash/public/cpp/ash_view_ids.h"
#include "ash/public/cpp/test/test_system_tray_client.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/system/extended_updates/extended_updates_metrics.h"
#include "ash/system/model/enterprise_domain_model.h"
#include "ash/system/model/system_tray_model.h"
#include "ash/system/unified/unified_system_tray_controller.h"
#include "ash/system/unified/unified_system_tray_model.h"
#include "ash/system/update/eol_notice_quick_settings_view.h"
#include "ash/test/ash_test_base.h"
#include "ash/test_shell_delegate.h"
#include "base/check.h"
#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "chromeos/ash/components/login/auth/auth_events_recorder.h"
#include "components/user_manager/user_type.h"
#include "components/version_info/channel.h"
#include "ui/events/test/event_generator.h"
#include "ui/views/controls/label.h"
#include "ui/views/view_utils.h"
namespace ash {
namespace {
EnterpriseDomainModel* GetEnterpriseDomainModel() {
return Shell::Get()->system_tray_model()->enterprise_domain();
}
} // namespace
class QuickSettingsHeaderTest : public NoSessionAshTestBase {
public:
QuickSettingsHeaderTest() = default;
// AshTestBase:
void SetUp() override {
// Install a test delegate to allow overriding channel version.
auto delegate = std::make_unique<TestShellDelegate>();
test_shell_delegate_ = delegate.get();
NoSessionAshTestBase::SetUp(std::move(delegate));
model_ = base::MakeRefCounted<UnifiedSystemTrayModel>(nullptr);
controller_ = std::make_unique<UnifiedSystemTrayController>(model_.get());
}
void TearDown() override {
header_ = nullptr;
widget_.reset();
controller_.reset();
model_.reset();
NoSessionAshTestBase::TearDown();
}
// Creates the object under test. Not part of SetUp() because sometimes tests
// need to setup the shell delegate or login before creating the header.
void CreateQuickSettingsHeader() {
// Instantiate view.
auto header = std::make_unique<QuickSettingsHeader>(controller_.get());
header_ = header.get();
// Place the view in a large views::Widget so the buttons are clickable.
widget_ = CreateFramelessTestWidget();
widget_->SetFullscreen(true);
widget_->SetContentsView(std::move(header));
}
views::View* GetManagedButton() {
return header_->GetViewByID(VIEW_ID_QS_MANAGED_BUTTON);
}
views::Label* GetManagedButtonLabel() {
return header_->GetManagedButtonLabelForTest();
}
views::View* GetSupervisedButton() {
return header_->GetViewByID(VIEW_ID_QS_SUPERVISED_BUTTON);
}
views::Label* GetSupervisedButtonLabel() {
return header_->GetSupervisedButtonLabelForTest();
}
raw_ptr<TestShellDelegate, DanglingUntriaged> test_shell_delegate_ = nullptr;
scoped_refptr<UnifiedSystemTrayModel> model_;
std::unique_ptr<UnifiedSystemTrayController> controller_;
std::unique_ptr<views::Widget> widget_;
raw_ptr<QuickSettingsHeader> header_ = nullptr;
};
TEST_F(QuickSettingsHeaderTest, HiddenOnStable) {
test_shell_delegate_->set_channel(version_info::Channel::STABLE);
CreateQuickSettingsHeader();
EXPECT_FALSE(GetManagedButton()->GetVisible());
EXPECT_FALSE(GetSupervisedButton()->GetVisible());
// Channel view is not created.
EXPECT_FALSE(header_->channel_view_for_test());
// Since no views are created, the header is hidden.
EXPECT_FALSE(header_->GetVisible());
}
TEST_F(QuickSettingsHeaderTest, ShowChannelViewBeforeLoginOnNonStable) {
test_shell_delegate_->set_channel(version_info::Channel::BETA);
CreateQuickSettingsHeader();
EXPECT_TRUE(header_->channel_view_for_test());
EXPECT_TRUE(header_->GetVisible());
}
TEST_F(QuickSettingsHeaderTest, ShowsChannelViewAfterLogin) {
test_shell_delegate_->set_channel(version_info::Channel::BETA);
SimulateUserLogin({"user@gmail.com"});
CreateQuickSettingsHeader();
// Channel view is created.
EXPECT_TRUE(header_->channel_view_for_test());
// Header is shown.
EXPECT_TRUE(header_->GetVisible());
}
TEST_F(QuickSettingsHeaderTest, EolNoticeVisible) {
Shell::Get()->system_tray_model()->SetShowEolNotice(true);
SimulateUserLogin({"user@gmail.com"});
CreateQuickSettingsHeader();
// Header is shown.
EXPECT_TRUE(header_->GetVisible());
// EOL notice is visible.
auto* eol_notice_view = header_->eol_notice_for_test();
ASSERT_TRUE(eol_notice_view);
EXPECT_TRUE(eol_notice_view->GetVisible());
LeftClickOn(eol_notice_view);
EXPECT_EQ(1, GetSystemTrayClient()->show_eol_info_count());
}
TEST_F(QuickSettingsHeaderTest, EolNoticeNotVisibleBeforeLogin) {
test_shell_delegate_->set_channel(version_info::Channel::BETA);
Shell::Get()->system_tray_model()->SetShowEolNotice(true);
CreateQuickSettingsHeader();
// Header is shown.
EXPECT_TRUE(header_->GetVisible());
// Channel view is created.
EXPECT_TRUE(header_->channel_view_for_test());
// EOL notice is not visible.
EXPECT_FALSE(header_->eol_notice_for_test());
}
TEST_F(QuickSettingsHeaderTest, ChannelIndicatorNotShownWithEolNotice) {
test_shell_delegate_->set_channel(version_info::Channel::BETA);
SimulateUserLogin({"user@gmail.com"});
Shell::Get()->system_tray_model()->SetShowEolNotice(true);
CreateQuickSettingsHeader();
// Header is shown.
EXPECT_TRUE(header_->GetVisible());
// No channel indicator.
EXPECT_FALSE(header_->channel_view_for_test());
// EOL notice is visible.
ASSERT_TRUE(header_->eol_notice_for_test());
EXPECT_TRUE(header_->eol_notice_for_test()->GetVisible());
}
TEST_F(QuickSettingsHeaderTest, ExtendedUpdatesNoticeVisible) {
Shell::Get()->system_tray_model()->SetShowExtendedUpdatesNotice(true);
SimulateUserLogin({"user@gmail.com"});
base::HistogramTester histogram_tester;
CreateQuickSettingsHeader();
// Header is shown.
EXPECT_TRUE(header_->GetVisible());
histogram_tester.ExpectBucketCount(
kExtendedUpdatesEntryPointEventMetric,
ExtendedUpdatesEntryPointEvent::kQuickSettingsBannerShown, 1);
// Extended Updates notice is visible.
auto* extended_updates_notice_view = header_->GetExtendedUpdatesViewForTest();
ASSERT_TRUE(extended_updates_notice_view);
EXPECT_TRUE(extended_updates_notice_view->GetVisible());
EXPECT_EQ(0, GetSystemTrayClient()->show_about_chromeos_count());
LeftClickOn(extended_updates_notice_view);
EXPECT_EQ(1, GetSystemTrayClient()->show_about_chromeos_count());
histogram_tester.ExpectBucketCount(
kExtendedUpdatesEntryPointEventMetric,
ExtendedUpdatesEntryPointEvent::kQuickSettingsBannerClicked, 1);
}
TEST_F(QuickSettingsHeaderTest, ExtendedUpdatesNoticeNotVisibleBeforeLogin) {
test_shell_delegate_->set_channel(version_info::Channel::BETA);
Shell::Get()->system_tray_model()->SetShowExtendedUpdatesNotice(true);
CreateQuickSettingsHeader();
// Header is shown.
EXPECT_TRUE(header_->GetVisible());
// Channel view is created.
EXPECT_TRUE(header_->channel_view_for_test());
// Extended Updates notice is not visible.
EXPECT_FALSE(header_->GetExtendedUpdatesViewForTest());
}
TEST_F(QuickSettingsHeaderTest,
ChannelIndicatorNotShownWithExtendedUpdatesNotice) {
test_shell_delegate_->set_channel(version_info::Channel::BETA);
SimulateUserLogin({"user@gmail.com"});
Shell::Get()->system_tray_model()->SetShowExtendedUpdatesNotice(true);
base::HistogramTester histogram_tester;
CreateQuickSettingsHeader();
// Header is shown.
EXPECT_TRUE(header_->GetVisible());
// No channel indicator.
EXPECT_FALSE(header_->channel_view_for_test());
// Extended Updates notice is visible.
ASSERT_TRUE(header_->GetExtendedUpdatesViewForTest());
EXPECT_TRUE(header_->GetExtendedUpdatesViewForTest()->GetVisible());
histogram_tester.ExpectBucketCount(
kExtendedUpdatesEntryPointEventMetric,
ExtendedUpdatesEntryPointEvent::kQuickSettingsBannerShown, 1);
}
TEST_F(QuickSettingsHeaderTest, ExtendedUpdatesNoticeNotShownWithEolNotice) {
SimulateUserLogin({"user@gmail.com"});
Shell::Get()->system_tray_model()->SetShowEolNotice(true);
Shell::Get()->system_tray_model()->SetShowExtendedUpdatesNotice(true);
base::HistogramTester histogram_tester;
CreateQuickSettingsHeader();
// Header is shown.
EXPECT_TRUE(header_->GetVisible());
// No channel indicator.
EXPECT_FALSE(header_->channel_view_for_test());
// EOL notice is visible.
ASSERT_TRUE(header_->eol_notice_for_test());
EXPECT_TRUE(header_->eol_notice_for_test()->GetVisible());
// Extended Updates notice is not visible.
EXPECT_FALSE(header_->GetExtendedUpdatesViewForTest());
histogram_tester.ExpectBucketCount(
kExtendedUpdatesEntryPointEventMetric,
ExtendedUpdatesEntryPointEvent::kQuickSettingsBannerShown, 0);
}
TEST_F(QuickSettingsHeaderTest, EnterpriseManagedDeviceVisible) {
CreateQuickSettingsHeader();
// Simulate enterprise information becoming available.
GetEnterpriseDomainModel()->SetDeviceEnterpriseInfo(DeviceEnterpriseInfo{
"example.com", ManagementDeviceMode::kChromeEnterprise});
EXPECT_TRUE(GetManagedButton()->GetVisible());
EXPECT_EQ(GetManagedButtonLabel()->GetText(), u"Managed by example.com");
EXPECT_EQ(GetManagedButton()->GetRenderedTooltipText({}),
u"Managed by example.com");
EXPECT_TRUE(header_->GetVisible());
}
TEST_F(QuickSettingsHeaderTest, EnterpriseManagedAccountVisible) {
CreateQuickSettingsHeader();
// Simulate enterprise information becoming available.
GetEnterpriseDomainModel()->SetEnterpriseAccountDomainInfo("example.com");
EXPECT_TRUE(GetManagedButton()->GetVisible());
EXPECT_EQ(GetManagedButtonLabel()->GetText(), u"Managed by example.com");
EXPECT_EQ(GetManagedButton()->GetRenderedTooltipText({}),
u"Managed by example.com");
EXPECT_TRUE(header_->GetVisible());
}
TEST_F(QuickSettingsHeaderTest, BothChannelAndEnterpriseVisible) {
test_shell_delegate_->set_channel(version_info::Channel::BETA);
GetEnterpriseDomainModel()->SetDeviceEnterpriseInfo(DeviceEnterpriseInfo{
"example.com", ManagementDeviceMode::kChromeEnterprise});
SimulateUserLogin({"user@gmail.com"});
CreateQuickSettingsHeader();
EXPECT_TRUE(GetManagedButton()->GetVisible());
// The label is the shorter "Managed" due to the two-column layout.
EXPECT_EQ(GetManagedButtonLabel()->GetText(), u"Managed");
EXPECT_EQ(GetManagedButton()->GetRenderedTooltipText({}),
u"Managed by example.com");
EXPECT_TRUE(header_->channel_view_for_test());
EXPECT_TRUE(header_->GetVisible());
}
TEST_F(QuickSettingsHeaderTest, BothEolNoticeAndEnterpriseVisible) {
GetEnterpriseDomainModel()->SetDeviceEnterpriseInfo(DeviceEnterpriseInfo{
"example.com", ManagementDeviceMode::kChromeEnterprise});
Shell::Get()->system_tray_model()->SetShowEolNotice(true);
SimulateUserLogin({"user@gmail.com"});
CreateQuickSettingsHeader();
EXPECT_TRUE(GetManagedButton()->GetVisible());
// The label is the shorter "Managed" due to the two-column layout.
EXPECT_EQ(GetManagedButtonLabel()->GetText(), u"Managed");
EXPECT_EQ(GetManagedButton()->GetRenderedTooltipText({}),
u"Managed by example.com");
EXPECT_TRUE(header_->GetVisible());
EolNoticeQuickSettingsView* eol_notice = header_->eol_notice_for_test();
ASSERT_TRUE(eol_notice);
EXPECT_TRUE(eol_notice->GetVisible());
// The label is shorter due to the two-column layout.
EXPECT_EQ(eol_notice->GetText(), u"Updates ended");
LeftClickOn(eol_notice);
EXPECT_EQ(1, GetSystemTrayClient()->show_eol_info_count());
}
TEST_F(QuickSettingsHeaderTest, ChildVisible) {
CreateQuickSettingsHeader();
// Before login the supervised user view is invisible.
EXPECT_FALSE(GetSupervisedButton()->GetVisible());
// Simulate supervised user logging in.
SessionControllerImpl* session = Shell::Get()->session_controller();
ClearLogin();
SimulateUserLogin({"child@test.com", user_manager::UserType::kChild});
UserSession user_session = *session->GetUserSession(0);
user_session.custodian_email = "parent@test.com";
session->UpdateUserSession(std::move(user_session));
// Recreate the header after login.
CreateQuickSettingsHeader();
// Now the supervised user view is visible.
EXPECT_TRUE(GetSupervisedButton()->GetVisible());
EXPECT_EQ(GetSupervisedButtonLabel()->GetText(), u"Supervised user");
EXPECT_EQ(GetSupervisedButton()->GetRenderedTooltipText({}),
u"Account managed by parent@test.com");
EXPECT_TRUE(header_->GetVisible());
LeftClickOn(GetSupervisedButton());
EXPECT_EQ(GetSystemTrayClient()->show_account_settings_count(), 1);
}
TEST_F(QuickSettingsHeaderTest, ShowManagementDisclosure) {
// This test relies on the lock screen actually being created (and creating
// the lock screen requires the existence of an `AuthEventsRecorder`).
std::unique_ptr<AuthEventsRecorder> auth_events_recorder =
AuthEventsRecorder::CreateForTesting();
// Setup to lock screen.
ClearLogin();
TestSessionControllerClient* client = GetSessionControllerClient();
client->set_show_lock_screen_views(true);
client->LockScreen();
client->SetSessionState(session_manager::SessionState::LOCKED);
// Create new lock screen for lock_contents.
ash::LockScreen::Get()->Destroy();
LockScreen::Show(LockScreen::ScreenType::kLock);
QuickSettingsHeader::ShowEnterpriseInfo(controller_.get(), true, true, true);
LockContentsViewTestApi lock_contents(
LockScreen::TestApi(LockScreen::Get()).contents_view());
EXPECT_TRUE(lock_contents.management_disclosure_dialog());
}
TEST_F(QuickSettingsHeaderTest, DoNotShowManagementDisclosure) {
// This test relies on the lock screen actually being created (and creating
// the lock screen requires the existence of an `AuthEventsRecorder`).
std::unique_ptr<AuthEventsRecorder> auth_events_recorder =
AuthEventsRecorder::CreateForTesting();
// Setup to lock screen.
ClearLogin();
TestSessionControllerClient* client = GetSessionControllerClient();
client->set_show_lock_screen_views(true);
client->LockScreen();
client->SetSessionState(session_manager::SessionState::LOCKED);
// Create new lock screen for lock_contents.
ash::LockScreen::Get()->Destroy();
LockScreen::Show(LockScreen::ScreenType::kLock);
// Feature disabled.
QuickSettingsHeader::ShowEnterpriseInfo(
controller_.get(), /*showManagementDisclosureDialog*/ false,
/*IsUserSessionBlocked*/ true, /*hasEnterpriseDomainManager*/ true);
LockContentsViewTestApi lock_contents_1(
LockScreen::TestApi(LockScreen::Get()).contents_view());
EXPECT_FALSE(lock_contents_1.management_disclosure_dialog());
// User session not blocked.
QuickSettingsHeader::ShowEnterpriseInfo(
controller_.get(), /*showManagementDisclosureDialog*/ true,
/*IsUserSessionBlocked*/ false, /*hasEnterpriseDomainManager*/ true);
LockContentsViewTestApi lock_contents_2(
LockScreen::TestApi(LockScreen::Get()).contents_view());
EXPECT_FALSE(lock_contents_2.management_disclosure_dialog());
// Not enterprise enrolled device.
QuickSettingsHeader::ShowEnterpriseInfo(
controller_.get(), /*showManagementDisclosureDialog*/ true,
/*IsUserSessionBlocked*/ true, /*hasEnterpriseDomainManager*/ false);
LockContentsViewTestApi lock_contents_3(
LockScreen::TestApi(LockScreen::Get()).contents_view());
EXPECT_FALSE(lock_contents_3.management_disclosure_dialog());
}
} // namespace ash