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 |