diff options
author | nsatragno <nsatragno@chromium.org> | 2016-02-05 04:55:09 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-05 12:56:48 +0000 |
commit | 2f82b23b3572d1fb653d971ee9b5e0232c4b37e5 (patch) | |
tree | 25fbfd18a4f56e7fda390c464c77494e56532ebd /content/browser/notifications | |
parent | d17a433e9635ed48248c8b63e24833075df47afc (diff) | |
download | chromium_src-2f82b23b3572d1fb653d971ee9b5e0232c4b37e5.zip chromium_src-2f82b23b3572d1fb653d971ee9b5e0232c4b37e5.tar.gz chromium_src-2f82b23b3572d1fb653d971ee9b5e0232c4b37e5.tar.bz2 |
Implement notificationclose event
This patch introduces a notificationclose event fired in the service
worker when a notification has been closed by the user.
Layout tests to come in a follow-up patch:
https://codereview.chromium.org/1656823002/
Intent to Implement and Ship:
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/fePanzKy6ec
BUG=579150
TEST=PlatformNotificationServiceBrowserTest.UserClosesPersistentNotification
Review URL: https://codereview.chromium.org/1619703002
Cr-Commit-Position: refs/heads/master@{#373799}
Diffstat (limited to 'content/browser/notifications')
-rw-r--r-- | content/browser/notifications/notification_event_dispatcher_impl.cc | 294 | ||||
-rw-r--r-- | content/browser/notifications/notification_event_dispatcher_impl.h | 12 |
2 files changed, 221 insertions, 85 deletions
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc index 06b8222..ca125fa 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 diff --git a/content/browser/notifications/notification_event_dispatcher_impl.h b/content/browser/notifications/notification_event_dispatcher_impl.h index fbc5d42..fc19dc9 100644 --- a/content/browser/notifications/notification_event_dispatcher_impl.h +++ b/content/browser/notifications/notification_event_dispatcher_impl.h @@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/memory/singleton.h" +#include "content/public/browser/notification_database_data.h" #include "content/public/browser/notification_event_dispatcher.h" namespace content { @@ -25,8 +26,15 @@ class NotificationEventDispatcherImpl : public NotificationEventDispatcher { int64_t persistent_notification_id, const GURL& origin, int action_index, - const NotificationClickDispatchCompleteCallback& - dispatch_complete_callback) override; + const NotificationDispatchCompleteCallback& dispatch_complete_callback) + override; + void DispatchNotificationCloseEvent( + BrowserContext* browser_context, + int64_t persistent_notification_id, + const GURL& origin, + bool by_user, + const NotificationDispatchCompleteCallback& dispatch_complete_callback) + override; private: NotificationEventDispatcherImpl(); |