OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/notifications/notification_event_dispatcher_impl.h" | 5 #include "content/browser/notifications/notification_event_dispatcher_impl.h" |
6 | 6 |
7 #include "base/callback.h" | 7 #include "base/callback.h" |
8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
9 #include "content/browser/notifications/platform_notification_context_impl.h" | 9 #include "content/browser/notifications/platform_notification_context_impl.h" |
10 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 10 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
11 #include "content/browser/service_worker/service_worker_registration.h" | 11 #include "content/browser/service_worker/service_worker_registration.h" |
12 #include "content/browser/service_worker/service_worker_storage.h" | 12 #include "content/browser/service_worker/service_worker_storage.h" |
13 #include "content/public/browser/browser_context.h" | 13 #include "content/public/browser/browser_context.h" |
14 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
15 #include "content/public/browser/notification_database_data.h" | |
16 #include "content/public/browser/storage_partition.h" | 15 #include "content/public/browser/storage_partition.h" |
17 #include "content/public/common/platform_notification_data.h" | 16 #include "content/public/common/platform_notification_data.h" |
18 | 17 |
19 namespace content { | 18 namespace content { |
20 namespace { | 19 namespace { |
21 | 20 |
22 using NotificationClickDispatchCompleteCallback = | 21 using NotificationDispatchCompleteCallback = |
23 NotificationEventDispatcher::NotificationClickDispatchCompleteCallback; | 22 NotificationEventDispatcher::NotificationDispatchCompleteCallback; |
23 using NotificationActionCallback = | |
24 NotificationEventDispatcherImpl::NotificationActionCallback; | |
24 | 25 |
25 // To be called when the notificationclick event has finished executing. Will | 26 // To be called when a notification event has finished executing. Will post a |
26 // post a task to call |dispatch_complete_callback| on the UI thread. | 27 // task to call |dispatch_complete_callback| on the UI thread. |
27 void NotificationClickEventFinished( | 28 void NotificationEventFinished( |
28 const NotificationClickDispatchCompleteCallback& dispatch_complete_callback, | 29 const NotificationDispatchCompleteCallback& dispatch_complete_callback, |
29 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration, | 30 PersistentNotificationStatus status) { |
30 ServiceWorkerStatusCode service_worker_status) { | |
31 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 31 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
32 | 32 |
33 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
34 base::Bind(dispatch_complete_callback, status)); | |
35 } | |
36 | |
37 // To be called when a notification event has finished with a | |
38 // ServiceWorkerStatusCode result. Will call NotificationEventFinished with a | |
39 // PersistentNotificationStatus derived from the service worker status. | |
40 void SWNotificationEventFinished( | |
Peter Beverloo
2016/01/26 16:13:45
nit: s/SW/ServiceWorker/ (we don't usually use acr
Nina
2016/01/27 18:48:58
Done.
| |
41 const NotificationDispatchCompleteCallback& dispatch_complete_callback, | |
42 ServiceWorkerStatusCode service_worker_status) { | |
33 #if defined(OS_ANDROID) | 43 #if defined(OS_ANDROID) |
34 // This LOG(INFO) deliberately exists to help track down the cause of | 44 // This LOG(INFO) deliberately exists to help track down the cause of |
35 // https://crbug.com/534537, where notifications sometimes do not react to | 45 // https://crbug.com/534537, where notifications sometimes do not react to |
36 // the user clicking on them. It should be removed once that's fixed. | 46 // the user clicking on them. It should be removed once that's fixed. |
37 LOG(INFO) << "The notificationclick event has finished: " | 47 LOG(INFO) << "The notificationclick event has finished: " |
38 << service_worker_status; | 48 << service_worker_status; |
39 #endif | 49 #endif |
40 | 50 |
41 PersistentNotificationStatus status = PERSISTENT_NOTIFICATION_STATUS_SUCCESS; | 51 PersistentNotificationStatus status = PERSISTENT_NOTIFICATION_STATUS_SUCCESS; |
42 switch (service_worker_status) { | 52 switch (service_worker_status) { |
(...skipping 18 matching lines...) Expand all Loading... | |
61 case SERVICE_WORKER_ERROR_TIMEOUT: | 71 case SERVICE_WORKER_ERROR_TIMEOUT: |
62 case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: | 72 case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: |
63 case SERVICE_WORKER_ERROR_DISK_CACHE: | 73 case SERVICE_WORKER_ERROR_DISK_CACHE: |
64 case SERVICE_WORKER_ERROR_REDUNDANT: | 74 case SERVICE_WORKER_ERROR_REDUNDANT: |
65 case SERVICE_WORKER_ERROR_DISALLOWED: | 75 case SERVICE_WORKER_ERROR_DISALLOWED: |
66 case SERVICE_WORKER_ERROR_DISABLED_WORKER: | 76 case SERVICE_WORKER_ERROR_DISABLED_WORKER: |
67 case SERVICE_WORKER_ERROR_MAX_VALUE: | 77 case SERVICE_WORKER_ERROR_MAX_VALUE: |
68 status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR; | 78 status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR; |
69 break; | 79 break; |
70 } | 80 } |
71 | 81 NotificationEventFinished(dispatch_complete_callback, status); |
72 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
73 base::Bind(dispatch_complete_callback, status)); | |
74 } | 82 } |
75 | 83 |
76 // Dispatches the notificationclick on |service_worker_registration| if the | 84 // Dispatches the given notification action event on |
77 // registration was available. Must be called on the IO thread. | 85 // |service_worker_registration| if the registration was available. Must be |
78 void DispatchNotificationClickEventOnRegistration( | 86 // called on the IO thread. |
87 void DispatchNotificationEventOnRegistration( | |
79 const NotificationDatabaseData& notification_database_data, | 88 const NotificationDatabaseData& notification_database_data, |
80 int action_index, | 89 const scoped_refptr<PlatformNotificationContext> notification_context, |
81 const NotificationClickDispatchCompleteCallback& dispatch_complete_callback, | 90 const NotificationActionCallback& dispatch_event_action, |
91 const NotificationDispatchCompleteCallback& dispatch_error_callback, | |
82 ServiceWorkerStatusCode service_worker_status, | 92 ServiceWorkerStatusCode service_worker_status, |
83 const scoped_refptr<ServiceWorkerRegistration>& | 93 const scoped_refptr<ServiceWorkerRegistration>& |
84 service_worker_registration) { | 94 service_worker_registration) { |
85 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 95 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
86 #if defined(OS_ANDROID) | 96 #if defined(OS_ANDROID) |
87 // This LOG(INFO) deliberately exists to help track down the cause of | 97 // This LOG(INFO) deliberately exists to help track down the cause of |
88 // https://crbug.com/534537, where notifications sometimes do not react to | 98 // https://crbug.com/534537, where notifications sometimes do not react to |
89 // the user clicking on them. It should be removed once that's fixed. | 99 // the user clicking on them. It should be removed once that's fixed. |
90 LOG(INFO) << "Trying to dispatch notification for SW with status: " | 100 LOG(INFO) << "Trying to dispatch notification for SW with status: " |
91 << service_worker_status << " action_index: " << action_index; | 101 << service_worker_status; |
92 #endif | 102 #endif |
93 if (service_worker_status == SERVICE_WORKER_OK) { | 103 if (service_worker_status == SERVICE_WORKER_OK) { |
94 base::Callback<void(ServiceWorkerStatusCode)> dispatch_event_callback = | 104 DCHECK(service_worker_registration->active_version()); |
95 base::Bind(&NotificationClickEventFinished, dispatch_complete_callback, | |
96 service_worker_registration); | |
97 | 105 |
98 DCHECK(service_worker_registration->active_version()); | 106 dispatch_event_action.Run(service_worker_registration.get(), |
99 service_worker_registration->active_version() | 107 notification_database_data); |
100 ->DispatchNotificationClickEvent( | |
101 dispatch_event_callback, notification_database_data.notification_id, | |
102 notification_database_data.notification_data, action_index); | |
103 return; | 108 return; |
104 } | 109 } |
105 | 110 |
106 PersistentNotificationStatus status = PERSISTENT_NOTIFICATION_STATUS_SUCCESS; | 111 PersistentNotificationStatus status = PERSISTENT_NOTIFICATION_STATUS_SUCCESS; |
107 switch (service_worker_status) { | 112 switch (service_worker_status) { |
108 case SERVICE_WORKER_ERROR_NOT_FOUND: | 113 case SERVICE_WORKER_ERROR_NOT_FOUND: |
109 status = PERSISTENT_NOTIFICATION_STATUS_NO_SERVICE_WORKER; | 114 status = PERSISTENT_NOTIFICATION_STATUS_NO_SERVICE_WORKER; |
110 break; | 115 break; |
111 case SERVICE_WORKER_ERROR_FAILED: | 116 case SERVICE_WORKER_ERROR_FAILED: |
112 case SERVICE_WORKER_ERROR_ABORT: | 117 case SERVICE_WORKER_ERROR_ABORT: |
(...skipping 15 matching lines...) Expand all Loading... | |
128 case SERVICE_WORKER_ERROR_DISABLED_WORKER: | 133 case SERVICE_WORKER_ERROR_DISABLED_WORKER: |
129 case SERVICE_WORKER_ERROR_MAX_VALUE: | 134 case SERVICE_WORKER_ERROR_MAX_VALUE: |
130 status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR; | 135 status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR; |
131 break; | 136 break; |
132 case SERVICE_WORKER_OK: | 137 case SERVICE_WORKER_OK: |
133 NOTREACHED(); | 138 NOTREACHED(); |
134 break; | 139 break; |
135 } | 140 } |
136 | 141 |
137 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 142 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
138 base::Bind(dispatch_complete_callback, status)); | 143 base::Bind(dispatch_error_callback, status)); |
139 } | 144 } |
140 | 145 |
141 // Finds the ServiceWorkerRegistration associated with the |origin| and | 146 // Finds the ServiceWorkerRegistration associated with the |origin| and |
142 // |service_worker_registration_id|. Must be called on the IO thread. | 147 // |service_worker_registration_id|. Must be called on the IO thread. |
143 void FindServiceWorkerRegistration( | 148 void FindServiceWorkerRegistration( |
144 const GURL& origin, | 149 const GURL& origin, |
145 int action_index, | |
146 const NotificationClickDispatchCompleteCallback& dispatch_complete_callback, | |
147 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, | 150 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, |
151 scoped_refptr<PlatformNotificationContext> notification_context, | |
152 const NotificationActionCallback& notification_action_callback, | |
153 const NotificationDispatchCompleteCallback& dispatch_error_callback, | |
148 bool success, | 154 bool success, |
149 const NotificationDatabaseData& notification_database_data) { | 155 const NotificationDatabaseData& notification_database_data) { |
150 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 156 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
151 | 157 |
152 #if defined(OS_ANDROID) | 158 #if defined(OS_ANDROID) |
153 // This LOG(INFO) deliberately exists to help track down the cause of | 159 // This LOG(INFO) deliberately exists to help track down the cause of |
154 // https://crbug.com/534537, where notifications sometimes do not react to | 160 // https://crbug.com/534537, where notifications sometimes do not react to |
155 // the user clicking on them. It should be removed once that's fixed. | 161 // the user clicking on them. It should be removed once that's fixed. |
156 LOG(INFO) << "Lookup for ServiceWoker Registration: success:" << success | 162 LOG(INFO) << "Lookup for ServiceWoker Registration"; |
157 << " action_index: " << action_index; | |
158 #endif | 163 #endif |
159 if (!success) { | 164 if (!success) { |
160 BrowserThread::PostTask( | 165 BrowserThread::PostTask( |
161 BrowserThread::UI, FROM_HERE, | 166 BrowserThread::UI, FROM_HERE, |
162 base::Bind(dispatch_complete_callback, | 167 base::Bind(dispatch_error_callback, |
163 PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR)); | 168 PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR)); |
164 return; | 169 return; |
165 } | 170 } |
166 | 171 |
167 service_worker_context->FindReadyRegistrationForId( | 172 service_worker_context->FindReadyRegistrationForId( |
168 notification_database_data.service_worker_registration_id, origin, | 173 notification_database_data.service_worker_registration_id, origin, |
169 base::Bind(&DispatchNotificationClickEventOnRegistration, | 174 base::Bind(&DispatchNotificationEventOnRegistration, |
170 notification_database_data, action_index, | 175 notification_database_data, notification_context, |
171 dispatch_complete_callback)); | 176 notification_action_callback, dispatch_error_callback)); |
172 } | 177 } |
173 | 178 |
174 // Reads the data associated with the |persistent_notification_id| belonging to | 179 // Reads the data associated with the |persistent_notification_id| belonging to |
175 // |origin| from the notification context. | 180 // |origin| from the notification context. |
176 void ReadNotificationDatabaseData( | 181 void ReadNotificationDatabaseData( |
177 int64_t persistent_notification_id, | 182 int64_t persistent_notification_id, |
178 const GURL& origin, | 183 const GURL& origin, |
179 int action_index, | |
180 const NotificationClickDispatchCompleteCallback& dispatch_complete_callback, | |
181 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, | 184 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, |
182 scoped_refptr<PlatformNotificationContextImpl> notification_context) { | 185 scoped_refptr<PlatformNotificationContext> notification_context, |
186 const NotificationActionCallback& notification_read_callback, | |
187 const NotificationDispatchCompleteCallback& dispatch_error_callback) { | |
183 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 188 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
184 notification_context->ReadNotificationData( | 189 notification_context->ReadNotificationData( |
185 persistent_notification_id, origin, | 190 persistent_notification_id, origin, |
186 base::Bind(&FindServiceWorkerRegistration, origin, action_index, | 191 base::Bind(&FindServiceWorkerRegistration, origin, service_worker_context, |
187 dispatch_complete_callback, service_worker_context)); | 192 notification_context, notification_read_callback, |
193 dispatch_error_callback)); | |
194 } | |
195 | |
196 // Dispatches the notification click event on the |service_worker_registration|. | |
197 void DoDispatchNotificationClickEvent( | |
198 int action_index, | |
199 const NotificationDispatchCompleteCallback& dispatch_complete_callback, | |
200 const scoped_refptr<PlatformNotificationContext> notification_context, | |
201 const ServiceWorkerRegistration* service_worker_registration, | |
202 const NotificationDatabaseData& notification_database_data) { | |
203 service_worker_registration->active_version()->DispatchNotificationClickEvent( | |
204 base::Bind(&SWNotificationEventFinished, dispatch_complete_callback), | |
205 notification_database_data.notification_id, | |
206 notification_database_data.notification_data, action_index); | |
207 } | |
208 | |
209 // Called when the notification data has been deleted to finish the notification | |
210 // close event. | |
211 void OnPersistentNotificationDataDeleted( | |
212 const NotificationDispatchCompleteCallback& dispatch_complete_callback, | |
213 bool success) { | |
214 if (success) { | |
Peter Beverloo
2016/01/26 16:13:45
You could reduce duplication by branching for the
Nina
2016/01/27 18:48:58
Done.
| |
215 NotificationEventFinished(dispatch_complete_callback, | |
216 PERSISTENT_NOTIFICATION_STATUS_SUCCESS); | |
217 } else { | |
218 NotificationEventFinished(dispatch_complete_callback, | |
219 PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR); | |
220 } | |
221 } | |
222 | |
223 // Called when the persistent notification close event has been handled | |
224 // to remove the notification from the database. | |
225 void OnDidDispatchNotificationCloseEvent( | |
226 const int64_t notification_id, | |
227 const GURL& origin, | |
228 scoped_refptr<PlatformNotificationContext> notification_context, | |
229 const NotificationDispatchCompleteCallback& dispatch_complete_callback, | |
230 ServiceWorkerStatusCode status_code) { | |
Peter Beverloo
2016/01/26 16:13:45
We'll want to return the result status of dispatch
Nina
2016/01/27 18:48:58
Sounds good. Since we want to call the callback on
| |
231 notification_context->DeleteNotificationData( | |
232 notification_id, origin, base::Bind(&OnPersistentNotificationDataDeleted, | |
233 dispatch_complete_callback)); | |
234 } | |
235 | |
236 // Actually dispatches the notification close event on the service worker | |
237 // registration. | |
238 void DoDispatchNotificationCloseEvent( | |
239 const NotificationDispatchCompleteCallback& dispatch_complete_callback, | |
240 scoped_refptr<PlatformNotificationContext> notification_context, | |
241 const ServiceWorkerRegistration* service_worker_registration, | |
242 const NotificationDatabaseData& notification_database_data) { | |
243 const base::Callback<void(ServiceWorkerStatusCode)> dispatch_event_callback = | |
244 base::Bind(&OnDidDispatchNotificationCloseEvent, | |
245 notification_database_data.notification_id, | |
246 notification_database_data.origin, notification_context, | |
247 dispatch_complete_callback); | |
248 service_worker_registration->active_version()->DispatchNotificationCloseEvent( | |
249 dispatch_event_callback, notification_database_data.notification_id, | |
250 notification_database_data.notification_data); | |
188 } | 251 } |
189 | 252 |
190 } // namespace | 253 } // namespace |
191 | 254 |
192 // static | 255 // static |
193 NotificationEventDispatcher* NotificationEventDispatcher::GetInstance() { | 256 NotificationEventDispatcher* NotificationEventDispatcher::GetInstance() { |
194 return NotificationEventDispatcherImpl::GetInstance(); | 257 return NotificationEventDispatcherImpl::GetInstance(); |
195 } | 258 } |
196 | 259 |
197 NotificationEventDispatcherImpl* | 260 NotificationEventDispatcherImpl* |
198 NotificationEventDispatcherImpl::GetInstance() { | 261 NotificationEventDispatcherImpl::GetInstance() { |
199 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 262 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
200 return base::Singleton<NotificationEventDispatcherImpl>::get(); | 263 return base::Singleton<NotificationEventDispatcherImpl>::get(); |
201 } | 264 } |
202 | 265 |
203 NotificationEventDispatcherImpl::NotificationEventDispatcherImpl() {} | 266 NotificationEventDispatcherImpl::NotificationEventDispatcherImpl() {} |
204 | 267 |
205 NotificationEventDispatcherImpl::~NotificationEventDispatcherImpl() {} | 268 NotificationEventDispatcherImpl::~NotificationEventDispatcherImpl() {} |
206 | 269 |
207 void NotificationEventDispatcherImpl::DispatchNotificationClickEvent( | 270 void NotificationEventDispatcherImpl::DispatchNotificationClickEvent( |
208 BrowserContext* browser_context, | 271 BrowserContext* browser_context, |
209 int64_t persistent_notification_id, | 272 int64_t persistent_notification_id, |
210 const GURL& origin, | 273 const GURL& origin, |
211 int action_index, | 274 int action_index, |
212 const NotificationClickDispatchCompleteCallback& | 275 const NotificationDispatchCompleteCallback& dispatch_complete_callback) { |
213 dispatch_complete_callback) { | 276 DispatchNotificationEvent( |
277 browser_context, persistent_notification_id, origin, | |
278 base::Bind(&DoDispatchNotificationClickEvent, action_index, | |
279 dispatch_complete_callback), | |
280 dispatch_complete_callback); | |
281 } | |
282 | |
283 void NotificationEventDispatcherImpl::DispatchNotificationCloseEvent( | |
284 BrowserContext* browser_context, | |
285 int64_t persistent_notification_id, | |
286 const GURL& origin, | |
287 const NotificationDispatchCompleteCallback& dispatch_complete_callback) { | |
288 DispatchNotificationEvent( | |
289 browser_context, persistent_notification_id, origin, | |
290 base::Bind(&DoDispatchNotificationCloseEvent, dispatch_complete_callback), | |
291 dispatch_complete_callback); | |
292 } | |
293 | |
294 void NotificationEventDispatcherImpl::DispatchNotificationEvent( | |
295 BrowserContext* browser_context, | |
296 int64_t persistent_notification_id, | |
297 const GURL& origin, | |
298 const CurriedNotificationActionCallback& notification_action_callback, | |
299 const NotificationDispatchCompleteCallback& notification_error_callback) { | |
214 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 300 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
215 DCHECK_GT(persistent_notification_id, 0); | 301 DCHECK_GT(persistent_notification_id, 0); |
216 DCHECK(origin.is_valid()); | 302 DCHECK(origin.is_valid()); |
217 | 303 |
218 StoragePartition* partition = | 304 StoragePartition* partition = |
219 BrowserContext::GetStoragePartitionForSite(browser_context, origin); | 305 BrowserContext::GetStoragePartitionForSite(browser_context, origin); |
220 | 306 |
221 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context = | 307 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context = |
222 static_cast<ServiceWorkerContextWrapper*>( | 308 static_cast<ServiceWorkerContextWrapper*>( |
223 partition->GetServiceWorkerContext()); | 309 partition->GetServiceWorkerContext()); |
224 scoped_refptr<PlatformNotificationContextImpl> notification_context = | 310 scoped_refptr<PlatformNotificationContext> notification_context = |
225 static_cast<PlatformNotificationContextImpl*>( | 311 partition->GetPlatformNotificationContext(); |
226 partition->GetPlatformNotificationContext()); | |
227 | 312 |
228 BrowserThread::PostTask( | 313 BrowserThread::PostTask( |
229 BrowserThread::IO, FROM_HERE, | 314 BrowserThread::IO, FROM_HERE, |
230 base::Bind(&ReadNotificationDatabaseData, persistent_notification_id, | 315 base::Bind(&ReadNotificationDatabaseData, persistent_notification_id, |
231 origin, action_index, dispatch_complete_callback, | 316 origin, service_worker_context, notification_context, |
232 service_worker_context, notification_context)); | 317 base::Bind(notification_action_callback, notification_context), |
318 notification_error_callback)); | |
233 } | 319 } |
234 | 320 |
235 } // namespace content | 321 } // namespace content |
OLD | NEW |