| 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, |
| 330 const std::string& tag, |
| 320 int64_t persistent_notification_id) { | 331 int64_t persistent_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 |
| 343 // TODO(peter): Plumb the |notification_id| string all the way through to |
| 344 // Blink, removing additional branches there. |
| 345 std::string notification_id = |
| 346 GetNotificationIdGenerator()->GenerateForPersistentNotification( |
| 347 origin, tag, persistent_notification_id); |
| 348 |
| 332 // There's no point in waiting until the database data has been removed before | 349 // 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. | 350 // closing the notification presented to the user. Post that task immediately. |
| 334 BrowserThread::PostTask( | 351 BrowserThread::PostTask( |
| 335 BrowserThread::UI, FROM_HERE, | 352 BrowserThread::UI, FROM_HERE, |
| 336 base::Bind(&PlatformNotificationService::ClosePersistentNotification, | 353 base::Bind(&PlatformNotificationService::ClosePersistentNotification, |
| 337 base::Unretained(service), // The service is a singleton. | 354 base::Unretained(service), // The service is a singleton. |
| 338 browser_context_, persistent_notification_id)); | 355 browser_context_, notification_id)); |
| 339 | 356 |
| 340 notification_context_->DeleteNotificationData( | 357 notification_context_->DeleteNotificationData( |
| 341 persistent_notification_id, origin, | 358 notification_id, origin, |
| 342 base::Bind( | 359 base::Bind( |
| 343 &NotificationMessageFilter::DidDeletePersistentNotificationData, | 360 &NotificationMessageFilter::DidDeletePersistentNotificationData, |
| 344 weak_factory_io_.GetWeakPtr())); | 361 weak_factory_io_.GetWeakPtr())); |
| 345 } | 362 } |
| 346 | 363 |
| 347 void NotificationMessageFilter::DidDeletePersistentNotificationData( | 364 void NotificationMessageFilter::DidDeletePersistentNotificationData( |
| 348 bool success) { | 365 bool success) { |
| 349 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 366 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 350 // TODO(peter): Consider feeding back to the renderer that the notification | 367 // TODO(peter): Consider feeding back to the renderer that the notification |
| 351 // has been closed. | 368 // has been closed. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 373 blink::mojom::PermissionStatus permission_status = | 390 blink::mojom::PermissionStatus permission_status = |
| 374 service->CheckPermissionOnUIThread(browser_context_, origin, process_id_); | 391 service->CheckPermissionOnUIThread(browser_context_, origin, process_id_); |
| 375 | 392 |
| 376 if (permission_status == blink::mojom::PermissionStatus::GRANTED) | 393 if (permission_status == blink::mojom::PermissionStatus::GRANTED) |
| 377 return true; | 394 return true; |
| 378 | 395 |
| 379 bad_message::ReceivedBadMessage(this, bad_message::NMF_NO_PERMISSION_VERIFY); | 396 bad_message::ReceivedBadMessage(this, bad_message::NMF_NO_PERMISSION_VERIFY); |
| 380 return false; | 397 return false; |
| 381 } | 398 } |
| 382 | 399 |
| 400 NotificationIdGenerator* NotificationMessageFilter::GetNotificationIdGenerator() |
| 401 const { |
| 402 return notification_context_->notification_id_generator(); |
| 403 } |
| 404 |
| 383 } // namespace content | 405 } // namespace content |
| OLD | NEW |