blob: 41c4ac8270c4990e0cc5df4f0700511066fc7d04 [file] [log] [blame]
// Copyright 2019 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 "content/browser/notifications/platform_notification_service_proxy.h"
#include <memory>
#include <utility>
#include "base/logging.h"
#include "base/task/post_task.h"
#include "content/browser/notifications/devtools_event_logging.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_database_data.h"
#include "content/public/browser/platform_notification_service.h"
namespace content {
PlatformNotificationServiceProxy::PlatformNotificationServiceProxy(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
BrowserContext* browser_context)
: service_worker_context_(service_worker_context),
browser_context_(browser_context),
notification_service_(
GetContentClient()->browser()->GetPlatformNotificationService(
browser_context)),
weak_ptr_factory_ui_(this),
weak_ptr_factory_io_(this) {}
PlatformNotificationServiceProxy::~PlatformNotificationServiceProxy() = default;
void PlatformNotificationServiceProxy::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
weak_ptr_factory_ui_.InvalidateWeakPtrs();
}
base::WeakPtr<PlatformNotificationServiceProxy>
PlatformNotificationServiceProxy::AsWeakPtr() {
return weak_ptr_factory_ui_.GetWeakPtr();
}
void PlatformNotificationServiceProxy::DoDisplayNotification(
const NotificationDatabaseData& data,
const GURL& service_worker_scope,
DisplayResultCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (notification_service_) {
notification_service_->DisplayPersistentNotification(
data.notification_id, service_worker_scope, data.origin,
data.notification_data,
data.notification_resources.value_or(blink::NotificationResources()));
notifications::LogNotificationDisplayedEventToDevTools(browser_context_,
data);
}
std::move(callback).Run(/* success= */ true, data.notification_id);
}
void PlatformNotificationServiceProxy::VerifyServiceWorkerScope(
const NotificationDatabaseData& data,
DisplayResultCallback callback,
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (status == blink::ServiceWorkerStatusCode::kOk &&
registration->scope().GetOrigin() == data.origin) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
base::BindOnce(&PlatformNotificationServiceProxy::DoDisplayNotification,
AsWeakPtr(), data, registration->scope(),
std::move(callback)));
} else {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
base::BindOnce(std::move(callback), /* success= */ false,
/* notification_id= */ ""));
}
}
void PlatformNotificationServiceProxy::DisplayNotification(
const NotificationDatabaseData& data,
DisplayResultCallback callback) {
if (!service_worker_context_) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
base::BindOnce(&PlatformNotificationServiceProxy::DoDisplayNotification,
AsWeakPtr(), data, GURL(), std::move(callback)));
return;
}
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO, base::TaskPriority::USER_VISIBLE},
base::BindOnce(
&ServiceWorkerContextWrapper::FindReadyRegistrationForId,
service_worker_context_, data.service_worker_registration_id,
data.origin,
base::BindOnce(
&PlatformNotificationServiceProxy::VerifyServiceWorkerScope,
weak_ptr_factory_io_.GetWeakPtr(), data, std::move(callback))));
}
void PlatformNotificationServiceProxy::CloseNotification(
const std::string& notification_id) {
if (!notification_service_)
return;
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
base::BindOnce(&PlatformNotificationServiceProxy::DoCloseNotification,
AsWeakPtr(), notification_id));
}
void PlatformNotificationServiceProxy::DoCloseNotification(
const std::string& notification_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
notification_service_->ClosePersistentNotification(notification_id);
}
void PlatformNotificationServiceProxy::ScheduleTrigger(base::Time timestamp) {
if (!notification_service_)
return;
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
base::BindOnce(&PlatformNotificationServiceProxy::DoScheduleTrigger,
AsWeakPtr(), timestamp));
}
void PlatformNotificationServiceProxy::DoScheduleTrigger(base::Time timestamp) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
notification_service_->ScheduleTrigger(timestamp);
}
void PlatformNotificationServiceProxy::ScheduleNotification(
const NotificationDatabaseData& data) {
DCHECK(data.notification_data.show_trigger_timestamp.has_value());
if (!notification_service_)
return;
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
base::BindOnce(&PlatformNotificationServiceProxy::DoScheduleNotification,
AsWeakPtr(), data));
}
void PlatformNotificationServiceProxy::DoScheduleNotification(
const NotificationDatabaseData& data) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::Time show_trigger_timestamp =
data.notification_data.show_trigger_timestamp.value();
notifications::LogNotificationScheduledEventToDevTools(
browser_context_, data, show_trigger_timestamp);
notification_service_->ScheduleTrigger(show_trigger_timestamp);
}
base::Time PlatformNotificationServiceProxy::GetNextTrigger() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!notification_service_)
return base::Time::Max();
return notification_service_->ReadNextTriggerTimestamp();
}
void PlatformNotificationServiceProxy::RecordNotificationUkmEvent(
const NotificationDatabaseData& data) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!notification_service_)
return;
notification_service_->RecordNotificationUkmEvent(data);
}
bool PlatformNotificationServiceProxy::ShouldLogClose(const GURL& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return notifications::ShouldLogNotificationEventToDevTools(browser_context_,
origin);
}
void PlatformNotificationServiceProxy::LogClose(
const NotificationDatabaseData& data) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI, base::TaskPriority::BEST_EFFORT},
base::BindOnce(&PlatformNotificationServiceProxy::DoLogClose, AsWeakPtr(),
data));
}
void PlatformNotificationServiceProxy::DoLogClose(
const NotificationDatabaseData& data) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
notifications::LogNotificationClosedEventToDevTools(browser_context_, data);
}
} // namespace content