| 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/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" |
| 11 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 12 #include "base/logging.h" | 14 #include "base/logging.h" |
| 13 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 14 #include "base/prefs/pref_service.h" | 16 #include "base/prefs/pref_service.h" |
| 15 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 17 #include "chrome/browser/browser_process.h" | 19 #include "chrome/browser/browser_process.h" |
| 18 #include "chrome/browser/notifications/notification_ui_manager.h" | 20 #include "chrome/browser/notifications/notification_ui_manager.h" |
| 19 #include "chrome/browser/notifications/platform_notification_service_impl.h" | 21 #include "chrome/browser/notifications/platform_notification_service_impl.h" |
| 20 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 case CONTENT_SETTING_BLOCK: | 78 case CONTENT_SETTING_BLOCK: |
| 77 return blink::WebPushPermissionStatusDenied; | 79 return blink::WebPushPermissionStatusDenied; |
| 78 case CONTENT_SETTING_ASK: | 80 case CONTENT_SETTING_ASK: |
| 79 return blink::WebPushPermissionStatusDefault; | 81 return blink::WebPushPermissionStatusDefault; |
| 80 default: | 82 default: |
| 81 NOTREACHED(); | 83 NOTREACHED(); |
| 82 return blink::WebPushPermissionStatusDenied; | 84 return blink::WebPushPermissionStatusDenied; |
| 83 } | 85 } |
| 84 } | 86 } |
| 85 | 87 |
| 88 void UnregisterCallbackToClosure( |
| 89 const base::Closure& closure, content::PushUnregistrationStatus status) { |
| 90 closure.Run(); |
| 91 } |
| 92 |
| 86 } // namespace | 93 } // namespace |
| 87 | 94 |
| 88 // static | 95 // static |
| 89 void PushMessagingServiceImpl::RegisterProfilePrefs( | 96 void PushMessagingServiceImpl::RegisterProfilePrefs( |
| 90 user_prefs::PrefRegistrySyncable* registry) { | 97 user_prefs::PrefRegistrySyncable* registry) { |
| 91 registry->RegisterIntegerPref( | 98 registry->RegisterIntegerPref( |
| 92 prefs::kPushMessagingRegistrationCount, | 99 prefs::kPushMessagingRegistrationCount, |
| 93 0, | 100 0, |
| 94 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 101 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 95 PushMessagingApplicationId::RegisterProfilePrefs(registry); | 102 PushMessagingApplicationId::RegisterProfilePrefs(registry); |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 } | 327 } |
| 321 #endif | 328 #endif |
| 322 | 329 |
| 323 // Don't track push messages that didn't show a notification but were exempt | 330 // Don't track push messages that didn't show a notification but were exempt |
| 324 // from needing to do so. | 331 // from needing to do so. |
| 325 if (notification_shown || notification_needed) { | 332 if (notification_shown || notification_needed) { |
| 326 content::ServiceWorkerContext* service_worker_context = | 333 content::ServiceWorkerContext* service_worker_context = |
| 327 content::BrowserContext::GetStoragePartitionForSite( | 334 content::BrowserContext::GetStoragePartitionForSite( |
| 328 profile_, requesting_origin)->GetServiceWorkerContext(); | 335 profile_, requesting_origin)->GetServiceWorkerContext(); |
| 329 | 336 |
| 330 PushMessagingService::GetNotificationsShownByLastFewPushes( | 337 GetNotificationsShownByLastFewPushes( |
| 331 service_worker_context, service_worker_registration_id, | 338 service_worker_context, service_worker_registration_id, |
| 332 base::Bind(&PushMessagingServiceImpl::DidGetNotificationsShown, | 339 base::Bind(&PushMessagingServiceImpl::DidGetNotificationsShown, |
| 333 weak_factory_.GetWeakPtr(), | 340 weak_factory_.GetWeakPtr(), |
| 334 requesting_origin, service_worker_registration_id, | 341 requesting_origin, service_worker_registration_id, |
| 335 notification_shown, notification_needed)); | 342 notification_shown, notification_needed)); |
| 336 } else { | 343 } else { |
| 337 RecordUserVisibleStatus( | 344 RecordUserVisibleStatus( |
| 338 content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_AND_NOT_SHOWN); | 345 content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_AND_NOT_SHOWN); |
| 339 } | 346 } |
| 340 #endif // defined(ENABLE_NOTIFICATIONS) | 347 #endif // defined(ENABLE_NOTIFICATIONS) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 358 std::bitset<MISSED_NOTIFICATIONS_LENGTH> missed_notifications(data); | 365 std::bitset<MISSED_NOTIFICATIONS_LENGTH> missed_notifications(data); |
| 359 | 366 |
| 360 bool needed_but_not_shown = notification_needed && !notification_shown; | 367 bool needed_but_not_shown = notification_needed && !notification_shown; |
| 361 | 368 |
| 362 // New entries go at the end, and old ones are shifted off the beginning once | 369 // New entries go at the end, and old ones are shifted off the beginning once |
| 363 // the history length is exceeded. | 370 // the history length is exceeded. |
| 364 missed_notifications <<= 1; | 371 missed_notifications <<= 1; |
| 365 missed_notifications[0] = needed_but_not_shown; | 372 missed_notifications[0] = needed_but_not_shown; |
| 366 std::string updated_data(missed_notifications. | 373 std::string updated_data(missed_notifications. |
| 367 to_string<char, std::string::traits_type, std::string::allocator_type>()); | 374 to_string<char, std::string::traits_type, std::string::allocator_type>()); |
| 368 PushMessagingService::SetNotificationsShownByLastFewPushes( | 375 SetNotificationsShownByLastFewPushes( |
| 369 service_worker_context, service_worker_registration_id, | 376 service_worker_context, service_worker_registration_id, |
| 370 requesting_origin, updated_data, | 377 requesting_origin, updated_data, |
| 371 base::Bind(&IgnoreResult)); // This is a heuristic; ignore failure. | 378 base::Bind(&IgnoreResult)); // This is a heuristic; ignore failure. |
| 372 | 379 |
| 373 if (notification_shown) { | 380 if (notification_shown) { |
| 374 RecordUserVisibleStatus( | 381 RecordUserVisibleStatus( |
| 375 notification_needed | 382 notification_needed |
| 376 ? content::PUSH_USER_VISIBLE_STATUS_REQUIRED_AND_SHOWN | 383 ? content::PUSH_USER_VISIBLE_STATUS_REQUIRED_AND_SHOWN |
| 377 : content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_BUT_SHOWN); | 384 : content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_BUT_SHOWN); |
| 378 return; | 385 return; |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 void PushMessagingServiceImpl::OnContentSettingChanged( | 695 void PushMessagingServiceImpl::OnContentSettingChanged( |
| 689 const ContentSettingsPattern& primary_pattern, | 696 const ContentSettingsPattern& primary_pattern, |
| 690 const ContentSettingsPattern& secondary_pattern, | 697 const ContentSettingsPattern& secondary_pattern, |
| 691 ContentSettingsType content_type, | 698 ContentSettingsType content_type, |
| 692 std::string resource_identifier) { | 699 std::string resource_identifier) { |
| 693 if (content_type != CONTENT_SETTINGS_TYPE_PUSH_MESSAGING && | 700 if (content_type != CONTENT_SETTINGS_TYPE_PUSH_MESSAGING && |
| 694 content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { | 701 content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { |
| 695 return; | 702 return; |
| 696 } | 703 } |
| 697 | 704 |
| 698 for (const auto& id : PushMessagingApplicationId::GetAll(profile_)) { | 705 std::vector<PushMessagingApplicationId> all_app_ids = |
| 706 PushMessagingApplicationId::GetAll(profile_); |
| 707 |
| 708 base::Closure barrier_closure = base::BarrierClosure( |
| 709 all_app_ids.size(), |
| 710 content_setting_changed_callback_for_testing_.is_null() |
| 711 ? base::Bind(&base::DoNothing) |
| 712 : content_setting_changed_callback_for_testing_); |
| 713 |
| 714 for (const auto& id : all_app_ids) { |
| 699 // If |primary_pattern| is not valid, we should always check for a | 715 // If |primary_pattern| is not valid, we should always check for a |
| 700 // permission change because it can happen for example when the entire | 716 // permission change because it can happen for example when the entire |
| 701 // Push or Notifications permissions are cleared. | 717 // Push or Notifications permissions are cleared. |
| 702 // Otherwise, the permission should be checked if the pattern matches the | 718 // Otherwise, the permission should be checked if the pattern matches the |
| 703 // origin. | 719 // origin. |
| 704 if (primary_pattern.IsValid() && !primary_pattern.Matches(id.origin())) | 720 if (primary_pattern.IsValid() && !primary_pattern.Matches(id.origin())) { |
| 721 barrier_closure.Run(); |
| 705 continue; | 722 continue; |
| 723 } |
| 706 | 724 |
| 707 if (HasPermission(id.origin())) | 725 if (HasPermission(id.origin())) { |
| 726 barrier_closure.Run(); |
| 708 continue; | 727 continue; |
| 728 } |
| 709 | 729 |
| 710 PushMessagingService::GetSenderId( | 730 GetSenderId( |
| 711 profile_, id.origin(), id.service_worker_registration_id(), | 731 profile_, id.origin(), id.service_worker_registration_id(), |
| 712 base::Bind( | 732 base::Bind( |
| 713 &PushMessagingServiceImpl::UnregisterBecausePermissionRevoked, | 733 &PushMessagingServiceImpl::UnregisterBecausePermissionRevoked, |
| 714 weak_factory_.GetWeakPtr(), id)); | 734 weak_factory_.GetWeakPtr(), id, barrier_closure)); |
| 715 } | 735 } |
| 716 } | 736 } |
| 717 | 737 |
| 718 void PushMessagingServiceImpl::UnregisterBecausePermissionRevoked( | 738 void PushMessagingServiceImpl::UnregisterBecausePermissionRevoked( |
| 719 const PushMessagingApplicationId& id, | 739 const PushMessagingApplicationId& id, const base::Closure& closure, |
| 720 const std::string& sender_id, bool success, bool not_found) { | 740 const std::string& sender_id, bool success, bool not_found) { |
| 741 base::Closure barrier_closure = base::BarrierClosure(2, closure); |
| 742 |
| 721 // Unregister the PushMessagingApplicationId with the push service. | 743 // Unregister the PushMessagingApplicationId with the push service. |
| 722 Unregister(id.app_id_guid(), sender_id, UnregisterCallback()); | 744 Unregister(id.app_id_guid(), sender_id, |
| 745 base::Bind(&UnregisterCallbackToClosure, barrier_closure)); |
| 723 | 746 |
| 724 // Clear the associated service worker push registration id. | 747 // Clear the associated service worker push registration id. |
| 725 PushMessagingService::ClearPushRegistrationID( | 748 ClearPushRegistrationID(profile_, id.origin(), |
| 726 profile_, id.origin(), id.service_worker_registration_id()); | 749 id.service_worker_registration_id(), barrier_closure); |
| 750 } |
| 751 |
| 752 void PushMessagingServiceImpl::SetContentSettingChangedCallbackForTesting( |
| 753 const base::Closure& callback) { |
| 754 content_setting_changed_callback_for_testing_ = callback; |
| 727 } | 755 } |
| 728 | 756 |
| 729 // KeyedService methods ------------------------------------------------------- | 757 // KeyedService methods ------------------------------------------------------- |
| 730 | 758 |
| 731 void PushMessagingServiceImpl::Shutdown() { | 759 void PushMessagingServiceImpl::Shutdown() { |
| 732 GetGCMDriver()->RemoveAppHandler(kPushMessagingApplicationIdPrefix); | 760 GetGCMDriver()->RemoveAppHandler(kPushMessagingApplicationIdPrefix); |
| 733 } | 761 } |
| 734 | 762 |
| 735 // Helper methods -------------------------------------------------------------- | 763 // Helper methods -------------------------------------------------------------- |
| 736 | 764 |
| 737 bool PushMessagingServiceImpl::HasPermission(const GURL& origin) { | 765 bool PushMessagingServiceImpl::HasPermission(const GURL& origin) { |
| 738 PushMessagingPermissionContext* permission_context = | 766 PushMessagingPermissionContext* permission_context = |
| 739 PushMessagingPermissionContextFactory::GetForProfile(profile_); | 767 PushMessagingPermissionContextFactory::GetForProfile(profile_); |
| 740 DCHECK(permission_context); | 768 DCHECK(permission_context); |
| 741 | 769 |
| 742 return permission_context->GetPermissionStatus(origin, origin) == | 770 return permission_context->GetPermissionStatus(origin, origin) == |
| 743 CONTENT_SETTING_ALLOW; | 771 CONTENT_SETTING_ALLOW; |
| 744 } | 772 } |
| 745 | 773 |
| 746 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { | 774 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { |
| 747 gcm::GCMProfileService* gcm_profile_service = | 775 gcm::GCMProfileService* gcm_profile_service = |
| 748 gcm::GCMProfileServiceFactory::GetForProfile(profile_); | 776 gcm::GCMProfileServiceFactory::GetForProfile(profile_); |
| 749 CHECK(gcm_profile_service); | 777 CHECK(gcm_profile_service); |
| 750 CHECK(gcm_profile_service->driver()); | 778 CHECK(gcm_profile_service->driver()); |
| 751 return gcm_profile_service->driver(); | 779 return gcm_profile_service->driver(); |
| 752 } | 780 } |
| OLD | NEW |