| 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/threading/sequenced_worker_pool.h" | 11 #include "base/threading/sequenced_worker_pool.h" |
| 12 #include "content/browser/notifications/blink_notification_service_impl.h" | 12 #include "content/browser/notifications/blink_notification_service_impl.h" |
| 13 #include "content/browser/notifications/notification_database.h" | 13 #include "content/browser/notifications/notification_database.h" |
| 14 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 14 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
| 15 #include "content/public/browser/browser_context.h" | 15 #include "content/public/browser/browser_context.h" |
| 16 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
| 17 #include "content/public/browser/content_browser_client.h" | 17 #include "content/public/browser/content_browser_client.h" |
| 18 #include "content/public/browser/notification_database_data.h" | 18 #include "content/public/browser/notification_database_data.h" |
| 19 #include "content/public/browser/platform_notification_service.h" | 19 #include "content/public/browser/platform_notification_service.h" |
| 20 | 20 |
| 21 using base::DoNothing; | 21 using base::DoNothing; |
| 22 | 22 |
| 23 namespace content { | 23 namespace content { |
| 24 namespace { |
| 24 | 25 |
| 25 // Name of the directory in the user's profile directory where the notification | 26 // Name of the directory in the user's profile directory where the notification |
| 26 // database files should be stored. | 27 // database files should be stored. |
| 27 const base::FilePath::CharType kPlatformNotificationsDirectory[] = | 28 const base::FilePath::CharType kPlatformNotificationsDirectory[] = |
| 28 FILE_PATH_LITERAL("Platform Notifications"); | 29 FILE_PATH_LITERAL("Platform Notifications"); |
| 29 | 30 |
| 31 } // namespace |
| 32 |
| 30 PlatformNotificationContextImpl::PlatformNotificationContextImpl( | 33 PlatformNotificationContextImpl::PlatformNotificationContextImpl( |
| 31 const base::FilePath& path, | 34 const base::FilePath& path, |
| 32 BrowserContext* browser_context, | 35 BrowserContext* browser_context, |
| 33 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) | 36 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) |
| 34 : path_(path), | 37 : path_(path), |
| 35 browser_context_(browser_context), | 38 browser_context_(browser_context), |
| 36 service_worker_context_(service_worker_context) { | 39 service_worker_context_(service_worker_context), |
| 40 notification_id_generator_(browser_context) { |
| 37 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 41 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 38 } | 42 } |
| 39 | 43 |
| 40 PlatformNotificationContextImpl::~PlatformNotificationContextImpl() { | 44 PlatformNotificationContextImpl::~PlatformNotificationContextImpl() { |
| 41 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 45 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 42 | 46 |
| 43 // If the database has been initialized, it must be deleted on the task runner | 47 // If the database has been initialized, it must be deleted on the task runner |
| 44 // thread as closing it may cause file I/O. | 48 // thread as closing it may cause file I/O. |
| 45 if (database_) { | 49 if (database_) { |
| 46 DCHECK(task_runner_); | 50 DCHECK(task_runner_); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 auto services_to_remove = std::remove_if( | 134 auto services_to_remove = std::remove_if( |
| 131 services_.begin(), services_.end(), | 135 services_.begin(), services_.end(), |
| 132 [service](const std::unique_ptr<BlinkNotificationServiceImpl>& ptr) { | 136 [service](const std::unique_ptr<BlinkNotificationServiceImpl>& ptr) { |
| 133 return ptr.get() == service; | 137 return ptr.get() == service; |
| 134 }); | 138 }); |
| 135 | 139 |
| 136 services_.erase(services_to_remove, services_.end()); | 140 services_.erase(services_to_remove, services_.end()); |
| 137 } | 141 } |
| 138 | 142 |
| 139 void PlatformNotificationContextImpl::ReadNotificationData( | 143 void PlatformNotificationContextImpl::ReadNotificationData( |
| 140 int64_t notification_id, | 144 const std::string& notification_id, |
| 141 const GURL& origin, | 145 const GURL& origin, |
| 142 const ReadResultCallback& callback) { | 146 const ReadResultCallback& callback) { |
| 143 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 147 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 148 |
| 144 LazyInitialize( | 149 LazyInitialize( |
| 145 base::Bind(&PlatformNotificationContextImpl::DoReadNotificationData, this, | 150 base::Bind(&PlatformNotificationContextImpl::DoReadNotificationData, this, |
| 146 notification_id, origin, callback), | 151 notification_id, origin, callback), |
| 147 base::Bind(callback, false /* success */, NotificationDatabaseData())); | 152 base::Bind(callback, false /* success */, NotificationDatabaseData())); |
| 148 } | 153 } |
| 149 | 154 |
| 150 void PlatformNotificationContextImpl::DoReadNotificationData( | 155 void PlatformNotificationContextImpl::DoReadNotificationData( |
| 151 int64_t notification_id, | 156 const std::string& notification_id, |
| 152 const GURL& origin, | 157 const GURL& origin, |
| 153 const ReadResultCallback& callback) { | 158 const ReadResultCallback& callback) { |
| 154 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 159 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 155 | 160 |
| 156 NotificationDatabaseData database_data; | 161 NotificationDatabaseData database_data; |
| 157 NotificationDatabase::Status status = | 162 NotificationDatabase::Status status = |
| 158 database_->ReadNotificationData(notification_id, origin, &database_data); | 163 database_->ReadNotificationData(notification_id, origin, &database_data); |
| 159 | 164 |
| 160 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.ReadResult", status, | 165 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.ReadResult", status, |
| 161 NotificationDatabase::STATUS_COUNT); | 166 NotificationDatabase::STATUS_COUNT); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 } | 228 } |
| 224 | 229 |
| 225 void PlatformNotificationContextImpl::WriteNotificationData( | 230 void PlatformNotificationContextImpl::WriteNotificationData( |
| 226 const GURL& origin, | 231 const GURL& origin, |
| 227 const NotificationDatabaseData& database_data, | 232 const NotificationDatabaseData& database_data, |
| 228 const WriteResultCallback& callback) { | 233 const WriteResultCallback& callback) { |
| 229 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 234 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 230 LazyInitialize( | 235 LazyInitialize( |
| 231 base::Bind(&PlatformNotificationContextImpl::DoWriteNotificationData, | 236 base::Bind(&PlatformNotificationContextImpl::DoWriteNotificationData, |
| 232 this, origin, database_data, callback), | 237 this, origin, database_data, callback), |
| 233 base::Bind(callback, false /* success */, 0 /* notification_id */)); | 238 base::Bind(callback, false /* success */, "" /* notification_id */)); |
| 234 } | 239 } |
| 235 | 240 |
| 236 void PlatformNotificationContextImpl::DoWriteNotificationData( | 241 void PlatformNotificationContextImpl::DoWriteNotificationData( |
| 237 const GURL& origin, | 242 const GURL& origin, |
| 238 const NotificationDatabaseData& database_data, | 243 const NotificationDatabaseData& database_data, |
| 239 const WriteResultCallback& callback) { | 244 const WriteResultCallback& callback) { |
| 240 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 245 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 241 | 246 |
| 242 // Eagerly delete data for replaced notifications from the database. | 247 // Eagerly delete data for replaced notifications from the database. |
| 243 if (!database_data.notification_data.tag.empty()) { | 248 if (!database_data.notification_data.tag.empty()) { |
| 244 std::set<int64_t> deleted_notification_set; | 249 std::set<std::string> deleted_notification_ids; |
| 245 NotificationDatabase::Status delete_status = | 250 NotificationDatabase::Status delete_status = |
| 246 database_->DeleteAllNotificationDataForOrigin( | 251 database_->DeleteAllNotificationDataForOrigin( |
| 247 origin, database_data.notification_data.tag, | 252 origin, database_data.notification_data.tag, |
| 248 &deleted_notification_set); | 253 &deleted_notification_ids); |
| 249 | 254 |
| 250 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteBeforeWriteResult", | 255 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteBeforeWriteResult", |
| 251 delete_status, | 256 delete_status, |
| 252 NotificationDatabase::STATUS_COUNT); | 257 NotificationDatabase::STATUS_COUNT); |
| 253 | 258 |
| 254 // Unless the database was corrupted following this change, there is no | 259 // Unless the database was corrupted following this change, there is no |
| 255 // reason to bail out here in event of failure because the notification | 260 // reason to bail out here in event of failure because the notification |
| 256 // display logic will handle notification replacement for the user. | 261 // display logic will handle notification replacement for the user. |
| 257 if (delete_status == NotificationDatabase::STATUS_ERROR_CORRUPTED) { | 262 if (delete_status == NotificationDatabase::STATUS_ERROR_CORRUPTED) { |
| 258 DestroyDatabase(); | 263 DestroyDatabase(); |
| 259 | 264 |
| 260 BrowserThread::PostTask( | 265 BrowserThread::PostTask( |
| 261 BrowserThread::IO, FROM_HERE, | 266 BrowserThread::IO, FROM_HERE, |
| 262 base::Bind(callback, false /* success */, 0 /* notification_id */)); | 267 base::Bind(callback, false /* success */, "" /* notification_id */)); |
| 263 return; | 268 return; |
| 264 } | 269 } |
| 265 } | 270 } |
| 266 | 271 |
| 267 int64_t notification_id = 0; | 272 // Create a copy of the |database_data| to store a generated notification ID. |
| 273 NotificationDatabaseData write_database_data = database_data; |
| 274 write_database_data.notification_id = |
| 275 notification_id_generator_.GenerateForPersistentNotification( |
| 276 origin, database_data.notification_data.tag, |
| 277 database_->GetNextPersistentNotificationId()); |
| 278 |
| 268 NotificationDatabase::Status status = | 279 NotificationDatabase::Status status = |
| 269 database_->WriteNotificationData(origin, database_data, ¬ification_id); | 280 database_->WriteNotificationData(origin, write_database_data); |
| 270 | 281 |
| 271 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.WriteResult", status, | 282 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.WriteResult", status, |
| 272 NotificationDatabase::STATUS_COUNT); | 283 NotificationDatabase::STATUS_COUNT); |
| 273 | 284 |
| 274 if (status == NotificationDatabase::STATUS_OK) { | 285 if (status == NotificationDatabase::STATUS_OK) { |
| 275 DCHECK_GT(notification_id, 0); | 286 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 276 BrowserThread::PostTask( | 287 base::Bind(callback, true /* success */, |
| 277 BrowserThread::IO, FROM_HERE, | 288 write_database_data.notification_id)); |
| 278 base::Bind(callback, true /* success */, notification_id)); | 289 |
| 279 return; | 290 return; |
| 280 } | 291 } |
| 281 | 292 |
| 282 // Blow away the database if writing data failed due to corruption. | 293 // Blow away the database if writing data failed due to corruption. |
| 283 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) | 294 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) |
| 284 DestroyDatabase(); | 295 DestroyDatabase(); |
| 285 | 296 |
| 286 BrowserThread::PostTask( | 297 BrowserThread::PostTask( |
| 287 BrowserThread::IO, FROM_HERE, | 298 BrowserThread::IO, FROM_HERE, |
| 288 base::Bind(callback, false /* success */, 0 /* notification_id */)); | 299 base::Bind(callback, false /* success */, "" /* notification_id */)); |
| 289 } | 300 } |
| 290 | 301 |
| 291 void PlatformNotificationContextImpl::DeleteNotificationData( | 302 void PlatformNotificationContextImpl::DeleteNotificationData( |
| 292 int64_t notification_id, | 303 const std::string& notification_id, |
| 293 const GURL& origin, | 304 const GURL& origin, |
| 294 const DeleteResultCallback& callback) { | 305 const DeleteResultCallback& callback) { |
| 295 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 306 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 307 |
| 296 LazyInitialize( | 308 LazyInitialize( |
| 297 base::Bind(&PlatformNotificationContextImpl::DoDeleteNotificationData, | 309 base::Bind(&PlatformNotificationContextImpl::DoDeleteNotificationData, |
| 298 this, notification_id, origin, callback), | 310 this, notification_id, origin, callback), |
| 299 base::Bind(callback, false /* success */)); | 311 base::Bind(callback, false /* success */)); |
| 300 } | 312 } |
| 301 | 313 |
| 302 void PlatformNotificationContextImpl::DoDeleteNotificationData( | 314 void PlatformNotificationContextImpl::DoDeleteNotificationData( |
| 303 int64_t notification_id, | 315 const std::string& notification_id, |
| 304 const GURL& origin, | 316 const GURL& origin, |
| 305 const DeleteResultCallback& callback) { | 317 const DeleteResultCallback& callback) { |
| 306 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 318 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 307 | 319 |
| 308 NotificationDatabase::Status status = | 320 NotificationDatabase::Status status = |
| 309 database_->DeleteNotificationData(notification_id, origin); | 321 database_->DeleteNotificationData(notification_id, origin); |
| 310 | 322 |
| 311 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteResult", status, | 323 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteResult", status, |
| 312 NotificationDatabase::STATUS_COUNT); | 324 NotificationDatabase::STATUS_COUNT); |
| 313 | 325 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 335 this, pattern.GetOrigin(), registration_id), | 347 this, pattern.GetOrigin(), registration_id), |
| 336 base::Bind(&DoNothing)); | 348 base::Bind(&DoNothing)); |
| 337 } | 349 } |
| 338 | 350 |
| 339 void PlatformNotificationContextImpl:: | 351 void PlatformNotificationContextImpl:: |
| 340 DoDeleteNotificationsForServiceWorkerRegistration( | 352 DoDeleteNotificationsForServiceWorkerRegistration( |
| 341 const GURL& origin, | 353 const GURL& origin, |
| 342 int64_t service_worker_registration_id) { | 354 int64_t service_worker_registration_id) { |
| 343 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 355 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 344 | 356 |
| 345 std::set<int64_t> deleted_notifications_set; | 357 std::set<std::string> deleted_notification_ids; |
| 346 NotificationDatabase::Status status = | 358 NotificationDatabase::Status status = |
| 347 database_->DeleteAllNotificationDataForServiceWorkerRegistration( | 359 database_->DeleteAllNotificationDataForServiceWorkerRegistration( |
| 348 origin, service_worker_registration_id, &deleted_notifications_set); | 360 origin, service_worker_registration_id, &deleted_notification_ids); |
| 349 | 361 |
| 350 UMA_HISTOGRAM_ENUMERATION( | 362 UMA_HISTOGRAM_ENUMERATION( |
| 351 "Notifications.Database.DeleteServiceWorkerRegistrationResult", status, | 363 "Notifications.Database.DeleteServiceWorkerRegistrationResult", status, |
| 352 NotificationDatabase::STATUS_COUNT); | 364 NotificationDatabase::STATUS_COUNT); |
| 353 | 365 |
| 354 // Blow away the database if a corruption error occurred during the deletion. | 366 // Blow away the database if a corruption error occurred during the deletion. |
| 355 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) | 367 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) |
| 356 DestroyDatabase(); | 368 DestroyDatabase(); |
| 357 | 369 |
| 358 // TODO(peter): Close the notifications in |deleted_notifications_set|. See | 370 // TODO(peter): Close the notifications in |deleted_notification_ids|. See |
| 359 // https://crbug.com/532436. | 371 // https://crbug.com/532436. |
| 360 } | 372 } |
| 361 | 373 |
| 362 void PlatformNotificationContextImpl::OnStorageWiped() { | 374 void PlatformNotificationContextImpl::OnStorageWiped() { |
| 363 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 375 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 364 LazyInitialize( | 376 LazyInitialize( |
| 365 base::Bind( | 377 base::Bind( |
| 366 base::IgnoreResult(&PlatformNotificationContextImpl::DestroyDatabase), | 378 base::IgnoreResult(&PlatformNotificationContextImpl::DestroyDatabase), |
| 367 this), | 379 this), |
| 368 base::Bind(&DoNothing)); | 380 base::Bind(&DoNothing)); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 | 476 |
| 465 return path_.Append(kPlatformNotificationsDirectory); | 477 return path_.Append(kPlatformNotificationsDirectory); |
| 466 } | 478 } |
| 467 | 479 |
| 468 void PlatformNotificationContextImpl::SetTaskRunnerForTesting( | 480 void PlatformNotificationContextImpl::SetTaskRunnerForTesting( |
| 469 const scoped_refptr<base::SequencedTaskRunner>& task_runner) { | 481 const scoped_refptr<base::SequencedTaskRunner>& task_runner) { |
| 470 task_runner_ = task_runner; | 482 task_runner_ = task_runner; |
| 471 } | 483 } |
| 472 | 484 |
| 473 } // namespace content | 485 } // namespace content |
| OLD | NEW |