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 (AreMessagePayloadsEnabled()) { | 214 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 215 switches::kEnablePushMessagePayload)) { |
215 gcm::MessageData::const_iterator it = message.data.find("data"); | 216 gcm::MessageData::const_iterator it = message.data.find("data"); |
216 if (it != message.data.end()) | 217 if (it != message.data.end()) |
217 data = it->second; | 218 data = it->second; |
218 } | 219 } |
219 | 220 |
220 content::BrowserContext::DeliverPushMessage( | 221 content::BrowserContext::DeliverPushMessage( |
221 profile_, | 222 profile_, |
222 app_identifier.origin(), | 223 app_identifier.origin(), |
223 app_identifier.service_worker_registration_id(), | 224 app_identifier.service_worker_registration_id(), |
224 data, | 225 data, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 const std::string& message_id) { | 308 const std::string& message_id) { |
308 NOTREACHED() << "The Push API shouldn't have sent messages upstream"; | 309 NOTREACHED() << "The Push API shouldn't have sent messages upstream"; |
309 } | 310 } |
310 | 311 |
311 // GetPushEndpoint method ------------------------------------------------------ | 312 // GetPushEndpoint method ------------------------------------------------------ |
312 | 313 |
313 GURL PushMessagingServiceImpl::GetPushEndpoint() { | 314 GURL PushMessagingServiceImpl::GetPushEndpoint() { |
314 return GURL(std::string(kPushMessagingEndpoint)); | 315 return GURL(std::string(kPushMessagingEndpoint)); |
315 } | 316 } |
316 | 317 |
| 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 |
317 // Subscribe and GetPermissionStatus methods ----------------------------------- | 329 // Subscribe and GetPermissionStatus methods ----------------------------------- |
318 | 330 |
319 void PushMessagingServiceImpl::SubscribeFromDocument( | 331 void PushMessagingServiceImpl::SubscribeFromDocument( |
320 const GURL& requesting_origin, | 332 const GURL& requesting_origin, |
321 int64 service_worker_registration_id, | 333 int64 service_worker_registration_id, |
322 const std::string& sender_id, | 334 const std::string& sender_id, |
323 int renderer_id, | 335 int renderer_id, |
324 int render_frame_id, | 336 int render_frame_id, |
325 bool user_visible, | 337 bool user_visible, |
326 const content::PushMessagingService::RegisterCallback& callback) { | 338 const content::PushMessagingService::RegisterCallback& callback) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 content::PushRegistrationStatus status) { | 440 content::PushRegistrationStatus status) { |
429 SubscribeEnd(callback, std::string() /* subscription_id */, | 441 SubscribeEnd(callback, std::string() /* subscription_id */, |
430 std::vector<uint8_t>() /* curve25519dh */, status); | 442 std::vector<uint8_t>() /* curve25519dh */, status); |
431 } | 443 } |
432 | 444 |
433 void PushMessagingServiceImpl::DidSubscribe( | 445 void PushMessagingServiceImpl::DidSubscribe( |
434 const PushMessagingAppIdentifier& app_identifier, | 446 const PushMessagingAppIdentifier& app_identifier, |
435 const content::PushMessagingService::RegisterCallback& callback, | 447 const content::PushMessagingService::RegisterCallback& callback, |
436 const std::string& subscription_id, | 448 const std::string& subscription_id, |
437 gcm::GCMClient::Result result) { | 449 gcm::GCMClient::Result result) { |
438 DecreasePushSubscriptionCount(1, true /* was_pending */); | |
439 | |
440 content::PushRegistrationStatus status = | 450 content::PushRegistrationStatus status = |
441 content::PUSH_REGISTRATION_STATUS_SERVICE_ERROR; | 451 content::PUSH_REGISTRATION_STATUS_SERVICE_ERROR; |
| 452 std::vector<uint8_t> curve25519dh; |
442 | 453 |
443 switch (result) { | 454 switch (result) { |
444 case gcm::GCMClient::SUCCESS: | 455 case gcm::GCMClient::SUCCESS: |
445 // Do not get a certificate if message payloads have not been enabled. | 456 status = content::PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE; |
446 if (!AreMessagePayloadsEnabled()) { | 457 app_identifier.PersistToPrefs(profile_); |
447 DidSubscribeWithPublicKey( | |
448 app_identifier, callback, subscription_id, | |
449 std::string() /* public_key */); | |
450 return; | |
451 } | |
452 | 458 |
453 // Make sure that this subscription has associated encryption keys prior | 459 // TODO(peter): Hook up getting the keys from the GCM Driver. |
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)); | |
462 | 460 |
463 return; | 461 IncreasePushSubscriptionCount(1, false /* is_pending */); |
| 462 break; |
464 case gcm::GCMClient::INVALID_PARAMETER: | 463 case gcm::GCMClient::INVALID_PARAMETER: |
465 case gcm::GCMClient::GCM_DISABLED: | 464 case gcm::GCMClient::GCM_DISABLED: |
466 case gcm::GCMClient::ASYNC_OPERATION_PENDING: | 465 case gcm::GCMClient::ASYNC_OPERATION_PENDING: |
467 case gcm::GCMClient::SERVER_ERROR: | 466 case gcm::GCMClient::SERVER_ERROR: |
468 case gcm::GCMClient::UNKNOWN_ERROR: | 467 case gcm::GCMClient::UNKNOWN_ERROR: |
469 status = content::PUSH_REGISTRATION_STATUS_SERVICE_ERROR; | 468 status = content::PUSH_REGISTRATION_STATUS_SERVICE_ERROR; |
470 break; | 469 break; |
471 case gcm::GCMClient::NETWORK_ERROR: | 470 case gcm::GCMClient::NETWORK_ERROR: |
472 case gcm::GCMClient::TTL_EXCEEDED: | 471 case gcm::GCMClient::TTL_EXCEEDED: |
473 status = content::PUSH_REGISTRATION_STATUS_NETWORK_ERROR; | 472 status = content::PUSH_REGISTRATION_STATUS_NETWORK_ERROR; |
474 break; | 473 break; |
475 } | 474 } |
476 | 475 |
477 SubscribeEndWithError(callback, status); | 476 SubscribeEnd(callback, subscription_id, curve25519dh, status); |
478 } | 477 DecreasePushSubscriptionCount(1, true /* was_pending */); |
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); | |
498 } | 478 } |
499 | 479 |
500 void PushMessagingServiceImpl::DidRequestPermission( | 480 void PushMessagingServiceImpl::DidRequestPermission( |
501 const PushMessagingAppIdentifier& app_identifier, | 481 const PushMessagingAppIdentifier& app_identifier, |
502 const std::string& sender_id, | 482 const std::string& sender_id, |
503 const content::PushMessagingService::RegisterCallback& register_callback, | 483 const content::PushMessagingService::RegisterCallback& register_callback, |
504 content::PermissionStatus permission_status) { | 484 content::PermissionStatus permission_status) { |
505 if (permission_status != content::PERMISSION_STATUS_GRANTED) { | 485 if (permission_status != content::PERMISSION_STATUS_GRANTED) { |
506 SubscribeEndWithError(register_callback, | 486 SubscribeEndWithError(register_callback, |
507 content::PUSH_REGISTRATION_STATUS_PERMISSION_DENIED); | 487 content::PUSH_REGISTRATION_STATUS_PERMISSION_DENIED); |
508 return; | 488 return; |
509 } | 489 } |
510 | 490 |
511 IncreasePushSubscriptionCount(1, true /* is_pending */); | 491 IncreasePushSubscriptionCount(1, true /* is_pending */); |
512 std::vector<std::string> sender_ids(1, sender_id); | 492 std::vector<std::string> sender_ids(1, sender_id); |
513 GetGCMDriver()->Register(app_identifier.app_id(), sender_ids, | 493 GetGCMDriver()->Register(app_identifier.app_id(), sender_ids, |
514 base::Bind(&PushMessagingServiceImpl::DidSubscribe, | 494 base::Bind(&PushMessagingServiceImpl::DidSubscribe, |
515 weak_factory_.GetWeakPtr(), | 495 weak_factory_.GetWeakPtr(), |
516 app_identifier, register_callback)); | 496 app_identifier, register_callback)); |
517 } | 497 } |
518 | 498 |
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 | |
553 // Unsubscribe methods --------------------------------------------------------- | 499 // Unsubscribe methods --------------------------------------------------------- |
554 | 500 |
555 void PushMessagingServiceImpl::Unsubscribe( | 501 void PushMessagingServiceImpl::Unsubscribe( |
556 const GURL& requesting_origin, | 502 const GURL& requesting_origin, |
557 int64 service_worker_registration_id, | 503 int64 service_worker_registration_id, |
558 const std::string& sender_id, | 504 const std::string& sender_id, |
559 const content::PushMessagingService::UnregisterCallback& callback) { | 505 const content::PushMessagingService::UnregisterCallback& callback) { |
560 PushMessagingAppIdentifier app_identifier = | 506 PushMessagingAppIdentifier app_identifier = |
561 PushMessagingAppIdentifier::FindByServiceWorker( | 507 PushMessagingAppIdentifier::FindByServiceWorker( |
562 profile_, requesting_origin, service_worker_registration_id); | 508 profile_, requesting_origin, service_worker_registration_id); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 | 665 |
720 // Helper methods -------------------------------------------------------------- | 666 // Helper methods -------------------------------------------------------------- |
721 | 667 |
722 // Assumes user_visible always since this is just meant to check | 668 // Assumes user_visible always since this is just meant to check |
723 // if the permission was previously granted and not revoked. | 669 // if the permission was previously granted and not revoked. |
724 bool PushMessagingServiceImpl::IsPermissionSet(const GURL& origin) { | 670 bool PushMessagingServiceImpl::IsPermissionSet(const GURL& origin) { |
725 return GetPermissionStatus(origin, origin, true /* user_visible */) == | 671 return GetPermissionStatus(origin, origin, true /* user_visible */) == |
726 blink::WebPushPermissionStatusGranted; | 672 blink::WebPushPermissionStatusGranted; |
727 } | 673 } |
728 | 674 |
729 bool PushMessagingServiceImpl::AreMessagePayloadsEnabled() const { | |
730 return base::CommandLine::ForCurrentProcess()->HasSwitch( | |
731 switches::kEnablePushMessagePayload); | |
732 } | |
733 | |
734 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { | 675 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { |
735 gcm::GCMProfileService* gcm_profile_service = | 676 gcm::GCMProfileService* gcm_profile_service = |
736 gcm::GCMProfileServiceFactory::GetForProfile(profile_); | 677 gcm::GCMProfileServiceFactory::GetForProfile(profile_); |
737 CHECK(gcm_profile_service); | 678 CHECK(gcm_profile_service); |
738 CHECK(gcm_profile_service->driver()); | 679 CHECK(gcm_profile_service->driver()); |
739 return gcm_profile_service->driver(); | 680 return gcm_profile_service->driver(); |
740 } | 681 } |
OLD | NEW |