| Index: components/gcm_driver/gcm_driver.cc
|
| diff --git a/components/gcm_driver/gcm_driver.cc b/components/gcm_driver/gcm_driver.cc
|
| index e41972e944770856d073a93788f2713687cfca58..866e6ca50fd2b26d20f15bea7718749edc0bc5a3 100644
|
| --- a/components/gcm_driver/gcm_driver.cc
|
| +++ b/components/gcm_driver/gcm_driver.cc
|
| @@ -4,818 +4,41 @@
|
|
|
| #include "components/gcm_driver/gcm_driver.h"
|
|
|
| -#include <algorithm>
|
| -#include <utility>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/location.h"
|
| #include "base/logging.h"
|
| -#include "base/sequenced_task_runner.h"
|
| -#include "base/threading/sequenced_worker_pool.h"
|
| #include "components/gcm_driver/gcm_app_handler.h"
|
| -#include "components/gcm_driver/gcm_client_factory.h"
|
| -#include "components/gcm_driver/system_encryptor.h"
|
| -#include "google_apis/gaia/oauth2_token_service.h"
|
| -#include "net/url_request/url_request_context_getter.h"
|
|
|
| namespace gcm {
|
|
|
| -// Helper class to save tasks to run until we're ready to execute them.
|
| -class GCMDriver::DelayedTaskController {
|
| - public:
|
| - DelayedTaskController();
|
| - ~DelayedTaskController();
|
| -
|
| - // Adds a task that will be invoked once we're ready.
|
| - void AddTask(const base::Closure& task);
|
| -
|
| - // Sets ready status. It is ready only when check-in is completed and
|
| - // the GCMClient is fully initialized.
|
| - void SetReady();
|
| -
|
| - // Returns true if it is ready to perform tasks.
|
| - bool CanRunTaskWithoutDelay() const;
|
| -
|
| - private:
|
| - void RunTasks();
|
| -
|
| - // Flag that indicates that GCM is ready.
|
| - bool ready_;
|
| -
|
| - std::vector<base::Closure> delayed_tasks_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(DelayedTaskController);
|
| -};
|
| -
|
| -GCMDriver::DelayedTaskController::DelayedTaskController() : ready_(false) {
|
| -}
|
| -
|
| -GCMDriver::DelayedTaskController::~DelayedTaskController() {
|
| -}
|
| -
|
| -void GCMDriver::DelayedTaskController::AddTask(const base::Closure& task) {
|
| - delayed_tasks_.push_back(task);
|
| -}
|
| -
|
| -void GCMDriver::DelayedTaskController::SetReady() {
|
| - ready_ = true;
|
| - RunTasks();
|
| -}
|
| -
|
| -bool GCMDriver::DelayedTaskController::CanRunTaskWithoutDelay() const {
|
| - return ready_;
|
| -}
|
| -
|
| -void GCMDriver::DelayedTaskController::RunTasks() {
|
| - DCHECK(ready_);
|
| -
|
| - for (size_t i = 0; i < delayed_tasks_.size(); ++i)
|
| - delayed_tasks_[i].Run();
|
| - delayed_tasks_.clear();
|
| -}
|
| -
|
| -class GCMDriver::IOWorker : public GCMClient::Delegate {
|
| - public:
|
| - // Called on UI thread.
|
| - IOWorker(const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
|
| - const scoped_refptr<base::SequencedTaskRunner>& io_thread);
|
| - virtual ~IOWorker();
|
| -
|
| - // Overridden from GCMClient::Delegate:
|
| - // Called on IO thread.
|
| - virtual void OnRegisterFinished(const std::string& app_id,
|
| - const std::string& registration_id,
|
| - GCMClient::Result result) OVERRIDE;
|
| - virtual void OnUnregisterFinished(const std::string& app_id,
|
| - GCMClient::Result result) OVERRIDE;
|
| - virtual void OnSendFinished(const std::string& app_id,
|
| - const std::string& message_id,
|
| - GCMClient::Result result) OVERRIDE;
|
| - virtual void OnMessageReceived(
|
| - const std::string& app_id,
|
| - const GCMClient::IncomingMessage& message) OVERRIDE;
|
| - virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
|
| - virtual void OnMessageSendError(
|
| - const std::string& app_id,
|
| - const GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
|
| - virtual void OnGCMReady() OVERRIDE;
|
| - virtual void OnActivityRecorded() OVERRIDE;
|
| -
|
| - // Called on IO thread.
|
| - void Initialize(
|
| - scoped_ptr<GCMClientFactory> gcm_client_factory,
|
| - const GCMClient::ChromeBuildInfo& chrome_build_info,
|
| - const base::FilePath& store_path,
|
| - const std::vector<std::string>& account_ids,
|
| - const scoped_refptr<net::URLRequestContextGetter>& request_context,
|
| - const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
|
| - void Start(const base::WeakPtr<GCMDriver>& service);
|
| - void Stop();
|
| - void CheckOut();
|
| - void Register(const std::string& app_id,
|
| - const std::vector<std::string>& sender_ids);
|
| - void Unregister(const std::string& app_id);
|
| - void Send(const std::string& app_id,
|
| - const std::string& receiver_id,
|
| - const GCMClient::OutgoingMessage& message);
|
| - void GetGCMStatistics(bool clear_logs);
|
| - void SetGCMRecording(bool recording);
|
| -
|
| - // For testing purpose. Can be called from UI thread. Use with care.
|
| - GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
|
| -
|
| - private:
|
| - scoped_refptr<base::SequencedTaskRunner> ui_thread_;
|
| - scoped_refptr<base::SequencedTaskRunner> io_thread_;
|
| -
|
| - base::WeakPtr<GCMDriver> service_;
|
| -
|
| - scoped_ptr<GCMClient> gcm_client_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(IOWorker);
|
| -};
|
| -
|
| -GCMDriver::IOWorker::IOWorker(
|
| - const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
|
| - const scoped_refptr<base::SequencedTaskRunner>& io_thread)
|
| - : ui_thread_(ui_thread),
|
| - io_thread_(io_thread) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -}
|
| -
|
| -GCMDriver::IOWorker::~IOWorker() {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::Initialize(
|
| - scoped_ptr<GCMClientFactory> gcm_client_factory,
|
| - const GCMClient::ChromeBuildInfo& chrome_build_info,
|
| - const base::FilePath& store_path,
|
| - const std::vector<std::string>& account_ids,
|
| - const scoped_refptr<net::URLRequestContextGetter>& request_context,
|
| - const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - gcm_client_ = gcm_client_factory->BuildInstance();
|
| -
|
| - gcm_client_->Initialize(chrome_build_info,
|
| - store_path,
|
| - account_ids,
|
| - blocking_task_runner,
|
| - request_context,
|
| - make_scoped_ptr<Encryptor>(new SystemEncryptor),
|
| - this);
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::OnRegisterFinished(
|
| - const std::string& app_id,
|
| - const std::string& registration_id,
|
| - GCMClient::Result result) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - ui_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::RegisterFinished, service_, app_id,
|
| - registration_id, result));
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::OnUnregisterFinished(const std::string& app_id,
|
| - GCMClient::Result result) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - ui_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::UnregisterFinished, service_, app_id, result));
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::OnSendFinished(const std::string& app_id,
|
| - const std::string& message_id,
|
| - GCMClient::Result result) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - ui_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::SendFinished, service_, app_id, message_id,
|
| - result));
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::OnMessageReceived(
|
| - const std::string& app_id,
|
| - const GCMClient::IncomingMessage& message) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - ui_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::MessageReceived, service_, app_id, message));
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::OnMessagesDeleted(const std::string& app_id) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - ui_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::MessagesDeleted, service_, app_id));
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::OnMessageSendError(
|
| - const std::string& app_id,
|
| - const GCMClient::SendErrorDetails& send_error_details) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - ui_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::MessageSendError, service_, app_id,
|
| - send_error_details));
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::OnGCMReady() {
|
| - ui_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::GCMClientReady, service_));
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::OnActivityRecorded() {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| - // When an activity is recorded, get all the stats and refresh the UI of
|
| - // gcm-internals page.
|
| - GetGCMStatistics(false);
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::Start(const base::WeakPtr<GCMDriver>& service) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - service_ = service;
|
| - gcm_client_->Start();
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::Stop() {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - gcm_client_->Stop();
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::CheckOut() {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - gcm_client_->CheckOut();
|
| -
|
| - // Note that we still need to keep GCMClient instance alive since the
|
| - // GCMDriver may check in again.
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::Register(
|
| - const std::string& app_id,
|
| - const std::vector<std::string>& sender_ids) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - gcm_client_->Register(app_id, sender_ids);
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::Unregister(const std::string& app_id) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - gcm_client_->Unregister(app_id);
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::Send(const std::string& app_id,
|
| - const std::string& receiver_id,
|
| - const GCMClient::OutgoingMessage& message) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - gcm_client_->Send(app_id, receiver_id, message);
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::GetGCMStatistics(bool clear_logs) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| - gcm::GCMClient::GCMStatistics stats;
|
| -
|
| - if (gcm_client_.get()) {
|
| - if (clear_logs)
|
| - gcm_client_->ClearActivityLogs();
|
| - stats = gcm_client_->GetStatistics();
|
| - }
|
| -
|
| - ui_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::GetGCMStatisticsFinished, service_, stats));
|
| -}
|
| -
|
| -void GCMDriver::IOWorker::SetGCMRecording(bool recording) {
|
| - DCHECK(io_thread_->RunsTasksOnCurrentThread());
|
| - gcm::GCMClient::GCMStatistics stats;
|
| -
|
| - if (gcm_client_.get()) {
|
| - gcm_client_->SetRecording(recording);
|
| - stats = gcm_client_->GetStatistics();
|
| - stats.gcm_client_created = true;
|
| - }
|
| -
|
| - ui_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::GetGCMStatisticsFinished, service_, stats));
|
| -}
|
| -
|
| -GCMDriver::GCMDriver(
|
| - scoped_ptr<GCMClientFactory> gcm_client_factory,
|
| - scoped_ptr<IdentityProvider> identity_provider,
|
| - const GCMClient::ChromeBuildInfo& chrome_build_info,
|
| - const base::FilePath& store_path,
|
| - const scoped_refptr<net::URLRequestContextGetter>& request_context,
|
| - const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
|
| - const scoped_refptr<base::SequencedTaskRunner>& io_thread,
|
| - const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner)
|
| - : gcm_enabled_(true),
|
| - gcm_client_ready_(false),
|
| - identity_provider_(identity_provider.Pass()),
|
| - ui_thread_(ui_thread),
|
| - io_thread_(io_thread),
|
| - weak_ptr_factory_(this) {
|
| - // Get the list of available accounts.
|
| - std::vector<std::string> account_ids;
|
| -#if !defined(OS_ANDROID)
|
| - account_ids = identity_provider_->GetTokenService()->GetAccounts();
|
| -#endif
|
| -
|
| - // Create and initialize the GCMClient. Note that this does not initiate the
|
| - // GCM check-in.
|
| - io_worker_.reset(new IOWorker(ui_thread, io_thread));
|
| - io_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::IOWorker::Initialize,
|
| - base::Unretained(io_worker_.get()),
|
| - base::Passed(&gcm_client_factory),
|
| - chrome_build_info,
|
| - store_path,
|
| - account_ids,
|
| - request_context,
|
| - blocking_task_runner));
|
| -
|
| - identity_provider_->AddObserver(this);
|
| -}
|
| -
|
| -GCMDriver::GCMDriver()
|
| - : gcm_enabled_(true),
|
| - gcm_client_ready_(false),
|
| - weak_ptr_factory_(this) {
|
| +GCMDriver::GCMDriver() {
|
| }
|
|
|
| GCMDriver::~GCMDriver() {
|
| }
|
|
|
| -void GCMDriver::Enable() {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - if (gcm_enabled_)
|
| - return;
|
| - gcm_enabled_ = true;
|
| -
|
| - EnsureStarted();
|
| -}
|
| -
|
| -void GCMDriver::Disable() {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - if (!gcm_enabled_)
|
| - return;
|
| - gcm_enabled_ = false;
|
| -
|
| - Stop();
|
| -}
|
| -
|
| -void GCMDriver::Stop() {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - // No need to stop GCM service if not started yet.
|
| - if (account_id_.empty())
|
| - return;
|
| -
|
| - RemoveCachedData();
|
| -
|
| - io_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::IOWorker::Stop,
|
| - base::Unretained(io_worker_.get())));
|
| -}
|
| -
|
| void GCMDriver::Shutdown() {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - identity_provider_->RemoveObserver(this);
|
| for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
|
| iter != app_handlers_.end(); ++iter) {
|
| iter->second->ShutdownHandler();
|
| }
|
| app_handlers_.clear();
|
| - io_thread_->DeleteSoon(FROM_HERE, io_worker_.release());
|
| }
|
|
|
| void GCMDriver::AddAppHandler(const std::string& app_id,
|
| GCMAppHandler* handler) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| DCHECK(!app_id.empty());
|
| DCHECK(handler);
|
| DCHECK(app_handlers_.find(app_id) == app_handlers_.end());
|
| -
|
| app_handlers_[app_id] = handler;
|
| -
|
| - // Ensures that the GCM service is started when there is an interest.
|
| - EnsureStarted();
|
| }
|
|
|
| void GCMDriver::RemoveAppHandler(const std::string& app_id) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| DCHECK(!app_id.empty());
|
| -
|
| app_handlers_.erase(app_id);
|
| -
|
| - // Stops the GCM service when no app intends to consume it.
|
| - if (app_handlers_.empty())
|
| - Stop();
|
| -}
|
| -
|
| -void GCMDriver::Register(const std::string& app_id,
|
| - const std::vector<std::string>& sender_ids,
|
| - const RegisterCallback& callback) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - DCHECK(!app_id.empty());
|
| - DCHECK(!sender_ids.empty());
|
| - DCHECK(!callback.is_null());
|
| -
|
| - GCMClient::Result result = EnsureStarted();
|
| - if (result != GCMClient::SUCCESS) {
|
| - callback.Run(std::string(), result);
|
| - return;
|
| - }
|
| -
|
| - // If previous un/register operation is still in progress, bail out.
|
| - if (IsAsyncOperationPending(app_id)) {
|
| - callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
|
| - return;
|
| - }
|
| -
|
| - register_callbacks_[app_id] = callback;
|
| -
|
| - // Delay the register operation until GCMClient is ready.
|
| - if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
|
| - delayed_task_controller_->AddTask(base::Bind(&GCMDriver::DoRegister,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - app_id,
|
| - sender_ids));
|
| - return;
|
| - }
|
| -
|
| - DoRegister(app_id, sender_ids);
|
| -}
|
| -
|
| -void GCMDriver::DoRegister(const std::string& app_id,
|
| - const std::vector<std::string>& sender_ids) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - std::map<std::string, RegisterCallback>::iterator callback_iter =
|
| - register_callbacks_.find(app_id);
|
| - if (callback_iter == register_callbacks_.end()) {
|
| - // The callback could have been removed when the app is uninstalled.
|
| - return;
|
| - }
|
| -
|
| - // Normalize the sender IDs by making them sorted.
|
| - std::vector<std::string> normalized_sender_ids = sender_ids;
|
| - std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
|
| -
|
| - io_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::IOWorker::Register,
|
| - base::Unretained(io_worker_.get()),
|
| - app_id,
|
| - normalized_sender_ids));
|
| -}
|
| -
|
| -void GCMDriver::Unregister(const std::string& app_id,
|
| - const UnregisterCallback& callback) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - DCHECK(!app_id.empty());
|
| - DCHECK(!callback.is_null());
|
| -
|
| - GCMClient::Result result = EnsureStarted();
|
| - if (result != GCMClient::SUCCESS) {
|
| - callback.Run(result);
|
| - return;
|
| - }
|
| -
|
| - // If previous un/register operation is still in progress, bail out.
|
| - if (IsAsyncOperationPending(app_id)) {
|
| - callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
|
| - return;
|
| - }
|
| -
|
| - unregister_callbacks_[app_id] = callback;
|
| -
|
| - // Delay the unregister operation until GCMClient is ready.
|
| - if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
|
| - delayed_task_controller_->AddTask(base::Bind(&GCMDriver::DoUnregister,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - app_id));
|
| - return;
|
| - }
|
| -
|
| - DoUnregister(app_id);
|
| -}
|
| -
|
| -void GCMDriver::DoUnregister(const std::string& app_id) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - // Ask the server to unregister it. There could be a small chance that the
|
| - // unregister request fails. If this occurs, it does not bring any harm since
|
| - // we simply reject the messages/events received from the server.
|
| - io_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::IOWorker::Unregister,
|
| - base::Unretained(io_worker_.get()),
|
| - app_id));
|
| -}
|
| -
|
| -void GCMDriver::Send(const std::string& app_id,
|
| - const std::string& receiver_id,
|
| - const GCMClient::OutgoingMessage& message,
|
| - const SendCallback& callback) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - DCHECK(!app_id.empty());
|
| - DCHECK(!receiver_id.empty());
|
| - DCHECK(!callback.is_null());
|
| -
|
| - GCMClient::Result result = EnsureStarted();
|
| - if (result != GCMClient::SUCCESS) {
|
| - callback.Run(std::string(), result);
|
| - return;
|
| - }
|
| -
|
| - // If the message with send ID is still in progress, bail out.
|
| - std::pair<std::string, std::string> key(app_id, message.id);
|
| - if (send_callbacks_.find(key) != send_callbacks_.end()) {
|
| - callback.Run(message.id, GCMClient::INVALID_PARAMETER);
|
| - return;
|
| - }
|
| -
|
| - send_callbacks_[key] = callback;
|
| -
|
| - // Delay the send operation until all GCMClient is ready.
|
| - if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
|
| - delayed_task_controller_->AddTask(base::Bind(&GCMDriver::DoSend,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - app_id,
|
| - receiver_id,
|
| - message));
|
| - return;
|
| - }
|
| -
|
| - DoSend(app_id, receiver_id, message);
|
| -}
|
| -
|
| -void GCMDriver::DoSend(const std::string& app_id,
|
| - const std::string& receiver_id,
|
| - const GCMClient::OutgoingMessage& message) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - io_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::IOWorker::Send,
|
| - base::Unretained(io_worker_.get()),
|
| - app_id,
|
| - receiver_id,
|
| - message));
|
| -}
|
| -
|
| -GCMClient* GCMDriver::GetGCMClientForTesting() const {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL;
|
| -}
|
| -
|
| -bool GCMDriver::IsStarted() const {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - return !account_id_.empty();
|
| -}
|
| -
|
| -bool GCMDriver::IsGCMClientReady() const {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - return gcm_client_ready_;
|
| -}
|
| -
|
| -void GCMDriver::GetGCMStatistics(const GetGCMStatisticsCallback& callback,
|
| - bool clear_logs) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - DCHECK(!callback.is_null());
|
| -
|
| - request_gcm_statistics_callback_ = callback;
|
| - io_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::IOWorker::GetGCMStatistics,
|
| - base::Unretained(io_worker_.get()),
|
| - clear_logs));
|
| -}
|
| -
|
| -void GCMDriver::SetGCMRecording(const GetGCMStatisticsCallback& callback,
|
| - bool recording) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - request_gcm_statistics_callback_ = callback;
|
| - io_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::IOWorker::SetGCMRecording,
|
| - base::Unretained(io_worker_.get()),
|
| - recording));
|
| -}
|
| -
|
| -void GCMDriver::OnActiveAccountLogin() {
|
| - EnsureStarted();
|
| -}
|
| -
|
| -void GCMDriver::OnActiveAccountLogout() {
|
| - CheckOut();
|
| -}
|
| -
|
| -GCMClient::Result GCMDriver::EnsureStarted() {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - if (!gcm_enabled_)
|
| - return GCMClient::GCM_DISABLED;
|
| -
|
| - // Have any app requested the service?
|
| - if (app_handlers_.empty())
|
| - return GCMClient::UNKNOWN_ERROR;
|
| -
|
| - // Is the user signed in?
|
| - const std::string account_id = identity_provider_->GetActiveAccountId();
|
| - if (account_id.empty())
|
| - return GCMClient::NOT_SIGNED_IN;
|
| -
|
| - // CheckIn could be called more than once when:
|
| - // 1) The password changes.
|
| - // 2) Register/send function calls it to ensure CheckIn is done.
|
| - if (account_id_ == account_id)
|
| - return GCMClient::SUCCESS;
|
| - account_id_ = account_id;
|
| -
|
| - DCHECK(!delayed_task_controller_);
|
| - delayed_task_controller_.reset(new DelayedTaskController);
|
| -
|
| - // Note that we need to pass weak pointer again since the existing weak
|
| - // pointer in IOWorker might have been invalidated when check-out occurs.
|
| - io_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::IOWorker::Start,
|
| - base::Unretained(io_worker_.get()),
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| -
|
| - return GCMClient::SUCCESS;
|
| -}
|
| -
|
| -void GCMDriver::RemoveCachedData() {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - // Remove all the queued tasks since they no longer make sense after
|
| - // GCM service is stopped.
|
| - weak_ptr_factory_.InvalidateWeakPtrs();
|
| -
|
| - account_id_.clear();
|
| - gcm_client_ready_ = false;
|
| - delayed_task_controller_.reset();
|
| - register_callbacks_.clear();
|
| - send_callbacks_.clear();
|
| -}
|
| -
|
| -void GCMDriver::CheckOut() {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - // We still proceed with the check-out logic even if the check-in is not
|
| - // initiated in the current session. This will make sure that all the
|
| - // persisted data written previously will get purged.
|
| -
|
| - RemoveCachedData();
|
| -
|
| - io_thread_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&GCMDriver::IOWorker::CheckOut,
|
| - base::Unretained(io_worker_.get())));
|
| -}
|
| -
|
| -bool GCMDriver::IsAsyncOperationPending(const std::string& app_id) const {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| - return register_callbacks_.find(app_id) != register_callbacks_.end() ||
|
| - unregister_callbacks_.find(app_id) != unregister_callbacks_.end();
|
| -}
|
| -
|
| -void GCMDriver::RegisterFinished(const std::string& app_id,
|
| - const std::string& registration_id,
|
| - GCMClient::Result result) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - std::map<std::string, RegisterCallback>::iterator callback_iter =
|
| - register_callbacks_.find(app_id);
|
| - if (callback_iter == register_callbacks_.end()) {
|
| - // The callback could have been removed when the app is uninstalled.
|
| - return;
|
| - }
|
| -
|
| - RegisterCallback callback = callback_iter->second;
|
| - register_callbacks_.erase(callback_iter);
|
| - callback.Run(registration_id, result);
|
| -}
|
| -
|
| -void GCMDriver::UnregisterFinished(const std::string& app_id,
|
| - GCMClient::Result result) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - std::map<std::string, UnregisterCallback>::iterator callback_iter =
|
| - unregister_callbacks_.find(app_id);
|
| - if (callback_iter == unregister_callbacks_.end())
|
| - return;
|
| -
|
| - UnregisterCallback callback = callback_iter->second;
|
| - unregister_callbacks_.erase(callback_iter);
|
| - callback.Run(result);
|
| -}
|
| -
|
| -void GCMDriver::SendFinished(const std::string& app_id,
|
| - const std::string& message_id,
|
| - GCMClient::Result result) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - std::map<std::pair<std::string, std::string>, SendCallback>::iterator
|
| - callback_iter = send_callbacks_.find(
|
| - std::pair<std::string, std::string>(app_id, message_id));
|
| - if (callback_iter == send_callbacks_.end()) {
|
| - // The callback could have been removed when the app is uninstalled.
|
| - return;
|
| - }
|
| -
|
| - SendCallback callback = callback_iter->second;
|
| - send_callbacks_.erase(callback_iter);
|
| - callback.Run(message_id, result);
|
| -}
|
| -
|
| -void GCMDriver::MessageReceived(const std::string& app_id,
|
| - GCMClient::IncomingMessage message) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - // Drop the event if signed out.
|
| - if (account_id_.empty())
|
| - return;
|
| -
|
| - GetAppHandler(app_id)->OnMessage(app_id, message);
|
| -}
|
| -
|
| -void GCMDriver::MessagesDeleted(const std::string& app_id) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - // Drop the event if signed out.
|
| - if (account_id_.empty())
|
| - return;
|
| -
|
| - GetAppHandler(app_id)->OnMessagesDeleted(app_id);
|
| -}
|
| -
|
| -void GCMDriver::MessageSendError(
|
| - const std::string& app_id,
|
| - const GCMClient::SendErrorDetails& send_error_details) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - // Drop the event if signed out.
|
| - if (account_id_.empty())
|
| - return;
|
| -
|
| - GetAppHandler(app_id)->OnSendError(app_id, send_error_details);
|
| -}
|
| -
|
| -void GCMDriver::GCMClientReady() {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - if (gcm_client_ready_)
|
| - return;
|
| - gcm_client_ready_ = true;
|
| -
|
| - delayed_task_controller_->SetReady();
|
| }
|
|
|
| GCMAppHandler* GCMDriver::GetAppHandler(const std::string& app_id) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - std::map<std::string, GCMAppHandler*>::const_iterator iter =
|
| - app_handlers_.find(app_id);
|
| + GCMAppHandlerMap::const_iterator iter = app_handlers_.find(app_id);
|
| return iter == app_handlers_.end() ? &default_app_handler_ : iter->second;
|
| }
|
|
|
| -void GCMDriver::GetGCMStatisticsFinished(GCMClient::GCMStatistics stats) {
|
| - DCHECK(ui_thread_->RunsTasksOnCurrentThread());
|
| -
|
| - // Normally request_gcm_statistics_callback_ would not be null.
|
| - if (!request_gcm_statistics_callback_.is_null())
|
| - request_gcm_statistics_callback_.Run(stats);
|
| - else
|
| - LOG(WARNING) << "request_gcm_statistics_callback_ is NULL.";
|
| -}
|
| -
|
| -std::string GCMDriver::SignedInUserName() const {
|
| - if (IsStarted())
|
| - return identity_provider_->GetActiveUsername();
|
| - return std::string();
|
| -}
|
| -
|
| } // namespace gcm
|
|
|