blob: cdc971b28fac28d9bedd19e7f1ed7944f0c99a2f [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/notifications/notification_platform_bridge_message_center.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/notifications/notification_display_service_impl.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/notifications/profile_notification.h"
#include "chrome/common/notifications/notification_operation.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "ui/message_center/public/cpp/notification.h"
namespace {
// A NotificationDelegate that passes through click actions to the notification
// display service (and on to the appropriate handler). This is a temporary
// class to ease the transition from NotificationDelegate to
// NotificationHandler.
// TODO(estade): also handle other NotificationDelegate actions as needed.
class PassThroughDelegate : public message_center::NotificationDelegate {
public:
PassThroughDelegate(Profile* profile,
const message_center::Notification& notification,
NotificationHandler::Type notification_type)
: profile_(profile),
notification_(notification),
notification_type_(notification_type) {
DCHECK_NE(notification_type, NotificationHandler::Type::TRANSIENT);
}
PassThroughDelegate(const PassThroughDelegate&) = delete;
PassThroughDelegate& operator=(const PassThroughDelegate&) = delete;
void SettingsClick() override {
NotificationDisplayServiceImpl::GetForProfile(profile_)
->ProcessNotificationOperation(
NotificationOperation::kSettings, notification_type_,
notification_.origin_url(), notification_.id(), std::nullopt,
std::nullopt, std::nullopt /* by_user */, base::DoNothing());
}
void DisableNotification() override {
NotificationDisplayServiceImpl::GetForProfile(profile_)
->ProcessNotificationOperation(
NotificationOperation::kDisablePermission, notification_type_,
notification_.origin_url(), notification_.id(),
std::nullopt /* action_index */, std::nullopt /* reply */,
std::nullopt /* by_user */, base::DoNothing());
}
void Close(bool by_user) override {
NotificationDisplayServiceImpl::GetForProfile(profile_)
->ProcessNotificationOperation(
NotificationOperation::kClose, notification_type_,
notification_.origin_url(), notification_.id(),
std::nullopt /* action_index */, std::nullopt /* reply */, by_user,
base::DoNothing());
}
void Click(const std::optional<int>& button_index,
const std::optional<std::u16string>& reply) override {
NotificationDisplayServiceImpl::GetForProfile(profile_)
->ProcessNotificationOperation(
NotificationOperation::kClick, notification_type_,
notification_.origin_url(), notification_.id(), button_index, reply,
std::nullopt /* by_user */, base::DoNothing());
}
protected:
~PassThroughDelegate() override = default;
private:
raw_ptr<Profile> profile_;
message_center::Notification notification_;
NotificationHandler::Type notification_type_;
};
} // namespace
// static
NotificationPlatformBridgeMessageCenter*
NotificationPlatformBridgeMessageCenter::Get() {
static base::NoDestructor<NotificationPlatformBridgeMessageCenter> instance;
return instance.get();
}
NotificationPlatformBridgeMessageCenter::
NotificationPlatformBridgeMessageCenter() = default;
NotificationPlatformBridgeMessageCenter::
~NotificationPlatformBridgeMessageCenter() = default;
void NotificationPlatformBridgeMessageCenter::Display(
NotificationHandler::Type notification_type,
Profile* profile,
const message_center::Notification& notification,
std::unique_ptr<NotificationCommon::Metadata> /* metadata */) {
NotificationUIManager* ui_manager =
g_browser_process->notification_ui_manager();
if (!ui_manager)
return; // The process is shutting down.
if (notification.delegate() ||
notification_type == NotificationHandler::Type::TRANSIENT) {
ui_manager->Add(notification, profile);
return;
}
// If there's no delegate, replace it with a PassThroughDelegate so clicks
// go back to the appropriate handler.
message_center::Notification notification_with_delegate(notification);
notification_with_delegate.set_delegate(base::WrapRefCounted(
new PassThroughDelegate(profile, notification, notification_type)));
ui_manager->Add(notification_with_delegate, profile);
}
void NotificationPlatformBridgeMessageCenter::Close(
Profile* profile,
const std::string& notification_id) {
NotificationUIManager* ui_manager =
g_browser_process->notification_ui_manager();
if (!ui_manager)
return; // the process is shutting down
ui_manager->CancelById(notification_id,
ProfileNotification::GetProfileID(profile));
}
void NotificationPlatformBridgeMessageCenter::GetDisplayed(
Profile* profile,
GetDisplayedNotificationsCallback callback) const {
std::set<std::string> displayed_notifications;
NotificationUIManager* ui_manager =
g_browser_process->notification_ui_manager();
if (ui_manager) {
displayed_notifications = ui_manager->GetAllIdsByProfile(
ProfileNotification::GetProfileID(profile));
}
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), std::move(displayed_notifications),
true /* supports_synchronization */));
}
void NotificationPlatformBridgeMessageCenter::GetDisplayedForOrigin(
Profile* profile,
const GURL& origin,
GetDisplayedNotificationsCallback callback) const {
std::set<std::string> displayed_notifications;
NotificationUIManager* ui_manager =
g_browser_process->notification_ui_manager();
if (ui_manager) {
displayed_notifications = ui_manager->GetAllIdsByProfileAndOrigin(
ProfileNotification::GetProfileID(profile), origin);
}
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), std::move(displayed_notifications),
true /* supports_synchronization */));
}
void NotificationPlatformBridgeMessageCenter::SetReadyCallback(
NotificationBridgeReadyCallback callback) {
std::move(callback).Run(true /* success */);
}
void NotificationPlatformBridgeMessageCenter::DisplayServiceShutDown(
Profile* profile) {}