| 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 <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/barrier_closure.h" | 9 #include "base/barrier_closure.h" |
| 10 #include "base/base64url.h" | 10 #include "base/base64url.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 void RecordDeliveryStatus(content::PushDeliveryStatus status) { | 83 void RecordDeliveryStatus(content::PushDeliveryStatus status) { |
| 84 UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus", status, | 84 UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus", status, |
| 85 content::PUSH_DELIVERY_STATUS_LAST + 1); | 85 content::PUSH_DELIVERY_STATUS_LAST + 1); |
| 86 } | 86 } |
| 87 | 87 |
| 88 void RecordUnsubscribeReason(content::PushUnregistrationReason reason) { | 88 void RecordUnsubscribeReason(content::PushUnregistrationReason reason) { |
| 89 UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationReason", reason, | 89 UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationReason", reason, |
| 90 content::PUSH_UNREGISTRATION_REASON_LAST + 1); | 90 content::PUSH_UNREGISTRATION_REASON_LAST + 1); |
| 91 } | 91 } |
| 92 | 92 |
| 93 void RecordUnsubscribeGCMResult(gcm::GCMClient::Result result) { |
| 94 UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationGCMResult", result, |
| 95 gcm::GCMClient::LAST_RESULT + 1); |
| 96 } |
| 97 |
| 98 void RecordUnsubscribeIIDResult(InstanceID::Result result) { |
| 99 UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationIIDResult", result, |
| 100 InstanceID::LAST_RESULT + 1); |
| 101 } |
| 102 |
| 93 blink::WebPushPermissionStatus ToPushPermission( | 103 blink::WebPushPermissionStatus ToPushPermission( |
| 94 blink::mojom::PermissionStatus permission_status) { | 104 blink::mojom::PermissionStatus permission_status) { |
| 95 switch (permission_status) { | 105 switch (permission_status) { |
| 96 case blink::mojom::PermissionStatus::GRANTED: | 106 case blink::mojom::PermissionStatus::GRANTED: |
| 97 return blink::WebPushPermissionStatusGranted; | 107 return blink::WebPushPermissionStatusGranted; |
| 98 case blink::mojom::PermissionStatus::DENIED: | 108 case blink::mojom::PermissionStatus::DENIED: |
| 99 return blink::WebPushPermissionStatusDenied; | 109 return blink::WebPushPermissionStatusDenied; |
| 100 case blink::mojom::PermissionStatus::ASK: | 110 case blink::mojom::PermissionStatus::ASK: |
| 101 return blink::WebPushPermissionStatusPrompt; | 111 return blink::WebPushPermissionStatusPrompt; |
| 102 } | 112 } |
| 103 NOTREACHED(); | 113 NOTREACHED(); |
| 104 return blink::WebPushPermissionStatusDenied; | 114 return blink::WebPushPermissionStatusDenied; |
| 105 } | 115 } |
| 106 | 116 |
| 107 content::PushUnregistrationStatus ToUnregisterStatus( | |
| 108 InstanceID::Result result) { | |
| 109 switch (result) { | |
| 110 case InstanceID::SUCCESS: | |
| 111 return content::PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTERED; | |
| 112 case InstanceID::INVALID_PARAMETER: | |
| 113 case InstanceID::DISABLED: | |
| 114 case InstanceID::SERVER_ERROR: | |
| 115 case InstanceID::UNKNOWN_ERROR: | |
| 116 return content::PUSH_UNREGISTRATION_STATUS_PENDING_SERVICE_ERROR; | |
| 117 case InstanceID::ASYNC_OPERATION_PENDING: | |
| 118 case InstanceID::NETWORK_ERROR: | |
| 119 return content::PUSH_UNREGISTRATION_STATUS_PENDING_NETWORK_ERROR; | |
| 120 } | |
| 121 NOTREACHED(); | |
| 122 return content::PUSH_UNREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE; | |
| 123 } | |
| 124 | |
| 125 content::PushUnregistrationStatus ToUnregisterStatus( | |
| 126 gcm::GCMClient::Result gcm_result) { | |
| 127 switch (gcm_result) { | |
| 128 case gcm::GCMClient::SUCCESS: | |
| 129 return content::PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTERED; | |
| 130 case gcm::GCMClient::INVALID_PARAMETER: | |
| 131 case gcm::GCMClient::GCM_DISABLED: | |
| 132 case gcm::GCMClient::SERVER_ERROR: | |
| 133 case gcm::GCMClient::UNKNOWN_ERROR: | |
| 134 return content::PUSH_UNREGISTRATION_STATUS_PENDING_SERVICE_ERROR; | |
| 135 case gcm::GCMClient::ASYNC_OPERATION_PENDING: | |
| 136 case gcm::GCMClient::NETWORK_ERROR: | |
| 137 case gcm::GCMClient::TTL_EXCEEDED: | |
| 138 return content::PUSH_UNREGISTRATION_STATUS_PENDING_NETWORK_ERROR; | |
| 139 } | |
| 140 NOTREACHED(); | |
| 141 return content::PUSH_UNREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE; | |
| 142 } | |
| 143 | |
| 144 void GCMCallbackToUnregisterCallback( | |
| 145 const content::PushMessagingService::UnregisterCallback& callback, | |
| 146 gcm::GCMClient::Result result) { | |
| 147 DCHECK(!callback.is_null()); | |
| 148 callback.Run(ToUnregisterStatus(result)); | |
| 149 } | |
| 150 | |
| 151 void UnregisterCallbackToClosure(const base::Closure& closure, | 117 void UnregisterCallbackToClosure(const base::Closure& closure, |
| 152 content::PushUnregistrationStatus status) { | 118 content::PushUnregistrationStatus status) { |
| 153 DCHECK(!closure.is_null()); | 119 DCHECK(!closure.is_null()); |
| 154 closure.Run(); | 120 closure.Run(); |
| 155 } | 121 } |
| 156 | 122 |
| 157 #if BUILDFLAG(ENABLE_BACKGROUND) | 123 #if BUILDFLAG(ENABLE_BACKGROUND) |
| 158 bool UseBackgroundMode() { | 124 bool UseBackgroundMode() { |
| 159 // Note: if push is ever enabled in incognito, the background mode integration | 125 // Note: if push is ever enabled in incognito, the background mode integration |
| 160 // should not be enabled for it. | 126 // should not be enabled for it. |
| (...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 // Delete the mapping for this app_id, to guarantee that no messages get | 720 // Delete the mapping for this app_id, to guarantee that no messages get |
| 755 // delivered in future (even if unregistration fails). | 721 // delivered in future (even if unregistration fails). |
| 756 // TODO(johnme): Instead of deleting these app ids, store them elsewhere, and | 722 // TODO(johnme): Instead of deleting these app ids, store them elsewhere, and |
| 757 // retry unregistration if it fails due to network errors (crbug.com/465399). | 723 // retry unregistration if it fails due to network errors (crbug.com/465399). |
| 758 PushMessagingAppIdentifier app_identifier = | 724 PushMessagingAppIdentifier app_identifier = |
| 759 PushMessagingAppIdentifier::FindByAppId(profile_, app_id); | 725 PushMessagingAppIdentifier::FindByAppId(profile_, app_id); |
| 760 bool was_subscribed = !app_identifier.is_null(); | 726 bool was_subscribed = !app_identifier.is_null(); |
| 761 if (was_subscribed) | 727 if (was_subscribed) |
| 762 app_identifier.DeleteFromPrefs(profile_); | 728 app_identifier.DeleteFromPrefs(profile_); |
| 763 | 729 |
| 730 // Run the unsubscribe callback *before* asking the InstanceIDDriver/GCMDriver |
| 731 // to unsubscribe, since that's a slow process involving network retries, and |
| 732 // by this point enough local state has been deleted that the subscription is |
| 733 // inactive. Note that DeliverMessageCallback automatically unsubscribes if |
| 734 // messages are later received for a subscription that was locally deleted, |
| 735 // so as long as messages keep getting sent to it, the unsubscription should |
| 736 // eventually reach GCM servers even if this particular attempt fails. |
| 737 callback.Run( |
| 738 was_subscribed |
| 739 ? content::PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTERED |
| 740 : content::PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED); |
| 741 |
| 764 if (PushMessagingAppIdentifier::UseInstanceID(app_id)) { | 742 if (PushMessagingAppIdentifier::UseInstanceID(app_id)) { |
| 765 GetInstanceIDDriver()->GetInstanceID(app_id)->DeleteID(base::Bind( | 743 GetInstanceIDDriver()->GetInstanceID(app_id)->DeleteID( |
| 766 &PushMessagingServiceImpl::DidDeleteID, weak_factory_.GetWeakPtr(), | 744 base::Bind(&PushMessagingServiceImpl::DidDeleteID, |
| 767 app_id, was_subscribed, callback)); | 745 weak_factory_.GetWeakPtr(), app_id, was_subscribed)); |
| 768 | 746 |
| 769 } else { | 747 } else { |
| 770 auto unregister_callback = | 748 auto unregister_callback = |
| 771 base::Bind(&GCMCallbackToUnregisterCallback, | 749 base::Bind(&PushMessagingServiceImpl::DidUnregister, |
| 772 base::Bind(&PushMessagingServiceImpl::DidUnsubscribe, | 750 weak_factory_.GetWeakPtr(), was_subscribed); |
| 773 weak_factory_.GetWeakPtr(), | |
| 774 std::string() /* app_id_when_instance_id */, | |
| 775 was_subscribed, callback)); | |
| 776 #if defined(OS_ANDROID) | 751 #if defined(OS_ANDROID) |
| 777 // On Android the backend is different, and requires the original sender_id. | 752 // On Android the backend is different, and requires the original sender_id. |
| 778 // UnsubscribeBecausePermissionRevoked and | 753 // UnsubscribeBecausePermissionRevoked and |
| 779 // DidDeleteServiceWorkerRegistration sometimes call us with an empty one. | 754 // DidDeleteServiceWorkerRegistration sometimes call us with an empty one. |
| 780 if (sender_id.empty()) { | 755 if (sender_id.empty()) { |
| 781 unregister_callback.Run(gcm::GCMClient::INVALID_PARAMETER); | 756 unregister_callback.Run(gcm::GCMClient::INVALID_PARAMETER); |
| 782 } else { | 757 } else { |
| 783 GetGCMDriver()->UnregisterWithSenderId( | 758 GetGCMDriver()->UnregisterWithSenderId( |
| 784 app_id, NormalizeSenderInfo(sender_id), unregister_callback); | 759 app_id, NormalizeSenderInfo(sender_id), unregister_callback); |
| 785 } | 760 } |
| 786 #else | 761 #else |
| 787 GetGCMDriver()->Unregister(app_id, unregister_callback); | 762 GetGCMDriver()->Unregister(app_id, unregister_callback); |
| 788 #endif | 763 #endif |
| 789 } | 764 } |
| 790 } | 765 } |
| 791 | 766 |
| 767 void PushMessagingServiceImpl::DidUnregister(bool was_subscribed, |
| 768 gcm::GCMClient::Result result) { |
| 769 RecordUnsubscribeGCMResult(result); |
| 770 DidUnsubscribe(std::string() /* app_id_when_instance_id */, was_subscribed); |
| 771 } |
| 772 |
| 792 void PushMessagingServiceImpl::DidDeleteID(const std::string& app_id, | 773 void PushMessagingServiceImpl::DidDeleteID(const std::string& app_id, |
| 793 bool was_subscribed, | 774 bool was_subscribed, |
| 794 const UnregisterCallback& callback, | |
| 795 InstanceID::Result result) { | 775 InstanceID::Result result) { |
| 776 RecordUnsubscribeIIDResult(result); |
| 796 // DidUnsubscribe must be run asynchronously when passing a non-empty | 777 // DidUnsubscribe must be run asynchronously when passing a non-empty |
| 797 // |app_id_when_instance_id|, since it calls | 778 // |app_id_when_instance_id|, since it calls |
| 798 // InstanceIDDriver::RemoveInstanceID which deletes the InstanceID itself. | 779 // InstanceIDDriver::RemoveInstanceID which deletes the InstanceID itself. |
| 799 // Calling that immediately would cause a use-after-free in our caller. | 780 // Calling that immediately would cause a use-after-free in our caller. |
| 800 base::ThreadTaskRunnerHandle::Get()->PostTask( | 781 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 801 FROM_HERE, base::Bind(&PushMessagingServiceImpl::DidUnsubscribe, | 782 FROM_HERE, |
| 802 weak_factory_.GetWeakPtr(), app_id, was_subscribed, | 783 base::Bind(&PushMessagingServiceImpl::DidUnsubscribe, |
| 803 callback, ToUnregisterStatus(result))); | 784 weak_factory_.GetWeakPtr(), app_id, was_subscribed)); |
| 804 } | 785 } |
| 805 | 786 |
| 806 void PushMessagingServiceImpl::DidUnsubscribe( | 787 void PushMessagingServiceImpl::DidUnsubscribe( |
| 807 const std::string& app_id_when_instance_id, | 788 const std::string& app_id_when_instance_id, |
| 808 bool was_subscribed, | 789 bool was_subscribed) { |
| 809 const UnregisterCallback& callback, | |
| 810 content::PushUnregistrationStatus status) { | |
| 811 if (!app_id_when_instance_id.empty()) | 790 if (!app_id_when_instance_id.empty()) |
| 812 GetInstanceIDDriver()->RemoveInstanceID(app_id_when_instance_id); | 791 GetInstanceIDDriver()->RemoveInstanceID(app_id_when_instance_id); |
| 813 | 792 |
| 814 DCHECK(!callback.is_null()); | 793 if (was_subscribed) |
| 794 DecreasePushSubscriptionCount(1, false /* was_pending */); |
| 815 | 795 |
| 816 if (was_subscribed) { | 796 if (!unsubscribe_callback_for_testing_.is_null()) |
| 817 DecreasePushSubscriptionCount(1, false /* was_pending */); | 797 unsubscribe_callback_for_testing_.Run(); |
| 818 callback.Run(status); | 798 } |
| 819 } else { | 799 |
| 820 // Override status since there was no record of an existing subscription. | 800 void PushMessagingServiceImpl::SetUnsubscribeCallbackForTesting( |
| 821 callback.Run( | 801 const base::Closure& callback) { |
| 822 content::PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED); | 802 unsubscribe_callback_for_testing_ = callback; |
| 823 } | |
| 824 } | 803 } |
| 825 | 804 |
| 826 // DidDeleteServiceWorkerRegistration methods ---------------------------------- | 805 // DidDeleteServiceWorkerRegistration methods ---------------------------------- |
| 827 | 806 |
| 828 void PushMessagingServiceImpl::DidDeleteServiceWorkerRegistration( | 807 void PushMessagingServiceImpl::DidDeleteServiceWorkerRegistration( |
| 829 const GURL& origin, | 808 const GURL& origin, |
| 830 int64_t service_worker_registration_id) { | 809 int64_t service_worker_registration_id) { |
| 831 const PushMessagingAppIdentifier& app_identifier = | 810 const PushMessagingAppIdentifier& app_identifier = |
| 832 PushMessagingAppIdentifier::FindByServiceWorker( | 811 PushMessagingAppIdentifier::FindByServiceWorker( |
| 833 profile_, origin, service_worker_registration_id); | 812 profile_, origin, service_worker_registration_id); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 } | 984 } |
| 1006 | 985 |
| 1007 instance_id::InstanceIDDriver* PushMessagingServiceImpl::GetInstanceIDDriver() | 986 instance_id::InstanceIDDriver* PushMessagingServiceImpl::GetInstanceIDDriver() |
| 1008 const { | 987 const { |
| 1009 instance_id::InstanceIDProfileService* instance_id_profile_service = | 988 instance_id::InstanceIDProfileService* instance_id_profile_service = |
| 1010 instance_id::InstanceIDProfileServiceFactory::GetForProfile(profile_); | 989 instance_id::InstanceIDProfileServiceFactory::GetForProfile(profile_); |
| 1011 CHECK(instance_id_profile_service); | 990 CHECK(instance_id_profile_service); |
| 1012 CHECK(instance_id_profile_service->driver()); | 991 CHECK(instance_id_profile_service->driver()); |
| 1013 return instance_id_profile_service->driver(); | 992 return instance_id_profile_service->driver(); |
| 1014 } | 993 } |
| OLD | NEW |