Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Side by Side Diff: content/browser/notifications/notification_event_dispatcher_impl.cc

Issue 1619703002: Implement notificationclose event (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed comments Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698