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 |