Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/platform_notification_context_impl.h" | 5 #include "content/browser/notifications/platform_notification_context_impl.h" |
| 6 | 6 |
| 7 #include "base/bind_helpers.h" | 7 #include "base/bind_helpers.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/threading/sequenced_worker_pool.h" | 12 #include "base/threading/sequenced_worker_pool.h" |
| 13 #include "base/time/default_clock.h" | |
| 13 #include "content/browser/notifications/blink_notification_service_impl.h" | 14 #include "content/browser/notifications/blink_notification_service_impl.h" |
| 14 #include "content/browser/notifications/notification_database.h" | 15 #include "content/browser/notifications/notification_database.h" |
| 15 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 16 #include "content/browser/service_worker/service_worker_context_wrapper.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/notification_database_data.h" | 20 #include "content/public/browser/notification_database_data.h" |
| 20 #include "content/public/browser/platform_notification_service.h" | 21 #include "content/public/browser/platform_notification_service.h" |
| 21 | 22 |
| 22 using base::DoNothing; | 23 using base::DoNothing; |
| 23 | 24 |
| 24 namespace content { | 25 namespace content { |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| 28 // Grace period, in seconds, during which we avoid deleting recently shown | |
| 29 // notifications from the database. | |
| 30 constexpr double kNotificationDisplayGraceSeconds = 5.0; | |
| 31 | |
| 27 // Name of the directory in the user's profile directory where the notification | 32 // Name of the directory in the user's profile directory where the notification |
| 28 // database files should be stored. | 33 // database files should be stored. |
| 29 const base::FilePath::CharType kPlatformNotificationsDirectory[] = | 34 const base::FilePath::CharType kPlatformNotificationsDirectory[] = |
| 30 FILE_PATH_LITERAL("Platform Notifications"); | 35 FILE_PATH_LITERAL("Platform Notifications"); |
| 31 | 36 |
| 32 } // namespace | 37 } // namespace |
| 33 | 38 |
| 34 PlatformNotificationContextImpl::PlatformNotificationContextImpl( | 39 PlatformNotificationContextImpl::PlatformNotificationContextImpl( |
| 35 const base::FilePath& path, | 40 const base::FilePath& path, |
| 36 BrowserContext* browser_context, | 41 BrowserContext* browser_context, |
| 37 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) | 42 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) |
| 38 : path_(path), | 43 : path_(path), |
| 39 browser_context_(browser_context), | 44 browser_context_(browser_context), |
| 40 service_worker_context_(service_worker_context), | 45 service_worker_context_(service_worker_context), |
| 41 notification_id_generator_(browser_context) { | 46 notification_id_generator_(browser_context), |
| 47 clock_(base::MakeUnique<base::DefaultClock>()) { | |
| 42 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 48 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 43 } | 49 } |
| 44 | 50 |
| 45 PlatformNotificationContextImpl::~PlatformNotificationContextImpl() { | 51 PlatformNotificationContextImpl::~PlatformNotificationContextImpl() { |
| 46 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 52 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 47 | 53 |
| 48 // If the database has been initialized, it must be deleted on the task runner | 54 // If the database has been initialized, it must be deleted on the task runner |
| 49 // thread as closing it may cause file I/O. | 55 // thread as closing it may cause file I/O. |
| 50 if (database_) { | 56 if (database_) { |
| 51 DCHECK(task_runner_); | 57 DCHECK(task_runner_); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 265 void PlatformNotificationContextImpl:: | 271 void PlatformNotificationContextImpl:: |
| 266 DoReadAllNotificationDataForServiceWorkerRegistration( | 272 DoReadAllNotificationDataForServiceWorkerRegistration( |
| 267 const GURL& origin, | 273 const GURL& origin, |
| 268 int64_t service_worker_registration_id, | 274 int64_t service_worker_registration_id, |
| 269 const ReadAllResultCallback& callback, | 275 const ReadAllResultCallback& callback, |
| 270 std::unique_ptr<std::set<std::string>> displayed_notifications, | 276 std::unique_ptr<std::set<std::string>> displayed_notifications, |
| 271 bool supports_synchronization) { | 277 bool supports_synchronization) { |
| 272 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 278 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 273 DCHECK(displayed_notifications); | 279 DCHECK(displayed_notifications); |
| 274 | 280 |
| 281 base::Time current_time = clock_->Now(); | |
| 282 | |
| 283 // Prune the list of recently shown notifications to those that were displayed | |
| 284 // in the past |kNotificationDisplayGraceSeconds| seconds. | |
| 285 auto iter = recent_notifications_.begin(); | |
| 286 while (iter != recent_notifications_.end()) { | |
| 287 base::TimeDelta display_time = current_time - iter->second; | |
| 288 if (display_time.InSecondsF() > kNotificationDisplayGraceSeconds) | |
| 289 iter = recent_notifications_.erase(iter); | |
| 290 else | |
| 291 iter++; | |
| 292 } | |
| 293 | |
| 275 std::vector<NotificationDatabaseData> notification_datas; | 294 std::vector<NotificationDatabaseData> notification_datas; |
| 276 | 295 |
| 277 NotificationDatabase::Status status = | 296 NotificationDatabase::Status status = |
| 278 database_->ReadAllNotificationDataForServiceWorkerRegistration( | 297 database_->ReadAllNotificationDataForServiceWorkerRegistration( |
| 279 origin, service_worker_registration_id, ¬ification_datas); | 298 origin, service_worker_registration_id, ¬ification_datas); |
| 280 | 299 |
| 281 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.ReadForServiceWorkerResult", | 300 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.ReadForServiceWorkerResult", |
| 282 status, NotificationDatabase::STATUS_COUNT); | 301 status, NotificationDatabase::STATUS_COUNT); |
| 283 | 302 |
| 284 std::vector<std::string> obsolete_notifications; | 303 std::vector<std::string> obsolete_notifications; |
| 285 | 304 |
| 286 if (status == NotificationDatabase::STATUS_OK) { | 305 if (status == NotificationDatabase::STATUS_OK) { |
| 287 if (supports_synchronization) { | 306 if (supports_synchronization) { |
| 288 for (auto it = notification_datas.begin(); | 307 for (auto it = notification_datas.begin(); |
| 289 it != notification_datas.end();) { | 308 it != notification_datas.end();) { |
| 290 // The database is only used for persistent notifications. | 309 // The database is only used for persistent notifications. |
| 291 DCHECK(NotificationIdGenerator::IsPersistentNotification( | 310 DCHECK(NotificationIdGenerator::IsPersistentNotification( |
| 292 it->notification_id)); | 311 it->notification_id)); |
| 293 if (displayed_notifications->count(it->notification_id)) { | 312 |
| 313 const bool notification_exists = | |
| 314 displayed_notifications->count(it->notification_id) || | |
| 315 recent_notifications_.count(it->notification_id); | |
| 316 | |
| 317 if (notification_exists) { | |
| 294 ++it; | 318 ++it; |
| 295 } else { | 319 } else { |
| 296 obsolete_notifications.push_back(it->notification_id); | 320 obsolete_notifications.push_back(it->notification_id); |
| 297 it = notification_datas.erase(it); | 321 it = notification_datas.erase(it); |
| 298 } | 322 } |
| 299 } | 323 } |
| 300 } | 324 } |
| 301 | 325 |
| 302 BrowserThread::PostTask( | 326 BrowserThread::PostTask( |
| 303 BrowserThread::IO, FROM_HERE, | 327 BrowserThread::IO, FROM_HERE, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 origin, database_data.notification_data.tag, | 392 origin, database_data.notification_data.tag, |
| 369 database_->GetNextPersistentNotificationId()); | 393 database_->GetNextPersistentNotificationId()); |
| 370 | 394 |
| 371 NotificationDatabase::Status status = | 395 NotificationDatabase::Status status = |
| 372 database_->WriteNotificationData(origin, write_database_data); | 396 database_->WriteNotificationData(origin, write_database_data); |
| 373 | 397 |
| 374 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.WriteResult", status, | 398 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.WriteResult", status, |
| 375 NotificationDatabase::STATUS_COUNT); | 399 NotificationDatabase::STATUS_COUNT); |
| 376 | 400 |
| 377 if (status == NotificationDatabase::STATUS_OK) { | 401 if (status == NotificationDatabase::STATUS_OK) { |
| 402 recent_notifications_[write_database_data.notification_id] = clock_->Now(); | |
| 403 | |
| 378 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 404 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 379 base::Bind(callback, true /* success */, | 405 base::Bind(callback, true /* success */, |
| 380 write_database_data.notification_id)); | 406 write_database_data.notification_id)); |
| 381 | 407 |
| 382 return; | 408 return; |
| 383 } | 409 } |
| 384 | 410 |
| 385 // Blow away the database if writing data failed due to corruption. | 411 // Blow away the database if writing data failed due to corruption. |
| 386 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) | 412 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) |
| 387 DestroyDatabase(); | 413 DestroyDatabase(); |
| 388 | 414 |
| 389 BrowserThread::PostTask( | 415 BrowserThread::PostTask( |
| 390 BrowserThread::IO, FROM_HERE, | 416 BrowserThread::IO, FROM_HERE, |
| 391 base::Bind(callback, false /* success */, "" /* notification_id */)); | 417 base::Bind(callback, false /* success */, "" /* notification_id */)); |
| 392 } | 418 } |
| 393 | 419 |
| 394 void PlatformNotificationContextImpl::DeleteNotificationData( | 420 void PlatformNotificationContextImpl::DeleteNotificationData( |
|
awdf
2017/05/11 10:38:53
Just to check my understanding - this DeleteNotifi
| |
| 395 const std::string& notification_id, | 421 const std::string& notification_id, |
| 396 const GURL& origin, | 422 const GURL& origin, |
| 397 const DeleteResultCallback& callback) { | 423 const DeleteResultCallback& callback) { |
| 398 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 424 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 399 | 425 |
| 400 LazyInitialize( | 426 LazyInitialize( |
| 401 base::Bind(&PlatformNotificationContextImpl::DoDeleteNotificationData, | 427 base::Bind(&PlatformNotificationContextImpl::DoDeleteNotificationData, |
| 402 this, notification_id, origin, callback), | 428 this, notification_id, origin, callback), |
| 403 base::Bind(callback, false /* success */)); | 429 base::Bind(callback, false /* success */)); |
| 404 } | 430 } |
| 405 | 431 |
| 406 void PlatformNotificationContextImpl::DoDeleteNotificationData( | 432 void PlatformNotificationContextImpl::DoDeleteNotificationData( |
| 407 const std::string& notification_id, | 433 const std::string& notification_id, |
| 408 const GURL& origin, | 434 const GURL& origin, |
| 409 const DeleteResultCallback& callback) { | 435 const DeleteResultCallback& callback) { |
| 410 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 436 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 411 | 437 |
| 412 NotificationDatabase::Status status = | 438 NotificationDatabase::Status status = |
| 413 database_->DeleteNotificationData(notification_id, origin); | 439 database_->DeleteNotificationData(notification_id, origin); |
| 414 | 440 |
| 415 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteResult", status, | 441 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteResult", status, |
| 416 NotificationDatabase::STATUS_COUNT); | 442 NotificationDatabase::STATUS_COUNT); |
| 417 | 443 |
| 444 recent_notifications_.erase(notification_id); | |
| 445 | |
| 418 bool success = status == NotificationDatabase::STATUS_OK; | 446 bool success = status == NotificationDatabase::STATUS_OK; |
| 419 | 447 |
| 420 // Blow away the database if deleting data failed due to corruption. Following | 448 // Blow away the database if deleting data failed due to corruption. Following |
| 421 // the contract of the delete methods, consider this to be a success as the | 449 // the contract of the delete methods, consider this to be a success as the |
| 422 // caller's goal has been achieved: the data is gone. | 450 // caller's goal has been achieved: the data is gone. |
| 423 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) { | 451 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) { |
| 424 DestroyDatabase(); | 452 DestroyDatabase(); |
| 425 success = true; | 453 success = true; |
| 426 } | 454 } |
| 427 | 455 |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 568 | 596 |
| 569 return path_.Append(kPlatformNotificationsDirectory); | 597 return path_.Append(kPlatformNotificationsDirectory); |
| 570 } | 598 } |
| 571 | 599 |
| 572 void PlatformNotificationContextImpl::SetTaskRunnerForTesting( | 600 void PlatformNotificationContextImpl::SetTaskRunnerForTesting( |
| 573 const scoped_refptr<base::SequencedTaskRunner>& task_runner) { | 601 const scoped_refptr<base::SequencedTaskRunner>& task_runner) { |
| 574 task_runner_ = task_runner; | 602 task_runner_ = task_runner; |
| 575 } | 603 } |
| 576 | 604 |
| 577 } // namespace content | 605 } // namespace content |
| OLD | NEW |