1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/notifications/notification_event_dispatcher_impl.h"
7 #include "base/callback.h"
8 #include "content/browser/notifications/platform_notification_context_impl.h"
9 #include "content/browser/service_worker/service_worker_context_wrapper.h"
10 #include "content/browser/service_worker/service_worker_registration.h"
11 #include "content/browser/service_worker/service_worker_storage.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/notification_database_data.h"
15 #include "content/public/browser/storage_partition.h"
16 #include "content/public/common/platform_notification_data.h"
21 using NotificationClickDispatchCompleteCallback
=
22 NotificationEventDispatcher::NotificationClickDispatchCompleteCallback
;
24 // To be called when the notificationclick event has finished executing. Will
25 // post a task to call |dispatch_complete_callback| on the UI thread.
26 void NotificationClickEventFinished(
27 const NotificationClickDispatchCompleteCallback
& dispatch_complete_callback
,
28 const scoped_refptr
<ServiceWorkerRegistration
>& service_worker_registration
,
29 ServiceWorkerStatusCode service_worker_status
) {
30 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
32 PersistentNotificationStatus status
= PERSISTENT_NOTIFICATION_STATUS_SUCCESS
;
33 switch (service_worker_status
) {
34 case SERVICE_WORKER_OK
:
35 // Success status was initialized above.
37 case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED
:
38 status
= PERSISTENT_NOTIFICATION_STATUS_EVENT_WAITUNTIL_REJECTED
;
40 case SERVICE_WORKER_ERROR_FAILED
:
41 case SERVICE_WORKER_ERROR_ABORT
:
42 case SERVICE_WORKER_ERROR_START_WORKER_FAILED
:
43 case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND
:
44 case SERVICE_WORKER_ERROR_NOT_FOUND
:
45 case SERVICE_WORKER_ERROR_EXISTS
:
46 case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
:
47 case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED
:
48 case SERVICE_WORKER_ERROR_IPC_FAILED
:
49 case SERVICE_WORKER_ERROR_NETWORK
:
50 case SERVICE_WORKER_ERROR_SECURITY
:
51 case SERVICE_WORKER_ERROR_STATE
:
52 case SERVICE_WORKER_ERROR_TIMEOUT
:
53 case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED
:
54 case SERVICE_WORKER_ERROR_MAX_VALUE
:
55 status
= PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR
;
59 BrowserThread::PostTask(BrowserThread::UI
,
61 base::Bind(dispatch_complete_callback
, status
));
64 // Dispatches the notificationclick on |service_worker_registration| if the
65 // registration was available. Must be called on the IO thread.
66 void DispatchNotificationClickEventOnRegistration(
67 const NotificationDatabaseData
& notification_database_data
,
68 const NotificationClickDispatchCompleteCallback
& dispatch_complete_callback
,
69 ServiceWorkerStatusCode service_worker_status
,
70 const scoped_refptr
<ServiceWorkerRegistration
>&
71 service_worker_registration
) {
72 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
73 if (service_worker_status
== SERVICE_WORKER_OK
) {
74 base::Callback
<void(ServiceWorkerStatusCode
)> dispatch_event_callback
=
75 base::Bind(&NotificationClickEventFinished
,
76 dispatch_complete_callback
,
77 service_worker_registration
);
79 service_worker_registration
->active_version()->
80 DispatchNotificationClickEvent(
81 dispatch_event_callback
,
82 notification_database_data
.notification_id
,
83 notification_database_data
.notification_data
);
87 PersistentNotificationStatus status
= PERSISTENT_NOTIFICATION_STATUS_SUCCESS
;
88 switch (service_worker_status
) {
89 case SERVICE_WORKER_ERROR_NOT_FOUND
:
90 status
= PERSISTENT_NOTIFICATION_STATUS_NO_SERVICE_WORKER
;
92 case SERVICE_WORKER_ERROR_FAILED
:
93 case SERVICE_WORKER_ERROR_ABORT
:
94 case SERVICE_WORKER_ERROR_START_WORKER_FAILED
:
95 case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND
:
96 case SERVICE_WORKER_ERROR_EXISTS
:
97 case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
:
98 case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED
:
99 case SERVICE_WORKER_ERROR_IPC_FAILED
:
100 case SERVICE_WORKER_ERROR_NETWORK
:
101 case SERVICE_WORKER_ERROR_SECURITY
:
102 case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED
:
103 case SERVICE_WORKER_ERROR_STATE
:
104 case SERVICE_WORKER_ERROR_TIMEOUT
:
105 case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED
:
106 case SERVICE_WORKER_ERROR_MAX_VALUE
:
107 status
= PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR
;
109 case SERVICE_WORKER_OK
:
114 BrowserThread::PostTask(BrowserThread::UI
,
116 base::Bind(dispatch_complete_callback
, status
));
119 // Finds the ServiceWorkerRegistration associated with the |origin| and
120 // |service_worker_registration_id|. Must be called on the IO thread.
121 void FindServiceWorkerRegistration(
123 const NotificationClickDispatchCompleteCallback
& dispatch_complete_callback
,
124 scoped_refptr
<ServiceWorkerContextWrapper
> service_worker_context
,
126 const NotificationDatabaseData
& notification_database_data
) {
127 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
129 BrowserThread::PostTask(
132 base::Bind(dispatch_complete_callback
,
133 PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR
));
137 service_worker_context
->FindRegistrationForId(
138 notification_database_data
.service_worker_registration_id
,
140 base::Bind(&DispatchNotificationClickEventOnRegistration
,
141 notification_database_data
,
142 dispatch_complete_callback
));
145 // Reads the data associated with the |persistent_notification_id| belonging to
146 // |origin| from the notification context.
147 void ReadNotificationDatabaseData(
148 int64_t persistent_notification_id
,
150 const NotificationClickDispatchCompleteCallback
& dispatch_complete_callback
,
151 scoped_refptr
<ServiceWorkerContextWrapper
> service_worker_context
,
152 scoped_refptr
<PlatformNotificationContextImpl
> notification_context
) {
153 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
154 notification_context
->ReadNotificationData(
155 persistent_notification_id
,
157 base::Bind(&FindServiceWorkerRegistration
,
158 origin
, dispatch_complete_callback
, service_worker_context
));
164 NotificationEventDispatcher
* NotificationEventDispatcher::GetInstance() {
165 return NotificationEventDispatcherImpl::GetInstance();
168 NotificationEventDispatcherImpl
*
169 NotificationEventDispatcherImpl::GetInstance() {
170 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
171 return Singleton
<NotificationEventDispatcherImpl
>::get();
174 NotificationEventDispatcherImpl::NotificationEventDispatcherImpl() {}
176 NotificationEventDispatcherImpl::~NotificationEventDispatcherImpl() {}
178 void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
179 BrowserContext
* browser_context
,
180 int64_t persistent_notification_id
,
182 const NotificationClickDispatchCompleteCallback
&
183 dispatch_complete_callback
) {
184 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
185 DCHECK_GT(persistent_notification_id
, 0);
186 DCHECK(origin
.is_valid());
188 StoragePartition
* partition
=
189 BrowserContext::GetStoragePartitionForSite(browser_context
, origin
);
191 scoped_refptr
<ServiceWorkerContextWrapper
> service_worker_context
=
192 static_cast<ServiceWorkerContextWrapper
*>(
193 partition
->GetServiceWorkerContext());
194 scoped_refptr
<PlatformNotificationContextImpl
> notification_context
=
195 static_cast<PlatformNotificationContextImpl
*>(
196 partition
->GetPlatformNotificationContext());
198 BrowserThread::PostTask(
201 base::Bind(&ReadNotificationDatabaseData
,
202 persistent_notification_id
,
204 dispatch_complete_callback
,
205 service_worker_context
,
206 notification_context
));
209 } // namespace content