#include "ash/system/firmware_update/firmware_update_notification_controller.h"
#include <memory>
#include <optional>
#include "ash/public/cpp/test/test_system_tray_client.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "base/memory/raw_ptr.h"
#include "chromeos/ash/components/dbus/fwupd/fwupd_client.h"
#include "chromeos/ash/components/fwupd/firmware_update_manager.h"
#include "chromeos/ash/components/network/network_handler.h"
#include "chromeos/ash/components/network/network_handler_test_helper.h"
#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
#include "components/user_manager/user_type.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/public/cpp/notification.h"
namespace ash {
namespace {
using ::message_center::MessageCenter;
const char kFirmwareUpdateNotificationId[] =
"cros_firmware_update_notification_id";
}
class FirmwareUpdateNotificationControllerTest : public AshTestBase {
public:
FirmwareUpdateNotificationControllerTest() = default;
FirmwareUpdateNotificationControllerTest(
const FirmwareUpdateNotificationControllerTest&) = delete;
FirmwareUpdateNotificationControllerTest& operator=(
const FirmwareUpdateNotificationControllerTest&) = delete;
~FirmwareUpdateNotificationControllerTest() override = default;
FirmwareUpdateNotificationController* controller() {
return Shell::Get()->firmware_update_notification_controller();
}
message_center::Notification* GetFirmwareUpdateNotification() {
return MessageCenter::Get()->FindVisibleNotificationById(
kFirmwareUpdateNotificationId);
}
int GetNumFirmwareUpdateUIOpened() {
return GetSystemTrayClient()->show_firmware_update_count();
}
void ClickNotification(std::optional<int> button_index) {
if (!button_index.has_value()) {
message_center::Notification* notification =
MessageCenter::Get()->FindVisibleNotificationById(
kFirmwareUpdateNotificationId);
notification->delegate()->Click(std::nullopt, std::nullopt);
return;
}
message_center::Notification* notification =
MessageCenter::Get()->FindVisibleNotificationById(
kFirmwareUpdateNotificationId);
notification->delegate()->Click(button_index, std::nullopt);
}
};
TEST_F(FirmwareUpdateNotificationControllerTest, FirmwareUpdateNotification) {
EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
controller()->NotifyFirmwareUpdateAvailable();
EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
message_center::Notification* notification = GetFirmwareUpdateNotification();
EXPECT_TRUE(notification);
EXPECT_EQ(1u, notification->buttons().size());
EXPECT_EQ(0, GetNumFirmwareUpdateUIOpened());
ClickNotification(0);
EXPECT_EQ(1, GetNumFirmwareUpdateUIOpened());
EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
controller()->NotifyFirmwareUpdateAvailable();
EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
ClickNotification(std::nullopt);
EXPECT_EQ(2, GetNumFirmwareUpdateUIOpened());
EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
}
class FirmwareUpdateStartupNotificationTest : public NoSessionAshTestBase {
public:
FirmwareUpdateStartupNotificationTest() = default;
~FirmwareUpdateStartupNotificationTest() override = default;
void SetUp() override {
network_handler_test_helper_.RegisterPrefs(profile_prefs_.registry(),
local_state()->registry());
network_handler_test_helper_.InitializePrefs(&profile_prefs_,
local_state());
FwupdClient::InitializeFake();
dbus_client_ = FwupdClient::Get();
firmware_update_manager_ = std::make_unique<FirmwareUpdateManager>();
EXPECT_TRUE(FirmwareUpdateManager::IsInitialized());
SetShouldShowNotificationForTest(true);
NoSessionAshTestBase::SetUp();
}
void TearDown() override {
firmware_update_notification_controller_.reset();
firmware_update_manager_.reset();
FwupdClient::Shutdown();
NetworkHandler::Get()->ShutdownPrefServices();
NoSessionAshTestBase::TearDown();
}
protected:
void InitializeNotificationController() {
firmware_update_notification_controller_ =
std::make_unique<FirmwareUpdateNotificationController>(
message_center());
}
message_center::MessageCenter* message_center() const {
return message_center::MessageCenter::Get();
}
message_center::Notification* FindShortcutsChangedNotification() {
return message_center::MessageCenter::Get()->FindVisibleNotificationById(
kFirmwareUpdateNotificationId);
}
void SetShouldShowNotificationForTest(bool show_notification) {
FirmwareUpdateManager::Get()->set_should_show_notification_for_test(
show_notification);
}
void SimulateFetchingUpdates() {
FirmwareUpdateManager::Get()->RequestAllUpdates(
FirmwareUpdateManager::Source::kStartup);
}
raw_ptr<FwupdClient, DanglingUntriaged> dbus_client_ = nullptr;
NetworkHandlerTestHelper network_handler_test_helper_;
TestingPrefServiceSimple profile_prefs_;
std::unique_ptr<FirmwareUpdateManager> firmware_update_manager_;
std::unique_ptr<FirmwareUpdateNotificationController>
firmware_update_notification_controller_;
};
TEST_F(FirmwareUpdateStartupNotificationTest,
StartupNotificationShownRegularUser) {
SimulateUserLogin({"user1@email.com"});
InitializeNotificationController();
SimulateFetchingUpdates();
EXPECT_TRUE(message_center()->FindVisibleNotificationById(
kFirmwareUpdateNotificationId));
}
TEST_F(FirmwareUpdateStartupNotificationTest,
StartupNotificationShownGuestUser) {
SimulateGuestLogin();
InitializeNotificationController();
SimulateFetchingUpdates();
EXPECT_FALSE(message_center()->FindVisibleNotificationById(
kFirmwareUpdateNotificationId));
}
TEST_F(FirmwareUpdateStartupNotificationTest, StartupNotificationShownKiosk) {
SimulateUserLogin(
{"user1@email.com", user_manager::UserType::kKioskChromeApp});
InitializeNotificationController();
SimulateFetchingUpdates();
EXPECT_FALSE(message_center()->FindVisibleNotificationById(
kFirmwareUpdateNotificationId));
}
TEST_F(FirmwareUpdateStartupNotificationTest,
StartupNotificationShownKioskPWA) {
SimulateUserLogin({"user1@email.com", user_manager::UserType::kKioskWebApp});
InitializeNotificationController();
SimulateFetchingUpdates();
EXPECT_FALSE(message_center()->FindVisibleNotificationById(
kFirmwareUpdateNotificationId));
}
}