| 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/bind.h" | 10 #include "base/bind.h" |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 // "registration_ids": ["FOO", "BAR"], | 204 // "registration_ids": ["FOO", "BAR"], |
| 205 // "data": { | 205 // "data": { |
| 206 // "data": "BAZ", | 206 // "data": "BAZ", |
| 207 // }, | 207 // }, |
| 208 // "delay_while_idle": true, | 208 // "delay_while_idle": true, |
| 209 // } | 209 // } |
| 210 // TODO(johnme): Make sure this is clearly documented for developers. | 210 // TODO(johnme): Make sure this is clearly documented for developers. |
| 211 std::string data; | 211 std::string data; |
| 212 // TODO(peter): Message payloads are disabled pending mandatory encryption. | 212 // TODO(peter): Message payloads are disabled pending mandatory encryption. |
| 213 // https://crbug.com/449184 | 213 // https://crbug.com/449184 |
| 214 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 214 if (AreMessagePayloadsEnabled()) { |
| 215 switches::kEnablePushMessagePayload)) { | |
| 216 gcm::MessageData::const_iterator it = message.data.find("data"); | 215 gcm::MessageData::const_iterator it = message.data.find("data"); |
| 217 if (it != message.data.end()) | 216 if (it != message.data.end()) |
| 218 data = it->second; | 217 data = it->second; |
| 219 } | 218 } |
| 220 | 219 |
| 221 content::BrowserContext::DeliverPushMessage( | 220 content::BrowserContext::DeliverPushMessage( |
| 222 profile_, | 221 profile_, |
| 223 app_identifier.origin(), | 222 app_identifier.origin(), |
| 224 app_identifier.service_worker_registration_id(), | 223 app_identifier.service_worker_registration_id(), |
| 225 data, | 224 data, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 const std::string& message_id) { | 307 const std::string& message_id) { |
| 309 NOTREACHED() << "The Push API shouldn't have sent messages upstream"; | 308 NOTREACHED() << "The Push API shouldn't have sent messages upstream"; |
| 310 } | 309 } |
| 311 | 310 |
| 312 // GetPushEndpoint method ------------------------------------------------------ | 311 // GetPushEndpoint method ------------------------------------------------------ |
| 313 | 312 |
| 314 GURL PushMessagingServiceImpl::GetPushEndpoint() { | 313 GURL PushMessagingServiceImpl::GetPushEndpoint() { |
| 315 return GURL(std::string(kPushMessagingEndpoint)); | 314 return GURL(std::string(kPushMessagingEndpoint)); |
| 316 } | 315 } |
| 317 | 316 |
| 318 // GetPublicEncryptionKey method ----------------------------------------------- | |
| 319 | |
| 320 void PushMessagingServiceImpl::GetPublicEncryptionKey( | |
| 321 const GURL& origin, | |
| 322 int64_t service_worker_registration_id, | |
| 323 const PushMessagingService::PublicKeyCallback& callback) { | |
| 324 // TODO(peter): Get the public key from the GCM Driver. Right now we have to | |
| 325 // return success=true here, otherwise subscriptions would fail. | |
| 326 callback.Run(true /* success */, std::vector<uint8_t>()); | |
| 327 } | |
| 328 | |
| 329 // Subscribe and GetPermissionStatus methods ----------------------------------- | 317 // Subscribe and GetPermissionStatus methods ----------------------------------- |
| 330 | 318 |
| 331 void PushMessagingServiceImpl::SubscribeFromDocument( | 319 void PushMessagingServiceImpl::SubscribeFromDocument( |
| 332 const GURL& requesting_origin, | 320 const GURL& requesting_origin, |
| 333 int64 service_worker_registration_id, | 321 int64 service_worker_registration_id, |
| 334 const std::string& sender_id, | 322 const std::string& sender_id, |
| 335 int renderer_id, | 323 int renderer_id, |
| 336 int render_frame_id, | 324 int render_frame_id, |
| 337 bool user_visible, | 325 bool user_visible, |
| 338 const content::PushMessagingService::RegisterCallback& callback) { | 326 const content::PushMessagingService::RegisterCallback& callback) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 content::PushRegistrationStatus status) { | 428 content::PushRegistrationStatus status) { |
| 441 SubscribeEnd(callback, std::string() /* subscription_id */, | 429 SubscribeEnd(callback, std::string() /* subscription_id */, |
| 442 std::vector<uint8_t>() /* curve25519dh */, status); | 430 std::vector<uint8_t>() /* curve25519dh */, status); |
| 443 } | 431 } |
| 444 | 432 |
| 445 void PushMessagingServiceImpl::DidSubscribe( | 433 void PushMessagingServiceImpl::DidSubscribe( |
| 446 const PushMessagingAppIdentifier& app_identifier, | 434 const PushMessagingAppIdentifier& app_identifier, |
| 447 const content::PushMessagingService::RegisterCallback& callback, | 435 const content::PushMessagingService::RegisterCallback& callback, |
| 448 const std::string& subscription_id, | 436 const std::string& subscription_id, |
| 449 gcm::GCMClient::Result result) { | 437 gcm::GCMClient::Result result) { |
| 438 DecreasePushSubscriptionCount(1, true /* was_pending */); |
| 439 |
| 450 content::PushRegistrationStatus status = | 440 content::PushRegistrationStatus status = |
| 451 content::PUSH_REGISTRATION_STATUS_SERVICE_ERROR; | 441 content::PUSH_REGISTRATION_STATUS_SERVICE_ERROR; |
| 452 std::vector<uint8_t> curve25519dh; | |
| 453 | 442 |
| 454 switch (result) { | 443 switch (result) { |
| 455 case gcm::GCMClient::SUCCESS: | 444 case gcm::GCMClient::SUCCESS: |
| 456 status = content::PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE; | 445 // Do not get a certificate if message payloads have not been enabled. |
| 457 app_identifier.PersistToPrefs(profile_); | 446 if (!AreMessagePayloadsEnabled()) { |
| 447 DidSubscribeWithPublicKey( |
| 448 app_identifier, callback, subscription_id, |
| 449 std::string() /* public_key */); |
| 450 return; |
| 451 } |
| 458 | 452 |
| 459 // TODO(peter): Hook up getting the keys from the GCM Driver. | 453 // Make sure that this subscription has associated encryption keys prior |
| 454 // to returning it to the developer - they'll need this information in |
| 455 // order to send payloads to the user. |
| 456 GetGCMDriver()->GetPublicKey( |
| 457 app_identifier.app_id(), |
| 458 base::Bind( |
| 459 &PushMessagingServiceImpl::DidSubscribeWithPublicKey, |
| 460 weak_factory_.GetWeakPtr(), app_identifier, callback, |
| 461 subscription_id)); |
| 460 | 462 |
| 461 IncreasePushSubscriptionCount(1, false /* is_pending */); | 463 return; |
| 462 break; | |
| 463 case gcm::GCMClient::INVALID_PARAMETER: | 464 case gcm::GCMClient::INVALID_PARAMETER: |
| 464 case gcm::GCMClient::GCM_DISABLED: | 465 case gcm::GCMClient::GCM_DISABLED: |
| 465 case gcm::GCMClient::ASYNC_OPERATION_PENDING: | 466 case gcm::GCMClient::ASYNC_OPERATION_PENDING: |
| 466 case gcm::GCMClient::SERVER_ERROR: | 467 case gcm::GCMClient::SERVER_ERROR: |
| 467 case gcm::GCMClient::UNKNOWN_ERROR: | 468 case gcm::GCMClient::UNKNOWN_ERROR: |
| 468 status = content::PUSH_REGISTRATION_STATUS_SERVICE_ERROR; | 469 status = content::PUSH_REGISTRATION_STATUS_SERVICE_ERROR; |
| 469 break; | 470 break; |
| 470 case gcm::GCMClient::NETWORK_ERROR: | 471 case gcm::GCMClient::NETWORK_ERROR: |
| 471 case gcm::GCMClient::TTL_EXCEEDED: | 472 case gcm::GCMClient::TTL_EXCEEDED: |
| 472 status = content::PUSH_REGISTRATION_STATUS_NETWORK_ERROR; | 473 status = content::PUSH_REGISTRATION_STATUS_NETWORK_ERROR; |
| 473 break; | 474 break; |
| 474 } | 475 } |
| 475 | 476 |
| 476 SubscribeEnd(callback, subscription_id, curve25519dh, status); | 477 SubscribeEndWithError(callback, status); |
| 477 DecreasePushSubscriptionCount(1, true /* was_pending */); | 478 } |
| 479 |
| 480 void PushMessagingServiceImpl::DidSubscribeWithPublicKey( |
| 481 const PushMessagingAppIdentifier& app_identifier, |
| 482 const content::PushMessagingService::RegisterCallback& callback, |
| 483 const std::string& subscription_id, |
| 484 const std::string& public_key) { |
| 485 if (!public_key.size() && AreMessagePayloadsEnabled()) { |
| 486 SubscribeEndWithError( |
| 487 callback, content::PUSH_REGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE); |
| 488 return; |
| 489 } |
| 490 |
| 491 app_identifier.PersistToPrefs(profile_); |
| 492 |
| 493 IncreasePushSubscriptionCount(1, false /* is_pending */); |
| 494 |
| 495 SubscribeEnd(callback, subscription_id, |
| 496 std::vector<uint8_t>(public_key.begin(), public_key.end()), |
| 497 content::PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE); |
| 478 } | 498 } |
| 479 | 499 |
| 480 void PushMessagingServiceImpl::DidRequestPermission( | 500 void PushMessagingServiceImpl::DidRequestPermission( |
| 481 const PushMessagingAppIdentifier& app_identifier, | 501 const PushMessagingAppIdentifier& app_identifier, |
| 482 const std::string& sender_id, | 502 const std::string& sender_id, |
| 483 const content::PushMessagingService::RegisterCallback& register_callback, | 503 const content::PushMessagingService::RegisterCallback& register_callback, |
| 484 content::PermissionStatus permission_status) { | 504 content::PermissionStatus permission_status) { |
| 485 if (permission_status != content::PERMISSION_STATUS_GRANTED) { | 505 if (permission_status != content::PERMISSION_STATUS_GRANTED) { |
| 486 SubscribeEndWithError(register_callback, | 506 SubscribeEndWithError(register_callback, |
| 487 content::PUSH_REGISTRATION_STATUS_PERMISSION_DENIED); | 507 content::PUSH_REGISTRATION_STATUS_PERMISSION_DENIED); |
| 488 return; | 508 return; |
| 489 } | 509 } |
| 490 | 510 |
| 491 IncreasePushSubscriptionCount(1, true /* is_pending */); | 511 IncreasePushSubscriptionCount(1, true /* is_pending */); |
| 492 std::vector<std::string> sender_ids(1, sender_id); | 512 std::vector<std::string> sender_ids(1, sender_id); |
| 493 GetGCMDriver()->Register(app_identifier.app_id(), sender_ids, | 513 GetGCMDriver()->Register(app_identifier.app_id(), sender_ids, |
| 494 base::Bind(&PushMessagingServiceImpl::DidSubscribe, | 514 base::Bind(&PushMessagingServiceImpl::DidSubscribe, |
| 495 weak_factory_.GetWeakPtr(), | 515 weak_factory_.GetWeakPtr(), |
| 496 app_identifier, register_callback)); | 516 app_identifier, register_callback)); |
| 497 } | 517 } |
| 498 | 518 |
| 519 // GetPublicEncryptionKey methods ---------------------------------------------- |
| 520 |
| 521 void PushMessagingServiceImpl::GetPublicEncryptionKey( |
| 522 const GURL& origin, |
| 523 int64_t service_worker_registration_id, |
| 524 const PushMessagingService::PublicKeyCallback& callback) { |
| 525 // An empty public key will be returned if payloads are not enabled. |
| 526 if (!AreMessagePayloadsEnabled()) { |
| 527 callback.Run(true /* success */, std::vector<uint8_t>()); |
| 528 return; |
| 529 } |
| 530 |
| 531 PushMessagingAppIdentifier app_identifier = |
| 532 PushMessagingAppIdentifier::FindByServiceWorker( |
| 533 profile_, origin, service_worker_registration_id); |
| 534 |
| 535 DCHECK(!app_identifier.is_null()); |
| 536 |
| 537 GetGCMDriver()->GetPublicKey( |
| 538 app_identifier.app_id(), |
| 539 base::Bind(&PushMessagingServiceImpl::DidGetPublicKey, |
| 540 weak_factory_.GetWeakPtr(), callback)); |
| 541 } |
| 542 |
| 543 void PushMessagingServiceImpl::DidGetPublicKey( |
| 544 const PushMessagingService::PublicKeyCallback& callback, |
| 545 const std::string& public_key) const { |
| 546 // I/O errors might prevent the GCM Driver from retrieving a key-pair. |
| 547 const bool success = !!public_key.size(); |
| 548 |
| 549 callback.Run(success, std::vector<uint8_t>(public_key.begin(), |
| 550 public_key.end())); |
| 551 } |
| 552 |
| 499 // Unsubscribe methods --------------------------------------------------------- | 553 // Unsubscribe methods --------------------------------------------------------- |
| 500 | 554 |
| 501 void PushMessagingServiceImpl::Unsubscribe( | 555 void PushMessagingServiceImpl::Unsubscribe( |
| 502 const GURL& requesting_origin, | 556 const GURL& requesting_origin, |
| 503 int64 service_worker_registration_id, | 557 int64 service_worker_registration_id, |
| 504 const std::string& sender_id, | 558 const std::string& sender_id, |
| 505 const content::PushMessagingService::UnregisterCallback& callback) { | 559 const content::PushMessagingService::UnregisterCallback& callback) { |
| 506 PushMessagingAppIdentifier app_identifier = | 560 PushMessagingAppIdentifier app_identifier = |
| 507 PushMessagingAppIdentifier::FindByServiceWorker( | 561 PushMessagingAppIdentifier::FindByServiceWorker( |
| 508 profile_, requesting_origin, service_worker_registration_id); | 562 profile_, requesting_origin, service_worker_registration_id); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 | 719 |
| 666 // Helper methods -------------------------------------------------------------- | 720 // Helper methods -------------------------------------------------------------- |
| 667 | 721 |
| 668 // Assumes user_visible always since this is just meant to check | 722 // Assumes user_visible always since this is just meant to check |
| 669 // if the permission was previously granted and not revoked. | 723 // if the permission was previously granted and not revoked. |
| 670 bool PushMessagingServiceImpl::IsPermissionSet(const GURL& origin) { | 724 bool PushMessagingServiceImpl::IsPermissionSet(const GURL& origin) { |
| 671 return GetPermissionStatus(origin, origin, true /* user_visible */) == | 725 return GetPermissionStatus(origin, origin, true /* user_visible */) == |
| 672 blink::WebPushPermissionStatusGranted; | 726 blink::WebPushPermissionStatusGranted; |
| 673 } | 727 } |
| 674 | 728 |
| 729 bool PushMessagingServiceImpl::AreMessagePayloadsEnabled() const { |
| 730 return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 731 switches::kEnablePushMessagePayload); |
| 732 } |
| 733 |
| 675 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { | 734 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { |
| 676 gcm::GCMProfileService* gcm_profile_service = | 735 gcm::GCMProfileService* gcm_profile_service = |
| 677 gcm::GCMProfileServiceFactory::GetForProfile(profile_); | 736 gcm::GCMProfileServiceFactory::GetForProfile(profile_); |
| 678 CHECK(gcm_profile_service); | 737 CHECK(gcm_profile_service); |
| 679 CHECK(gcm_profile_service->driver()); | 738 CHECK(gcm_profile_service->driver()); |
| 680 return gcm_profile_service->driver(); | 739 return gcm_profile_service->driver(); |
| 681 } | 740 } |
| OLD | NEW |