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_message_filter.h" | 5 #include "content/browser/notifications/notification_message_filter.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "content/browser/bad_message.h" | 11 #include "content/browser/bad_message.h" |
| 12 #include "content/browser/notifications/notification_id_generator.h" |
12 #include "content/browser/notifications/page_notification_delegate.h" | 13 #include "content/browser/notifications/page_notification_delegate.h" |
13 #include "content/browser/notifications/platform_notification_context_impl.h" | 14 #include "content/browser/notifications/platform_notification_context_impl.h" |
14 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 15 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
15 #include "content/common/platform_notification_messages.h" | 16 #include "content/common/platform_notification_messages.h" |
16 #include "content/public/browser/browser_context.h" | 17 #include "content/public/browser/browser_context.h" |
17 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
18 #include "content/public/browser/content_browser_client.h" | 19 #include "content/public/browser/content_browser_client.h" |
19 #include "content/public/browser/desktop_notification_delegate.h" | 20 #include "content/public/browser/desktop_notification_delegate.h" |
20 #include "content/public/browser/notification_database_data.h" | 21 #include "content/public/browser/notification_database_data.h" |
21 #include "content/public/browser/platform_notification_service.h" | 22 #include "content/public/browser/platform_notification_service.h" |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 : BrowserMessageFilter(PlatformNotificationMsgStart), | 91 : BrowserMessageFilter(PlatformNotificationMsgStart), |
91 process_id_(process_id), | 92 process_id_(process_id), |
92 notification_context_(notification_context), | 93 notification_context_(notification_context), |
93 resource_context_(resource_context), | 94 resource_context_(resource_context), |
94 service_worker_context_(service_worker_context), | 95 service_worker_context_(service_worker_context), |
95 browser_context_(browser_context), | 96 browser_context_(browser_context), |
96 weak_factory_io_(this) {} | 97 weak_factory_io_(this) {} |
97 | 98 |
98 NotificationMessageFilter::~NotificationMessageFilter() {} | 99 NotificationMessageFilter::~NotificationMessageFilter() {} |
99 | 100 |
100 void NotificationMessageFilter::DidCloseNotification(int notification_id) { | 101 void NotificationMessageFilter::DidCloseNotification( |
| 102 const std::string& notification_id) { |
101 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 103 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
102 | |
103 close_closures_.erase(notification_id); | 104 close_closures_.erase(notification_id); |
104 } | 105 } |
105 | 106 |
106 void NotificationMessageFilter::OnDestruct() const { | 107 void NotificationMessageFilter::OnDestruct() const { |
107 BrowserThread::DeleteOnIOThread::Destruct(this); | 108 BrowserThread::DeleteOnIOThread::Destruct(this); |
108 } | 109 } |
109 | 110 |
110 bool NotificationMessageFilter::OnMessageReceived(const IPC::Message& message) { | 111 bool NotificationMessageFilter::OnMessageReceived(const IPC::Message& message) { |
111 bool handled = true; | 112 bool handled = true; |
112 IPC_BEGIN_MESSAGE_MAP(NotificationMessageFilter, message) | 113 IPC_BEGIN_MESSAGE_MAP(NotificationMessageFilter, message) |
(...skipping 15 matching lines...) Expand all Loading... |
128 | 129 |
129 void NotificationMessageFilter::OverrideThreadForMessage( | 130 void NotificationMessageFilter::OverrideThreadForMessage( |
130 const IPC::Message& message, | 131 const IPC::Message& message, |
131 content::BrowserThread::ID* thread) { | 132 content::BrowserThread::ID* thread) { |
132 if (message.type() == PlatformNotificationHostMsg_Show::ID || | 133 if (message.type() == PlatformNotificationHostMsg_Show::ID || |
133 message.type() == PlatformNotificationHostMsg_Close::ID) | 134 message.type() == PlatformNotificationHostMsg_Close::ID) |
134 *thread = BrowserThread::UI; | 135 *thread = BrowserThread::UI; |
135 } | 136 } |
136 | 137 |
137 void NotificationMessageFilter::OnShowPlatformNotification( | 138 void NotificationMessageFilter::OnShowPlatformNotification( |
138 int notification_id, | 139 int non_persistent_notification_id, |
139 const GURL& origin, | 140 const GURL& origin, |
140 const PlatformNotificationData& notification_data, | 141 const PlatformNotificationData& notification_data, |
141 const NotificationResources& notification_resources) { | 142 const NotificationResources& notification_resources) { |
142 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 143 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
143 if (!RenderProcessHost::FromID(process_id_)) | 144 if (!RenderProcessHost::FromID(process_id_)) |
144 return; | 145 return; |
145 | 146 |
146 if (!ValidateNotificationResources(notification_resources)) { | 147 if (!ValidateNotificationResources(notification_resources)) { |
147 bad_message::ReceivedBadMessage(this, bad_message::NMF_INVALID_ARGUMENT); | 148 bad_message::ReceivedBadMessage(this, bad_message::NMF_INVALID_ARGUMENT); |
148 return; | 149 return; |
149 } | 150 } |
150 | 151 |
151 std::unique_ptr<DesktopNotificationDelegate> delegate( | |
152 new PageNotificationDelegate(process_id_, notification_id)); | |
153 | |
154 PlatformNotificationService* service = | 152 PlatformNotificationService* service = |
155 GetContentClient()->browser()->GetPlatformNotificationService(); | 153 GetContentClient()->browser()->GetPlatformNotificationService(); |
156 DCHECK(service); | 154 DCHECK(service); |
157 | 155 |
158 if (!VerifyNotificationPermissionGranted(service, origin)) | 156 if (!VerifyNotificationPermissionGranted(service, origin)) |
159 return; | 157 return; |
160 | 158 |
| 159 std::string notification_id = |
| 160 GetNotificationIdGenerator()->GenerateForNonPersistentNotification( |
| 161 origin, notification_data.tag, non_persistent_notification_id, |
| 162 process_id_); |
| 163 |
| 164 std::unique_ptr<DesktopNotificationDelegate> delegate( |
| 165 new PageNotificationDelegate(process_id_, non_persistent_notification_id, |
| 166 notification_id)); |
| 167 |
161 base::Closure close_closure; | 168 base::Closure close_closure; |
162 service->DisplayNotification( | 169 service->DisplayNotification(browser_context_, notification_id, origin, |
163 browser_context_, origin, SanitizeNotificationData(notification_data), | 170 SanitizeNotificationData(notification_data), |
164 notification_resources, std::move(delegate), &close_closure); | 171 notification_resources, std::move(delegate), |
| 172 &close_closure); |
165 | 173 |
166 if (!close_closure.is_null()) | 174 if (!close_closure.is_null()) |
167 close_closures_[notification_id] = close_closure; | 175 close_closures_[notification_id] = close_closure; |
168 } | 176 } |
169 | 177 |
170 void NotificationMessageFilter::OnShowPersistentNotification( | 178 void NotificationMessageFilter::OnShowPersistentNotification( |
171 int request_id, | 179 int request_id, |
172 int64_t service_worker_registration_id, | 180 int64_t service_worker_registration_id, |
173 const GURL& origin, | 181 const GURL& origin, |
174 const PlatformNotificationData& notification_data, | 182 const PlatformNotificationData& notification_data, |
(...skipping 11 matching lines...) Expand all Loading... |
186 } | 194 } |
187 | 195 |
188 NotificationDatabaseData database_data; | 196 NotificationDatabaseData database_data; |
189 database_data.origin = origin; | 197 database_data.origin = origin; |
190 database_data.service_worker_registration_id = service_worker_registration_id; | 198 database_data.service_worker_registration_id = service_worker_registration_id; |
191 | 199 |
192 PlatformNotificationData sanitized_notification_data = | 200 PlatformNotificationData sanitized_notification_data = |
193 SanitizeNotificationData(notification_data); | 201 SanitizeNotificationData(notification_data); |
194 database_data.notification_data = sanitized_notification_data; | 202 database_data.notification_data = sanitized_notification_data; |
195 | 203 |
196 // TODO(peter): Significantly reduce the amount of information we need to | |
197 // retain outside of the database for displaying notifications. | |
198 notification_context_->WriteNotificationData( | 204 notification_context_->WriteNotificationData( |
199 origin, database_data, | 205 origin, database_data, |
200 base::Bind(&NotificationMessageFilter::DidWritePersistentNotificationData, | 206 base::Bind(&NotificationMessageFilter::DidWritePersistentNotificationData, |
201 weak_factory_io_.GetWeakPtr(), request_id, | 207 weak_factory_io_.GetWeakPtr(), request_id, |
202 service_worker_registration_id, origin, | 208 service_worker_registration_id, origin, |
203 sanitized_notification_data, notification_resources)); | 209 sanitized_notification_data, notification_resources)); |
204 } | 210 } |
205 | 211 |
206 void NotificationMessageFilter::DidWritePersistentNotificationData( | 212 void NotificationMessageFilter::DidWritePersistentNotificationData( |
207 int request_id, | 213 int request_id, |
208 int64_t service_worker_registration_id, | 214 int64_t service_worker_registration_id, |
209 const GURL& origin, | 215 const GURL& origin, |
210 const PlatformNotificationData& notification_data, | 216 const PlatformNotificationData& notification_data, |
211 const NotificationResources& notification_resources, | 217 const NotificationResources& notification_resources, |
212 bool success, | 218 bool success, |
213 int64_t persistent_notification_id) { | 219 const std::string& notification_id) { |
214 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 220 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
215 | 221 |
216 if (!success) { | 222 if (!success) { |
217 Send(new PlatformNotificationMsg_DidShowPersistent(request_id, false)); | 223 Send(new PlatformNotificationMsg_DidShowPersistent(request_id, false)); |
218 return; | 224 return; |
219 } | 225 } |
220 | 226 |
221 // Get the service worker scope. | 227 // Get the service worker scope. |
222 service_worker_context_->FindReadyRegistrationForId( | 228 service_worker_context_->FindReadyRegistrationForId( |
223 service_worker_registration_id, origin, | 229 service_worker_registration_id, origin, |
224 base::Bind(&NotificationMessageFilter::DidFindServiceWorkerRegistration, | 230 base::Bind(&NotificationMessageFilter::DidFindServiceWorkerRegistration, |
225 weak_factory_io_.GetWeakPtr(), request_id, origin, | 231 weak_factory_io_.GetWeakPtr(), request_id, origin, |
226 notification_data, notification_resources, | 232 notification_data, notification_resources, notification_id)); |
227 persistent_notification_id)); | |
228 } | 233 } |
229 | 234 |
230 void NotificationMessageFilter::DidFindServiceWorkerRegistration( | 235 void NotificationMessageFilter::DidFindServiceWorkerRegistration( |
231 int request_id, | 236 int request_id, |
232 const GURL& origin, | 237 const GURL& origin, |
233 const PlatformNotificationData& notification_data, | 238 const PlatformNotificationData& notification_data, |
234 const NotificationResources& notification_resources, | 239 const NotificationResources& notification_resources, |
235 int64_t persistent_notification_id, | 240 const std::string& notification_id, |
236 content::ServiceWorkerStatusCode service_worker_status, | 241 content::ServiceWorkerStatusCode service_worker_status, |
237 scoped_refptr<content::ServiceWorkerRegistration> registration) { | 242 scoped_refptr<content::ServiceWorkerRegistration> registration) { |
238 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 243 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
239 | 244 |
240 if (service_worker_status != SERVICE_WORKER_OK) { | 245 if (service_worker_status != SERVICE_WORKER_OK) { |
241 Send(new PlatformNotificationMsg_DidShowPersistent(request_id, false)); | 246 Send(new PlatformNotificationMsg_DidShowPersistent(request_id, false)); |
242 LOG(ERROR) << "Registration not found for " << origin.spec(); | 247 LOG(ERROR) << "Registration not found for " << origin.spec(); |
243 // TODO(peter): Add UMA to track how often this occurs. | 248 // TODO(peter): Add UMA to track how often this occurs. |
244 return; | 249 return; |
245 } | 250 } |
246 | 251 |
247 PlatformNotificationService* service = | 252 PlatformNotificationService* service = |
248 GetContentClient()->browser()->GetPlatformNotificationService(); | 253 GetContentClient()->browser()->GetPlatformNotificationService(); |
249 DCHECK(service); | 254 DCHECK(service); |
250 | 255 |
251 BrowserThread::PostTask( | 256 BrowserThread::PostTask( |
252 BrowserThread::UI, FROM_HERE, | 257 BrowserThread::UI, FROM_HERE, |
253 base::Bind(&PlatformNotificationService::DisplayPersistentNotification, | 258 base::Bind(&PlatformNotificationService::DisplayPersistentNotification, |
254 base::Unretained(service), // The service is a singleton. | 259 base::Unretained(service), // The service is a singleton. |
255 browser_context_, persistent_notification_id, | 260 browser_context_, notification_id, registration->pattern(), |
256 registration->pattern(), origin, notification_data, | 261 origin, notification_data, notification_resources)); |
257 notification_resources)); | |
258 | 262 |
259 Send(new PlatformNotificationMsg_DidShowPersistent(request_id, true)); | 263 Send(new PlatformNotificationMsg_DidShowPersistent(request_id, true)); |
260 } | 264 } |
261 | 265 |
262 void NotificationMessageFilter::OnGetNotifications( | 266 void NotificationMessageFilter::OnGetNotifications( |
263 int request_id, | 267 int request_id, |
264 int64_t service_worker_registration_id, | 268 int64_t service_worker_registration_id, |
265 const GURL& origin, | 269 const GURL& origin, |
266 const std::string& filter_tag) { | 270 const std::string& filter_tag) { |
267 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 271 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
(...skipping 28 matching lines...) Expand all Loading... |
296 | 300 |
297 persistent_notifications.push_back(std::make_pair( | 301 persistent_notifications.push_back(std::make_pair( |
298 database_data.notification_id, database_data.notification_data)); | 302 database_data.notification_id, database_data.notification_data)); |
299 } | 303 } |
300 | 304 |
301 Send(new PlatformNotificationMsg_DidGetNotifications( | 305 Send(new PlatformNotificationMsg_DidGetNotifications( |
302 request_id, persistent_notifications)); | 306 request_id, persistent_notifications)); |
303 } | 307 } |
304 | 308 |
305 void NotificationMessageFilter::OnClosePlatformNotification( | 309 void NotificationMessageFilter::OnClosePlatformNotification( |
306 int notification_id) { | 310 const GURL& origin, |
| 311 const std::string& tag, |
| 312 int non_persistent_notification_id) { |
307 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 313 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
308 if (!RenderProcessHost::FromID(process_id_)) | 314 if (!RenderProcessHost::FromID(process_id_)) |
309 return; | 315 return; |
310 | 316 |
| 317 std::string notification_id = |
| 318 GetNotificationIdGenerator()->GenerateForNonPersistentNotification( |
| 319 origin, tag, non_persistent_notification_id, process_id_); |
| 320 |
311 if (!close_closures_.count(notification_id)) | 321 if (!close_closures_.count(notification_id)) |
312 return; | 322 return; |
313 | 323 |
314 close_closures_[notification_id].Run(); | 324 close_closures_[notification_id].Run(); |
315 close_closures_.erase(notification_id); | 325 close_closures_.erase(notification_id); |
316 } | 326 } |
317 | 327 |
318 void NotificationMessageFilter::OnClosePersistentNotification( | 328 void NotificationMessageFilter::OnClosePersistentNotification( |
319 const GURL& origin, | 329 const GURL& origin, |
320 int64_t persistent_notification_id) { | 330 const std::string& tag, |
| 331 const std::string& notification_id) { |
321 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 332 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
322 if (GetPermissionForOriginOnIO(origin) != | 333 if (GetPermissionForOriginOnIO(origin) != |
323 blink::mojom::PermissionStatus::GRANTED) { | 334 blink::mojom::PermissionStatus::GRANTED) { |
324 bad_message::ReceivedBadMessage(this, bad_message::NMF_NO_PERMISSION_CLOSE); | 335 bad_message::ReceivedBadMessage(this, bad_message::NMF_NO_PERMISSION_CLOSE); |
325 return; | 336 return; |
326 } | 337 } |
327 | 338 |
328 PlatformNotificationService* service = | 339 PlatformNotificationService* service = |
329 GetContentClient()->browser()->GetPlatformNotificationService(); | 340 GetContentClient()->browser()->GetPlatformNotificationService(); |
330 DCHECK(service); | 341 DCHECK(service); |
331 | 342 |
332 // There's no point in waiting until the database data has been removed before | 343 // There's no point in waiting until the database data has been removed before |
333 // closing the notification presented to the user. Post that task immediately. | 344 // closing the notification presented to the user. Post that task immediately. |
334 BrowserThread::PostTask( | 345 BrowserThread::PostTask( |
335 BrowserThread::UI, FROM_HERE, | 346 BrowserThread::UI, FROM_HERE, |
336 base::Bind(&PlatformNotificationService::ClosePersistentNotification, | 347 base::Bind(&PlatformNotificationService::ClosePersistentNotification, |
337 base::Unretained(service), // The service is a singleton. | 348 base::Unretained(service), // The service is a singleton. |
338 browser_context_, persistent_notification_id)); | 349 browser_context_, notification_id)); |
339 | 350 |
340 notification_context_->DeleteNotificationData( | 351 notification_context_->DeleteNotificationData( |
341 persistent_notification_id, origin, | 352 notification_id, origin, |
342 base::Bind( | 353 base::Bind( |
343 &NotificationMessageFilter::DidDeletePersistentNotificationData, | 354 &NotificationMessageFilter::DidDeletePersistentNotificationData, |
344 weak_factory_io_.GetWeakPtr())); | 355 weak_factory_io_.GetWeakPtr())); |
345 } | 356 } |
346 | 357 |
347 void NotificationMessageFilter::DidDeletePersistentNotificationData( | 358 void NotificationMessageFilter::DidDeletePersistentNotificationData( |
348 bool success) { | 359 bool success) { |
349 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 360 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
350 // TODO(peter): Consider feeding back to the renderer that the notification | 361 // TODO(peter): Consider feeding back to the renderer that the notification |
351 // has been closed. | 362 // has been closed. |
(...skipping 21 matching lines...) Expand all Loading... |
373 blink::mojom::PermissionStatus permission_status = | 384 blink::mojom::PermissionStatus permission_status = |
374 service->CheckPermissionOnUIThread(browser_context_, origin, process_id_); | 385 service->CheckPermissionOnUIThread(browser_context_, origin, process_id_); |
375 | 386 |
376 if (permission_status == blink::mojom::PermissionStatus::GRANTED) | 387 if (permission_status == blink::mojom::PermissionStatus::GRANTED) |
377 return true; | 388 return true; |
378 | 389 |
379 bad_message::ReceivedBadMessage(this, bad_message::NMF_NO_PERMISSION_VERIFY); | 390 bad_message::ReceivedBadMessage(this, bad_message::NMF_NO_PERMISSION_VERIFY); |
380 return false; | 391 return false; |
381 } | 392 } |
382 | 393 |
| 394 NotificationIdGenerator* NotificationMessageFilter::GetNotificationIdGenerator() |
| 395 const { |
| 396 return notification_context_->notification_id_generator(); |
| 397 } |
| 398 |
383 } // namespace content | 399 } // namespace content |
OLD | NEW |