OLD | NEW |
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 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 content::ServiceWorkerContext* service_worker_context = | 376 content::ServiceWorkerContext* service_worker_context = |
377 content::BrowserContext::GetStoragePartitionForSite( | 377 content::BrowserContext::GetStoragePartitionForSite( |
378 profile_, requesting_origin)->GetServiceWorkerContext(); | 378 profile_, requesting_origin)->GetServiceWorkerContext(); |
379 | 379 |
380 // We remember whether the last (up to) 10 pushes showed notifications. | 380 // We remember whether the last (up to) 10 pushes showed notifications. |
381 const size_t MISSED_NOTIFICATIONS_LENGTH = 10; | 381 const size_t MISSED_NOTIFICATIONS_LENGTH = 10; |
382 // data is a string like "0001000", where '0' means shown, and '1' means | 382 // data is a string like "0001000", where '0' means shown, and '1' means |
383 // needed but not shown. We manipulate it in bitset form. | 383 // needed but not shown. We manipulate it in bitset form. |
384 std::bitset<MISSED_NOTIFICATIONS_LENGTH> missed_notifications(data); | 384 std::bitset<MISSED_NOTIFICATIONS_LENGTH> missed_notifications(data); |
385 | 385 |
| 386 DCHECK(notification_shown || notification_needed); // Caller must ensure this |
386 bool needed_but_not_shown = notification_needed && !notification_shown; | 387 bool needed_but_not_shown = notification_needed && !notification_shown; |
387 | 388 |
388 // New entries go at the end, and old ones are shifted off the beginning once | 389 // New entries go at the end, and old ones are shifted off the beginning once |
389 // the history length is exceeded. | 390 // the history length is exceeded. |
390 missed_notifications <<= 1; | 391 missed_notifications <<= 1; |
391 missed_notifications[0] = needed_but_not_shown; | 392 missed_notifications[0] = needed_but_not_shown; |
392 std::string updated_data(missed_notifications. | 393 std::string updated_data(missed_notifications. |
393 to_string<char, std::string::traits_type, std::string::allocator_type>()); | 394 to_string<char, std::string::traits_type, std::string::allocator_type>()); |
394 SetNotificationsShownByLastFewPushes( | 395 SetNotificationsShownByLastFewPushes( |
395 service_worker_context, service_worker_registration_id, | 396 service_worker_context, service_worker_registration_id, |
396 requesting_origin, updated_data, | 397 requesting_origin, updated_data, |
397 base::Bind(&IgnoreResult)); // This is a heuristic; ignore failure. | 398 base::Bind(&IgnoreResult)); // This is a heuristic; ignore failure. |
398 | 399 |
399 if (notification_shown) { | 400 if (notification_shown) { |
400 RecordUserVisibleStatus( | 401 RecordUserVisibleStatus( |
401 notification_needed | 402 notification_needed |
402 ? content::PUSH_USER_VISIBLE_STATUS_REQUIRED_AND_SHOWN | 403 ? content::PUSH_USER_VISIBLE_STATUS_REQUIRED_AND_SHOWN |
403 : content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_BUT_SHOWN); | 404 : content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_BUT_SHOWN); |
404 message_handled_closure.Run(); | 405 message_handled_closure.Run(); |
405 return; | 406 return; |
406 } | 407 } |
407 if (needed_but_not_shown) { | 408 DCHECK(needed_but_not_shown); |
408 if (missed_notifications.count() <= 1) { // apply grace | 409 if (missed_notifications.count() <= 1) { // Apply grace. |
409 RecordUserVisibleStatus( | |
410 content::PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_USED_GRACE); | |
411 message_handled_closure.Run(); | |
412 return; | |
413 } | |
414 RecordUserVisibleStatus( | 410 RecordUserVisibleStatus( |
415 content:: | 411 content::PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_USED_GRACE); |
416 PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_GRACE_EXCEEDED); | |
417 rappor::SampleDomainAndRegistryFromGURL( | |
418 g_browser_process->rappor_service(), | |
419 "PushMessaging.GenericNotificationShown.Origin", | |
420 requesting_origin); | |
421 // The site failed to show a notification when one was needed, and they have | |
422 // already failed once in the previous 10 push messages, so we will show a | |
423 // generic notification. See https://crbug.com/437277. | |
424 // TODO(johnme): The generic notification should probably automatically | |
425 // close itself when the next push message arrives? | |
426 content::PlatformNotificationData notification_data; | |
427 // TODO(johnme): Switch to FormatOriginForDisplay from crbug.com/402698 | |
428 notification_data.title = base::UTF8ToUTF16(requesting_origin.host()); | |
429 notification_data.direction = | |
430 content::PlatformNotificationData::NotificationDirectionLeftToRight; | |
431 notification_data.body = | |
432 l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY); | |
433 notification_data.tag = kPushMessagingForcedNotificationTag; | |
434 notification_data.icon = GURL(); // TODO(johnme): Better icon? | |
435 notification_data.silent = true; | |
436 PlatformNotificationServiceImpl* notification_service = | |
437 PlatformNotificationServiceImpl::GetInstance(); | |
438 notification_service->DisplayPersistentNotification( | |
439 profile_, | |
440 service_worker_registration_id, | |
441 requesting_origin, | |
442 SkBitmap() /* icon */, | |
443 notification_data); | |
444 message_handled_closure.Run(); | 412 message_handled_closure.Run(); |
| 413 return; |
445 } | 414 } |
| 415 RecordUserVisibleStatus( |
| 416 content:: |
| 417 PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_GRACE_EXCEEDED); |
| 418 rappor::SampleDomainAndRegistryFromGURL( |
| 419 g_browser_process->rappor_service(), |
| 420 "PushMessaging.GenericNotificationShown.Origin", |
| 421 requesting_origin); |
| 422 // The site failed to show a notification when one was needed, and they have |
| 423 // already failed once in the previous 10 push messages, so we will show a |
| 424 // generic notification. See https://crbug.com/437277. |
| 425 // TODO(johnme): The generic notification should probably automatically |
| 426 // close itself when the next push message arrives? |
| 427 content::PlatformNotificationData notification_data; |
| 428 // TODO(johnme): Switch to FormatOriginForDisplay from crbug.com/402698 |
| 429 notification_data.title = base::UTF8ToUTF16(requesting_origin.host()); |
| 430 notification_data.direction = |
| 431 content::PlatformNotificationData::NotificationDirectionLeftToRight; |
| 432 notification_data.body = |
| 433 l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY); |
| 434 notification_data.tag = kPushMessagingForcedNotificationTag; |
| 435 notification_data.icon = GURL(); // TODO(johnme): Better icon? |
| 436 notification_data.silent = true; |
| 437 PlatformNotificationServiceImpl* notification_service = |
| 438 PlatformNotificationServiceImpl::GetInstance(); |
| 439 notification_service->DisplayPersistentNotification( |
| 440 profile_, |
| 441 service_worker_registration_id, |
| 442 requesting_origin, |
| 443 SkBitmap() /* icon */, |
| 444 notification_data); |
| 445 message_handled_closure.Run(); |
446 } | 446 } |
447 | 447 |
448 void PushMessagingServiceImpl::SetMessageCallbackForTesting( | 448 void PushMessagingServiceImpl::SetMessageCallbackForTesting( |
449 const base::Closure& callback) { | 449 const base::Closure& callback) { |
450 message_callback_for_testing_ = callback; | 450 message_callback_for_testing_ = callback; |
451 } | 451 } |
452 | 452 |
453 // Other gcm::GCMAppHandler methods ------------------------------------------- | 453 // Other gcm::GCMAppHandler methods ------------------------------------------- |
454 | 454 |
455 void PushMessagingServiceImpl::OnMessagesDeleted(const std::string& app_id) { | 455 void PushMessagingServiceImpl::OnMessagesDeleted(const std::string& app_id) { |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 CONTENT_SETTING_ALLOW; | 820 CONTENT_SETTING_ALLOW; |
821 } | 821 } |
822 | 822 |
823 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { | 823 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { |
824 gcm::GCMProfileService* gcm_profile_service = | 824 gcm::GCMProfileService* gcm_profile_service = |
825 gcm::GCMProfileServiceFactory::GetForProfile(profile_); | 825 gcm::GCMProfileServiceFactory::GetForProfile(profile_); |
826 CHECK(gcm_profile_service); | 826 CHECK(gcm_profile_service); |
827 CHECK(gcm_profile_service->driver()); | 827 CHECK(gcm_profile_service->driver()); |
828 return gcm_profile_service->driver(); | 828 return gcm_profile_service->driver(); |
829 } | 829 } |
OLD | NEW |