Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Side by Side Diff: chrome/browser/push_messaging/push_messaging_service_impl.cc

Issue 1099093003: Push API: Forced notifications should use Notifications database (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address Peter's review nits Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "chrome/browser/push_messaging/push_messaging_service_impl.h" 5 #include "chrome/browser/push_messaging/push_messaging_service_impl.h"
6 6
7 #include <bitset> 7 #include <bitset>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/barrier_closure.h" 10 #include "base/barrier_closure.h"
(...skipping 19 matching lines...) Expand all
30 #include "chrome/common/chrome_switches.h" 30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/pref_names.h" 31 #include "chrome/common/pref_names.h"
32 #include "chrome/grit/generated_resources.h" 32 #include "chrome/grit/generated_resources.h"
33 #include "components/content_settings/core/browser/host_content_settings_map.h" 33 #include "components/content_settings/core/browser/host_content_settings_map.h"
34 #include "components/content_settings/core/common/permission_request_id.h" 34 #include "components/content_settings/core/common/permission_request_id.h"
35 #include "components/gcm_driver/gcm_driver.h" 35 #include "components/gcm_driver/gcm_driver.h"
36 #include "components/pref_registry/pref_registry_syncable.h" 36 #include "components/pref_registry/pref_registry_syncable.h"
37 #include "components/rappor/rappor_utils.h" 37 #include "components/rappor/rappor_utils.h"
38 #include "content/public/browser/browser_context.h" 38 #include "content/public/browser/browser_context.h"
39 #include "content/public/browser/browser_thread.h" 39 #include "content/public/browser/browser_thread.h"
40 #include "content/public/browser/notification_database_data.h"
41 #include "content/public/browser/platform_notification_context.h"
40 #include "content/public/browser/render_frame_host.h" 42 #include "content/public/browser/render_frame_host.h"
41 #include "content/public/browser/service_worker_context.h" 43 #include "content/public/browser/service_worker_context.h"
42 #include "content/public/browser/storage_partition.h" 44 #include "content/public/browser/storage_partition.h"
43 #include "content/public/browser/web_contents.h" 45 #include "content/public/browser/web_contents.h"
44 #include "content/public/common/child_process_host.h" 46 #include "content/public/common/child_process_host.h"
45 #include "content/public/common/content_switches.h" 47 #include "content/public/common/content_switches.h"
46 #include "content/public/common/platform_notification_data.h" 48 #include "content/public/common/platform_notification_data.h"
47 #include "content/public/common/push_messaging_status.h" 49 #include "content/public/common/push_messaging_status.h"
48 #include "third_party/skia/include/core/SkBitmap.h" 50 #include "third_party/skia/include/core/SkBitmap.h"
49 #include "ui/base/l10n/l10n_util.h" 51 #include "ui/base/l10n/l10n_util.h"
50 52
51 #if defined(OS_ANDROID) 53 #if defined(OS_ANDROID)
52 #include "chrome/browser/ui/android/tab_model/tab_model.h" 54 #include "chrome/browser/ui/android/tab_model/tab_model.h"
53 #include "chrome/browser/ui/android/tab_model/tab_model_list.h" 55 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
54 #else 56 #else
55 #include "chrome/browser/ui/browser.h" 57 #include "chrome/browser/ui/browser.h"
56 #include "chrome/browser/ui/browser_iterator.h" 58 #include "chrome/browser/ui/browser_iterator.h"
57 #include "chrome/browser/ui/tabs/tab_strip_model.h" 59 #include "chrome/browser/ui/tabs/tab_strip_model.h"
58 #endif 60 #endif
59 61
62 using content::BrowserThread;
63
60 namespace { 64 namespace {
61 const int kMaxRegistrations = 1000000; 65 const int kMaxRegistrations = 1000000;
62 66
63 void RecordDeliveryStatus(content::PushDeliveryStatus status) { 67 void RecordDeliveryStatus(content::PushDeliveryStatus status) {
64 UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus", 68 UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus",
65 status, 69 status,
66 content::PUSH_DELIVERY_STATUS_LAST + 1); 70 content::PUSH_DELIVERY_STATUS_LAST + 1);
67 } 71 }
68 72
69 void RecordUserVisibleStatus(content::PushUserVisibleStatus status) { 73 void RecordUserVisibleStatus(content::PushUserVisibleStatus status) {
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 case content::PUSH_DELIVERY_STATUS_NO_SERVICE_WORKER: 275 case content::PUSH_DELIVERY_STATUS_NO_SERVICE_WORKER:
272 Unregister(app_id_guid, message.sender_id, 276 Unregister(app_id_guid, message.sender_id,
273 base::Bind(&UnregisterCallbackToClosure, 277 base::Bind(&UnregisterCallbackToClosure,
274 message_handled_closure)); 278 message_handled_closure));
275 break; 279 break;
276 } 280 }
277 RecordDeliveryStatus(status); 281 RecordDeliveryStatus(status);
278 } 282 }
279 283
280 void PushMessagingServiceImpl::RequireUserVisibleUX( 284 void PushMessagingServiceImpl::RequireUserVisibleUX(
281 const GURL& requesting_origin, int64 service_worker_registration_id, 285 const GURL& requesting_origin, int64_t service_worker_registration_id,
282 const base::Closure& message_handled_closure) { 286 const base::Closure& message_handled_closure) {
287 DCHECK_CURRENTLY_ON(BrowserThread::UI);
283 #if defined(ENABLE_NOTIFICATIONS) 288 #if defined(ENABLE_NOTIFICATIONS)
284 // TODO(johnme): Relax this heuristic slightly. 289 // TODO(johnme): Relax this heuristic slightly.
285 PlatformNotificationServiceImpl* notification_service = 290 scoped_refptr<content::PlatformNotificationContext> notification_context =
286 PlatformNotificationServiceImpl::GetInstance(); 291 content::BrowserContext::GetStoragePartitionForSite(
287 // Can't use g_browser_process->notification_ui_manager(), since the test uses 292 profile_, requesting_origin)->GetPlatformNotificationContext();
288 // PlatformNotificationServiceImpl::SetNotificationUIManagerForTesting. 293 BrowserThread::PostTask(
289 // TODO(peter): Remove the need to use both APIs here once Notification.get() 294 BrowserThread::IO, FROM_HERE,
290 // is supported. 295 base::Bind(
291 int notification_count = notification_service->GetNotificationUIManager()-> 296 &content::PlatformNotificationContext
292 GetAllIdsByProfileAndSourceOrigin(profile_, requesting_origin).size(); 297 ::ReadAllNotificationDataForServiceWorkerRegistration,
298 notification_context,
299 requesting_origin, service_worker_registration_id,
300 base::Bind(
301 &PushMessagingServiceImpl::DidGetNotificationsFromDatabaseIOProxy,
302 weak_factory_.GetWeakPtr(),
303 requesting_origin, service_worker_registration_id,
304 message_handled_closure)));
305 #else
306 message_handled_closure.Run();
307 #endif // defined(ENABLE_NOTIFICATIONS)
308 }
309
310 // static
311 void PushMessagingServiceImpl::DidGetNotificationsFromDatabaseIOProxy(
312 const base::WeakPtr<PushMessagingServiceImpl>& ui_weak_ptr,
313 const GURL& requesting_origin,
314 int64_t service_worker_registration_id,
315 const base::Closure& message_handled_closure,
316 bool success,
317 const std::vector<content::NotificationDatabaseData>& data) {
318 DCHECK_CURRENTLY_ON(BrowserThread::IO);
319 BrowserThread::PostTask(
320 BrowserThread::UI, FROM_HERE,
321 base::Bind(&PushMessagingServiceImpl::DidGetNotificationsFromDatabase,
322 ui_weak_ptr,
323 requesting_origin, service_worker_registration_id,
324 message_handled_closure,
325 success, data));
326 }
327
328 void PushMessagingServiceImpl::DidGetNotificationsFromDatabase(
329 const GURL& requesting_origin, int64_t service_worker_registration_id,
330 const base::Closure& message_handled_closure,
331 bool success, const std::vector<content::NotificationDatabaseData>& data) {
332 DCHECK_CURRENTLY_ON(BrowserThread::UI);
293 // TODO(johnme): Hiding an existing notification should also count as a useful 333 // TODO(johnme): Hiding an existing notification should also count as a useful
294 // user-visible action done in response to a push message - but make sure that 334 // user-visible action done in response to a push message - but make sure that
295 // sending two messages in rapid succession which show then hide a 335 // sending two messages in rapid succession which show then hide a
296 // notification doesn't count. 336 // notification doesn't count.
337 int notification_count = success ? data.size() : 0;
297 bool notification_shown = notification_count > 0; 338 bool notification_shown = notification_count > 0;
298 339
299 bool notification_needed = true; 340 bool notification_needed = true;
300 // Sites with a currently visible tab don't need to show notifications. 341 // Sites with a currently visible tab don't need to show notifications.
301 #if defined(OS_ANDROID) 342 #if defined(OS_ANDROID)
302 for (auto it = TabModelList::begin(); it != TabModelList::end(); ++it) { 343 for (auto it = TabModelList::begin(); it != TabModelList::end(); ++it) {
303 Profile* profile = (*it)->GetProfile(); 344 Profile* profile = (*it)->GetProfile();
304 content::WebContents* active_web_contents = 345 content::WebContents* active_web_contents =
305 (*it)->GetActiveWebContents(); 346 (*it)->GetActiveWebContents();
306 #else 347 #else
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 381
341 // Don't track push messages that didn't show a notification but were exempt 382 // Don't track push messages that didn't show a notification but were exempt
342 // from needing to do so. 383 // from needing to do so.
343 if (notification_shown || notification_needed) { 384 if (notification_shown || notification_needed) {
344 content::ServiceWorkerContext* service_worker_context = 385 content::ServiceWorkerContext* service_worker_context =
345 content::BrowserContext::GetStoragePartitionForSite( 386 content::BrowserContext::GetStoragePartitionForSite(
346 profile_, requesting_origin)->GetServiceWorkerContext(); 387 profile_, requesting_origin)->GetServiceWorkerContext();
347 388
348 GetNotificationsShownByLastFewPushes( 389 GetNotificationsShownByLastFewPushes(
349 service_worker_context, service_worker_registration_id, 390 service_worker_context, service_worker_registration_id,
350 base::Bind(&PushMessagingServiceImpl::DidGetNotificationsShown, 391 base::Bind(&PushMessagingServiceImpl::DidGetNotificationsShownAndNeeded,
351 weak_factory_.GetWeakPtr(), 392 weak_factory_.GetWeakPtr(),
352 requesting_origin, service_worker_registration_id, 393 requesting_origin, service_worker_registration_id,
353 notification_shown, notification_needed, 394 notification_shown, notification_needed,
354 message_handled_closure)); 395 message_handled_closure));
355 } else { 396 } else {
356 RecordUserVisibleStatus( 397 RecordUserVisibleStatus(
357 content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_AND_NOT_SHOWN); 398 content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_AND_NOT_SHOWN);
358 message_handled_closure.Run(); 399 message_handled_closure.Run();
359 } 400 }
360 #else
361 message_handled_closure.Run();
362 #endif // defined(ENABLE_NOTIFICATIONS)
363 } 401 }
364 402
365 static void IgnoreResult(bool unused) { 403 static void IgnoreResult(bool unused) {
366 } 404 }
367 405
368 void PushMessagingServiceImpl::DidGetNotificationsShown( 406 void PushMessagingServiceImpl::DidGetNotificationsShownAndNeeded(
369 const GURL& requesting_origin, int64 service_worker_registration_id, 407 const GURL& requesting_origin, int64_t service_worker_registration_id,
370 bool notification_shown, bool notification_needed, 408 bool notification_shown, bool notification_needed,
371 const base::Closure& message_handled_closure, 409 const base::Closure& message_handled_closure,
372 const std::string& data, bool success, bool not_found) { 410 const std::string& data, bool success, bool not_found) {
411 DCHECK_CURRENTLY_ON(BrowserThread::UI);
373 content::ServiceWorkerContext* service_worker_context = 412 content::ServiceWorkerContext* service_worker_context =
374 content::BrowserContext::GetStoragePartitionForSite( 413 content::BrowserContext::GetStoragePartitionForSite(
375 profile_, requesting_origin)->GetServiceWorkerContext(); 414 profile_, requesting_origin)->GetServiceWorkerContext();
376 415
377 // We remember whether the last (up to) 10 pushes showed notifications. 416 // We remember whether the last (up to) 10 pushes showed notifications.
378 const size_t MISSED_NOTIFICATIONS_LENGTH = 10; 417 const size_t MISSED_NOTIFICATIONS_LENGTH = 10;
379 // data is a string like "0001000", where '0' means shown, and '1' means 418 // data is a string like "0001000", where '0' means shown, and '1' means
380 // needed but not shown. We manipulate it in bitset form. 419 // needed but not shown. We manipulate it in bitset form.
381 std::bitset<MISSED_NOTIFICATIONS_LENGTH> missed_notifications(data); 420 std::bitset<MISSED_NOTIFICATIONS_LENGTH> missed_notifications(data);
382 421
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 // TODO(johnme): The generic notification should probably automatically 461 // TODO(johnme): The generic notification should probably automatically
423 // close itself when the next push message arrives? 462 // close itself when the next push message arrives?
424 content::PlatformNotificationData notification_data; 463 content::PlatformNotificationData notification_data;
425 // TODO(johnme): Switch to FormatOriginForDisplay from crbug.com/402698 464 // TODO(johnme): Switch to FormatOriginForDisplay from crbug.com/402698
426 notification_data.title = base::UTF8ToUTF16(requesting_origin.host()); 465 notification_data.title = base::UTF8ToUTF16(requesting_origin.host());
427 notification_data.direction = 466 notification_data.direction =
428 content::PlatformNotificationData::NotificationDirectionLeftToRight; 467 content::PlatformNotificationData::NotificationDirectionLeftToRight;
429 notification_data.body = 468 notification_data.body =
430 l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY); 469 l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY);
431 notification_data.tag = kPushMessagingForcedNotificationTag; 470 notification_data.tag = kPushMessagingForcedNotificationTag;
432 notification_data.icon = GURL(); // TODO(johnme): Better icon? 471 notification_data.icon = GURL();
433 notification_data.silent = true; 472 notification_data.silent = true;
434 PlatformNotificationServiceImpl* notification_service = 473
435 PlatformNotificationServiceImpl::GetInstance(); 474 content::NotificationDatabaseData database_data;
436 notification_service->DisplayPersistentNotification( 475 database_data.origin = requesting_origin;
476 database_data.service_worker_registration_id =
477 service_worker_registration_id;
478 database_data.notification_data = notification_data;
479
480 scoped_refptr<content::PlatformNotificationContext> notification_context =
481 content::BrowserContext::GetStoragePartitionForSite(
482 profile_, requesting_origin)->GetPlatformNotificationContext();
483 BrowserThread::PostTask(
484 BrowserThread::IO, FROM_HERE,
485 base::Bind(
486 &content::PlatformNotificationContext::WriteNotificationData,
487 notification_context,
488 requesting_origin, database_data,
489 base::Bind(&PushMessagingServiceImpl::DidWriteNotificationDataIOProxy,
490 weak_factory_.GetWeakPtr(),
491 requesting_origin, notification_data,
492 message_handled_closure)));
493 }
494
495 // static
496 void PushMessagingServiceImpl::DidWriteNotificationDataIOProxy(
497 const base::WeakPtr<PushMessagingServiceImpl>& ui_weak_ptr,
498 const GURL& requesting_origin,
499 const content::PlatformNotificationData& notification_data,
500 const base::Closure& message_handled_closure,
501 bool success,
502 int64_t persistent_notification_id) {
503 DCHECK_CURRENTLY_ON(BrowserThread::IO);
504 BrowserThread::PostTask(
505 BrowserThread::UI, FROM_HERE,
506 base::Bind(&PushMessagingServiceImpl::DidWriteNotificationData,
507 ui_weak_ptr,
508 requesting_origin, notification_data, message_handled_closure,
509 success, persistent_notification_id));
510 }
511
512 void PushMessagingServiceImpl::DidWriteNotificationData(
513 const GURL& requesting_origin,
514 const content::PlatformNotificationData& notification_data,
515 const base::Closure& message_handled_closure,
516 bool success,
517 int64_t persistent_notification_id) {
518 DCHECK_CURRENTLY_ON(BrowserThread::UI);
519 if (!success) {
520 DLOG(ERROR) << "Writing forced notification to database should not fail";
521 message_handled_closure.Run();
522 return;
523 }
524 PlatformNotificationServiceImpl::GetInstance()->DisplayPersistentNotification(
437 profile_, 525 profile_,
438 service_worker_registration_id, 526 persistent_notification_id,
439 requesting_origin, 527 requesting_origin,
440 SkBitmap() /* icon */, 528 SkBitmap() /* icon */,
441 notification_data); 529 notification_data);
442 message_handled_closure.Run(); 530 message_handled_closure.Run();
443 } 531 }
444 532
445 void PushMessagingServiceImpl::SetMessageCallbackForTesting( 533 void PushMessagingServiceImpl::SetMessageCallbackForTesting(
446 const base::Closure& callback) { 534 const base::Closure& callback) {
447 message_callback_for_testing_ = callback; 535 message_callback_for_testing_ = callback;
448 } 536 }
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 CONTENT_SETTING_ALLOW; 905 CONTENT_SETTING_ALLOW;
818 } 906 }
819 907
820 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { 908 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const {
821 gcm::GCMProfileService* gcm_profile_service = 909 gcm::GCMProfileService* gcm_profile_service =
822 gcm::GCMProfileServiceFactory::GetForProfile(profile_); 910 gcm::GCMProfileServiceFactory::GetForProfile(profile_);
823 CHECK(gcm_profile_service); 911 CHECK(gcm_profile_service);
824 CHECK(gcm_profile_service->driver()); 912 CHECK(gcm_profile_service->driver());
825 return gcm_profile_service->driver(); 913 return gcm_profile_service->driver();
826 } 914 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698