blob: 46ec45e8138098f21bdafd1f845a4a00b6bb5fde [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_chromeos.h"
#include <memory>
#include "base/callback_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/notifications/chrome_ash_message_center_client.h"
#include "chrome/browser/notifications/notification_display_service_factory.h"
#include "chrome/browser/notifications/notification_display_service_impl.h"
#include "chrome/browser/notifications/profile_notification.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_icon_loader.h"
#include "chrome/common/notifications/notification_operation.h"
#include "ui/gfx/image/image.h"
// static
std::unique_ptr<NotificationPlatformBridge>
NotificationPlatformBridge::Create() {
return std::make_unique<NotificationPlatformBridgeChromeOs>();
}
// static
bool NotificationPlatformBridge::CanHandleType(
NotificationHandler::Type notification_type) {
return true;
}
NotificationPlatformBridgeChromeOs::NotificationPlatformBridgeChromeOs()
: impl_(std::make_unique<ChromeAshMessageCenterClient>(this)) {}
NotificationPlatformBridgeChromeOs::~NotificationPlatformBridgeChromeOs() =
default;
void NotificationPlatformBridgeChromeOs::Display(
NotificationHandler::Type notification_type,
Profile* profile,
const message_center::Notification& notification,
std::unique_ptr<NotificationCommon::Metadata> metadata) {
auto active_notification = std::make_unique<ProfileNotification>(
profile, notification, notification_type);
impl_->Display(active_notification->type(), profile,
active_notification->notification(), std::move(metadata));
std::string profile_notification_id =
active_notification->notification().id();
active_notifications_.erase(profile_notification_id);
active_notifications_.emplace(profile_notification_id,
std::move(active_notification));
}
void NotificationPlatformBridgeChromeOs::Close(
Profile* profile,
const std::string& notification_id) {
const std::string profile_notification_id =
ProfileNotification::GetProfileNotificationId(
notification_id, ProfileNotification::GetProfileID(profile));
impl_->Close(profile, profile_notification_id);
}
void NotificationPlatformBridgeChromeOs::GetDisplayed(
Profile* profile,
GetDisplayedNotificationsCallback callback) const {
impl_->GetDisplayed(
profile,
base::BindOnce(&NotificationPlatformBridgeChromeOs::OnGetDisplayed,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void NotificationPlatformBridgeChromeOs::GetDisplayedForOrigin(
Profile* profile,
const GURL& origin,
GetDisplayedNotificationsCallback callback) const {
impl_->GetDisplayedForOrigin(
profile, origin,
base::BindOnce(&NotificationPlatformBridgeChromeOs::OnGetDisplayed,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void NotificationPlatformBridgeChromeOs::SetReadyCallback(
NotificationBridgeReadyCallback callback) {
impl_->SetReadyCallback(std::move(callback));
}
void NotificationPlatformBridgeChromeOs::DisplayServiceShutDown(
Profile* profile) {
// Notify delegates/handlers of the service shutdown and remove the
// notifications associated with the profile whose service is being destroyed.
// Otherwise Ash might asynchronously notify the bridge of operations on a
// notification associated with a profile that has already been destroyed).
std::list<std::string> ids_to_close;
for (const auto& iter : active_notifications_) {
if (iter.second->profile() == profile)
ids_to_close.push_back(iter.second->notification().id());
}
for (auto id : ids_to_close)
HandleNotificationClosed(id, false);
impl_->DisplayServiceShutDown(profile);
}
void NotificationPlatformBridgeChromeOs::HandleNotificationClosed(
const std::string& id,
bool by_user) {
auto iter = active_notifications_.find(id);
if (iter == active_notifications_.end())
return;
ProfileNotification* notification = iter->second.get();
if (notification->type() == NotificationHandler::Type::TRANSIENT) {
notification->notification().delegate()->Close(by_user);
} else {
NotificationDisplayServiceImpl::GetForProfile(notification->profile())
->ProcessNotificationOperation(
NotificationOperation::kClose, notification->type(),
notification->notification().origin_url(),
notification->original_id(), std::nullopt, std::nullopt, by_user,
base::DoNothing());
}
active_notifications_.erase(iter);
}
void NotificationPlatformBridgeChromeOs::HandleNotificationClicked(
const std::string& id) {
ProfileNotification* notification = GetProfileNotification(id);
if (!notification)
return;
if (notification->type() == NotificationHandler::Type::TRANSIENT) {
notification->notification().delegate()->Click(std::nullopt, std::nullopt);
} else {
NotificationDisplayServiceImpl::GetForProfile(notification->profile())
->ProcessNotificationOperation(
NotificationOperation::kClick, notification->type(),
notification->notification().origin_url(),
notification->original_id(), std::nullopt, std::nullopt,
std::nullopt, base::DoNothing());
}
}
void NotificationPlatformBridgeChromeOs::HandleNotificationButtonClicked(
const std::string& id,
int button_index,
const std::optional<std::u16string>& reply) {
ProfileNotification* notification = GetProfileNotification(id);
if (!notification)
return;
if (notification->type() == NotificationHandler::Type::TRANSIENT) {
notification->notification().delegate()->Click(button_index, reply);
} else {
NotificationDisplayServiceImpl::GetForProfile(notification->profile())
->ProcessNotificationOperation(
NotificationOperation::kClick, notification->type(),
notification->notification().origin_url(),
notification->original_id(), button_index, reply, std::nullopt,
base::DoNothing());
}
}
void NotificationPlatformBridgeChromeOs::
HandleNotificationSettingsButtonClicked(const std::string& id) {
ProfileNotification* notification = GetProfileNotification(id);
if (!notification)
return;
if (notification->type() == NotificationHandler::Type::TRANSIENT) {
notification->notification().delegate()->SettingsClick();
} else {
NotificationDisplayServiceImpl::GetForProfile(notification->profile())
->ProcessNotificationOperation(
NotificationOperation::kSettings, notification->type(),
notification->notification().origin_url(),
notification->original_id(), std::nullopt, std::nullopt,
std::nullopt, base::DoNothing());
}
}
void NotificationPlatformBridgeChromeOs::DisableNotification(
const std::string& id) {
ProfileNotification* notification = GetProfileNotification(id);
if (!notification)
return;
DCHECK_NE(NotificationHandler::Type::TRANSIENT, notification->type());
NotificationDisplayServiceImpl::GetForProfile(notification->profile())
->ProcessNotificationOperation(
NotificationOperation::kDisablePermission, notification->type(),
notification->notification().origin_url(),
notification->original_id(), std::nullopt, std::nullopt, std::nullopt,
base::DoNothing());
}
ProfileNotification* NotificationPlatformBridgeChromeOs::GetProfileNotification(
const std::string& profile_notification_id) {
auto iter = active_notifications_.find(profile_notification_id);
if (iter == active_notifications_.end())
return nullptr;
return iter->second.get();
}
void NotificationPlatformBridgeChromeOs::OnGetDisplayed(
GetDisplayedNotificationsCallback callback,
std::set<std::string> notification_ids,
bool supports_synchronization) const {
std::set<std::string> original_notification_ids;
for (const auto& id : notification_ids) {
auto iter = active_notifications_.find(id);
if (iter != active_notifications_.end())
original_notification_ids.insert(iter->second->original_id());
}
std::move(callback).Run(std::move(original_notification_ids),
supports_synchronization);
}