Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Side by Side Diff: chrome/browser/push_messaging/push_messaging_service_impl.cc

Issue 2675293003: Push API: Don't wait for network when unsubscribing (Closed)
Patch Set: Address peter's review comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/push_messaging/push_messaging_service_impl.h ('k') | components/gcm_driver/gcm_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698