| Index: content/browser/notifications/notification_event_dispatcher_impl.cc
|
| diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc
|
| index 06b822243795bf553b45c8367782d95a309661d9..ca125fa584f72a2b69200f8bb06381d684351903 100644
|
| --- a/content/browser/notifications/notification_event_dispatcher_impl.cc
|
| +++ b/content/browser/notifications/notification_event_dispatcher_impl.cc
|
| @@ -13,30 +13,44 @@
|
| #include "content/common/service_worker/service_worker_messages.h"
|
| #include "content/public/browser/browser_context.h"
|
| #include "content/public/browser/browser_thread.h"
|
| -#include "content/public/browser/notification_database_data.h"
|
| #include "content/public/browser/storage_partition.h"
|
| #include "content/public/common/platform_notification_data.h"
|
|
|
| namespace content {
|
| namespace {
|
|
|
| -using NotificationClickDispatchCompleteCallback =
|
| - NotificationEventDispatcher::NotificationClickDispatchCompleteCallback;
|
| +using NotificationDispatchCompleteCallback =
|
| + NotificationEventDispatcher::NotificationDispatchCompleteCallback;
|
| +using NotificationOperationCallback =
|
| + base::Callback<void(const ServiceWorkerRegistration*,
|
| + const NotificationDatabaseData&)>;
|
| +using NotificationOperationCallbackWithContext =
|
| + base::Callback<void(const scoped_refptr<PlatformNotificationContext>&,
|
| + const ServiceWorkerRegistration*,
|
| + const NotificationDatabaseData&)>;
|
|
|
| -// To be called when the notificationclick event has finished executing. Will
|
| -// post a task to call |dispatch_complete_callback| on the UI thread.
|
| -void NotificationClickEventFinished(
|
| - const NotificationClickDispatchCompleteCallback& dispatch_complete_callback,
|
| - const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
|
| - ServiceWorkerStatusCode service_worker_status) {
|
| +// To be called when a notification event has finished executing. Will post a
|
| +// task to call |dispatch_complete_callback| on the UI thread.
|
| +void NotificationEventFinished(
|
| + const NotificationDispatchCompleteCallback& dispatch_complete_callback,
|
| + PersistentNotificationStatus status) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| + base::Bind(dispatch_complete_callback, status));
|
| +}
|
| +
|
| +// To be called when a notification event has finished with a
|
| +// ServiceWorkerStatusCode result. Will call NotificationEventFinished with a
|
| +// PersistentNotificationStatus derived from the service worker status.
|
| +void ServiceWorkerNotificationEventFinished(
|
| + const NotificationDispatchCompleteCallback& dispatch_complete_callback,
|
| + ServiceWorkerStatusCode service_worker_status) {
|
| #if defined(OS_ANDROID)
|
| // This LOG(INFO) deliberately exists to help track down the cause of
|
| // https://crbug.com/534537, where notifications sometimes do not react to
|
| // the user clicking on them. It should be removed once that's fixed.
|
| - LOG(INFO) << "The notificationclick event has finished: "
|
| - << service_worker_status;
|
| + LOG(INFO) << "The notification event has finished: " << service_worker_status;
|
| #endif
|
|
|
| PersistentNotificationStatus status = PERSISTENT_NOTIFICATION_STATUS_SUCCESS;
|
| @@ -69,35 +83,17 @@ void NotificationClickEventFinished(
|
| status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR;
|
| break;
|
| }
|
| -
|
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| - base::Bind(dispatch_complete_callback, status));
|
| + NotificationEventFinished(dispatch_complete_callback, status);
|
| }
|
|
|
| -// Dispatches the notificationclick event on |service_worker|. Most be called on
|
| -// the IO thread, and with the worker running.
|
| -void DispatchNotificationClickEventOnWorker(
|
| - const scoped_refptr<ServiceWorkerVersion>& service_worker,
|
| +// Dispatches the given notification action event on
|
| +// |service_worker_registration| if the registration was available. Must be
|
| +// called on the IO thread.
|
| +void DispatchNotificationEventOnRegistration(
|
| const NotificationDatabaseData& notification_database_data,
|
| - int action_index,
|
| - const ServiceWorkerVersion::StatusCallback& callback) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - int request_id = service_worker->StartRequest(
|
| - ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK, callback);
|
| - service_worker->DispatchSimpleEvent<
|
| - ServiceWorkerHostMsg_NotificationClickEventFinished>(
|
| - request_id,
|
| - ServiceWorkerMsg_NotificationClickEvent(
|
| - request_id, notification_database_data.notification_id,
|
| - notification_database_data.notification_data, action_index));
|
| -}
|
| -
|
| -// Dispatches the notificationclick on |service_worker_registration| if the
|
| -// registration was available. Must be called on the IO thread.
|
| -void DispatchNotificationClickEventOnRegistration(
|
| - const NotificationDatabaseData& notification_database_data,
|
| - int action_index,
|
| - const NotificationClickDispatchCompleteCallback& dispatch_complete_callback,
|
| + const scoped_refptr<PlatformNotificationContext>& notification_context,
|
| + const NotificationOperationCallback& dispatch_event_action,
|
| + const NotificationDispatchCompleteCallback& dispatch_error_callback,
|
| ServiceWorkerStatusCode service_worker_status,
|
| const scoped_refptr<ServiceWorkerRegistration>&
|
| service_worker_registration) {
|
| @@ -107,20 +103,13 @@ void DispatchNotificationClickEventOnRegistration(
|
| // https://crbug.com/534537, where notifications sometimes do not react to
|
| // the user clicking on them. It should be removed once that's fixed.
|
| LOG(INFO) << "Trying to dispatch notification for SW with status: "
|
| - << service_worker_status << " action_index: " << action_index;
|
| + << service_worker_status;
|
| #endif
|
| if (service_worker_status == SERVICE_WORKER_OK) {
|
| - ServiceWorkerVersion::StatusCallback dispatch_event_callback =
|
| - base::Bind(&NotificationClickEventFinished, dispatch_complete_callback,
|
| - service_worker_registration);
|
| -
|
| DCHECK(service_worker_registration->active_version());
|
| - service_worker_registration->active_version()->RunAfterStartWorker(
|
| - base::Bind(
|
| - &DispatchNotificationClickEventOnWorker,
|
| - make_scoped_refptr(service_worker_registration->active_version()),
|
| - notification_database_data, action_index, dispatch_event_callback),
|
| - dispatch_event_callback);
|
| +
|
| + dispatch_event_action.Run(service_worker_registration.get(),
|
| + notification_database_data);
|
| return;
|
| }
|
|
|
| @@ -156,16 +145,17 @@ void DispatchNotificationClickEventOnRegistration(
|
| }
|
|
|
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| - base::Bind(dispatch_complete_callback, status));
|
| + base::Bind(dispatch_error_callback, status));
|
| }
|
|
|
| // Finds the ServiceWorkerRegistration associated with the |origin| and
|
| // |service_worker_registration_id|. Must be called on the IO thread.
|
| void FindServiceWorkerRegistration(
|
| const GURL& origin,
|
| - int action_index,
|
| - const NotificationClickDispatchCompleteCallback& dispatch_complete_callback,
|
| - scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
|
| + const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
|
| + const scoped_refptr<PlatformNotificationContext>& notification_context,
|
| + const NotificationOperationCallback& notification_action_callback,
|
| + const NotificationDispatchCompleteCallback& dispatch_error_callback,
|
| bool success,
|
| const NotificationDatabaseData& notification_database_data) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| @@ -174,22 +164,21 @@ void FindServiceWorkerRegistration(
|
| // This LOG(INFO) deliberately exists to help track down the cause of
|
| // https://crbug.com/534537, where notifications sometimes do not react to
|
| // the user clicking on them. It should be removed once that's fixed.
|
| - LOG(INFO) << "Lookup for ServiceWoker Registration: success:" << success
|
| - << " action_index: " << action_index;
|
| + LOG(INFO) << "Lookup for ServiceWoker Registration: success: " << success;
|
| #endif
|
| if (!success) {
|
| BrowserThread::PostTask(
|
| BrowserThread::UI, FROM_HERE,
|
| - base::Bind(dispatch_complete_callback,
|
| + base::Bind(dispatch_error_callback,
|
| PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR));
|
| return;
|
| }
|
|
|
| service_worker_context->FindReadyRegistrationForId(
|
| notification_database_data.service_worker_registration_id, origin,
|
| - base::Bind(&DispatchNotificationClickEventOnRegistration,
|
| - notification_database_data, action_index,
|
| - dispatch_complete_callback));
|
| + base::Bind(&DispatchNotificationEventOnRegistration,
|
| + notification_database_data, notification_context,
|
| + notification_action_callback, dispatch_error_callback));
|
| }
|
|
|
| // Reads the data associated with the |persistent_notification_id| belonging to
|
| @@ -197,41 +186,138 @@ void FindServiceWorkerRegistration(
|
| void ReadNotificationDatabaseData(
|
| int64_t persistent_notification_id,
|
| const GURL& origin,
|
| - int action_index,
|
| - const NotificationClickDispatchCompleteCallback& dispatch_complete_callback,
|
| - scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
|
| - scoped_refptr<PlatformNotificationContextImpl> notification_context) {
|
| + const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
|
| + const scoped_refptr<PlatformNotificationContext>& notification_context,
|
| + const NotificationOperationCallback& notification_read_callback,
|
| + const NotificationDispatchCompleteCallback& dispatch_error_callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| notification_context->ReadNotificationData(
|
| persistent_notification_id, origin,
|
| - base::Bind(&FindServiceWorkerRegistration, origin, action_index,
|
| - dispatch_complete_callback, service_worker_context));
|
| + base::Bind(&FindServiceWorkerRegistration, origin, service_worker_context,
|
| + notification_context, notification_read_callback,
|
| + dispatch_error_callback));
|
| }
|
|
|
| -} // namespace
|
| +// -----------------------------------------------------------------------------
|
|
|
| -// static
|
| -NotificationEventDispatcher* NotificationEventDispatcher::GetInstance() {
|
| - return NotificationEventDispatcherImpl::GetInstance();
|
| +// Dispatches the notificationclick event on |service_worker|. Must be called on
|
| +// the IO thread, and with the worker running.
|
| +void DispatchNotificationClickEventOnWorker(
|
| + const scoped_refptr<ServiceWorkerVersion>& service_worker,
|
| + const NotificationDatabaseData& notification_database_data,
|
| + int action_index,
|
| + const ServiceWorkerVersion::StatusCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + int request_id = service_worker->StartRequest(
|
| + ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK, callback);
|
| + service_worker->DispatchSimpleEvent<
|
| + ServiceWorkerHostMsg_NotificationClickEventFinished>(
|
| + request_id,
|
| + ServiceWorkerMsg_NotificationClickEvent(
|
| + request_id, notification_database_data.notification_id,
|
| + notification_database_data.notification_data, action_index));
|
| }
|
|
|
| -NotificationEventDispatcherImpl*
|
| -NotificationEventDispatcherImpl::GetInstance() {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| - return base::Singleton<NotificationEventDispatcherImpl>::get();
|
| +// Dispatches the notification click event on the |service_worker_registration|.
|
| +void DoDispatchNotificationClickEvent(
|
| + int action_index,
|
| + const NotificationDispatchCompleteCallback& dispatch_complete_callback,
|
| + const scoped_refptr<PlatformNotificationContext>& notification_context,
|
| + const ServiceWorkerRegistration* service_worker_registration,
|
| + const NotificationDatabaseData& notification_database_data) {
|
| + ServiceWorkerVersion::StatusCallback status_callback = base::Bind(
|
| + &ServiceWorkerNotificationEventFinished, dispatch_complete_callback);
|
| + service_worker_registration->active_version()->RunAfterStartWorker(
|
| + base::Bind(
|
| + &DispatchNotificationClickEventOnWorker,
|
| + make_scoped_refptr(service_worker_registration->active_version()),
|
| + notification_database_data, action_index, status_callback),
|
| + status_callback);
|
| }
|
|
|
| -NotificationEventDispatcherImpl::NotificationEventDispatcherImpl() {}
|
| +// -----------------------------------------------------------------------------
|
|
|
| -NotificationEventDispatcherImpl::~NotificationEventDispatcherImpl() {}
|
| +// Called when the notification data has been deleted to finish the notification
|
| +// close event.
|
| +void OnPersistentNotificationDataDeleted(
|
| + ServiceWorkerStatusCode service_worker_status,
|
| + const NotificationDispatchCompleteCallback& dispatch_complete_callback,
|
| + bool success) {
|
| + if (service_worker_status != SERVICE_WORKER_OK) {
|
| + ServiceWorkerNotificationEventFinished(dispatch_complete_callback,
|
| + service_worker_status);
|
| + return;
|
| + }
|
| + NotificationEventFinished(
|
| + dispatch_complete_callback,
|
| + success ? PERSISTENT_NOTIFICATION_STATUS_SUCCESS
|
| + : PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR);
|
| +}
|
|
|
| -void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
|
| +// Called when the persistent notification close event has been handled
|
| +// to remove the notification from the database.
|
| +void DeleteNotificationDataFromDatabase(
|
| + const int64_t notification_id,
|
| + const GURL& origin,
|
| + const scoped_refptr<PlatformNotificationContext>& notification_context,
|
| + const NotificationDispatchCompleteCallback& dispatch_complete_callback,
|
| + ServiceWorkerStatusCode status_code) {
|
| + notification_context->DeleteNotificationData(
|
| + notification_id, origin,
|
| + base::Bind(&OnPersistentNotificationDataDeleted, status_code,
|
| + dispatch_complete_callback));
|
| +}
|
| +
|
| +// Dispatches the notificationclose event on |service_worker|. Must be called on
|
| +// the IO thread, and with the worker running.
|
| +void DispatchNotificationCloseEventOnWorker(
|
| + const scoped_refptr<ServiceWorkerVersion>& service_worker,
|
| + const NotificationDatabaseData& notification_database_data,
|
| + const ServiceWorkerVersion::StatusCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + int request_id = service_worker->StartRequest(
|
| + ServiceWorkerMetrics::EventType::NOTIFICATION_CLOSE, callback);
|
| + service_worker->DispatchSimpleEvent<
|
| + ServiceWorkerHostMsg_NotificationCloseEventFinished>(
|
| + request_id, ServiceWorkerMsg_NotificationCloseEvent(
|
| + request_id, notification_database_data.notification_id,
|
| + notification_database_data.notification_data));
|
| +}
|
| +
|
| +// Actually dispatches the notification close event on the service worker
|
| +// registration.
|
| +void DoDispatchNotificationCloseEvent(
|
| + bool by_user,
|
| + const NotificationDispatchCompleteCallback& dispatch_complete_callback,
|
| + const scoped_refptr<PlatformNotificationContext>& notification_context,
|
| + const ServiceWorkerRegistration* service_worker_registration,
|
| + const NotificationDatabaseData& notification_database_data) {
|
| + const ServiceWorkerVersion::StatusCallback dispatch_event_callback =
|
| + base::Bind(&DeleteNotificationDataFromDatabase,
|
| + notification_database_data.notification_id,
|
| + notification_database_data.origin, notification_context,
|
| + dispatch_complete_callback);
|
| + if (by_user) {
|
| + service_worker_registration->active_version()->RunAfterStartWorker(
|
| + base::Bind(
|
| + &DispatchNotificationCloseEventOnWorker,
|
| + make_scoped_refptr(service_worker_registration->active_version()),
|
| + notification_database_data, dispatch_event_callback),
|
| + dispatch_event_callback);
|
| + } else {
|
| + dispatch_event_callback.Run(ServiceWorkerStatusCode::SERVICE_WORKER_OK);
|
| + }
|
| +}
|
| +
|
| +// Dispatches any notification event. The actual, specific event dispatch should
|
| +// be done by the |notification_action_callback|.
|
| +void DispatchNotificationEvent(
|
| BrowserContext* browser_context,
|
| int64_t persistent_notification_id,
|
| const GURL& origin,
|
| - int action_index,
|
| - const NotificationClickDispatchCompleteCallback&
|
| - dispatch_complete_callback) {
|
| + const NotificationOperationCallbackWithContext&
|
| + notification_action_callback,
|
| + const NotificationDispatchCompleteCallback& notification_error_callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| DCHECK_GT(persistent_notification_id, 0);
|
| DCHECK(origin.is_valid());
|
| @@ -242,15 +328,57 @@ void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
|
| scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
|
| static_cast<ServiceWorkerContextWrapper*>(
|
| partition->GetServiceWorkerContext());
|
| - scoped_refptr<PlatformNotificationContextImpl> notification_context =
|
| - static_cast<PlatformNotificationContextImpl*>(
|
| - partition->GetPlatformNotificationContext());
|
| + scoped_refptr<PlatformNotificationContext> notification_context =
|
| + partition->GetPlatformNotificationContext();
|
|
|
| BrowserThread::PostTask(
|
| BrowserThread::IO, FROM_HERE,
|
| base::Bind(&ReadNotificationDatabaseData, persistent_notification_id,
|
| - origin, action_index, dispatch_complete_callback,
|
| - service_worker_context, notification_context));
|
| + origin, service_worker_context, notification_context,
|
| + base::Bind(notification_action_callback, notification_context),
|
| + notification_error_callback));
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +NotificationEventDispatcher* NotificationEventDispatcher::GetInstance() {
|
| + return NotificationEventDispatcherImpl::GetInstance();
|
| +}
|
| +
|
| +NotificationEventDispatcherImpl*
|
| +NotificationEventDispatcherImpl::GetInstance() {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + return base::Singleton<NotificationEventDispatcherImpl>::get();
|
| +}
|
| +
|
| +NotificationEventDispatcherImpl::NotificationEventDispatcherImpl() {}
|
| +
|
| +NotificationEventDispatcherImpl::~NotificationEventDispatcherImpl() {}
|
| +
|
| +void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
|
| + BrowserContext* browser_context,
|
| + int64_t persistent_notification_id,
|
| + const GURL& origin,
|
| + int action_index,
|
| + const NotificationDispatchCompleteCallback& dispatch_complete_callback) {
|
| + DispatchNotificationEvent(
|
| + browser_context, persistent_notification_id, origin,
|
| + base::Bind(&DoDispatchNotificationClickEvent, action_index,
|
| + dispatch_complete_callback),
|
| + dispatch_complete_callback);
|
| +}
|
| +
|
| +void NotificationEventDispatcherImpl::DispatchNotificationCloseEvent(
|
| + BrowserContext* browser_context,
|
| + int64_t persistent_notification_id,
|
| + const GURL& origin,
|
| + bool by_user,
|
| + const NotificationDispatchCompleteCallback& dispatch_complete_callback) {
|
| + DispatchNotificationEvent(browser_context, persistent_notification_id, origin,
|
| + base::Bind(&DoDispatchNotificationCloseEvent,
|
| + by_user, dispatch_complete_callback),
|
| + dispatch_complete_callback);
|
| }
|
|
|
| } // namespace content
|
|
|