Chromium Code Reviews| 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..7684d40d820a9c49465b968a58235757947df6f7 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 NotificationActionCallback = |
| + base::Callback<void(const ServiceWorkerRegistration*, |
| + const NotificationDatabaseData&)>; |
| +using CurriedNotificationActionCallback = |
| + base::Callback<void(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,12 +83,10 @@ 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 |
| +// 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, |
| @@ -92,12 +104,30 @@ void DispatchNotificationClickEventOnWorker( |
| 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( |
| +// 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, |
| - int action_index, |
| - const NotificationClickDispatchCompleteCallback& dispatch_complete_callback, |
| + 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)); |
| +} |
| + |
| +// 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, |
| + const scoped_refptr<PlatformNotificationContext> notification_context, |
| + const NotificationActionCallback& dispatch_event_action, |
| + const NotificationDispatchCompleteCallback& dispatch_error_callback, |
| ServiceWorkerStatusCode service_worker_status, |
| const scoped_refptr<ServiceWorkerRegistration>& |
| service_worker_registration) { |
| @@ -107,20 +137,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 +179,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, |
| + scoped_refptr<PlatformNotificationContext> notification_context, |
| + const NotificationActionCallback& notification_action_callback, |
| + const NotificationDispatchCompleteCallback& dispatch_error_callback, |
| bool success, |
| const NotificationDatabaseData& notification_database_data) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| @@ -174,22 +198,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"; |
| #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,15 +220,89 @@ 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) { |
| + scoped_refptr<PlatformNotificationContext> notification_context, |
| + const NotificationActionCallback& 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)); |
| +} |
| + |
| +// 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); |
| +} |
| + |
| +// 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); |
| +} |
| + |
| +// Called when the persistent notification close event has been handled |
| +// to remove the notification from the database. |
| +void OnDidDispatchNotificationCloseEvent( |
|
Nina
2016/01/27 18:48:58
Should we rename this to OnMaybeDidDispatchNotific
|
| + const int64_t notification_id, |
| + const GURL& origin, |
| + 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)); |
| +} |
| + |
| +// Actually dispatches the notification close event on the service worker |
| +// registration. |
| +void DoDispatchNotificationCloseEvent( |
| + bool by_user, |
| + const NotificationDispatchCompleteCallback& dispatch_complete_callback, |
| + scoped_refptr<PlatformNotificationContext> notification_context, |
| + const ServiceWorkerRegistration* service_worker_registration, |
| + const NotificationDatabaseData& notification_database_data) { |
| + const ServiceWorkerVersion::StatusCallback dispatch_event_callback = |
| + base::Bind(&OnDidDispatchNotificationCloseEvent, |
| + 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); |
| + } |
| } |
| } // namespace |
| @@ -221,17 +318,14 @@ NotificationEventDispatcherImpl::GetInstance() { |
| return base::Singleton<NotificationEventDispatcherImpl>::get(); |
| } |
| -NotificationEventDispatcherImpl::NotificationEventDispatcherImpl() {} |
| - |
| -NotificationEventDispatcherImpl::~NotificationEventDispatcherImpl() {} |
| - |
| -void NotificationEventDispatcherImpl::DispatchNotificationClickEvent( |
| +// 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 CurriedNotificationActionCallback& 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 +336,44 @@ 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)); |
| +} |
| + |
| +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 |