Index: content/browser/notifications/platform_notification_context_impl.cc |
diff --git a/content/browser/notifications/platform_notification_context_impl.cc b/content/browser/notifications/platform_notification_context_impl.cc |
index 8a15289d8aac51406bc6db6714058e99d5dc3317..757612288da826b48f0c381036359cd7884dc2be 100644 |
--- a/content/browser/notifications/platform_notification_context_impl.cc |
+++ b/content/browser/notifications/platform_notification_context_impl.cc |
@@ -10,6 +10,7 @@ |
#include "base/metrics/histogram_macros.h" |
#include "base/stl_util.h" |
#include "base/threading/sequenced_worker_pool.h" |
+#include "base/time/default_clock.h" |
#include "content/browser/notifications/blink_notification_service_impl.h" |
#include "content/browser/notifications/notification_database.h" |
#include "content/browser/service_worker/service_worker_context_wrapper.h" |
@@ -24,6 +25,10 @@ using base::DoNothing; |
namespace content { |
namespace { |
+// Grace period, in seconds, during which we avoid deleting recently shown |
+// notifications from the database. |
+constexpr double kNotificationDisplayGraceSeconds = 5.0; |
+ |
// Name of the directory in the user's profile directory where the notification |
// database files should be stored. |
const base::FilePath::CharType kPlatformNotificationsDirectory[] = |
@@ -38,7 +43,8 @@ PlatformNotificationContextImpl::PlatformNotificationContextImpl( |
: path_(path), |
browser_context_(browser_context), |
service_worker_context_(service_worker_context), |
- notification_id_generator_(browser_context) { |
+ notification_id_generator_(browser_context), |
+ clock_(base::MakeUnique<base::DefaultClock>()) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
} |
@@ -272,6 +278,19 @@ void PlatformNotificationContextImpl:: |
DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
DCHECK(displayed_notifications); |
+ base::Time current_time = clock_->Now(); |
+ |
+ // Prune the list of recently shown notifications to those that were displayed |
+ // in the past |kNotificationDisplayGraceSeconds| seconds. |
+ auto iter = recent_notifications_.begin(); |
+ while (iter != recent_notifications_.end()) { |
+ base::TimeDelta display_time = current_time - iter->second; |
+ if (display_time.InSecondsF() > kNotificationDisplayGraceSeconds) |
+ iter = recent_notifications_.erase(iter); |
+ else |
+ iter++; |
+ } |
+ |
std::vector<NotificationDatabaseData> notification_datas; |
NotificationDatabase::Status status = |
@@ -290,7 +309,12 @@ void PlatformNotificationContextImpl:: |
// The database is only used for persistent notifications. |
DCHECK(NotificationIdGenerator::IsPersistentNotification( |
it->notification_id)); |
- if (displayed_notifications->count(it->notification_id)) { |
+ |
+ const bool notification_exists = |
+ displayed_notifications->count(it->notification_id) || |
+ recent_notifications_.count(it->notification_id); |
+ |
+ if (notification_exists) { |
++it; |
} else { |
obsolete_notifications.push_back(it->notification_id); |
@@ -375,6 +399,8 @@ void PlatformNotificationContextImpl::DoWriteNotificationData( |
NotificationDatabase::STATUS_COUNT); |
if (status == NotificationDatabase::STATUS_OK) { |
+ recent_notifications_[write_database_data.notification_id] = clock_->Now(); |
+ |
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
base::Bind(callback, true /* success */, |
write_database_data.notification_id)); |
@@ -415,6 +441,8 @@ void PlatformNotificationContextImpl::DoDeleteNotificationData( |
UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteResult", status, |
NotificationDatabase::STATUS_COUNT); |
+ recent_notifications_.erase(notification_id); |
+ |
bool success = status == NotificationDatabase::STATUS_OK; |
// Blow away the database if deleting data failed due to corruption. Following |