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 <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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 "Chrome currently only supports the Push API for subscriptions that will " | 76 "Chrome currently only supports the Push API for subscriptions that will " |
| 77 "result in user-visible messages. You can indicate this by calling " | 77 "result in user-visible messages. You can indicate this by calling " |
| 78 "pushManager.subscribe({userVisibleOnly: true}) instead. See " | 78 "pushManager.subscribe({userVisibleOnly: true}) instead. See " |
| 79 "https://goo.gl/yqv4Q4 for more details."; | 79 "https://goo.gl/yqv4Q4 for more details."; |
| 80 | 80 |
| 81 void RecordDeliveryStatus(content::PushDeliveryStatus status) { | 81 void RecordDeliveryStatus(content::PushDeliveryStatus status) { |
| 82 UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus", status, | 82 UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus", status, |
| 83 content::PUSH_DELIVERY_STATUS_LAST + 1); | 83 content::PUSH_DELIVERY_STATUS_LAST + 1); |
| 84 } | 84 } |
| 85 | 85 |
| 86 void RecordUnsubscribeReason(content::PushUnregistrationReason reason) { | |
| 87 UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationReason", reason, | |
| 88 content::PUSH_UNREGISTRATION_REASON_LAST + 1); | |
| 89 } | |
| 90 | |
| 86 blink::WebPushPermissionStatus ToPushPermission( | 91 blink::WebPushPermissionStatus ToPushPermission( |
| 87 blink::mojom::PermissionStatus permission_status) { | 92 blink::mojom::PermissionStatus permission_status) { |
| 88 switch (permission_status) { | 93 switch (permission_status) { |
| 89 case blink::mojom::PermissionStatus::GRANTED: | 94 case blink::mojom::PermissionStatus::GRANTED: |
| 90 return blink::WebPushPermissionStatusGranted; | 95 return blink::WebPushPermissionStatusGranted; |
| 91 case blink::mojom::PermissionStatus::DENIED: | 96 case blink::mojom::PermissionStatus::DENIED: |
| 92 return blink::WebPushPermissionStatusDenied; | 97 return blink::WebPushPermissionStatusDenied; |
| 93 case blink::mojom::PermissionStatus::ASK: | 98 case blink::mojom::PermissionStatus::ASK: |
| 94 return blink::WebPushPermissionStatusPrompt; | 99 return blink::WebPushPermissionStatusPrompt; |
| 95 default: | 100 default: |
| 96 NOTREACHED(); | 101 NOTREACHED(); |
| 97 return blink::WebPushPermissionStatusDenied; | 102 return blink::WebPushPermissionStatusDenied; |
| 98 } | 103 } |
| 99 } | 104 } |
| 100 | 105 |
| 106 content::PushUnregistrationStatus ToUnregisterStatus( | |
| 107 InstanceID::Result result) { | |
| 108 switch (result) { | |
| 109 case InstanceID::SUCCESS: | |
| 110 return content::PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTERED; | |
| 111 case InstanceID::INVALID_PARAMETER: | |
| 112 case InstanceID::DISABLED: | |
| 113 case InstanceID::SERVER_ERROR: | |
| 114 case InstanceID::UNKNOWN_ERROR: | |
| 115 return content::PUSH_UNREGISTRATION_STATUS_PENDING_SERVICE_ERROR; | |
| 116 case InstanceID::ASYNC_OPERATION_PENDING: | |
| 117 case InstanceID::NETWORK_ERROR: | |
| 118 return content::PUSH_UNREGISTRATION_STATUS_PENDING_NETWORK_ERROR; | |
| 119 } | |
|
Peter Beverloo
2016/09/30 14:26:06
Most compilers will want you to return a default v
johnme
2016/09/30 17:02:09
No, default is evil! It prevents compilers from wa
| |
| 120 } | |
| 121 | |
| 122 content::PushUnregistrationStatus ToUnregisterStatus( | |
| 123 gcm::GCMClient::Result gcm_result) { | |
| 124 switch (gcm_result) { | |
| 125 case gcm::GCMClient::SUCCESS: | |
| 126 return content::PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTERED; | |
| 127 case gcm::GCMClient::INVALID_PARAMETER: | |
| 128 case gcm::GCMClient::GCM_DISABLED: | |
| 129 case gcm::GCMClient::SERVER_ERROR: | |
| 130 case gcm::GCMClient::UNKNOWN_ERROR: | |
| 131 return content::PUSH_UNREGISTRATION_STATUS_PENDING_SERVICE_ERROR; | |
| 132 case gcm::GCMClient::ASYNC_OPERATION_PENDING: | |
| 133 case gcm::GCMClient::NETWORK_ERROR: | |
| 134 case gcm::GCMClient::TTL_EXCEEDED: | |
| 135 return content::PUSH_UNREGISTRATION_STATUS_PENDING_NETWORK_ERROR; | |
| 136 } | |
| 137 } | |
| 138 | |
| 139 void GCMCallbackToUnregisterCallback( | |
| 140 const content::PushMessagingService::UnregisterCallback& callback, | |
| 141 gcm::GCMClient::Result result) { | |
| 142 DCHECK(!callback.is_null()); | |
| 143 callback.Run(ToUnregisterStatus(result)); | |
| 144 } | |
| 145 | |
| 101 void UnregisterCallbackToClosure(const base::Closure& closure, | 146 void UnregisterCallbackToClosure(const base::Closure& closure, |
| 102 content::PushUnregistrationStatus status) { | 147 content::PushUnregistrationStatus status) { |
| 148 DCHECK(!closure.is_null()); | |
| 103 closure.Run(); | 149 closure.Run(); |
| 104 } | 150 } |
| 105 | 151 |
| 106 #if BUILDFLAG(ENABLE_BACKGROUND) | 152 #if BUILDFLAG(ENABLE_BACKGROUND) |
| 107 bool UseBackgroundMode() { | 153 bool UseBackgroundMode() { |
| 108 // Note: if push is ever enabled in incognito, the background mode integration | 154 // Note: if push is ever enabled in incognito, the background mode integration |
| 109 // should not be enabled for it. | 155 // should not be enabled for it. |
| 110 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 156 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 111 if (command_line->HasSwitch(switches::kDisablePushApiBackgroundMode)) | 157 if (command_line->HasSwitch(switches::kDisablePushApiBackgroundMode)) |
| 112 return false; | 158 return false; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 } | 275 } |
| 230 #endif | 276 #endif |
| 231 | 277 |
| 232 base::Closure message_handled_closure = | 278 base::Closure message_handled_closure = |
| 233 message_callback_for_testing_.is_null() ? base::Bind(&base::DoNothing) | 279 message_callback_for_testing_.is_null() ? base::Bind(&base::DoNothing) |
| 234 : message_callback_for_testing_; | 280 : message_callback_for_testing_; |
| 235 PushMessagingAppIdentifier app_identifier = | 281 PushMessagingAppIdentifier app_identifier = |
| 236 PushMessagingAppIdentifier::FindByAppId(profile_, app_id); | 282 PushMessagingAppIdentifier::FindByAppId(profile_, app_id); |
| 237 // Drop message and unregister if app_id was unknown (maybe recently deleted). | 283 // Drop message and unregister if app_id was unknown (maybe recently deleted). |
| 238 if (app_identifier.is_null()) { | 284 if (app_identifier.is_null()) { |
| 239 DeliverMessageCallback(app_id, GURL::EmptyGURL(), -1, message, | 285 DeliverMessageCallback(app_id, GURL::EmptyGURL(), |
| 240 message_handled_closure, | 286 -1 /* kInvalidServiceWorkerRegistrationId */, |
| 287 message, message_handled_closure, | |
| 241 content::PUSH_DELIVERY_STATUS_UNKNOWN_APP_ID); | 288 content::PUSH_DELIVERY_STATUS_UNKNOWN_APP_ID); |
| 242 return; | 289 return; |
| 243 } | 290 } |
| 244 // Drop message and unregister if |origin| has lost push permission. | 291 // Drop message and unregister if |origin| has lost push permission. |
| 245 if (!IsPermissionSet(app_identifier.origin())) { | 292 if (!IsPermissionSet(app_identifier.origin())) { |
| 246 DeliverMessageCallback(app_id, app_identifier.origin(), | 293 DeliverMessageCallback(app_id, app_identifier.origin(), |
| 247 app_identifier.service_worker_registration_id(), | 294 app_identifier.service_worker_registration_id(), |
| 248 message, message_handled_closure, | 295 message, message_handled_closure, |
| 249 content::PUSH_DELIVERY_STATUS_PERMISSION_DENIED); | 296 content::PUSH_DELIVERY_STATUS_PERMISSION_DENIED); |
| 250 return; | 297 return; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 280 | 327 |
| 281 void PushMessagingServiceImpl::DeliverMessageCallback( | 328 void PushMessagingServiceImpl::DeliverMessageCallback( |
| 282 const std::string& app_id, | 329 const std::string& app_id, |
| 283 const GURL& requesting_origin, | 330 const GURL& requesting_origin, |
| 284 int64_t service_worker_registration_id, | 331 int64_t service_worker_registration_id, |
| 285 const gcm::IncomingMessage& message, | 332 const gcm::IncomingMessage& message, |
| 286 const base::Closure& message_handled_closure, | 333 const base::Closure& message_handled_closure, |
| 287 content::PushDeliveryStatus status) { | 334 content::PushDeliveryStatus status) { |
| 288 DCHECK_GE(in_flight_message_deliveries_.count(app_id), 1u); | 335 DCHECK_GE(in_flight_message_deliveries_.count(app_id), 1u); |
| 289 | 336 |
| 337 RecordDeliveryStatus(status); | |
| 338 | |
| 290 base::Closure completion_closure = | 339 base::Closure completion_closure = |
| 291 base::Bind(&PushMessagingServiceImpl::DidHandleMessage, | 340 base::Bind(&PushMessagingServiceImpl::DidHandleMessage, |
| 292 weak_factory_.GetWeakPtr(), app_id, message_handled_closure); | 341 weak_factory_.GetWeakPtr(), app_id, message_handled_closure); |
| 293 // The completion_closure should run by default at the end of this function, | 342 // The completion_closure should run by default at the end of this function, |
| 294 // unless it is explicitly passed to another function. | 343 // unless it is explicitly passed to another function. |
| 295 base::ScopedClosureRunner completion_closure_runner(completion_closure); | 344 base::ScopedClosureRunner completion_closure_runner(completion_closure); |
| 296 | 345 |
| 346 // Dummy reason meaning this function should not automatically unsubscribe. | |
| 347 const content::PushUnregistrationReason DO_NOT_UNSUBSCRIBE = | |
| 348 content::PUSH_UNREGISTRATION_REASON_JAVASCRIPT_API; | |
|
Peter Beverloo
2016/09/30 14:26:06
What about defining a PUSH_UNREGISTRATION_REASON_U
johnme
2016/09/30 17:02:10
Done.
| |
| 349 | |
| 350 // Whether and why automatic unsubscription is necessary. | |
| 351 content::PushUnregistrationReason unsubscribe_reason = DO_NOT_UNSUBSCRIBE; | |
| 352 | |
| 297 // TODO(mvanouwerkerk): Show a warning in the developer console of the | 353 // TODO(mvanouwerkerk): Show a warning in the developer console of the |
| 298 // Service Worker corresponding to app_id (and/or on an internals page). | 354 // Service Worker corresponding to app_id (and/or on an internals page). |
| 299 // See https://crbug.com/508516 for options. | 355 // See https://crbug.com/508516 for options. |
| 300 switch (status) { | 356 switch (status) { |
| 301 // Call EnforceUserVisibleOnlyRequirements if the message was delivered to | 357 // Call EnforceUserVisibleOnlyRequirements if the message was delivered to |
| 302 // the Service Worker JavaScript, even if the website's event handler failed | 358 // the Service Worker JavaScript, even if the website's event handler failed |
| 303 // (to prevent sites deliberately failing in order to avoid having to show | 359 // (to prevent sites deliberately failing in order to avoid having to show |
| 304 // notifications). | 360 // notifications). |
| 305 case content::PUSH_DELIVERY_STATUS_SUCCESS: | 361 case content::PUSH_DELIVERY_STATUS_SUCCESS: |
| 306 case content::PUSH_DELIVERY_STATUS_EVENT_WAITUNTIL_REJECTED: | 362 case content::PUSH_DELIVERY_STATUS_EVENT_WAITUNTIL_REJECTED: |
| 307 #if defined(ENABLE_NOTIFICATIONS) | 363 #if defined(ENABLE_NOTIFICATIONS) |
| 308 // Only enforce the user visible requirements if this is currently running | 364 // Only enforce the user visible requirements if this is currently running |
| 309 // as the delivery callback for the last in-flight message, and silent | 365 // as the delivery callback for the last in-flight message, and silent |
| 310 // push has not been enabled through a command line flag. | 366 // push has not been enabled through a command line flag. |
| 311 if (in_flight_message_deliveries_.count(app_id) == 1 && | 367 if (in_flight_message_deliveries_.count(app_id) == 1 && |
| 312 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 368 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 313 switches::kAllowSilentPush)) { | 369 switches::kAllowSilentPush)) { |
| 314 notification_manager_.EnforceUserVisibleOnlyRequirements( | 370 notification_manager_.EnforceUserVisibleOnlyRequirements( |
| 315 requesting_origin, service_worker_registration_id, | 371 requesting_origin, service_worker_registration_id, |
| 316 completion_closure_runner.Release()); | 372 completion_closure_runner.Release()); |
| 317 } | 373 } |
| 318 #endif | 374 #endif |
| 319 break; | 375 break; |
| 320 case content::PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR: | 376 case content::PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR: |
| 377 // Do nothing, and hope the error is transient. | |
| 321 break; | 378 break; |
| 322 case content::PUSH_DELIVERY_STATUS_UNKNOWN_APP_ID: | 379 case content::PUSH_DELIVERY_STATUS_UNKNOWN_APP_ID: |
| 380 unsubscribe_reason = | |
| 381 content::PUSH_UNREGISTRATION_REASON_DELIVERY_UNKNOWN_APP_ID; | |
| 382 break; | |
| 323 case content::PUSH_DELIVERY_STATUS_PERMISSION_DENIED: | 383 case content::PUSH_DELIVERY_STATUS_PERMISSION_DENIED: |
| 384 unsubscribe_reason = | |
| 385 content::PUSH_UNREGISTRATION_REASON_DELIVERY_PERMISSION_DENIED; | |
| 386 break; | |
| 324 case content::PUSH_DELIVERY_STATUS_NO_SERVICE_WORKER: | 387 case content::PUSH_DELIVERY_STATUS_NO_SERVICE_WORKER: |
| 325 Unsubscribe(app_id, message.sender_id, | 388 unsubscribe_reason = |
| 326 base::Bind(&UnregisterCallbackToClosure, | 389 content::PUSH_UNREGISTRATION_REASON_DELIVERY_NO_SERVICE_WORKER; |
| 327 completion_closure_runner.Release())); | |
| 328 break; | 390 break; |
| 329 } | 391 } |
| 330 | 392 |
| 331 RecordDeliveryStatus(status); | 393 if (unsubscribe_reason != DO_NOT_UNSUBSCRIBE) { |
| 394 PushMessagingAppIdentifier app_identifier = | |
| 395 PushMessagingAppIdentifier::FindByAppId(profile_, app_id); | |
| 396 UnsubscribeInternal( | |
| 397 unsubscribe_reason, | |
| 398 app_identifier.is_null() ? GURL::EmptyGURL() : app_identifier.origin(), | |
| 399 app_identifier.is_null() | |
| 400 ? -1 /* kInvalidServiceWorkerRegistrationId */ | |
| 401 : app_identifier.service_worker_registration_id(), | |
| 402 app_id, message.sender_id, | |
| 403 base::Bind(&UnregisterCallbackToClosure, | |
| 404 completion_closure_runner.Release())); | |
| 405 } | |
| 332 } | 406 } |
| 333 | 407 |
| 334 void PushMessagingServiceImpl::DidHandleMessage( | 408 void PushMessagingServiceImpl::DidHandleMessage( |
| 335 const std::string& app_id, | 409 const std::string& app_id, |
| 336 const base::Closure& message_handled_closure) { | 410 const base::Closure& message_handled_closure) { |
| 337 auto in_flight_iterator = in_flight_message_deliveries_.find(app_id); | 411 auto in_flight_iterator = in_flight_message_deliveries_.find(app_id); |
| 338 DCHECK(in_flight_iterator != in_flight_message_deliveries_.end()); | 412 DCHECK(in_flight_iterator != in_flight_message_deliveries_.end()); |
| 339 | 413 |
| 340 // Remove a single in-flight delivery for |app_id|. This has to be done using | 414 // Remove a single in-flight delivery for |app_id|. This has to be done using |
| 341 // an iterator rather than by value, as the latter removes all entries. | 415 // an iterator rather than by value, as the latter removes all entries. |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 607 // Unsubscribe methods --------------------------------------------------------- | 681 // Unsubscribe methods --------------------------------------------------------- |
| 608 | 682 |
| 609 void PushMessagingServiceImpl::Unsubscribe( | 683 void PushMessagingServiceImpl::Unsubscribe( |
| 610 const GURL& requesting_origin, | 684 const GURL& requesting_origin, |
| 611 int64_t service_worker_registration_id, | 685 int64_t service_worker_registration_id, |
| 612 const std::string& sender_id, | 686 const std::string& sender_id, |
| 613 const content::PushMessagingService::UnregisterCallback& callback) { | 687 const content::PushMessagingService::UnregisterCallback& callback) { |
| 614 PushMessagingAppIdentifier app_identifier = | 688 PushMessagingAppIdentifier app_identifier = |
| 615 PushMessagingAppIdentifier::FindByServiceWorker( | 689 PushMessagingAppIdentifier::FindByServiceWorker( |
| 616 profile_, requesting_origin, service_worker_registration_id); | 690 profile_, requesting_origin, service_worker_registration_id); |
| 617 if (app_identifier.is_null()) { | 691 |
| 692 UnsubscribeInternal( | |
| 693 content::PUSH_UNREGISTRATION_REASON_JAVASCRIPT_API, requesting_origin, | |
| 694 service_worker_registration_id, | |
| 695 app_identifier.is_null() ? std::string() : app_identifier.app_id(), | |
| 696 sender_id, callback); | |
| 697 } | |
| 698 | |
| 699 void PushMessagingServiceImpl::UnsubscribeInternal( | |
| 700 content::PushUnregistrationReason reason, | |
| 701 const GURL& origin, | |
| 702 int64_t service_worker_registration_id, | |
| 703 const std::string& app_id, | |
| 704 const std::string& sender_id, | |
| 705 const content::PushMessagingService::UnregisterCallback& callback) { | |
| 706 DCHECK(!app_id.empty() || (!origin.is_empty() && | |
| 707 service_worker_registration_id != | |
| 708 -1 /* kInvalidServiceWorkerRegistrationId */)) | |
| 709 << "Need an app_id and/or origin+service_worker_registration_id"; | |
| 710 | |
| 711 RecordUnsubscribeReason(reason); | |
| 712 | |
| 713 if (origin.is_empty() || | |
| 714 service_worker_registration_id == | |
| 715 -1 /* kInvalidServiceWorkerRegistrationId */) { | |
| 716 // Can't clear Service Worker database. | |
| 717 DidClearPushSubscriptionId(reason, app_id, sender_id, callback); | |
| 718 return; | |
| 719 } | |
| 720 ClearPushSubscriptionId( | |
| 721 profile_, origin, service_worker_registration_id, | |
| 722 base::Bind(&PushMessagingServiceImpl::DidClearPushSubscriptionId, | |
| 723 weak_factory_.GetWeakPtr(), reason, app_id, sender_id, | |
| 724 callback)); | |
| 725 } | |
| 726 | |
| 727 void PushMessagingServiceImpl::DidClearPushSubscriptionId( | |
| 728 content::PushUnregistrationReason reason, | |
| 729 const std::string& app_id, | |
| 730 const std::string& sender_id, | |
| 731 const content::PushMessagingService::UnregisterCallback& callback) { | |
|
Peter Beverloo
2016/09/30 14:26:06
Specific to UnregisterCallback, since this is the
Peter Beverloo
2016/09/30 14:26:06
We probably want to have a `using` statement in th
johnme
2016/09/30 17:02:10
I just removed all occurrences of (content::)?Push
johnme
2016/09/30 17:02:10
I just removed all occurrences of (content::)?Push
| |
| 732 if (app_id.empty()) { | |
| 733 // There's nothing more we can do. | |
|
Peter Beverloo
2016/09/30 14:26:06
// We cannot unsubscribe with the GCM Driver witho
johnme
2016/09/30 17:02:10
Done (expanded to cover PushMessagingAppIdentifier
| |
| 618 callback.Run( | 734 callback.Run( |
| 619 content::PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED); | 735 content::PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED); |
| 620 return; | 736 return; |
| 621 } | 737 } |
| 622 | 738 |
| 623 Unsubscribe(app_identifier.app_id(), sender_id, callback); | |
| 624 } | |
| 625 | |
| 626 void PushMessagingServiceImpl::Unsubscribe( | |
| 627 const std::string& app_id, | |
| 628 const std::string& sender_id, | |
| 629 const content::PushMessagingService::UnregisterCallback& callback) { | |
| 630 // Delete the mapping for this app_id, to guarantee that no messages get | 739 // Delete the mapping for this app_id, to guarantee that no messages get |
| 631 // delivered in future (even if unregistration fails). | 740 // delivered in future (even if unregistration fails). |
| 632 // TODO(johnme): Instead of deleting these app ids, store them elsewhere, and | 741 // TODO(johnme): Instead of deleting these app ids, store them elsewhere, and |
| 633 // retry unregistration if it fails due to network errors (crbug.com/465399). | 742 // retry unregistration if it fails due to network errors (crbug.com/465399). |
| 634 PushMessagingAppIdentifier app_identifier = | 743 PushMessagingAppIdentifier app_identifier = |
| 635 PushMessagingAppIdentifier::FindByAppId(profile_, app_id); | 744 PushMessagingAppIdentifier::FindByAppId(profile_, app_id); |
| 636 bool was_subscribed = !app_identifier.is_null(); | 745 bool was_subscribed = !app_identifier.is_null(); |
| 637 if (was_subscribed) | 746 if (was_subscribed) |
| 638 app_identifier.DeleteFromPrefs(profile_); | 747 app_identifier.DeleteFromPrefs(profile_); |
| 639 | 748 |
| 640 if (PushMessagingAppIdentifier::UseInstanceID(app_id)) { | 749 if (PushMessagingAppIdentifier::UseInstanceID(app_id)) { |
| 641 GetInstanceIDDriver()->GetInstanceID(app_id)->DeleteID(base::Bind( | 750 GetInstanceIDDriver()->GetInstanceID(app_id)->DeleteID(base::Bind( |
| 642 &PushMessagingServiceImpl::DidDeleteID, weak_factory_.GetWeakPtr(), | 751 &PushMessagingServiceImpl::DidDeleteID, weak_factory_.GetWeakPtr(), |
| 643 app_id, was_subscribed, callback)); | 752 app_id, was_subscribed, callback)); |
| 753 | |
| 644 } else { | 754 } else { |
| 645 auto unregister_callback = | 755 auto unregister_callback = |
| 646 base::Bind(&PushMessagingServiceImpl::DidUnsubscribe, | 756 base::Bind(&GCMCallbackToUnregisterCallback, |
| 647 weak_factory_.GetWeakPtr(), was_subscribed, callback); | 757 base::Bind(&PushMessagingServiceImpl::DidUnsubscribe, |
| 758 weak_factory_.GetWeakPtr(), | |
| 759 std::string() /* app_id_if_was_instance_id */, | |
| 760 was_subscribed, callback)); | |
| 648 #if defined(OS_ANDROID) | 761 #if defined(OS_ANDROID) |
| 649 // On Android the backend is different, and requires the original sender_id. | 762 // On Android the backend is different, and requires the original sender_id. |
| 650 // UnsubscribeBecausePermissionRevoked sometimes calls us with an empty one. | 763 // UnsubscribeBecausePermissionRevoked sometimes calls us with an empty one. |
| 651 if (sender_id.empty()) { | 764 if (sender_id.empty()) { |
| 652 unregister_callback.Run(gcm::GCMClient::INVALID_PARAMETER); | 765 unregister_callback.Run(gcm::GCMClient::INVALID_PARAMETER); |
| 653 } else { | 766 } else { |
| 654 GetGCMDriver()->UnregisterWithSenderId( | 767 GetGCMDriver()->UnregisterWithSenderId( |
| 655 app_id, NormalizeSenderInfo(sender_id), unregister_callback); | 768 app_id, NormalizeSenderInfo(sender_id), unregister_callback); |
| 656 } | 769 } |
| 657 #else | 770 #else |
| 658 GetGCMDriver()->Unregister(app_id, unregister_callback); | 771 GetGCMDriver()->Unregister(app_id, unregister_callback); |
| 659 #endif | 772 #endif |
| 660 } | 773 } |
| 661 } | 774 } |
| 662 | 775 |
| 663 void PushMessagingServiceImpl::DidDeleteID( | 776 void PushMessagingServiceImpl::DidDeleteID( |
| 664 const std::string& app_id, | 777 const std::string& app_id, |
| 665 bool was_subscribed, | 778 bool was_subscribed, |
| 666 const content::PushMessagingService::UnregisterCallback& callback, | 779 const content::PushMessagingService::UnregisterCallback& callback, |
| 667 InstanceID::Result result) { | 780 InstanceID::Result result) { |
| 668 // DidUnsubscribeInstanceID must be run asynchronously, since it calls | 781 // DidUnsubscribe must be run asynchronously when passing a non-empty |
| 782 // |app_id_if_was_instance_id|, since it calls | |
| 669 // InstanceIDDriver::RemoveInstanceID which deletes the InstanceID itself. | 783 // InstanceIDDriver::RemoveInstanceID which deletes the InstanceID itself. |
| 670 // Calling that immediately would cause a use-after-free in our caller. | 784 // Calling that immediately would cause a use-after-free in our caller. |
| 671 base::ThreadTaskRunnerHandle::Get()->PostTask( | 785 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 672 FROM_HERE, base::Bind(&PushMessagingServiceImpl::DidUnsubscribeInstanceID, | 786 FROM_HERE, base::Bind(&PushMessagingServiceImpl::DidUnsubscribe, |
| 673 weak_factory_.GetWeakPtr(), app_id, was_subscribed, | 787 weak_factory_.GetWeakPtr(), app_id, was_subscribed, |
| 674 callback, result)); | 788 callback, ToUnregisterStatus(result))); |
| 675 } | 789 } |
| 676 | 790 |
| 677 void PushMessagingServiceImpl::DidUnsubscribeInstanceID( | 791 void PushMessagingServiceImpl::DidUnsubscribe( |
| 678 const std::string& app_id, | 792 const std::string& app_id_if_was_instance_id, |
| 679 bool was_subscribed, | 793 bool was_subscribed, |
| 680 const content::PushMessagingService::UnregisterCallback& callback, | 794 const content::PushMessagingService::UnregisterCallback& callback, |
| 681 InstanceID::Result result) { | 795 content::PushUnregistrationStatus status) { |
| 682 GetInstanceIDDriver()->RemoveInstanceID(app_id); | 796 if (!app_id_if_was_instance_id.empty()) |
| 683 | 797 GetInstanceIDDriver()->RemoveInstanceID(app_id_if_was_instance_id); |
| 684 if (was_subscribed) | |
| 685 DecreasePushSubscriptionCount(1, false /* was_pending */); | |
| 686 | 798 |
| 687 DCHECK(!callback.is_null()); | 799 DCHECK(!callback.is_null()); |
| 688 | 800 |
| 689 if (!was_subscribed) { | 801 if (was_subscribed) { |
| 802 DecreasePushSubscriptionCount(1, false /* was_pending */); | |
| 803 callback.Run(status); | |
| 804 } else { | |
| 805 // Override status since there was no record of an existing subscription. | |
| 690 callback.Run( | 806 callback.Run( |
| 691 content::PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED); | 807 content::PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED); |
| 692 return; | |
| 693 } | |
| 694 switch (result) { | |
| 695 case InstanceID::SUCCESS: | |
| 696 callback.Run(content::PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTERED); | |
| 697 break; | |
| 698 case InstanceID::INVALID_PARAMETER: | |
| 699 case InstanceID::DISABLED: | |
| 700 case InstanceID::SERVER_ERROR: | |
| 701 case InstanceID::UNKNOWN_ERROR: | |
| 702 callback.Run(content::PUSH_UNREGISTRATION_STATUS_PENDING_SERVICE_ERROR); | |
| 703 break; | |
| 704 case InstanceID::ASYNC_OPERATION_PENDING: | |
| 705 case InstanceID::NETWORK_ERROR: | |
| 706 callback.Run(content::PUSH_UNREGISTRATION_STATUS_PENDING_NETWORK_ERROR); | |
| 707 break; | |
| 708 } | 808 } |
| 709 } | 809 } |
| 710 | 810 |
| 711 void PushMessagingServiceImpl::DidUnsubscribe( | |
| 712 bool was_subscribed, | |
| 713 const content::PushMessagingService::UnregisterCallback& callback, | |
| 714 gcm::GCMClient::Result gcm_result) { | |
| 715 if (was_subscribed) | |
| 716 DecreasePushSubscriptionCount(1, false /* was_pending */); | |
| 717 | |
| 718 DCHECK(!callback.is_null()); | |
| 719 | |
| 720 if (!was_subscribed) { | |
| 721 callback.Run( | |
| 722 content::PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED); | |
| 723 return; | |
| 724 } | |
| 725 switch (gcm_result) { | |
| 726 case gcm::GCMClient::SUCCESS: | |
| 727 callback.Run(content::PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTERED); | |
| 728 break; | |
| 729 case gcm::GCMClient::INVALID_PARAMETER: | |
| 730 case gcm::GCMClient::GCM_DISABLED: | |
| 731 case gcm::GCMClient::SERVER_ERROR: | |
| 732 case gcm::GCMClient::UNKNOWN_ERROR: | |
| 733 callback.Run(content::PUSH_UNREGISTRATION_STATUS_PENDING_SERVICE_ERROR); | |
| 734 break; | |
| 735 case gcm::GCMClient::ASYNC_OPERATION_PENDING: | |
| 736 case gcm::GCMClient::NETWORK_ERROR: | |
| 737 case gcm::GCMClient::TTL_EXCEEDED: | |
| 738 callback.Run(content::PUSH_UNREGISTRATION_STATUS_PENDING_NETWORK_ERROR); | |
| 739 break; | |
| 740 } | |
| 741 } | |
| 742 | |
| 743 // OnContentSettingChanged methods --------------------------------------------- | 811 // OnContentSettingChanged methods --------------------------------------------- |
| 744 | 812 |
| 745 void PushMessagingServiceImpl::OnContentSettingChanged( | 813 void PushMessagingServiceImpl::OnContentSettingChanged( |
| 746 const ContentSettingsPattern& primary_pattern, | 814 const ContentSettingsPattern& primary_pattern, |
| 747 const ContentSettingsPattern& secondary_pattern, | 815 const ContentSettingsPattern& secondary_pattern, |
| 748 ContentSettingsType content_type, | 816 ContentSettingsType content_type, |
| 749 std::string resource_identifier) { | 817 std::string resource_identifier) { |
| 750 if (content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS) | 818 if (content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS) |
| 751 return; | 819 return; |
| 752 | 820 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 780 #if defined(OS_ANDROID) | 848 #if defined(OS_ANDROID) |
| 781 need_sender_id = | 849 need_sender_id = |
| 782 !PushMessagingAppIdentifier::UseInstanceID(app_identifier.app_id()); | 850 !PushMessagingAppIdentifier::UseInstanceID(app_identifier.app_id()); |
| 783 #endif | 851 #endif |
| 784 if (need_sender_id) { | 852 if (need_sender_id) { |
| 785 GetSenderId( | 853 GetSenderId( |
| 786 profile_, app_identifier.origin(), | 854 profile_, app_identifier.origin(), |
| 787 app_identifier.service_worker_registration_id(), | 855 app_identifier.service_worker_registration_id(), |
| 788 base::Bind( | 856 base::Bind( |
| 789 &PushMessagingServiceImpl::UnsubscribeBecausePermissionRevoked, | 857 &PushMessagingServiceImpl::UnsubscribeBecausePermissionRevoked, |
| 790 weak_factory_.GetWeakPtr(), app_identifier, barrier_closure)); | 858 weak_factory_.GetWeakPtr(), app_identifier, |
| 859 base::Bind(&UnregisterCallbackToClosure, barrier_closure))); | |
| 791 } else { | 860 } else { |
| 792 UnsubscribeBecausePermissionRevoked( | 861 UnsubscribeInternal( |
| 793 app_identifier, barrier_closure, "" /* sender_id */, | 862 content::PUSH_UNREGISTRATION_REASON_PERMISSION_REVOKED, |
| 794 true /* success */, true /* not_found */); | 863 app_identifier.origin(), |
| 864 app_identifier.service_worker_registration_id(), | |
| 865 app_identifier.app_id(), std::string() /* sender_id */, | |
| 866 base::Bind(&UnregisterCallbackToClosure, barrier_closure)); | |
| 795 } | 867 } |
| 796 } | 868 } |
| 797 } | 869 } |
| 798 | 870 |
| 799 void PushMessagingServiceImpl::UnsubscribeBecausePermissionRevoked( | 871 void PushMessagingServiceImpl::UnsubscribeBecausePermissionRevoked( |
| 800 const PushMessagingAppIdentifier& app_identifier, | 872 const PushMessagingAppIdentifier& app_identifier, |
| 801 const base::Closure& closure, | 873 const content::PushMessagingService::UnregisterCallback& callback, |
| 802 const std::string& sender_id, | 874 const std::string& sender_id, |
| 803 bool success, | 875 bool success, |
| 804 bool not_found) { | 876 bool not_found) { |
| 805 base::Closure barrier_closure = base::BarrierClosure(2, closure); | |
| 806 | |
| 807 // Unsubscribe the PushMessagingAppIdentifier with the push service. | 877 // Unsubscribe the PushMessagingAppIdentifier with the push service. |
| 808 // It's possible for GetSenderId to have failed and sender_id to be empty, if | 878 // It's possible for GetSenderId to have failed and sender_id to be empty, if |
| 809 // cookies (and the SW database) for an origin got cleared before permissions | 879 // cookies (and the SW database) for an origin got cleared before permissions |
| 810 // are cleared for the origin. In that case for legacy GCM registrations on | 880 // are cleared for the origin. In that case for legacy GCM registrations on |
| 811 // Android, Unsubscribe will just delete the app identifier to block future | 881 // Android, Unsubscribe will just delete the app identifier to block future |
| 812 // messages. | 882 // messages. |
| 813 // TODO(johnme): Auto-unregister before SW DB is cleared | 883 // TODO(johnme): Auto-unregister before SW DB is cleared (crbug.com/402458). |
| 814 // (https://crbug.com/402458). | 884 UnsubscribeInternal(content::PUSH_UNREGISTRATION_REASON_PERMISSION_REVOKED, |
| 815 Unsubscribe(app_identifier.app_id(), sender_id, | 885 app_identifier.origin(), |
| 816 base::Bind(&UnregisterCallbackToClosure, barrier_closure)); | 886 app_identifier.service_worker_registration_id(), |
| 817 | 887 app_identifier.app_id(), sender_id, callback); |
| 818 // Clear the associated service worker push registration id. | |
| 819 ClearPushSubscriptionID(profile_, app_identifier.origin(), | |
| 820 app_identifier.service_worker_registration_id(), | |
| 821 barrier_closure); | |
| 822 } | 888 } |
| 823 | 889 |
| 824 void PushMessagingServiceImpl::SetContentSettingChangedCallbackForTesting( | 890 void PushMessagingServiceImpl::SetContentSettingChangedCallbackForTesting( |
| 825 const base::Closure& callback) { | 891 const base::Closure& callback) { |
| 826 content_setting_changed_callback_for_testing_ = callback; | 892 content_setting_changed_callback_for_testing_ = callback; |
| 827 } | 893 } |
| 828 | 894 |
| 829 // KeyedService methods ------------------------------------------------------- | 895 // KeyedService methods ------------------------------------------------------- |
| 830 | 896 |
| 831 void PushMessagingServiceImpl::Shutdown() { | 897 void PushMessagingServiceImpl::Shutdown() { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 893 } | 959 } |
| 894 | 960 |
| 895 instance_id::InstanceIDDriver* PushMessagingServiceImpl::GetInstanceIDDriver() | 961 instance_id::InstanceIDDriver* PushMessagingServiceImpl::GetInstanceIDDriver() |
| 896 const { | 962 const { |
| 897 instance_id::InstanceIDProfileService* instance_id_profile_service = | 963 instance_id::InstanceIDProfileService* instance_id_profile_service = |
| 898 instance_id::InstanceIDProfileServiceFactory::GetForProfile(profile_); | 964 instance_id::InstanceIDProfileServiceFactory::GetForProfile(profile_); |
| 899 CHECK(instance_id_profile_service); | 965 CHECK(instance_id_profile_service); |
| 900 CHECK(instance_id_profile_service->driver()); | 966 CHECK(instance_id_profile_service->driver()); |
| 901 return instance_id_profile_service->driver(); | 967 return instance_id_profile_service->driver(); |
| 902 } | 968 } |
| OLD | NEW |