blob: 763d56e99319fd0a912dcc1ac383dd0706bed41a [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/notifications/notification_blocker.h"
#include "chrome/browser/notifications/notification_display_queue.h"
#include "chrome/browser/notifications/notification_display_service_impl.h"
#include "chrome/browser/notifications/notification_platform_bridge_delegator.h"
#include "chrome/browser/notifications/stub_notification_platform_bridge.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/public/cpp/notification_delegate.h"
#include "ui/message_center/public/cpp/notification_types.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h"
#endif
namespace {
class FakeNotificationBlocker : public NotificationBlocker {
public:
FakeNotificationBlocker() = default;
~FakeNotificationBlocker() override = default;
// NotificationDisplayQueue::NotificationBlocker:
bool ShouldBlockNotification(
const message_center::Notification& notification) override {
return should_block_;
}
void SetShouldBlockNotifications(bool should_block) {
should_block_ = should_block;
NotifyBlockingStateChanged();
}
private:
bool should_block_ = false;
};
class TestNotificationPlatformBridgeDelegator
: public NotificationPlatformBridgeDelegator {
public:
explicit TestNotificationPlatformBridgeDelegator(Profile* profile)
: NotificationPlatformBridgeDelegator(profile, base::DoNothing()) {}
~TestNotificationPlatformBridgeDelegator() override = default;
// NotificationPlatformBridgeDelegator:
void Display(
NotificationHandler::Type notification_type,
const message_center::Notification& notification,
std::unique_ptr<NotificationCommon::Metadata> metadata) override {
notification_ids_.insert(notification.id());
}
void Close(NotificationHandler::Type notification_type,
const std::string& notification_id) override {
notification_ids_.erase(notification_id);
}
void GetDisplayed(GetDisplayedNotificationsCallback callback) const override {
std::move(callback).Run(notification_ids_, /*supports_sync=*/true);
}
private:
std::set<std::string> notification_ids_;
};
message_center::Notification CreateNotification(const std::string& id) {
return message_center::Notification(
message_center::NOTIFICATION_TYPE_SIMPLE, id, /*title=*/std::u16string(),
/*message=*/std::u16string(), /*icon=*/gfx::Image(),
/*display_source=*/std::u16string(),
/*origin_url=*/GURL(), message_center::NotifierId(),
message_center::RichNotificationData(), /*delegate=*/nullptr);
}
} // namespace
class NotificationDisplayServiceImplTest : public testing::Test {
protected:
NotificationDisplayServiceImplTest() = default;
~NotificationDisplayServiceImplTest() override = default;
// BrowserWithTestWindowTest:
void SetUp() override {
TestingBrowserProcess* browser_process = TestingBrowserProcess::GetGlobal();
if (browser_process) {
browser_process->SetNotificationPlatformBridge(
std::make_unique<StubNotificationPlatformBridge>());
}
service_ = std::make_unique<NotificationDisplayServiceImpl>(&profile_);
auto notification_delegator =
std::make_unique<TestNotificationPlatformBridgeDelegator>(&profile_);
notification_delegator_ = notification_delegator.get();
service_->SetNotificationPlatformBridgeDelegatorForTesting(
std::move(notification_delegator));
auto blocker = std::make_unique<FakeNotificationBlocker>();
notification_blocker_ = blocker.get();
NotificationDisplayQueue::NotificationBlockers blockers;
blockers.push_back(std::move(blocker));
service_->SetBlockersForTesting(std::move(blockers));
}
Profile* profile() { return &profile_; }
NotificationDisplayServiceImpl& service() { return *service_; }
FakeNotificationBlocker& notification_blocker() {
return *notification_blocker_;
}
protected:
std::set<std::string> GetDisplayedServiceSync() {
std::set<std::string> displayed_ids;
base::RunLoop run_loop;
service_->GetDisplayed(
base::BindLambdaForTesting([&](std::set<std::string> notification_ids,
bool supports_synchronization) {
displayed_ids = std::move(notification_ids);
run_loop.Quit();
}));
run_loop.Run();
return displayed_ids;
}
std::set<std::string> GetDisplayedPlatformSync() {
std::set<std::string> displayed_ids;
base::RunLoop run_loop;
notification_delegator_->GetDisplayed(
base::BindLambdaForTesting([&](std::set<std::string> notification_ids,
bool supports_synchronization) {
displayed_ids = std::move(notification_ids);
run_loop.Quit();
}));
run_loop.Run();
return displayed_ids;
}
void DisplayNotification(const std::string id) {
service_->Display(NotificationHandler::Type::WEB_PERSISTENT,
CreateNotification(id), /*metadata=*/nullptr);
}
void CloseNotification(const std::string id) {
service_->Close(NotificationHandler::Type::WEB_PERSISTENT, id);
}
private:
content::BrowserTaskEnvironment task_environment_;
TestingProfile profile_;
std::unique_ptr<NotificationDisplayServiceImpl> service_;
TestNotificationPlatformBridgeDelegator* notification_delegator_ = nullptr;
FakeNotificationBlocker* notification_blocker_ = nullptr;
};
TEST_F(NotificationDisplayServiceImplTest, DisplayWithoutBlockers) {
service().SetBlockersForTesting({});
std::string notification_id = "id";
DisplayNotification(notification_id);
std::set<std::string> displayed = GetDisplayedServiceSync();
EXPECT_EQ(1u, displayed.size());
EXPECT_EQ(1u, displayed.count(notification_id));
EXPECT_EQ(displayed, GetDisplayedPlatformSync());
}
TEST_F(NotificationDisplayServiceImplTest, DisplayWithAllowingBlocker) {
std::string notification_id = "id";
DisplayNotification(notification_id);
std::set<std::string> displayed = GetDisplayedServiceSync();
EXPECT_EQ(1u, displayed.size());
EXPECT_EQ(1u, displayed.count(notification_id));
EXPECT_EQ(displayed, GetDisplayedPlatformSync());
}
TEST_F(NotificationDisplayServiceImplTest, DisplayWithBlockingBlocker) {
notification_blocker().SetShouldBlockNotifications(true);
std::string notification_id = "id";
DisplayNotification(notification_id);
std::set<std::string> displayed = GetDisplayedServiceSync();
EXPECT_EQ(1u, displayed.size());
EXPECT_EQ(1u, displayed.count(notification_id));
EXPECT_TRUE(GetDisplayedPlatformSync().empty());
}
TEST_F(NotificationDisplayServiceImplTest, UnblockQueuedNotification) {
notification_blocker().SetShouldBlockNotifications(true);
std::string notification_id = "id";
DisplayNotification(notification_id);
EXPECT_TRUE(GetDisplayedPlatformSync().empty());
notification_blocker().SetShouldBlockNotifications(false);
std::set<std::string> displayed = GetDisplayedServiceSync();
EXPECT_EQ(1u, displayed.size());
EXPECT_EQ(1u, displayed.count(notification_id));
EXPECT_EQ(displayed, GetDisplayedPlatformSync());
}
TEST_F(NotificationDisplayServiceImplTest, CloseQueuedNotification) {
notification_blocker().SetShouldBlockNotifications(true);
std::string notification_id = "id";
DisplayNotification(notification_id);
EXPECT_EQ(1u, GetDisplayedServiceSync().size());
EXPECT_TRUE(GetDisplayedPlatformSync().empty());
CloseNotification(notification_id);
EXPECT_TRUE(GetDisplayedServiceSync().empty());
EXPECT_TRUE(GetDisplayedPlatformSync().empty());
notification_blocker().SetShouldBlockNotifications(false);
EXPECT_TRUE(GetDisplayedServiceSync().empty());
EXPECT_TRUE(GetDisplayedPlatformSync().empty());
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(NotificationDisplayServiceImplTest, NearbyNotificationHandler) {
// Add the Nearby Share handler if and only if Nearby Share is supported.
{
NearbySharingServiceFactory::
SetIsNearbyShareSupportedForBrowserContextForTesting(false);
NotificationDisplayServiceImpl service(profile());
EXPECT_FALSE(service.GetNotificationHandler(
NotificationHandler::Type::NEARBY_SHARE));
}
{
NearbySharingServiceFactory::
SetIsNearbyShareSupportedForBrowserContextForTesting(true);
NotificationDisplayServiceImpl service(profile());
EXPECT_TRUE(service.GetNotificationHandler(
NotificationHandler::Type::NEARBY_SHARE));
}
}
#endif