summaryrefslogtreecommitdiffstats
path: root/content/browser/notifications
diff options
context:
space:
mode:
authornsatragno <nsatragno@chromium.org>2016-02-05 04:55:09 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-05 12:56:48 +0000
commit2f82b23b3572d1fb653d971ee9b5e0232c4b37e5 (patch)
tree25fbfd18a4f56e7fda390c464c77494e56532ebd /content/browser/notifications
parentd17a433e9635ed48248c8b63e24833075df47afc (diff)
downloadchromium_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.cc294
-rw-r--r--content/browser/notifications/notification_event_dispatcher_impl.h12
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();