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 |