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/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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 133 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 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 |
| 143 std::string PlatformNotificationContextImpl::GenerateNotificationId( | |
| 144 const GURL& origin, | |
| 145 const std::string& tag, | |
| 146 int64_t persistent_notification_id) { | |
| 147 return notification_id_generator_.GenerateForPersistentNotification( | |
| 148 origin, tag, persistent_notification_id); | |
| 149 } | |
| 150 | |
| 139 void PlatformNotificationContextImpl::ReadNotificationData( | 151 void PlatformNotificationContextImpl::ReadNotificationData( |
| 140 int64_t notification_id, | 152 const std::string& notification_id, |
| 141 const GURL& origin, | 153 const GURL& origin, |
| 142 const ReadResultCallback& callback) { | 154 const ReadResultCallback& callback) { |
| 143 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 155 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 156 | |
| 144 LazyInitialize( | 157 LazyInitialize( |
| 145 base::Bind(&PlatformNotificationContextImpl::DoReadNotificationData, this, | 158 base::Bind(&PlatformNotificationContextImpl::DoReadNotificationData, this, |
| 146 notification_id, origin, callback), | 159 notification_id, origin, callback), |
| 147 base::Bind(callback, false /* success */, NotificationDatabaseData())); | 160 base::Bind(callback, false /* success */, NotificationDatabaseData())); |
| 148 } | 161 } |
| 149 | 162 |
| 150 void PlatformNotificationContextImpl::DoReadNotificationData( | 163 void PlatformNotificationContextImpl::DoReadNotificationData( |
| 151 int64_t notification_id, | 164 const std::string& notification_id, |
| 152 const GURL& origin, | 165 const GURL& origin, |
| 153 const ReadResultCallback& callback) { | 166 const ReadResultCallback& callback) { |
| 154 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 167 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 155 | 168 |
| 156 NotificationDatabaseData database_data; | 169 NotificationDatabaseData database_data; |
| 157 NotificationDatabase::Status status = | 170 int64_t persistent_notification_id; |
| 158 database_->ReadNotificationData(notification_id, origin, &database_data); | 171 |
| 172 NotificationDatabase::Status status = database_->ReadIdAssociation( | |
|
johnme
2016/09/02 15:07:44
I guess this is the hacked in part you were talkin
Peter Beverloo
2016/09/05 15:11:01
No? This is kinda fine...
| |
| 173 notification_id, &persistent_notification_id); | |
| 174 | |
| 175 if (status == NotificationDatabase::STATUS_OK) { | |
| 176 status = database_->ReadNotificationData(persistent_notification_id, origin, | |
| 177 &database_data); | |
| 178 } | |
| 159 | 179 |
| 160 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.ReadResult", status, | 180 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.ReadResult", status, |
| 161 NotificationDatabase::STATUS_COUNT); | 181 NotificationDatabase::STATUS_COUNT); |
| 162 | 182 |
| 163 if (status == NotificationDatabase::STATUS_OK) { | 183 if (status == NotificationDatabase::STATUS_OK) { |
| 164 BrowserThread::PostTask( | 184 BrowserThread::PostTask( |
| 165 BrowserThread::IO, FROM_HERE, | 185 BrowserThread::IO, FROM_HERE, |
| 166 base::Bind(callback, true /* success */, database_data)); | 186 base::Bind(callback, true /* success */, database_data)); |
| 167 return; | 187 return; |
| 168 } | 188 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 } | 243 } |
| 224 | 244 |
| 225 void PlatformNotificationContextImpl::WriteNotificationData( | 245 void PlatformNotificationContextImpl::WriteNotificationData( |
| 226 const GURL& origin, | 246 const GURL& origin, |
| 227 const NotificationDatabaseData& database_data, | 247 const NotificationDatabaseData& database_data, |
| 228 const WriteResultCallback& callback) { | 248 const WriteResultCallback& callback) { |
| 229 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 249 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 230 LazyInitialize( | 250 LazyInitialize( |
| 231 base::Bind(&PlatformNotificationContextImpl::DoWriteNotificationData, | 251 base::Bind(&PlatformNotificationContextImpl::DoWriteNotificationData, |
| 232 this, origin, database_data, callback), | 252 this, origin, database_data, callback), |
| 233 base::Bind(callback, false /* success */, 0 /* notification_id */)); | 253 base::Bind(callback, false /* success */, "" /* notification_id */)); |
| 234 } | 254 } |
| 235 | 255 |
| 236 void PlatformNotificationContextImpl::DoWriteNotificationData( | 256 void PlatformNotificationContextImpl::DoWriteNotificationData( |
| 237 const GURL& origin, | 257 const GURL& origin, |
| 238 const NotificationDatabaseData& database_data, | 258 const NotificationDatabaseData& database_data, |
| 239 const WriteResultCallback& callback) { | 259 const WriteResultCallback& callback) { |
| 240 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 260 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 241 | 261 |
| 242 // Eagerly delete data for replaced notifications from the database. | 262 // Eagerly delete data for replaced notifications from the database. |
| 243 if (!database_data.notification_data.tag.empty()) { | 263 if (!database_data.notification_data.tag.empty()) { |
| 244 std::set<int64_t> deleted_notification_set; | 264 std::set<int64_t> deleted_notification_set; |
| 245 NotificationDatabase::Status delete_status = | 265 NotificationDatabase::Status delete_status = |
| 246 database_->DeleteAllNotificationDataForOrigin( | 266 database_->DeleteAllNotificationDataForOrigin( |
| 247 origin, database_data.notification_data.tag, | 267 origin, database_data.notification_data.tag, |
| 248 &deleted_notification_set); | 268 &deleted_notification_set); |
| 249 | 269 |
| 250 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteBeforeWriteResult", | 270 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteBeforeWriteResult", |
| 251 delete_status, | 271 delete_status, |
| 252 NotificationDatabase::STATUS_COUNT); | 272 NotificationDatabase::STATUS_COUNT); |
| 253 | 273 |
| 254 // Unless the database was corrupted following this change, there is no | 274 // Unless the database was corrupted following this change, there is no |
| 255 // reason to bail out here in event of failure because the notification | 275 // reason to bail out here in event of failure because the notification |
| 256 // display logic will handle notification replacement for the user. | 276 // display logic will handle notification replacement for the user. |
| 257 if (delete_status == NotificationDatabase::STATUS_ERROR_CORRUPTED) { | 277 if (delete_status == NotificationDatabase::STATUS_ERROR_CORRUPTED) { |
| 258 DestroyDatabase(); | 278 DestroyDatabase(); |
| 259 | 279 |
| 260 BrowserThread::PostTask( | 280 BrowserThread::PostTask( |
| 261 BrowserThread::IO, FROM_HERE, | 281 BrowserThread::IO, FROM_HERE, |
| 262 base::Bind(callback, false /* success */, 0 /* notification_id */)); | 282 base::Bind(callback, false /* success */, "" /* notification_id */)); |
| 263 return; | 283 return; |
| 264 } | 284 } |
| 265 } | 285 } |
| 266 | 286 |
| 267 int64_t notification_id = 0; | 287 int64_t persistent_notification_id = 0; |
| 268 NotificationDatabase::Status status = | 288 std::string notification_id; |
| 269 database_->WriteNotificationData(origin, database_data, ¬ification_id); | 289 |
| 290 NotificationDatabase::Status status = database_->WriteNotificationData( | |
| 291 origin, database_data, &persistent_notification_id); | |
| 292 if (status == NotificationDatabase::STATUS_OK) { | |
| 293 DCHECK_GT(persistent_notification_id, 0); | |
| 294 notification_id = | |
| 295 notification_id_generator_.GenerateForPersistentNotification( | |
| 296 origin, database_data.notification_data.tag, | |
| 297 persistent_notification_id); | |
| 298 | |
| 299 status = database_->StoreIdAssociation(notification_id, | |
| 300 persistent_notification_id); | |
| 301 } | |
| 270 | 302 |
| 271 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.WriteResult", status, | 303 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.WriteResult", status, |
| 272 NotificationDatabase::STATUS_COUNT); | 304 NotificationDatabase::STATUS_COUNT); |
| 273 | 305 |
| 274 if (status == NotificationDatabase::STATUS_OK) { | 306 if (status == NotificationDatabase::STATUS_OK) { |
| 275 DCHECK_GT(notification_id, 0); | |
| 276 BrowserThread::PostTask( | 307 BrowserThread::PostTask( |
| 277 BrowserThread::IO, FROM_HERE, | 308 BrowserThread::IO, FROM_HERE, |
| 278 base::Bind(callback, true /* success */, notification_id)); | 309 base::Bind(callback, true /* success */, notification_id)); |
| 310 | |
| 279 return; | 311 return; |
| 280 } | 312 } |
| 281 | 313 |
| 282 // Blow away the database if writing data failed due to corruption. | 314 // Blow away the database if writing data failed due to corruption. |
| 283 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) | 315 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) |
| 284 DestroyDatabase(); | 316 DestroyDatabase(); |
| 285 | 317 |
| 286 BrowserThread::PostTask( | 318 BrowserThread::PostTask( |
| 287 BrowserThread::IO, FROM_HERE, | 319 BrowserThread::IO, FROM_HERE, |
| 288 base::Bind(callback, false /* success */, 0 /* notification_id */)); | 320 base::Bind(callback, false /* success */, "" /* notification_id */)); |
| 289 } | 321 } |
| 290 | 322 |
| 291 void PlatformNotificationContextImpl::DeleteNotificationData( | 323 void PlatformNotificationContextImpl::DeleteNotificationData( |
| 292 int64_t notification_id, | 324 const std::string& notification_id, |
| 293 const GURL& origin, | 325 const GURL& origin, |
| 294 const DeleteResultCallback& callback) { | 326 const DeleteResultCallback& callback) { |
| 295 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 327 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 328 | |
| 296 LazyInitialize( | 329 LazyInitialize( |
| 297 base::Bind(&PlatformNotificationContextImpl::DoDeleteNotificationData, | 330 base::Bind(&PlatformNotificationContextImpl::DoDeleteNotificationData, |
| 298 this, notification_id, origin, callback), | 331 this, notification_id, origin, callback), |
| 299 base::Bind(callback, false /* success */)); | 332 base::Bind(callback, false /* success */)); |
| 300 } | 333 } |
| 301 | 334 |
| 302 void PlatformNotificationContextImpl::DoDeleteNotificationData( | 335 void PlatformNotificationContextImpl::DoDeleteNotificationData( |
| 303 int64_t notification_id, | 336 const std::string& notification_id, |
| 304 const GURL& origin, | 337 const GURL& origin, |
| 305 const DeleteResultCallback& callback) { | 338 const DeleteResultCallback& callback) { |
| 306 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 339 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 307 | 340 |
| 308 NotificationDatabase::Status status = | 341 int64_t persistent_notification_id; |
| 309 database_->DeleteNotificationData(notification_id, origin); | 342 |
| 343 NotificationDatabase::Status status = database_->ReadIdAssociation( | |
| 344 notification_id, &persistent_notification_id); | |
| 345 | |
| 346 if (status == NotificationDatabase::STATUS_OK) { | |
| 347 status = | |
| 348 database_->DeleteNotificationData(persistent_notification_id, origin); | |
| 349 } | |
| 310 | 350 |
| 311 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteResult", status, | 351 UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteResult", status, |
| 312 NotificationDatabase::STATUS_COUNT); | 352 NotificationDatabase::STATUS_COUNT); |
| 313 | 353 |
| 314 bool success = status == NotificationDatabase::STATUS_OK; | 354 bool success = status == NotificationDatabase::STATUS_OK || |
| 355 status == NotificationDatabase::STATUS_ERROR_NOT_FOUND; | |
|
johnme
2016/09/02 15:07:44
Seems reasonable. Does changing this have any side
Peter Beverloo
2016/09/05 15:11:01
No. LevelDB already returns STATUS_OK instead of E
| |
| 315 | 356 |
| 316 // Blow away the database if deleting data failed due to corruption. Following | 357 // Blow away the database if deleting data failed due to corruption. Following |
| 317 // the contract of the delete methods, consider this to be a success as the | 358 // the contract of the delete methods, consider this to be a success as the |
| 318 // caller's goal has been achieved: the data is gone. | 359 // caller's goal has been achieved: the data is gone. |
| 319 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) { | 360 if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) { |
| 320 DestroyDatabase(); | 361 DestroyDatabase(); |
| 321 success = true; | 362 success = true; |
| 322 } | 363 } |
| 323 | 364 |
| 324 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 365 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 | 505 |
| 465 return path_.Append(kPlatformNotificationsDirectory); | 506 return path_.Append(kPlatformNotificationsDirectory); |
| 466 } | 507 } |
| 467 | 508 |
| 468 void PlatformNotificationContextImpl::SetTaskRunnerForTesting( | 509 void PlatformNotificationContextImpl::SetTaskRunnerForTesting( |
| 469 const scoped_refptr<base::SequencedTaskRunner>& task_runner) { | 510 const scoped_refptr<base::SequencedTaskRunner>& task_runner) { |
| 470 task_runner_ = task_runner; | 511 task_runner_ = task_runner; |
| 471 } | 512 } |
| 472 | 513 |
| 473 } // namespace content | 514 } // namespace content |
| OLD | NEW |