Chromium Code Reviews| 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 | |
|
Peter Beverloo
2015/04/26 19:42:22
nit: I prefer to have DCHECKs validating the argum
| |
| 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 |