| 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/services/gcm/gcm_driver.h" | 5 #include "chrome/browser/services/gcm/gcm_driver.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 stats = gcm_client_->GetStatistics(); | 375 stats = gcm_client_->GetStatistics(); |
| 376 stats.gcm_client_created = true; | 376 stats.gcm_client_created = true; |
| 377 } | 377 } |
| 378 | 378 |
| 379 content::BrowserThread::PostTask( | 379 content::BrowserThread::PostTask( |
| 380 content::BrowserThread::UI, | 380 content::BrowserThread::UI, |
| 381 FROM_HERE, | 381 FROM_HERE, |
| 382 base::Bind(&GCMDriver::GetGCMStatisticsFinished, service_, stats)); | 382 base::Bind(&GCMDriver::GetGCMStatisticsFinished, service_, stats)); |
| 383 } | 383 } |
| 384 | 384 |
| 385 GCMDriver::GCMDriver(scoped_ptr<IdentityProvider> identity_provider) | 385 GCMDriver::GCMDriver( |
| 386 : identity_provider_(identity_provider.Pass()), | 386 scoped_ptr<GCMClientFactory> gcm_client_factory, |
| 387 scoped_ptr<IdentityProvider> identity_provider, |
| 388 const base::FilePath& store_path, |
| 389 const scoped_refptr<net::URLRequestContextGetter>& request_context) |
| 390 : gcm_enabled_(true), |
| 387 gcm_client_ready_(false), | 391 gcm_client_ready_(false), |
| 392 identity_provider_(identity_provider.Pass()), |
| 388 weak_ptr_factory_(this) { | 393 weak_ptr_factory_(this) { |
| 389 } | |
| 390 | |
| 391 GCMDriver::~GCMDriver() { | |
| 392 } | |
| 393 | |
| 394 void GCMDriver::Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory) { | |
| 395 // Get the list of available accounts. | 394 // Get the list of available accounts. |
| 396 std::vector<std::string> account_ids; | 395 std::vector<std::string> account_ids; |
| 397 #if !defined(OS_ANDROID) | 396 #if !defined(OS_ANDROID) |
| 398 account_ids = identity_provider_->GetTokenService()->GetAccounts(); | 397 account_ids = identity_provider_->GetTokenService()->GetAccounts(); |
| 399 #endif | 398 #endif |
| 400 | 399 |
| 401 // Create and initialize the GCMClient. Note that this does not initiate the | 400 // Create and initialize the GCMClient. Note that this does not initiate the |
| 402 // GCM check-in. | 401 // GCM check-in. |
| 403 DCHECK(!io_worker_); | |
| 404 io_worker_.reset(new IOWorker()); | 402 io_worker_.reset(new IOWorker()); |
| 405 content::BrowserThread::PostTask( | 403 content::BrowserThread::PostTask( |
| 406 content::BrowserThread::IO, | 404 content::BrowserThread::IO, |
| 407 FROM_HERE, | 405 FROM_HERE, |
| 408 base::Bind(&GCMDriver::IOWorker::Initialize, | 406 base::Bind(&GCMDriver::IOWorker::Initialize, |
| 409 base::Unretained(io_worker_.get()), | 407 base::Unretained(io_worker_.get()), |
| 410 base::Passed(&gcm_client_factory), | 408 base::Passed(&gcm_client_factory), |
| 411 GetStorePath(), | 409 store_path, |
| 412 account_ids, | 410 account_ids, |
| 413 GetURLRequestContextGetter())); | 411 request_context)); |
| 414 | |
| 415 // Start the GCM service if the rollout signal indicates yes. | |
| 416 if (ShouldStartAutomatically()) | |
| 417 EnsureStarted(); | |
| 418 | 412 |
| 419 identity_provider_->AddObserver(this); | 413 identity_provider_->AddObserver(this); |
| 420 } | 414 } |
| 421 | 415 |
| 422 void GCMDriver::Start() { | 416 GCMDriver::GCMDriver() |
| 417 : gcm_enabled_(true), |
| 418 gcm_client_ready_(false), |
| 419 weak_ptr_factory_(this) { |
| 420 } |
| 421 |
| 422 GCMDriver::~GCMDriver() { |
| 423 } |
| 424 |
| 425 void GCMDriver::Enable() { |
| 423 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 426 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 424 | 427 |
| 428 if (gcm_enabled_) |
| 429 return; |
| 430 gcm_enabled_ = true; |
| 431 |
| 425 EnsureStarted(); | 432 EnsureStarted(); |
| 426 } | 433 } |
| 427 | 434 |
| 435 void GCMDriver::Disable() { |
| 436 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 437 |
| 438 if (!gcm_enabled_) |
| 439 return; |
| 440 gcm_enabled_ = false; |
| 441 |
| 442 Stop(); |
| 443 } |
| 444 |
| 428 void GCMDriver::Stop() { | 445 void GCMDriver::Stop() { |
| 429 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 446 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 430 | 447 |
| 431 // No need to stop GCM service if not started yet. | 448 // No need to stop GCM service if not started yet. |
| 432 if (account_id_.empty()) | 449 if (account_id_.empty()) |
| 433 return; | 450 return; |
| 434 | 451 |
| 435 RemoveCachedData(); | 452 RemoveCachedData(); |
| 436 | 453 |
| 437 content::BrowserThread::PostTask( | 454 content::BrowserThread::PostTask( |
| 438 content::BrowserThread::IO, | 455 content::BrowserThread::IO, |
| 439 FROM_HERE, | 456 FROM_HERE, |
| 440 base::Bind(&GCMDriver::IOWorker::Stop, | 457 base::Bind(&GCMDriver::IOWorker::Stop, |
| 441 base::Unretained(io_worker_.get()))); | 458 base::Unretained(io_worker_.get()))); |
| 442 } | 459 } |
| 443 | 460 |
| 444 void GCMDriver::ShutdownService() { | 461 void GCMDriver::Shutdown() { |
| 445 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 462 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 446 identity_provider_->RemoveObserver(this); | 463 identity_provider_->RemoveObserver(this); |
| 447 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin(); | 464 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin(); |
| 448 iter != app_handlers_.end(); ++iter) { | 465 iter != app_handlers_.end(); ++iter) { |
| 449 iter->second->ShutdownHandler(); | 466 iter->second->ShutdownHandler(); |
| 450 } | 467 } |
| 451 app_handlers_.clear(); | 468 app_handlers_.clear(); |
| 452 content::BrowserThread::DeleteSoon(content::BrowserThread::IO, | 469 content::BrowserThread::DeleteSoon(content::BrowserThread::IO, |
| 453 FROM_HERE, | 470 FROM_HERE, |
| 454 io_worker_.release()); | 471 io_worker_.release()); |
| 455 } | 472 } |
| 456 | 473 |
| 457 void GCMDriver::AddAppHandler(const std::string& app_id, | 474 void GCMDriver::AddAppHandler(const std::string& app_id, |
| 458 GCMAppHandler* handler) { | 475 GCMAppHandler* handler) { |
| 459 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 476 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 460 DCHECK(!app_id.empty()); | 477 DCHECK(!app_id.empty()); |
| 461 DCHECK(handler); | 478 DCHECK(handler); |
| 462 DCHECK(app_handlers_.find(app_id) == app_handlers_.end()); | 479 DCHECK(app_handlers_.find(app_id) == app_handlers_.end()); |
| 463 | 480 |
| 464 app_handlers_[app_id] = handler; | 481 app_handlers_[app_id] = handler; |
| 482 |
| 483 // Ensures that the GCM service is started when there is an interest. |
| 484 EnsureStarted(); |
| 465 } | 485 } |
| 466 | 486 |
| 467 void GCMDriver::RemoveAppHandler(const std::string& app_id) { | 487 void GCMDriver::RemoveAppHandler(const std::string& app_id) { |
| 468 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 488 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 469 DCHECK(!app_id.empty()); | 489 DCHECK(!app_id.empty()); |
| 470 | 490 |
| 471 app_handlers_.erase(app_id); | 491 app_handlers_.erase(app_id); |
| 472 } | 492 } |
| 473 | 493 |
| 474 void GCMDriver::Register(const std::string& app_id, | 494 void GCMDriver::Register(const std::string& app_id, |
| 475 const std::vector<std::string>& sender_ids, | 495 const std::vector<std::string>& sender_ids, |
| 476 const RegisterCallback& callback) { | 496 const RegisterCallback& callback) { |
| 477 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 497 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 478 DCHECK(!app_id.empty()); | 498 DCHECK(!app_id.empty()); |
| 479 DCHECK(!sender_ids.empty()); | 499 DCHECK(!sender_ids.empty()); |
| 480 DCHECK(!callback.is_null()); | 500 DCHECK(!callback.is_null()); |
| 481 | 501 |
| 482 GCMClient::Result result = EnsureAppReady(app_id); | 502 GCMClient::Result result = EnsureStarted(); |
| 483 if (result != GCMClient::SUCCESS) { | 503 if (result != GCMClient::SUCCESS) { |
| 484 callback.Run(std::string(), result); | 504 callback.Run(std::string(), result); |
| 485 return; | 505 return; |
| 486 } | 506 } |
| 487 | 507 |
| 488 // If previous un/register operation is still in progress, bail out. | 508 // If previous un/register operation is still in progress, bail out. |
| 489 if (IsAsyncOperationPending(app_id)) { | 509 if (IsAsyncOperationPending(app_id)) { |
| 490 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); | 510 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); |
| 491 return; | 511 return; |
| 492 } | 512 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 app_id, | 547 app_id, |
| 528 normalized_sender_ids)); | 548 normalized_sender_ids)); |
| 529 } | 549 } |
| 530 | 550 |
| 531 void GCMDriver::Unregister(const std::string& app_id, | 551 void GCMDriver::Unregister(const std::string& app_id, |
| 532 const UnregisterCallback& callback) { | 552 const UnregisterCallback& callback) { |
| 533 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 553 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 534 DCHECK(!app_id.empty()); | 554 DCHECK(!app_id.empty()); |
| 535 DCHECK(!callback.is_null()); | 555 DCHECK(!callback.is_null()); |
| 536 | 556 |
| 537 GCMClient::Result result = EnsureAppReady(app_id); | 557 GCMClient::Result result = EnsureStarted(); |
| 538 if (result != GCMClient::SUCCESS) { | 558 if (result != GCMClient::SUCCESS) { |
| 539 callback.Run(result); | 559 callback.Run(result); |
| 540 return; | 560 return; |
| 541 } | 561 } |
| 542 | 562 |
| 543 // If previous un/register operation is still in progress, bail out. | 563 // If previous un/register operation is still in progress, bail out. |
| 544 if (IsAsyncOperationPending(app_id)) { | 564 if (IsAsyncOperationPending(app_id)) { |
| 545 callback.Run(GCMClient::ASYNC_OPERATION_PENDING); | 565 callback.Run(GCMClient::ASYNC_OPERATION_PENDING); |
| 546 return; | 566 return; |
| 547 } | 567 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 575 | 595 |
| 576 void GCMDriver::Send(const std::string& app_id, | 596 void GCMDriver::Send(const std::string& app_id, |
| 577 const std::string& receiver_id, | 597 const std::string& receiver_id, |
| 578 const GCMClient::OutgoingMessage& message, | 598 const GCMClient::OutgoingMessage& message, |
| 579 const SendCallback& callback) { | 599 const SendCallback& callback) { |
| 580 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 600 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 581 DCHECK(!app_id.empty()); | 601 DCHECK(!app_id.empty()); |
| 582 DCHECK(!receiver_id.empty()); | 602 DCHECK(!receiver_id.empty()); |
| 583 DCHECK(!callback.is_null()); | 603 DCHECK(!callback.is_null()); |
| 584 | 604 |
| 585 GCMClient::Result result = EnsureAppReady(app_id); | 605 GCMClient::Result result = EnsureStarted(); |
| 586 if (result != GCMClient::SUCCESS) { | 606 if (result != GCMClient::SUCCESS) { |
| 587 callback.Run(std::string(), result); | 607 callback.Run(std::string(), result); |
| 588 return; | 608 return; |
| 589 } | 609 } |
| 590 | 610 |
| 591 // If the message with send ID is still in progress, bail out. | 611 // If the message with send ID is still in progress, bail out. |
| 592 std::pair<std::string, std::string> key(app_id, message.id); | 612 std::pair<std::string, std::string> key(app_id, message.id); |
| 593 if (send_callbacks_.find(key) != send_callbacks_.end()) { | 613 if (send_callbacks_.find(key) != send_callbacks_.end()) { |
| 594 callback.Run(message.id, GCMClient::INVALID_PARAMETER); | 614 callback.Run(message.id, GCMClient::INVALID_PARAMETER); |
| 595 return; | 615 return; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 request_gcm_statistics_callback_ = callback; | 680 request_gcm_statistics_callback_ = callback; |
| 661 content::BrowserThread::PostTask( | 681 content::BrowserThread::PostTask( |
| 662 content::BrowserThread::IO, | 682 content::BrowserThread::IO, |
| 663 FROM_HERE, | 683 FROM_HERE, |
| 664 base::Bind(&GCMDriver::IOWorker::SetGCMRecording, | 684 base::Bind(&GCMDriver::IOWorker::SetGCMRecording, |
| 665 base::Unretained(io_worker_.get()), | 685 base::Unretained(io_worker_.get()), |
| 666 recording)); | 686 recording)); |
| 667 } | 687 } |
| 668 | 688 |
| 669 void GCMDriver::OnActiveAccountLogin() { | 689 void GCMDriver::OnActiveAccountLogin() { |
| 670 if (ShouldStartAutomatically()) | 690 EnsureStarted(); |
| 671 EnsureStarted(); | |
| 672 } | 691 } |
| 673 | 692 |
| 674 void GCMDriver::OnActiveAccountLogout() { | 693 void GCMDriver::OnActiveAccountLogout() { |
| 675 CheckOut(); | 694 CheckOut(); |
| 676 } | 695 } |
| 677 | 696 |
| 678 void GCMDriver::EnsureStarted() { | 697 GCMClient::Result GCMDriver::EnsureStarted() { |
| 679 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 698 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 699 |
| 700 if (!gcm_enabled_) |
| 701 return GCMClient::GCM_DISABLED; |
| 702 |
| 703 // Is the user signed in? |
| 680 const std::string account_id = identity_provider_->GetActiveAccountId(); | 704 const std::string account_id = identity_provider_->GetActiveAccountId(); |
| 681 if (account_id.empty()) | 705 if (account_id.empty()) |
| 682 return; | 706 return GCMClient::NOT_SIGNED_IN; |
| 683 | 707 |
| 684 // CheckIn could be called more than once when: | 708 // CheckIn could be called more than once when: |
| 685 // 1) The password changes. | 709 // 1) The password changes. |
| 686 // 2) Register/send function calls it to ensure CheckIn is done. | 710 // 2) Register/send function calls it to ensure CheckIn is done. |
| 687 if (account_id_ == account_id) | 711 if (account_id_ == account_id) |
| 688 return; | 712 return GCMClient::SUCCESS; |
| 689 account_id_ = account_id; | 713 account_id_ = account_id; |
| 690 | 714 |
| 691 DCHECK(!delayed_task_controller_); | 715 DCHECK(!delayed_task_controller_); |
| 692 delayed_task_controller_.reset(new DelayedTaskController); | 716 delayed_task_controller_.reset(new DelayedTaskController); |
| 693 | 717 |
| 694 // Note that we need to pass weak pointer again since the existing weak | 718 // Note that we need to pass weak pointer again since the existing weak |
| 695 // pointer in IOWorker might have been invalidated when check-out occurs. | 719 // pointer in IOWorker might have been invalidated when check-out occurs. |
| 696 content::BrowserThread::PostTask( | 720 content::BrowserThread::PostTask( |
| 697 content::BrowserThread::IO, | 721 content::BrowserThread::IO, |
| 698 FROM_HERE, | 722 FROM_HERE, |
| 699 base::Bind(&GCMDriver::IOWorker::Start, | 723 base::Bind(&GCMDriver::IOWorker::Start, |
| 700 base::Unretained(io_worker_.get()), | 724 base::Unretained(io_worker_.get()), |
| 701 weak_ptr_factory_.GetWeakPtr())); | 725 weak_ptr_factory_.GetWeakPtr())); |
| 726 |
| 727 return GCMClient::SUCCESS; |
| 702 } | 728 } |
| 703 | 729 |
| 704 void GCMDriver::RemoveCachedData() { | 730 void GCMDriver::RemoveCachedData() { |
| 705 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 731 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 706 // Remove all the queued tasks since they no longer make sense after | 732 // Remove all the queued tasks since they no longer make sense after |
| 707 // GCM service is stopped. | 733 // GCM service is stopped. |
| 708 weak_ptr_factory_.InvalidateWeakPtrs(); | 734 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 709 | 735 |
| 710 account_id_.clear(); | 736 account_id_.clear(); |
| 711 gcm_client_ready_ = false; | 737 gcm_client_ready_ = false; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 723 | 749 |
| 724 RemoveCachedData(); | 750 RemoveCachedData(); |
| 725 | 751 |
| 726 content::BrowserThread::PostTask( | 752 content::BrowserThread::PostTask( |
| 727 content::BrowserThread::IO, | 753 content::BrowserThread::IO, |
| 728 FROM_HERE, | 754 FROM_HERE, |
| 729 base::Bind(&GCMDriver::IOWorker::CheckOut, | 755 base::Bind(&GCMDriver::IOWorker::CheckOut, |
| 730 base::Unretained(io_worker_.get()))); | 756 base::Unretained(io_worker_.get()))); |
| 731 } | 757 } |
| 732 | 758 |
| 733 GCMClient::Result GCMDriver::EnsureAppReady(const std::string& app_id) { | |
| 734 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 735 | |
| 736 // Starts the service if not yet. | |
| 737 EnsureStarted(); | |
| 738 | |
| 739 // If the service cannot be started, bail out. | |
| 740 if (account_id_.empty()) | |
| 741 return GCMClient::NOT_SIGNED_IN; | |
| 742 | |
| 743 return GCMClient::SUCCESS; | |
| 744 } | |
| 745 | |
| 746 bool GCMDriver::IsAsyncOperationPending(const std::string& app_id) const { | 759 bool GCMDriver::IsAsyncOperationPending(const std::string& app_id) const { |
| 747 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 760 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 748 return register_callbacks_.find(app_id) != register_callbacks_.end() || | 761 return register_callbacks_.find(app_id) != register_callbacks_.end() || |
| 749 unregister_callbacks_.find(app_id) != unregister_callbacks_.end(); | 762 unregister_callbacks_.find(app_id) != unregister_callbacks_.end(); |
| 750 } | 763 } |
| 751 | 764 |
| 752 void GCMDriver::RegisterFinished(const std::string& app_id, | 765 void GCMDriver::RegisterFinished(const std::string& app_id, |
| 753 const std::string& registration_id, | 766 const std::string& registration_id, |
| 754 GCMClient::Result result) { | 767 GCMClient::Result result) { |
| 755 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 768 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 void GCMDriver::GetGCMStatisticsFinished(GCMClient::GCMStatistics stats) { | 865 void GCMDriver::GetGCMStatisticsFinished(GCMClient::GCMStatistics stats) { |
| 853 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 866 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 854 | 867 |
| 855 // Normally request_gcm_statistics_callback_ would not be null. | 868 // Normally request_gcm_statistics_callback_ would not be null. |
| 856 if (!request_gcm_statistics_callback_.is_null()) | 869 if (!request_gcm_statistics_callback_.is_null()) |
| 857 request_gcm_statistics_callback_.Run(stats); | 870 request_gcm_statistics_callback_.Run(stats); |
| 858 else | 871 else |
| 859 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL."; | 872 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL."; |
| 860 } | 873 } |
| 861 | 874 |
| 875 std::string GCMDriver::SignedInUserName() const { |
| 876 if (IsStarted()) |
| 877 return identity_provider_->GetActiveUsername(); |
| 878 return std::string(); |
| 879 } |
| 880 |
| 862 } // namespace gcm | 881 } // namespace gcm |
| OLD | NEW |