blob: ab71d61df6b684fe864664d75793f427f1f02bad [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/message_center/message_center_impl.h"
#include <memory>
#include <utility>
#include "ash/constants/ash_features.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/current_thread.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/size.h"
#include "ui/message_center/lock_screen/fake_lock_screen_controller.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_types.h"
#include "ui/message_center/notification_blocker.h"
#include "ui/message_center/public/cpp/message_center_constants.h"
#include "ui/message_center/public/cpp/notification_types.h"
#include "ui/message_center/public/cpp/notifier_id.h"
#include "base/logging.h"
using base::UTF8ToUTF16;
namespace message_center {
namespace {
class CheckObserver : public MessageCenterObserver {
public:
CheckObserver(MessageCenter* message_center, const std::string& target_id)
: message_center_(message_center), target_id_(target_id) {
DCHECK(message_center);
DCHECK(!target_id.empty());
}
CheckObserver(const CheckObserver&) = delete;
CheckObserver& operator=(const CheckObserver&) = delete;
void OnNotificationUpdated(const std::string& notification_id) override {
EXPECT_TRUE(message_center_->FindVisibleNotificationById(target_id_));
}
private:
raw_ptr<MessageCenter> message_center_;
std::string target_id_;
};
class RemoveObserver : public MessageCenterObserver {
public:
RemoveObserver(MessageCenter* message_center, const std::string& target_id)
: message_center_(message_center), target_id_(target_id) {
DCHECK(message_center);
DCHECK(!target_id.empty());
}
RemoveObserver(const RemoveObserver&) = delete;
RemoveObserver& operator=(const RemoveObserver&) = delete;
void OnNotificationUpdated(const std::string& notification_id) override {
message_center_->RemoveNotification(target_id_, false);
}
private:
raw_ptr<MessageCenter> message_center_;
std::string target_id_;
};
class TestAddObserver : public MessageCenterObserver {
public:
explicit TestAddObserver(MessageCenter* message_center)
: message_center_(message_center) {
message_center_->AddObserver(this);
}
~TestAddObserver() override { message_center_->RemoveObserver(this); }
void OnNotificationAdded(const std::string& id) override {
std::string log = logs_[id];
if (!log.empty())
log += "_";
logs_[id] = log + "add-" + id;
}
void OnNotificationUpdated(const std::string& id) override {
std::string log = logs_[id];
if (!log.empty())
log += "_";
logs_[id] = log + "update-" + id;
}
const std::string log(const std::string& id) { return logs_[id]; }
void reset_logs() { logs_.clear(); }
private:
std::map<std::string, std::string> logs_;
raw_ptr<MessageCenter> message_center_;
};
class TestDelegate : public NotificationDelegate {
public:
TestDelegate() = default;
void Close(bool by_user) override {
log_ += "Close_";
log_ += (by_user ? "by_user_" : "programmatically_");
}
TestDelegate(const TestDelegate&) = delete;
TestDelegate& operator=(const TestDelegate&) = delete;
void Click(const std::optional<int>& button_index,
const std::optional<std::u16string>& reply) override {
if (button_index) {
if (!reply) {
log_ += "ButtonClick_";
log_ += base::NumberToString(*button_index) + "_";
} else {
log_ += "ReplyButtonClick_";
log_ += base::NumberToString(*button_index) + "_";
log_ += base::UTF16ToUTF8(*reply) + "_";
}
} else {
log_ += "Click_";
}
}
const std::string& log() { return log_; }
private:
~TestDelegate() override = default;
std::string log_;
};
class DeleteOnCloseDelegate : public NotificationDelegate {
public:
DeleteOnCloseDelegate(MessageCenter* message_center,
const std::string& notification_id)
: message_center_(message_center), notification_id_(notification_id) {}
DeleteOnCloseDelegate(const DeleteOnCloseDelegate&) = delete;
DeleteOnCloseDelegate& operator=(const DeleteOnCloseDelegate&) = delete;
void Close(bool by_user) override {
// Removing the same notification inside Close should be a noop.
message_center_->RemoveNotification(notification_id_, false /* by_user */);
}
void Click(const std::optional<int>& button_index,
const std::optional<std::u16string>& reply) override {}
private:
~DeleteOnCloseDelegate() override = default;
raw_ptr<MessageCenter> message_center_;
std::string notification_id_;
};
// The default app id used to create simple notifications.
const char kDefaultAppId[] = "app1";
} // anonymous namespace
class MessageCenterImplTest : public testing::Test {
public:
MessageCenterImplTest() = default;
MessageCenterImplTest(const MessageCenterImplTest&) = delete;
MessageCenterImplTest& operator=(const MessageCenterImplTest&) = delete;
void SetUp() override {
MessageCenter::Initialize(std::make_unique<FakeLockScreenController>());
message_center_ = MessageCenter::Get();
task_environment_ =
std::make_unique<base::test::SingleThreadTaskEnvironment>();
run_loop_ = std::make_unique<base::RunLoop>();
closure_ = run_loop_->QuitClosure();
}
void TearDown() override {
run_loop_.reset();
task_environment_.reset();
message_center_ = nullptr;
MessageCenter::Shutdown();
}
MessageCenter* message_center() const { return message_center_; }
MessageCenterImpl* message_center_impl() const {
return reinterpret_cast<MessageCenterImpl*>(message_center_.get());
}
base::RunLoop* run_loop() const { return run_loop_.get(); }
base::RepeatingClosure closure() const { return closure_; }
protected:
std::unique_ptr<Notification> CreateSimpleNotification(
const std::string& id) {
return CreateNotificationWithNotifierId(id, kDefaultAppId,
NOTIFICATION_TYPE_SIMPLE);
}
std::unique_ptr<Notification> CreateSimpleNotificationWithNotifierId(
const std::string& id,
const std::string& notifier_id) {
return CreateNotificationWithNotifierId(
id,
notifier_id,
NOTIFICATION_TYPE_SIMPLE);
}
std::unique_ptr<Notification> CreateSimpleNotificationWithDelegate(
const std::string& id,
scoped_refptr<NotificationDelegate> delegate) {
return CreateNotificationWithNotifierIdAndDelegate(
id, kDefaultAppId, NOTIFICATION_TYPE_SIMPLE, delegate,
RichNotificationData());
}
std::unique_ptr<Notification> CreateSimpleNotificationWithOptionalFields(
const std::string& id,
const RichNotificationData& optional_fields) {
return CreateNotificationWithNotifierIdAndDelegate(
id, kDefaultAppId, NOTIFICATION_TYPE_SIMPLE,
base::MakeRefCounted<TestDelegate>(), optional_fields);
}
std::unique_ptr<Notification> CreateNotification(const std::string& id,
NotificationType type) {
return CreateNotificationWithNotifierId(id, kDefaultAppId, type);
}
std::unique_ptr<Notification> CreateNotificationWithNotifierId(
const std::string& id,
const std::string& notifier_id,
NotificationType type) {
return CreateNotificationWithNotifierIdAndDelegate(
id, notifier_id, type, base::MakeRefCounted<TestDelegate>(),
RichNotificationData());
}
std::unique_ptr<Notification> CreateNotificationWithNotifierIdAndDelegate(
const std::string& id,
const std::string& notifier_id,
NotificationType type,
scoped_refptr<NotificationDelegate> delegate,
const RichNotificationData& optional_fields) {
return std::make_unique<Notification>(
type, id, u"title", UTF8ToUTF16(id), ui::ImageModel() /* icon */,
std::u16string() /* display_source */, GURL(),
NotifierId(NotifierType::APPLICATION, notifier_id), optional_fields,
delegate);
}
TestDelegate* GetDelegate(const std::string& id) const {
Notification* n = message_center()->FindVisibleNotificationById(id);
return n ? static_cast<TestDelegate*>(n->delegate()) : nullptr;
}
FakeLockScreenController* lock_screen_controller() const {
return static_cast<FakeLockScreenController*>(
message_center_impl()->lock_screen_controller());
}
private:
raw_ptr<MessageCenter> message_center_;
std::unique_ptr<base::test::SingleThreadTaskEnvironment> task_environment_;
std::unique_ptr<base::RunLoop> run_loop_;
base::RepeatingClosure closure_;
};
namespace {
class ToggledNotificationBlocker : public NotificationBlocker {
public:
explicit ToggledNotificationBlocker(MessageCenter* message_center)
: NotificationBlocker(message_center) {}
ToggledNotificationBlocker(const ToggledNotificationBlocker&) = delete;
ToggledNotificationBlocker& operator=(const ToggledNotificationBlocker&) =
delete;
~ToggledNotificationBlocker() override = default;
void SetPopupNotificationsEnabled(bool enabled) {
if (popup_notifications_enabled_ == enabled)
return;
popup_notifications_enabled_ = enabled;
NotifyBlockingStateChanged();
}
void SetNotificationsEnabled(bool enabled) {
if (notifications_enabled_ == enabled)
return;
notifications_enabled_ = enabled;
NotifyBlockingStateChanged();
}
// NotificationBlocker overrides:
bool ShouldShowNotificationAsPopup(
const Notification& notification) const override {
return popup_notifications_enabled_;
}
bool ShouldShowNotification(const Notification& notification) const override {
return notifications_enabled_;
}
private:
bool notifications_enabled_ = true;
bool popup_notifications_enabled_ = true;
};
class PopupNotificationBlocker : public ToggledNotificationBlocker {
public:
PopupNotificationBlocker(MessageCenter* message_center,
const NotifierId& allowed_notifier)
: ToggledNotificationBlocker(message_center),
allowed_notifier_(allowed_notifier) {}
PopupNotificationBlocker(const PopupNotificationBlocker&) = delete;
PopupNotificationBlocker& operator=(const PopupNotificationBlocker&) = delete;
~PopupNotificationBlocker() override = default;
// NotificationBlocker overrides:
bool ShouldShowNotificationAsPopup(
const Notification& notification) const override {
return (notification.notifier_id() == allowed_notifier_) ||
ToggledNotificationBlocker::ShouldShowNotificationAsPopup(
notification);
}
protected:
const NotifierId allowed_notifier_;
};
class NearTotalNotificationBlocker : public PopupNotificationBlocker {
public:
NearTotalNotificationBlocker(MessageCenter* message_center,
const NotifierId& allowed_notifier)
: PopupNotificationBlocker(message_center, allowed_notifier) {}
NearTotalNotificationBlocker(const NearTotalNotificationBlocker&) = delete;
NearTotalNotificationBlocker& operator=(const NearTotalNotificationBlocker&) =
delete;
~NearTotalNotificationBlocker() override = default;
// NotificationBlocker overrides:
bool ShouldShowNotification(const Notification& notification) const override {
return (notification.notifier_id() == allowed_notifier_) ||
ToggledNotificationBlocker::ShouldShowNotification(notification);
}
};
class TotalNotificationBlocker : public NotificationBlocker {
public:
explicit TotalNotificationBlocker(MessageCenter* message_center)
: NotificationBlocker(message_center) {}
TotalNotificationBlocker(const TotalNotificationBlocker&) = delete;
TotalNotificationBlocker& operator=(const TotalNotificationBlocker&) = delete;
~TotalNotificationBlocker() override = default;
// NotificationBlocker:
bool ShouldShowNotification(const Notification& notification) const override {
return false;
}
bool ShouldShowNotificationAsPopup(
const Notification& notification) const override {
return false;
}
};
bool PopupNotificationsContain(
const NotificationList::PopupNotifications& popups,
const std::string& id) {
for (const Notification* popup : popups) {
if (popup->id() == id)
return true;
}
return false;
}
// Right now, MessageCenter::HasNotification() returns regardless of blockers.
bool NotificationsContain(
const NotificationList::Notifications& notifications,
const std::string& id) {
for (const Notification* notification : notifications) {
if (notification->id() == id)
return true;
}
return false;
}
} // namespace
namespace internal {
class MockPopupTimersController : public PopupTimersController {
public:
MockPopupTimersController(MessageCenter* message_center,
base::RepeatingClosure quit_closure)
: PopupTimersController(message_center),
timer_finished_(0),
quit_closure_(quit_closure) {}
~MockPopupTimersController() override = default;
void TimerFinished(const std::string& id) override {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE,
quit_closure_);
timer_finished_++;
last_id_ = id;
}
int timer_finished() const { return timer_finished_; }
const std::string& last_id() const { return last_id_; }
private:
int timer_finished_;
std::string last_id_;
base::RepeatingClosure quit_closure_;
};
TEST_F(MessageCenterImplTest, PopupTimersEmptyController) {
std::unique_ptr<PopupTimersController> popup_timers_controller =
std::make_unique<PopupTimersController>(message_center());
// Test that all functions succeed without any timers created.
popup_timers_controller->PauseAll();
popup_timers_controller->StartAll();
popup_timers_controller->CancelAll();
popup_timers_controller->TimerFinished("unknown");
popup_timers_controller->CancelTimer("unknown");
}
TEST_F(MessageCenterImplTest, PopupTimersControllerStartTimer) {
std::unique_ptr<MockPopupTimersController> popup_timers_controller =
std::make_unique<MockPopupTimersController>(message_center(), closure());
popup_timers_controller->StartTimer("test", base::Milliseconds(1));
run_loop()->Run();
EXPECT_EQ(popup_timers_controller->timer_finished(), 1);
}
TEST_F(MessageCenterImplTest, PopupTimersControllerCancelTimer) {
std::unique_ptr<MockPopupTimersController> popup_timers_controller =
std::make_unique<MockPopupTimersController>(message_center(), closure());
popup_timers_controller->StartTimer("test", base::Milliseconds(1));
popup_timers_controller->CancelTimer("test");
run_loop()->RunUntilIdle();
EXPECT_EQ(popup_timers_controller->timer_finished(), 0);
}
TEST_F(MessageCenterImplTest, PopupTimersControllerPauseAllTimers) {
std::unique_ptr<MockPopupTimersController> popup_timers_controller =
std::make_unique<MockPopupTimersController>(message_center(), closure());
popup_timers_controller->StartTimer("test", base::Milliseconds(1));
popup_timers_controller->PauseAll();
run_loop()->RunUntilIdle();
EXPECT_EQ(popup_timers_controller->timer_finished(), 0);
}
TEST_F(MessageCenterImplTest, PopupTimersControllerStartAllTimers) {
std::unique_ptr<MockPopupTimersController> popup_timers_controller =
std::make_unique<MockPopupTimersController>(message_center(), closure());
popup_timers_controller->StartTimer("test", base::Milliseconds(1));
popup_timers_controller->PauseAll();
popup_timers_controller->StartAll();
run_loop()->Run();
EXPECT_EQ(popup_timers_controller->timer_finished(), 1);
}
TEST_F(MessageCenterImplTest, PopupTimersControllerStartMultipleTimers) {
std::unique_ptr<MockPopupTimersController> popup_timers_controller =
std::make_unique<MockPopupTimersController>(message_center(), closure());
popup_timers_controller->StartTimer("test", base::TimeDelta::Max());
popup_timers_controller->StartTimer("test2", base::Milliseconds(1));
popup_timers_controller->StartTimer("test3", base::TimeDelta::Max());
popup_timers_controller->PauseAll();
popup_timers_controller->StartAll();
run_loop()->Run();
EXPECT_EQ(popup_timers_controller->last_id(), "test2");
EXPECT_EQ(popup_timers_controller->timer_finished(), 1);
}
TEST_F(MessageCenterImplTest, PopupTimersControllerRestartOnUpdate) {
scoped_refptr<base::SingleThreadTaskRunner> old_task_runner =
base::SingleThreadTaskRunner::GetCurrentDefault();
scoped_refptr<base::TestMockTimeTaskRunner> task_runner =
base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
base::CurrentThread::Get()->SetTaskRunner(task_runner);
NotifierId notifier_id(GURL("https://example.com"));
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id, RichNotificationData(), nullptr));
std::unique_ptr<MockPopupTimersController> popup_timers_controller =
std::make_unique<MockPopupTimersController>(message_center(), closure());
popup_timers_controller->OnNotificationDisplayed("id1", DISPLAY_SOURCE_POPUP);
ASSERT_EQ(popup_timers_controller->timer_finished(), 0);
#if BUILDFLAG(IS_CHROMEOS_ASH)
const int dismiss_time =
popup_timers_controller->GetNotificationTimeoutDefault();
#else
const int dismiss_time = kAutocloseHighPriorityDelaySeconds;
#endif
// Fast forward the |task_runner| by one second less than the auto-close timer
// frequency for Web Notifications. (As set by the |notifier_id|.)
task_runner->FastForwardBy(base::Seconds(dismiss_time - 1));
ASSERT_EQ(popup_timers_controller->timer_finished(), 0);
// Trigger a replacement of the notification in the timer controller.
popup_timers_controller->OnNotificationUpdated("id1");
// Fast forward the |task_runner| by one second less than the auto-close timer
// frequency for Web Notifications again. It should have been reset.
task_runner->FastForwardBy(base::Seconds(dismiss_time - 1));
ASSERT_EQ(popup_timers_controller->timer_finished(), 0);
// Now fast forward the |task_runner| by two seconds (to avoid flakiness),
// after which the timer should have fired.
task_runner->FastForwardBy(base::Seconds(2));
ASSERT_EQ(popup_timers_controller->timer_finished(), 1);
base::CurrentThread::Get()->SetTaskRunner(old_task_runner);
}
TEST_F(MessageCenterImplTest, Renotify) {
message_center()->SetHasMessageCenterView(true);
const std::string id("id");
// Add notification initially.
std::unique_ptr<Notification> notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
auto popups = message_center()->GetPopupNotifications();
EXPECT_EQ(1u, popups.size());
EXPECT_TRUE(PopupNotificationsContain(popups, id));
// Mark notification as shown.
message_center()->MarkSinglePopupAsShown(id, true);
EXPECT_EQ(0u, message_center()->GetPopupNotifications().size());
// Add notification again without |renotify| flag. It should not pop-up again.
notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
EXPECT_EQ(0u, message_center()->GetPopupNotifications().size());
// Add notification again with |renotify| flag. It should pop-up again.
notification = CreateSimpleNotification(id);
notification->set_renotify(true);
message_center()->AddNotification(std::move(notification));
popups = message_center()->GetPopupNotifications();
EXPECT_EQ(1u, popups.size());
EXPECT_TRUE(PopupNotificationsContain(popups, id));
}
TEST_F(MessageCenterImplTest, NotificationBlocker) {
NotifierId notifier_id(NotifierType::APPLICATION, "app1");
// Multiple blockers to verify the case that one blocker blocks but another
// doesn't.
ToggledNotificationBlocker blocker1(message_center());
blocker1.Init();
ToggledNotificationBlocker blocker2(message_center());
blocker2.Init();
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id, RichNotificationData(), nullptr));
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id, RichNotificationData(), nullptr));
EXPECT_EQ(2u, message_center()->GetPopupNotifications().size());
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
// "id1" is displayed as a pop-up so that it will be closed when blocked.
message_center()->DisplayedNotification("id1", DISPLAY_SOURCE_POPUP);
// Block all notifications. All popups are gone and message center should be
// hidden.
blocker1.SetPopupNotificationsEnabled(false);
EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
// Updates |blocker2| state, which doesn't affect the global state.
blocker2.SetPopupNotificationsEnabled(false);
EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
blocker2.SetPopupNotificationsEnabled(true);
EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
// If |blocker2| blocks, then unblocking blocker1 doesn't change the global
// state.
blocker2.SetPopupNotificationsEnabled(false);
blocker1.SetPopupNotificationsEnabled(true);
EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
// Unblock both blockers, which recovers the global state, the displayed
// pop-ups before blocking aren't shown but the never-displayed ones will
// be shown.
blocker2.SetPopupNotificationsEnabled(true);
NotificationList::PopupNotifications popups =
message_center()->GetPopupNotifications();
EXPECT_EQ(1u, popups.size());
EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
}
TEST_F(MessageCenterImplTest, MarkPopupAsShownWhileBlocked) {
const std::string kMarkedId = "id1";
const std::string kNotMarkedId = "id2";
ToggledNotificationBlocker blocker(message_center());
blocker.Init();
message_center()->AddNotification(CreateSimpleNotification(kMarkedId));
message_center()->AddNotification(CreateSimpleNotification(kNotMarkedId));
EXPECT_EQ(message_center()->GetPopupNotifications().size(), 2u);
EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 2u);
// Block all notifications. There should be no popups or visible
// notifications.
blocker.SetPopupNotificationsEnabled(false);
blocker.SetNotificationsEnabled(false);
EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
EXPECT_TRUE(message_center()->GetVisibleNotifications().empty());
EXPECT_EQ(message_center()->GetNotifications().size(), 2u);
// Mark one notification as being shown as a popup, so that when blocking ends
// it will not be displayed.
message_center()->MarkSinglePopupAsShown(kMarkedId, false);
// Stop blocking notifications, which should cause notifications to show as
// popups and in notifications center depending on their state.
blocker.SetPopupNotificationsEnabled(true);
blocker.SetNotificationsEnabled(true);
// Only the notification we did not mark should show as a popup.
NotificationList::PopupNotifications popups =
message_center()->GetPopupNotifications();
EXPECT_EQ(popups.size(), 1u);
EXPECT_TRUE(PopupNotificationsContain(popups, kNotMarkedId));
// Both notifications should be visible.
EXPECT_EQ(message_center()->GetNotifications().size(), 2u);
EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 2u);
}
TEST_F(MessageCenterImplTest, VisibleNotificationsWithoutBlocker) {
NotifierId notifier_id1(NotifierType::APPLICATION, /*id=*/"app1");
NotifierId notifier_id2(NotifierType::APPLICATION, /*id=*/"app2");
NearTotalNotificationBlocker blocker_1(message_center(), notifier_id1);
blocker_1.Init();
NearTotalNotificationBlocker blocker_2(message_center(), notifier_id2);
blocker_2.Init();
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id1, RichNotificationData(), nullptr));
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id2, RichNotificationData(), nullptr));
blocker_1.SetNotificationsEnabled(false);
blocker_2.SetNotificationsEnabled(false);
// Without blocker 1, notification 2 is visible.
NotificationList::Notifications notifications_1 =
message_center()->GetVisibleNotificationsWithoutBlocker(&blocker_1);
EXPECT_EQ(1u, notifications_1.size());
EXPECT_TRUE(NotificationsContain(notifications_1, "id2"));
// Without blocker 2, notification 1 is visible.
NotificationList::Notifications notifications_2 =
message_center()->GetVisibleNotificationsWithoutBlocker(&blocker_2);
EXPECT_EQ(1u, notifications_2.size());
EXPECT_TRUE(NotificationsContain(notifications_2, "id1"));
}
TEST_F(MessageCenterImplTest, PopupsWithoutBlocker) {
NotifierId notifier_id1(NotifierType::APPLICATION, "app1");
NotifierId notifier_id2(NotifierType::APPLICATION, "app2");
NotifierId notifier_id3(NotifierType::APPLICATION, "app3");
PopupNotificationBlocker blocker_1(message_center(), notifier_id1);
blocker_1.Init();
PopupNotificationBlocker blocker_2(message_center(), notifier_id2);
blocker_2.Init();
PopupNotificationBlocker blocker_3(message_center(), notifier_id3);
blocker_3.Init();
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id1, RichNotificationData(), nullptr));
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id2, RichNotificationData(), nullptr));
// Verify that the method doesn't mark popups as seen.
NotificationList::PopupNotifications initial_popups =
message_center()->GetPopupNotificationsWithoutBlocker(blocker_3);
NotificationList::PopupNotifications final_popups =
message_center()->GetPopupNotificationsWithoutBlocker(blocker_3);
EXPECT_EQ(2u, initial_popups.size());
EXPECT_TRUE(PopupNotificationsContain(initial_popups, "id1"));
EXPECT_TRUE(PopupNotificationsContain(initial_popups, "id2"));
EXPECT_EQ(initial_popups, final_popups);
blocker_1.SetPopupNotificationsEnabled(false);
blocker_2.SetPopupNotificationsEnabled(false);
// Without blocker 1, popup 2 can be seen.
NotificationList::PopupNotifications popups_1 =
message_center()->GetPopupNotificationsWithoutBlocker(blocker_1);
EXPECT_EQ(1u, popups_1.size());
EXPECT_TRUE(PopupNotificationsContain(popups_1, "id2"));
// Without blocker 2, popup 1 can be seen.
NotificationList::PopupNotifications popups_2 =
message_center()->GetPopupNotificationsWithoutBlocker(blocker_2);
EXPECT_EQ(1u, popups_2.size());
EXPECT_TRUE(PopupNotificationsContain(popups_2, "id1"));
}
TEST_F(MessageCenterImplTest, NotificationsDuringBlocked) {
NotifierId notifier_id(NotifierType::APPLICATION, "app1");
ToggledNotificationBlocker blocker(message_center());
blocker.Init();
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id, RichNotificationData(), nullptr));
EXPECT_EQ(1u, message_center()->GetPopupNotifications().size());
EXPECT_EQ(1u, message_center()->GetVisibleNotifications().size());
// "id1" is displayed as a pop-up so that it will be closed when blocked.
message_center()->DisplayedNotification("id1", DISPLAY_SOURCE_POPUP);
// Create a notification during blocked. Still no popups.
blocker.SetPopupNotificationsEnabled(false);
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id, RichNotificationData(), nullptr));
EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
// Unblock notifications, the id1 should appear as a popup.
blocker.SetPopupNotificationsEnabled(true);
NotificationList::PopupNotifications popups =
message_center()->GetPopupNotifications();
EXPECT_EQ(1u, popups.size());
EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
}
TEST_F(MessageCenterImplTest, GetNotifications) {
NotifierId notifier_id(NotifierType::APPLICATION, "app1");
ToggledNotificationBlocker blocker(message_center());
blocker.Init();
// Create a notification without any blockers.
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id, RichNotificationData(), nullptr));
EXPECT_EQ(1u, message_center()->GetPopupNotifications().size());
EXPECT_EQ(1u, message_center()->GetVisibleNotifications().size());
EXPECT_EQ(1u, message_center()->GetNotifications().size());
// Create a notification while blocking popup notifications.
blocker.SetPopupNotificationsEnabled(false);
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id, RichNotificationData(), nullptr));
EXPECT_EQ(0u, message_center()->GetPopupNotifications().size());
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
EXPECT_EQ(2u, message_center()->GetNotifications().size());
// Create a notification while any notification is blocked.
blocker.SetNotificationsEnabled(false);
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id3", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id, RichNotificationData(), nullptr));
EXPECT_EQ(0u, message_center()->GetPopupNotifications().size());
EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size());
EXPECT_EQ(3u, message_center()->GetNotifications().size());
// Allow non-popup notifications again.
blocker.SetNotificationsEnabled(true);
EXPECT_EQ(0u, message_center()->GetPopupNotifications().size());
EXPECT_EQ(3u, message_center()->GetVisibleNotifications().size());
EXPECT_EQ(3u, message_center()->GetNotifications().size());
// Allow popup notifications again.
blocker.SetPopupNotificationsEnabled(true);
EXPECT_EQ(3u, message_center()->GetPopupNotifications().size());
EXPECT_EQ(3u, message_center()->GetVisibleNotifications().size());
EXPECT_EQ(3u, message_center()->GetNotifications().size());
}
// Similar to other blocker cases but this test case allows |notifier_id2| even
// in blocked.
TEST_F(MessageCenterImplTest, NotificationBlockerAllowsPopups) {
NotifierId notifier_id1(NotifierType::APPLICATION, "app1");
NotifierId notifier_id2(NotifierType::APPLICATION, "app2");
PopupNotificationBlocker blocker(message_center(), notifier_id2);
blocker.Init();
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id1, RichNotificationData(), nullptr));
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id2, RichNotificationData(), nullptr));
// "id1" is displayed as a pop-up so that it will be closed when blocked.
message_center()->DisplayedNotification("id1", DISPLAY_SOURCE_POPUP);
// "id1" is closed but "id2" is still visible as a popup.
blocker.SetPopupNotificationsEnabled(false);
NotificationList::PopupNotifications popups =
message_center()->GetPopupNotifications();
EXPECT_EQ(1u, popups.size());
EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id3", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id1, RichNotificationData(), nullptr));
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id4", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id2, RichNotificationData(), nullptr));
popups = message_center()->GetPopupNotifications();
EXPECT_EQ(2u, popups.size());
EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
EXPECT_TRUE(PopupNotificationsContain(popups, "id4"));
EXPECT_EQ(4u, message_center()->GetVisibleNotifications().size());
blocker.SetPopupNotificationsEnabled(true);
popups = message_center()->GetPopupNotifications();
EXPECT_EQ(3u, popups.size());
EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
EXPECT_TRUE(PopupNotificationsContain(popups, "id3"));
EXPECT_TRUE(PopupNotificationsContain(popups, "id4"));
EXPECT_EQ(4u, message_center()->GetVisibleNotifications().size());
}
// NearTotalNotificationBlocker suppresses showing notifications even from the
// list. This would provide the feature to 'separated' message centers
// per-profile for ChromeOS multi-login.
TEST_F(MessageCenterImplTest, NearTotalNotificationBlocker) {
NotifierId notifier_id1(NotifierType::APPLICATION, "app1");
NotifierId notifier_id2(NotifierType::APPLICATION, "app2");
NearTotalNotificationBlocker blocker(message_center(), notifier_id2);
blocker.Init();
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id1, RichNotificationData(), nullptr));
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id2, RichNotificationData(), nullptr));
// "id1" becomes invisible while "id2" is still visible.
blocker.SetNotificationsEnabled(false);
EXPECT_EQ(1u, message_center()->NotificationCount());
NotificationList::Notifications notifications =
message_center()->GetVisibleNotifications();
EXPECT_FALSE(NotificationsContain(notifications, "id1"));
EXPECT_TRUE(NotificationsContain(notifications, "id2"));
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id3", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id1, RichNotificationData(), nullptr));
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id4", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id2, RichNotificationData(), nullptr));
EXPECT_EQ(2u, message_center()->NotificationCount());
notifications = message_center()->GetVisibleNotifications();
EXPECT_FALSE(NotificationsContain(notifications, "id1"));
EXPECT_TRUE(NotificationsContain(notifications, "id2"));
EXPECT_FALSE(NotificationsContain(notifications, "id3"));
EXPECT_TRUE(NotificationsContain(notifications, "id4"));
blocker.SetNotificationsEnabled(true);
EXPECT_EQ(4u, message_center()->NotificationCount());
notifications = message_center()->GetVisibleNotifications();
EXPECT_TRUE(NotificationsContain(notifications, "id1"));
EXPECT_TRUE(NotificationsContain(notifications, "id2"));
EXPECT_TRUE(NotificationsContain(notifications, "id3"));
EXPECT_TRUE(NotificationsContain(notifications, "id4"));
// Remove just visible notifications.
blocker.SetNotificationsEnabled(false);
message_center()->RemoveAllNotifications(
false /* by_user */, MessageCenter::RemoveType::NON_PINNED);
EXPECT_EQ(0u, message_center()->NotificationCount());
blocker.SetNotificationsEnabled(true);
EXPECT_EQ(2u, message_center()->NotificationCount());
notifications = message_center()->GetVisibleNotifications();
EXPECT_TRUE(NotificationsContain(notifications, "id1"));
EXPECT_FALSE(NotificationsContain(notifications, "id2"));
EXPECT_TRUE(NotificationsContain(notifications, "id3"));
EXPECT_FALSE(NotificationsContain(notifications, "id4"));
// And remove all including invisible notifications.
blocker.SetNotificationsEnabled(false);
message_center()->RemoveAllNotifications(false /* by_user */,
MessageCenter::RemoveType::ALL);
EXPECT_EQ(0u, message_center()->NotificationCount());
}
// Tests that notification state is updated when a notification blocker is
// added.
TEST_F(MessageCenterImplTest, NotificationsUpdatedWhenBlockerAdded) {
// Add a notification and display it as a popup.
NotifierId notifier_id1(NotifierType::APPLICATION, "app1");
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id1", notifier_id1.id));
message_center()->DisplayedNotification("id1", DISPLAY_SOURCE_POPUP);
// Verify that it is not blocked.
ASSERT_EQ(1u, message_center()->NotificationCount());
NotificationList::Notifications notifications =
message_center()->GetVisibleNotifications();
ASSERT_TRUE(NotificationsContain(notifications, "id1"));
NotificationList::PopupNotifications popups =
message_center()->GetPopupNotifications();
ASSERT_EQ(1u, popups.size());
ASSERT_TRUE(PopupNotificationsContain(popups, "id1"));
// Create a `NotificationBlocker` that blocks all notifications (even popups).
TotalNotificationBlocker blocker(message_center());
blocker.Init();
// Verify that "id1" is now blocked.
EXPECT_EQ(0u, message_center()->NotificationCount());
EXPECT_FALSE(
NotificationsContain(message_center()->GetVisibleNotifications(), "id1"));
popups = message_center()->GetPopupNotifications();
EXPECT_EQ(0u, popups.size());
EXPECT_FALSE(PopupNotificationsContain(popups, "id1"));
}
// Tests that notification state is updated when a notification blocker is
// removed.
TEST_F(MessageCenterImplTest, NotificationsUpdatedWhenBlockerRemoved) {
// Add two notifications and display them as popups.
NotifierId notifier_id1(NotifierType::APPLICATION, "app1");
NotifierId notifier_id2(NotifierType::APPLICATION, "app2");
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id1", notifier_id1.id));
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id2", notifier_id2.id));
message_center()->DisplayedNotification("id1", DISPLAY_SOURCE_POPUP);
message_center()->DisplayedNotification("id2", DISPLAY_SOURCE_POPUP);
// Verify that they are not blocked.
ASSERT_EQ(2u, message_center()->NotificationCount());
NotificationList::Notifications notifications =
message_center()->GetVisibleNotifications();
ASSERT_TRUE(NotificationsContain(notifications, "id1"));
ASSERT_TRUE(NotificationsContain(notifications, "id2"));
NotificationList::PopupNotifications popups =
message_center()->GetPopupNotifications();
ASSERT_EQ(2u, popups.size());
ASSERT_TRUE(PopupNotificationsContain(popups, "id1"));
ASSERT_TRUE(PopupNotificationsContain(popups, "id2"));
{
// Block all notifications, including popups (except those from
// `notifier_id2`).
NearTotalNotificationBlocker blocker(message_center(), notifier_id2);
blocker.Init();
blocker.SetNotificationsEnabled(false);
blocker.SetPopupNotificationsEnabled(false);
// Verify that "id1" is blocked and "id2" is not.
ASSERT_EQ(1u, message_center()->NotificationCount());
ASSERT_FALSE(NotificationsContain(
message_center()->GetVisibleNotifications(), "id1"));
ASSERT_TRUE(NotificationsContain(
message_center()->GetVisibleNotifications(), "id2"));
popups = message_center()->GetPopupNotifications();
ASSERT_EQ(1u, popups.size());
ASSERT_FALSE(PopupNotificationsContain(popups, "id1"));
ASSERT_TRUE(PopupNotificationsContain(popups, "id2"));
// Add a third notification.
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id3", notifier_id1.id));
message_center()->DisplayedNotification("id3", DISPLAY_SOURCE_POPUP);
// Verify that "id3" is blocked.
ASSERT_EQ(1u, message_center()->NotificationCount());
ASSERT_FALSE(NotificationsContain(
message_center()->GetVisibleNotifications(), "id3"));
popups = message_center()->GetPopupNotifications();
ASSERT_EQ(1u, popups.size());
ASSERT_FALSE(PopupNotificationsContain(popups, "id3"));
// Remove the blocker (it is removed in its dtor, which is called when
// exiting this scope).
}
// Verify that the notifications are not blocked, and in particular that "id2"
// is now shown as a popup since it didn't initially get to show as a popup.
EXPECT_EQ(3u, message_center()->NotificationCount());
notifications = message_center()->GetVisibleNotifications();
EXPECT_TRUE(NotificationsContain(notifications, "id1"));
EXPECT_TRUE(NotificationsContain(notifications, "id2"));
EXPECT_TRUE(NotificationsContain(notifications, "id3"));
popups = message_center()->GetPopupNotifications();
EXPECT_EQ(2u, popups.size());
EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
EXPECT_TRUE(PopupNotificationsContain(popups, "id3"));
}
TEST_F(MessageCenterImplTest, RemoveAllNotifications) {
NotifierId notifier_id1(NotifierType::APPLICATION, "app1");
NotifierId notifier_id2(NotifierType::APPLICATION, "app2");
NearTotalNotificationBlocker blocker(message_center(), notifier_id1);
blocker.Init();
blocker.SetNotificationsEnabled(false);
// Notification 1: Visible, non-pinned
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id1, RichNotificationData(), nullptr));
// Notification 2: Invisible, non-pinned
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id2, RichNotificationData(), nullptr));
// Remove all the notifications which are visible and non-pinned.
message_center()->RemoveAllNotifications(
false /* by_user */, MessageCenter::RemoveType::NON_PINNED);
EXPECT_EQ(0u, message_center()->NotificationCount());
blocker.SetNotificationsEnabled(true); // Show invisible notifications.
EXPECT_EQ(1u, message_center()->NotificationCount());
NotificationList::Notifications notifications =
message_center()->GetVisibleNotifications();
// Notification 1 should be removed.
EXPECT_FALSE(NotificationsContain(notifications, "id1"));
// Notification 2 shouldn't be removed since it was invisible.
EXPECT_TRUE(NotificationsContain(notifications, "id2"));
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(MessageCenterImplTest, RemoveAllNotificationsWithPinned) {
NotifierId notifier_id1(NotifierType::APPLICATION, "app1");
NotifierId notifier_id2(NotifierType::APPLICATION, "app2");
NearTotalNotificationBlocker blocker(message_center(), notifier_id1);
blocker.Init();
blocker.SetNotificationsEnabled(false);
// Notification 1: Visible, non-pinned
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id1, RichNotificationData(), nullptr));
// Notification 2: Invisible, non-pinned
message_center()->AddNotification(std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id2, RichNotificationData(), nullptr));
// Notification 3: Visible, pinned
auto notification3 = std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id3", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id1, RichNotificationData(), nullptr);
notification3->set_pinned(true);
message_center()->AddNotification(std::move(notification3));
// Notification 4: Invisible, pinned
auto notification4 = std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, "id4", u"title", u"message",
ui::ImageModel() /* icon */, std::u16string() /* display_source */,
GURL(), notifier_id2, RichNotificationData(), nullptr);
notification4->set_pinned(true);
message_center()->AddNotification(std::move(notification4));
// Remove all the notifications which are visible and non-pinned.
message_center()->RemoveAllNotifications(
false /* by_user */, MessageCenter::RemoveType::NON_PINNED);
EXPECT_EQ(1u, message_center()->NotificationCount());
blocker.SetNotificationsEnabled(true); // Show invisible notifications.
EXPECT_EQ(3u, message_center()->NotificationCount());
NotificationList::Notifications notifications =
message_center()->GetVisibleNotifications();
// Notification 1 should be removed.
EXPECT_FALSE(NotificationsContain(notifications, "id1"));
// Notification 2 shouldn't be removed since it was invisible.
EXPECT_TRUE(NotificationsContain(notifications, "id2"));
// Notification 3 shouldn't be removed since it was pinned.
EXPECT_TRUE(NotificationsContain(notifications, "id3"));
// Notification 4 shouldn't be removed since it was invisible and pinned.
EXPECT_TRUE(NotificationsContain(notifications, "id4"));
}
#endif
TEST_F(MessageCenterImplTest, NotifierEnabledChanged) {
ASSERT_EQ(0u, message_center()->NotificationCount());
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id1-1", "app1"));
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id1-2", "app1"));
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id1-3", "app1"));
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id2-1", "app2"));
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id2-2", "app2"));
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id2-3", "app2"));
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id2-4", "app2"));
message_center()->AddNotification(
CreateSimpleNotificationWithNotifierId("id2-5", "app2"));
ASSERT_EQ(8u, message_center()->NotificationCount());
// Removing all of app2's notifications should only leave app1's.
message_center()->RemoveNotificationsForNotifierId(
NotifierId(NotifierType::APPLICATION, "app2"));
ASSERT_EQ(3u, message_center()->NotificationCount());
// Removal operations should be idempotent.
message_center()->RemoveNotificationsForNotifierId(
NotifierId(NotifierType::APPLICATION, "app2"));
ASSERT_EQ(3u, message_center()->NotificationCount());
// Now we remove the remaining notifications.
message_center()->RemoveNotificationsForNotifierId(
NotifierId(NotifierType::APPLICATION, "app1"));
ASSERT_EQ(0u, message_center()->NotificationCount());
}
TEST_F(MessageCenterImplTest, UpdateWhileMessageCenterVisible) {
std::string id1("id1");
std::string id2("id2");
NotifierId notifier_id1(NotifierType::APPLICATION, "app1");
// First, add and update a notification to ensure updates happen
// normally.
std::unique_ptr<Notification> notification = CreateSimpleNotification(id1);
message_center()->AddNotification(std::move(notification));
notification = CreateSimpleNotification(id2);
message_center()->UpdateNotification(id1, std::move(notification));
EXPECT_TRUE(message_center()->FindVisibleNotificationById(id2));
EXPECT_FALSE(message_center()->FindVisibleNotificationById(id1));
// Then open the message center.
message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
// Then update a notification; the update should have propagated.
notification = CreateSimpleNotification(id1);
message_center()->UpdateNotification(id2, std::move(notification));
EXPECT_FALSE(message_center()->FindVisibleNotificationById(id2));
EXPECT_TRUE(message_center()->FindVisibleNotificationById(id1));
}
TEST_F(MessageCenterImplTest, AddWhileMessageCenterVisible) {
std::string id("id1");
// Then open the message center.
message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
// Add a notification and confirm the adding should have propagated.
std::unique_ptr<Notification> notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
EXPECT_TRUE(message_center()->FindVisibleNotificationById(id));
}
TEST_F(MessageCenterImplTest, RemoveWhileMessageCenterVisible) {
std::string id("id1");
// First, add a notification to ensure updates happen normally.
std::unique_ptr<Notification> notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
EXPECT_TRUE(message_center()->FindVisibleNotificationById(id));
// Then open the message center.
message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
// Then update a notification; the update should have propagated.
message_center()->RemoveNotification(id, false);
EXPECT_FALSE(message_center()->FindVisibleNotificationById(id));
}
TEST_F(MessageCenterImplTest, RemoveNonVisibleNotification) {
// Add two notifications.
message_center()->AddNotification(CreateSimpleNotification("id1"));
message_center()->AddNotification(CreateSimpleNotification("id2"));
EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
// Add a blocker to block all notifications.
NotifierId allowed_notifier_id(NotifierType::APPLICATION, "notifier");
NearTotalNotificationBlocker blocker(message_center(), allowed_notifier_id);
blocker.Init();
blocker.SetNotificationsEnabled(false);
EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size());
// Removing a non-visible notification should work.
message_center()->RemoveNotification("id1", false);
blocker.SetNotificationsEnabled(true);
EXPECT_EQ(1u, message_center()->GetVisibleNotifications().size());
// Also try removing a visible notification.
message_center()->RemoveNotification("id2", false);
EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size());
}
TEST_F(MessageCenterImplTest, RemoveInCloseHandler) {
const std::string id("id1");
// Create a notification that calls RemoveNotification() on close.
auto notification = CreateSimpleNotificationWithDelegate(
id, base::MakeRefCounted<DeleteOnCloseDelegate>(message_center(), id));
message_center()->AddNotification(std::move(notification));
EXPECT_TRUE(message_center()->FindVisibleNotificationById(id));
// Then remove the notification which calls RemoveNotification() reentrantly.
message_center()->RemoveNotification(id, true /* by_user */);
EXPECT_FALSE(message_center()->FindVisibleNotificationById(id));
}
// Regression test for https://crbug.com/1135709
TEST_F(MessageCenterImplTest, RemoveInCloseHandlerCloseAll) {
const std::string id1("id1");
const std::string id2("id2");
// Create two notifications that call RemoveNotification() on close.
auto notification1 = CreateSimpleNotificationWithDelegate(
id1, base::MakeRefCounted<DeleteOnCloseDelegate>(message_center(), id1));
auto notification2 = CreateSimpleNotificationWithDelegate(
id2, base::MakeRefCounted<DeleteOnCloseDelegate>(message_center(), id2));
message_center()->AddNotification(std::move(notification1));
message_center()->AddNotification(std::move(notification2));
EXPECT_TRUE(message_center()->FindVisibleNotificationById(id1));
EXPECT_TRUE(message_center()->FindVisibleNotificationById(id2));
// Then remove all notifications which calls RemoveNotification() reentrantly.
message_center()->RemoveAllNotifications(
true /* by_user */,
message_center::MessageCenter::RemoveType::NON_PINNED);
EXPECT_FALSE(message_center()->FindVisibleNotificationById(id1));
EXPECT_FALSE(message_center()->FindVisibleNotificationById(id2));
}
TEST_F(MessageCenterImplTest, FindNotificationsByAppId) {
message_center()->SetHasMessageCenterView(true);
const std::string app_id1("app_id1");
const std::string app_id2("app_id2");
{
// Add a notification for |app_id1|.
const std::string id1("id1");
std::unique_ptr<Notification> notification =
CreateNotificationWithNotifierId(id1, app_id1,
NOTIFICATION_TYPE_SIMPLE);
message_center()->AddNotification(std::move(notification));
EXPECT_EQ(1u, message_center()->FindNotificationsByAppId(app_id1).size());
// Mark the notification as shown but not read.
message_center()->MarkSinglePopupAsShown(id1, false);
EXPECT_EQ(1u, message_center()->FindNotificationsByAppId(app_id1).size());
// Mark the notification as shown and read.
message_center()->MarkSinglePopupAsShown(id1, true);
EXPECT_EQ(1u, message_center()->FindNotificationsByAppId(app_id1).size());
// Remove the notification.
message_center()->RemoveNotification(id1, true);
EXPECT_EQ(0u, message_center()->FindNotificationsByAppId(app_id1).size());
// Add two notifications for |app_id1|.
notification = CreateNotificationWithNotifierId(id1, app_id1,
NOTIFICATION_TYPE_SIMPLE);
message_center()->AddNotification(std::move(notification));
const std::string id2("id2");
notification = CreateNotificationWithNotifierId(id2, app_id1,
NOTIFICATION_TYPE_SIMPLE);
message_center()->AddNotification(std::move(notification));
EXPECT_EQ(2u, message_center()->FindNotificationsByAppId(app_id1).size());
// Remove |id2|,there should only be one notification for |app_id1|.
message_center()->RemoveNotification(id2, true);
EXPECT_EQ(1u, message_center()->FindNotificationsByAppId(app_id1).size());
// Add a notification for |app_id2|.
const std::string id3("id3");
notification = CreateNotificationWithNotifierId(id3, app_id2,
NOTIFICATION_TYPE_SIMPLE);
message_center()->AddNotification(std::move(notification));
EXPECT_EQ(1u, message_center()->FindNotificationsByAppId(app_id1).size());
EXPECT_EQ(1u, message_center()->FindNotificationsByAppId(app_id2).size());
}
for (std::string app_id : {app_id1, app_id2}) {
for (Notification* notification :
message_center()->FindNotificationsByAppId(app_id)) {
EXPECT_EQ(app_id, notification->notifier_id().id);
}
}
// Remove all notifications.
message_center()->RemoveAllNotifications(true,
MessageCenterImpl::RemoveType::ALL);
EXPECT_EQ(0u, message_center()->FindNotificationsByAppId(app_id1).size());
EXPECT_EQ(0u, message_center()->FindNotificationsByAppId(app_id2).size());
}
TEST_F(MessageCenterImplTest, QueueWhenCenterVisible) {
TestAddObserver observer(message_center());
message_center()->AddNotification(CreateSimpleNotification("n"));
message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
message_center()->AddNotification(CreateSimpleNotification("n2"));
// 'update-n' should happen since SetVisibility updates is_read status of n.
EXPECT_EQ("add-n_update-n", observer.log("n"));
message_center()->SetVisibility(VISIBILITY_TRANSIENT);
EXPECT_EQ("add-n2", observer.log("n2"));
}
TEST_F(MessageCenterImplTest, UpdateProgressNotificationWhenCenterVisible) {
TestAddObserver observer(message_center());
// Add a progress notification and update it while the message center
// is visible.
std::unique_ptr<Notification> notification = CreateSimpleNotification("n");
notification->set_type(NOTIFICATION_TYPE_PROGRESS);
Notification notification_copy = *notification;
message_center()->AddNotification(std::move(notification));
message_center()->ClickOnNotification("n");
message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
observer.reset_logs();
notification_copy.set_progress(50);
message_center()->UpdateNotification(
"n", std::make_unique<Notification>(notification_copy));
// Expect that the progress notification update is performed.
EXPECT_EQ("update-n", observer.log("n"));
}
TEST_F(MessageCenterImplTest, UpdateNonProgressNotificationWhenCenterVisible) {
TestAddObserver observer(message_center());
// Add a non-progress notification and update it while the message center
// is visible.
std::unique_ptr<Notification> notification = CreateSimpleNotification("n");
Notification notification_copy = *notification;
message_center()->AddNotification(std::move(notification));
message_center()->ClickOnNotification("n");
message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
observer.reset_logs();
notification_copy.set_title(u"title2");
message_center()->UpdateNotification(
notification_copy.id(),
std::make_unique<Notification>(notification_copy));
// Expect that the notification update is done.
EXPECT_NE("", observer.log("n"));
message_center()->SetVisibility(VISIBILITY_TRANSIENT);
EXPECT_EQ("update-n", observer.log("n"));
}
TEST_F(MessageCenterImplTest,
UpdateNonProgressToProgressNotificationWhenCenterVisible) {
TestAddObserver observer(message_center());
// Add a non-progress notification and change the type to progress while the
// message center is visible.
std::unique_ptr<Notification> notification = CreateSimpleNotification("n");
Notification notification_copy = *notification;
message_center()->AddNotification(std::move(notification));
message_center()->ClickOnNotification("n");
message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
observer.reset_logs();
notification_copy.set_type(NOTIFICATION_TYPE_PROGRESS);
message_center()->UpdateNotification(
"n", std::make_unique<Notification>(notification_copy));
// Expect that the notification update is done.
EXPECT_NE("", observer.log("n"));
message_center()->SetVisibility(VISIBILITY_TRANSIENT);
EXPECT_EQ("update-n", observer.log("n"));
}
TEST_F(MessageCenterImplTest, Click) {
TestAddObserver observer(message_center());
std::string id("n");
std::unique_ptr<Notification> notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
message_center()->ClickOnNotification(id);
EXPECT_EQ("Click_", GetDelegate(id)->log());
}
TEST_F(MessageCenterImplTest, ButtonClick) {
TestAddObserver observer(message_center());
std::string id("n");
std::unique_ptr<Notification> notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
message_center()->ClickOnNotificationButton(id, 1);
EXPECT_EQ("ButtonClick_1_", GetDelegate(id)->log());
}
TEST_F(MessageCenterImplTest, RemoveAfterClick) {
const std::string id = "n";
RichNotificationData notification_data;
ASSERT_FALSE(message_center()->FindNotificationById(id));
message_center()->AddNotification(
CreateSimpleNotificationWithOptionalFields(id, notification_data));
ASSERT_TRUE(message_center()->FindNotificationById(id));
message_center()->ClickOnNotification(id);
EXPECT_TRUE(message_center()->FindNotificationById(id));
message_center()->RemoveNotification(id, false);
ASSERT_FALSE(message_center()->FindNotificationById(id));
notification_data.remove_on_click = true;
message_center()->AddNotification(
CreateSimpleNotificationWithOptionalFields(id, notification_data));
ASSERT_TRUE(message_center()->FindNotificationById(id));
message_center()->ClickOnNotification(id);
EXPECT_FALSE(message_center()->FindNotificationById(id));
}
TEST_F(MessageCenterImplTest, RemoveAfterButtonClick) {
const std::string id = "n";
RichNotificationData notification_data;
notification_data.buttons.emplace_back(u"button");
message_center()->AddNotification(
CreateSimpleNotificationWithOptionalFields(id, notification_data));
ASSERT_TRUE(message_center()->FindNotificationById(id));
message_center()->ClickOnNotificationButton(id, 0);
EXPECT_TRUE(message_center()->FindNotificationById(id));
message_center()->RemoveNotification(id, false);
ASSERT_FALSE(message_center()->FindNotificationById(id));
notification_data.remove_on_click = true;
message_center()->AddNotification(
CreateSimpleNotificationWithOptionalFields(id, notification_data));
ASSERT_TRUE(message_center()->FindNotificationById(id));
message_center()->ClickOnNotificationButton(id, 0);
EXPECT_FALSE(message_center()->FindNotificationById(id));
}
TEST_F(MessageCenterImplTest, ButtonClickWithReply) {
TestAddObserver observer(message_center());
std::string id("n");
std::unique_ptr<Notification> notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
message_center()->ClickOnNotificationButtonWithReply(id, 1, u"REPLYTEXT");
EXPECT_EQ("ReplyButtonClick_1_REPLYTEXT_", GetDelegate(id)->log());
}
TEST_F(MessageCenterImplTest, Unlock) {
lock_screen_controller()->set_is_screen_locked(true);
EXPECT_FALSE(lock_screen_controller()->HasPendingCallback());
EXPECT_TRUE(lock_screen_controller()->IsScreenLocked());
lock_screen_controller()->SimulateUnlock();
EXPECT_FALSE(lock_screen_controller()->HasPendingCallback());
EXPECT_FALSE(lock_screen_controller()->IsScreenLocked());
lock_screen_controller()->set_is_screen_locked(true);
EXPECT_FALSE(lock_screen_controller()->HasPendingCallback());
EXPECT_TRUE(lock_screen_controller()->IsScreenLocked());
lock_screen_controller()->SimulateUnlock();
EXPECT_FALSE(lock_screen_controller()->HasPendingCallback());
EXPECT_FALSE(lock_screen_controller()->IsScreenLocked());
}
TEST_F(MessageCenterImplTest, ClickOnLockScreen) {
lock_screen_controller()->set_is_screen_locked(true);
TestAddObserver observer(message_center());
std::string id("n");
std::unique_ptr<Notification> notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
message_center()->ClickOnNotification(id);
EXPECT_EQ("", GetDelegate(id)->log());
EXPECT_TRUE(lock_screen_controller()->HasPendingCallback());
EXPECT_TRUE(lock_screen_controller()->IsScreenLocked());
lock_screen_controller()->SimulateUnlock();
EXPECT_EQ("Click_", GetDelegate(id)->log());
EXPECT_FALSE(lock_screen_controller()->HasPendingCallback());
EXPECT_FALSE(lock_screen_controller()->IsScreenLocked());
}
TEST_F(MessageCenterImplTest, ClickAndCancelOnLockScreen) {
lock_screen_controller()->set_is_screen_locked(true);
TestAddObserver observer(message_center());
std::string id("n");
std::unique_ptr<Notification> notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
message_center()->ClickOnNotification(id);
EXPECT_EQ("", GetDelegate(id)->log());
EXPECT_TRUE(lock_screen_controller()->HasPendingCallback());
EXPECT_TRUE(lock_screen_controller()->IsScreenLocked());
lock_screen_controller()->CancelClick();
EXPECT_EQ("", GetDelegate(id)->log());
EXPECT_FALSE(lock_screen_controller()->HasPendingCallback());
EXPECT_TRUE(lock_screen_controller()->IsScreenLocked());
lock_screen_controller()->SimulateUnlock();
EXPECT_EQ("", GetDelegate(id)->log());
EXPECT_FALSE(lock_screen_controller()->HasPendingCallback());
EXPECT_FALSE(lock_screen_controller()->IsScreenLocked());
}
TEST_F(MessageCenterImplTest, ButtonClickOnLockScreen) {
lock_screen_controller()->set_is_screen_locked(true);
TestAddObserver observer(message_center());
std::string id("n");
std::unique_ptr<Notification> notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
message_center()->ClickOnNotificationButton(id, 1);
EXPECT_EQ("", GetDelegate(id)->log());
EXPECT_TRUE(lock_screen_controller()->HasPendingCallback());
EXPECT_TRUE(lock_screen_controller()->IsScreenLocked());
lock_screen_controller()->SimulateUnlock();
EXPECT_EQ("ButtonClick_1_", GetDelegate(id)->log());
EXPECT_FALSE(lock_screen_controller()->HasPendingCallback());
EXPECT_FALSE(lock_screen_controller()->IsScreenLocked());
}
TEST_F(MessageCenterImplTest, ButtonClickWithReplyOnLockScreen) {
lock_screen_controller()->set_is_screen_locked(true);
TestAddObserver observer(message_center());
std::string id("n");
std::unique_ptr<Notification> notification = CreateSimpleNotification(id);
message_center()->AddNotification(std::move(notification));
message_center()->ClickOnNotificationButtonWithReply(id, 1, u"REPLYTEXT");
EXPECT_EQ("", GetDelegate(id)->log());
EXPECT_TRUE(lock_screen_controller()->HasPendingCallback());
EXPECT_TRUE(lock_screen_controller()->IsScreenLocked());
lock_screen_controller()->SimulateUnlock();
EXPECT_EQ("ReplyButtonClick_1_REPLYTEXT_", GetDelegate(id)->log());
EXPECT_FALSE(lock_screen_controller()->HasPendingCallback());
EXPECT_FALSE(lock_screen_controller()->IsScreenLocked());
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
class NotificationLimitMessageCenterImplTest : public MessageCenterImplTest {
public:
NotificationLimitMessageCenterImplTest() = default;
NotificationLimitMessageCenterImplTest(
const NotificationLimitMessageCenterImplTest&) = delete;
NotificationLimitMessageCenterImplTest& operator=(
const NotificationLimitMessageCenterImplTest&) = delete;
~NotificationLimitMessageCenterImplTest() override = default;
// MessageCenterImplTest:
void SetUp() override {
scoped_feature_list_.InitAndEnableFeature(
ash::features::kNotificationLimit);
MessageCenterImplTest::SetUp();
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
// Tests that the notification limit is respected, and the oldest notification
// (when priorities are equal) is removed first.
TEST_F(NotificationLimitMessageCenterImplTest, NotificationLimit) {
// Add to notifications until the limit is met.
size_t notifications_submitted = 0;
while (notifications_submitted <=
message_center()->GetNotifications().size()) {
message_center()->AddNotification(CreateSimpleNotification(
base::NumberToString(notifications_submitted++)));
}
// The oldest notification should have been removed, so the last notification
// will be the second one submitted.
EXPECT_EQ(base::NumberToString(1),
(*message_center()->GetNotifications().rbegin())->id());
size_t number_of_notifications = message_center()->GetNotifications().size();
// Add one more, the limit should be respected.
message_center()->AddNotification(CreateSimpleNotification(
base::NumberToString(notifications_submitted++)));
EXPECT_EQ(number_of_notifications,
message_center()->GetNotifications().size());
auto notifications = message_center()->GetNotifications();
}
// Tests that the oldest, lowest priority notification is removed first.
TEST_F(NotificationLimitMessageCenterImplTest,
NotificationLimitWithPriorities) {
// Add notifications so that the first few are chronologically in this order.
// {`SYSTEM_PRIORITY`, `SYSTEM_PRIORITY`, `MIN_PRIORITY`, `MAX_PRIORITY`,
// `DEFAULT_PRIORITY`}
std::string fourth_removed_notification_id = "oldest_system_priority";
auto oldest_system_priority_notification =
CreateSimpleNotification(fourth_removed_notification_id);
oldest_system_priority_notification->set_priority(
NotificationPriority ::SYSTEM_PRIORITY);
message_center()->AddNotification(
std::move(oldest_system_priority_notification));
std::string last_removed_notification_id = "second_oldest_system_priority";
auto second_oldest_system_priority_notification =
CreateSimpleNotification(last_removed_notification_id);
second_oldest_system_priority_notification->set_priority(
NotificationPriority ::SYSTEM_PRIORITY);
message_center()->AddNotification(
std::move(second_oldest_system_priority_notification));
std::string first_removed_notification_id =
"oldest_min_priority_notification";
auto oldest_min_priority_notification =
CreateSimpleNotification(first_removed_notification_id);
oldest_min_priority_notification->set_priority(
NotificationPriority ::MIN_PRIORITY);
message_center()->AddNotification(
std::move(oldest_min_priority_notification));
std::string third_removed_notification_id =
"oldest_max_priority_notification";
auto oldest_max_priority_notification =
CreateSimpleNotification(third_removed_notification_id);
oldest_max_priority_notification->set_priority(
NotificationPriority ::MAX_PRIORITY);
message_center()->AddNotification(
std::move(oldest_max_priority_notification));
std::string second_removed_notification_id =
"oldest_default_priority_notification";
auto oldest_default_priority_notification =
CreateSimpleNotification(second_removed_notification_id);
oldest_default_priority_notification->set_priority(
NotificationPriority ::DEFAULT_PRIORITY);
message_center()->AddNotification(
std::move(oldest_default_priority_notification));
size_t notifications_submitted = 5;
// Start adding more `SYSTEM_PRIORITY` notifications until the max is hit,
// then incrementally add more and ensure the notifications are deleted as
// expected.
while (notifications_submitted <=
message_center()->GetNotifications().size()) {
auto notification = CreateSimpleNotification(
base::NumberToString(notifications_submitted++));
notification->set_priority(NotificationPriority::SYSTEM_PRIORITY);
message_center()->AddNotification(std::move(notification));
}
EXPECT_FALSE(
message_center()->FindNotificationById(first_removed_notification_id));
EXPECT_TRUE(
message_center()->FindNotificationById(second_removed_notification_id));
EXPECT_TRUE(
message_center()->FindNotificationById(fourth_removed_notification_id));
EXPECT_TRUE(
message_center()->FindNotificationById(last_removed_notification_id));
EXPECT_TRUE(
message_center()->FindNotificationById(third_removed_notification_id));
auto notification =
CreateSimpleNotification(base::NumberToString(notifications_submitted++));
notification->set_priority(NotificationPriority::SYSTEM_PRIORITY);
message_center()->AddNotification(std::move(notification));
EXPECT_FALSE(
message_center()->FindNotificationById(second_removed_notification_id));
EXPECT_TRUE(
message_center()->FindNotificationById(last_removed_notification_id));
EXPECT_TRUE(
message_center()->FindNotificationById(third_removed_notification_id));
EXPECT_TRUE(
message_center()->FindNotificationById(fourth_removed_notification_id));
notification =
CreateSimpleNotification(base::NumberToString(notifications_submitted++));
notification->set_priority(NotificationPriority::SYSTEM_PRIORITY);
message_center()->AddNotification(std::move(notification));
EXPECT_FALSE(
message_center()->FindNotificationById(third_removed_notification_id));
EXPECT_TRUE(
message_center()->FindNotificationById(last_removed_notification_id));
EXPECT_TRUE(
message_center()->FindNotificationById(fourth_removed_notification_id));
notification =
CreateSimpleNotification(base::NumberToString(notifications_submitted++));
notification->set_priority(NotificationPriority::SYSTEM_PRIORITY);
message_center()->AddNotification(std::move(notification));
EXPECT_FALSE(
message_center()->FindNotificationById(fourth_removed_notification_id));
EXPECT_TRUE(
message_center()->FindNotificationById(last_removed_notification_id));
notification =
CreateSimpleNotification(base::NumberToString(notifications_submitted++));
notification->set_priority(NotificationPriority::SYSTEM_PRIORITY);
message_center()->AddNotification(std::move(notification));
EXPECT_FALSE(
message_center()->FindNotificationById(last_removed_notification_id));
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
} // namespace internal
} // namespace message_center