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
3 // found in the LICENSE file.
5 #include "components/gcm_driver/gcm_driver.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/files/file_path.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/threading/sequenced_worker_pool.h"
17 #include "components/gcm_driver/gcm_app_handler.h"
18 #include "components/gcm_driver/gcm_client_factory.h"
19 #include "components/gcm_driver/system_encryptor.h"
20 #include "google_apis/gaia/oauth2_token_service.h"
21 #include "net/url_request/url_request_context_getter.h"
25 // Helper class to save tasks to run until we're ready to execute them.
26 class GCMDriver::DelayedTaskController
{
28 DelayedTaskController();
29 ~DelayedTaskController();
31 // Adds a task that will be invoked once we're ready.
32 void AddTask(const base::Closure
& task
);
34 // Sets ready status. It is ready only when check-in is completed and
35 // the GCMClient is fully initialized.
38 // Returns true if it is ready to perform tasks.
39 bool CanRunTaskWithoutDelay() const;
44 // Flag that indicates that GCM is ready.
47 std::vector
<base::Closure
> delayed_tasks_
;
49 DISALLOW_COPY_AND_ASSIGN(DelayedTaskController
);
52 GCMDriver::DelayedTaskController::DelayedTaskController() : ready_(false) {
55 GCMDriver::DelayedTaskController::~DelayedTaskController() {
58 void GCMDriver::DelayedTaskController::AddTask(const base::Closure
& task
) {
59 delayed_tasks_
.push_back(task
);
62 void GCMDriver::DelayedTaskController::SetReady() {
67 bool GCMDriver::DelayedTaskController::CanRunTaskWithoutDelay() const {
71 void GCMDriver::DelayedTaskController::RunTasks() {
74 for (size_t i
= 0; i
< delayed_tasks_
.size(); ++i
)
75 delayed_tasks_
[i
].Run();
76 delayed_tasks_
.clear();
79 class GCMDriver::IOWorker
: public GCMClient::Delegate
{
81 // Called on UI thread.
82 IOWorker(const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
83 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
);
86 // Overridden from GCMClient::Delegate:
87 // Called on IO thread.
88 virtual void OnRegisterFinished(const std::string
& app_id
,
89 const std::string
& registration_id
,
90 GCMClient::Result result
) OVERRIDE
;
91 virtual void OnUnregisterFinished(const std::string
& app_id
,
92 GCMClient::Result result
) OVERRIDE
;
93 virtual void OnSendFinished(const std::string
& app_id
,
94 const std::string
& message_id
,
95 GCMClient::Result result
) OVERRIDE
;
96 virtual void OnMessageReceived(
97 const std::string
& app_id
,
98 const GCMClient::IncomingMessage
& message
) OVERRIDE
;
99 virtual void OnMessagesDeleted(const std::string
& app_id
) OVERRIDE
;
100 virtual void OnMessageSendError(
101 const std::string
& app_id
,
102 const GCMClient::SendErrorDetails
& send_error_details
) OVERRIDE
;
103 virtual void OnGCMReady() OVERRIDE
;
104 virtual void OnActivityRecorded() OVERRIDE
;
106 // Called on IO thread.
108 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
109 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
110 const base::FilePath
& store_path
,
111 const std::vector
<std::string
>& account_ids
,
112 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
113 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
);
114 void Start(const base::WeakPtr
<GCMDriver
>& service
);
117 void Register(const std::string
& app_id
,
118 const std::vector
<std::string
>& sender_ids
);
119 void Unregister(const std::string
& app_id
);
120 void Send(const std::string
& app_id
,
121 const std::string
& receiver_id
,
122 const GCMClient::OutgoingMessage
& message
);
123 void GetGCMStatistics(bool clear_logs
);
124 void SetGCMRecording(bool recording
);
126 // For testing purpose. Can be called from UI thread. Use with care.
127 GCMClient
* gcm_client_for_testing() const { return gcm_client_
.get(); }
130 scoped_refptr
<base::SequencedTaskRunner
> ui_thread_
;
131 scoped_refptr
<base::SequencedTaskRunner
> io_thread_
;
133 base::WeakPtr
<GCMDriver
> service_
;
135 scoped_ptr
<GCMClient
> gcm_client_
;
137 DISALLOW_COPY_AND_ASSIGN(IOWorker
);
140 GCMDriver::IOWorker::IOWorker(
141 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
142 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
)
143 : ui_thread_(ui_thread
),
144 io_thread_(io_thread
) {
145 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
148 GCMDriver::IOWorker::~IOWorker() {
149 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
152 void GCMDriver::IOWorker::Initialize(
153 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
154 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
155 const base::FilePath
& store_path
,
156 const std::vector
<std::string
>& account_ids
,
157 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
158 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
) {
159 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
161 gcm_client_
= gcm_client_factory
->BuildInstance();
163 gcm_client_
->Initialize(chrome_build_info
,
166 blocking_task_runner
,
168 make_scoped_ptr
<Encryptor
>(new SystemEncryptor
),
172 void GCMDriver::IOWorker::OnRegisterFinished(
173 const std::string
& app_id
,
174 const std::string
& registration_id
,
175 GCMClient::Result result
) {
176 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
178 ui_thread_
->PostTask(
180 base::Bind(&GCMDriver::RegisterFinished
, service_
, app_id
,
181 registration_id
, result
));
184 void GCMDriver::IOWorker::OnUnregisterFinished(const std::string
& app_id
,
185 GCMClient::Result result
) {
186 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
188 ui_thread_
->PostTask(
190 base::Bind(&GCMDriver::UnregisterFinished
, service_
, app_id
, result
));
193 void GCMDriver::IOWorker::OnSendFinished(const std::string
& app_id
,
194 const std::string
& message_id
,
195 GCMClient::Result result
) {
196 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
198 ui_thread_
->PostTask(
200 base::Bind(&GCMDriver::SendFinished
, service_
, app_id
, message_id
,
204 void GCMDriver::IOWorker::OnMessageReceived(
205 const std::string
& app_id
,
206 const GCMClient::IncomingMessage
& message
) {
207 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
209 ui_thread_
->PostTask(
211 base::Bind(&GCMDriver::MessageReceived
, service_
, app_id
, message
));
214 void GCMDriver::IOWorker::OnMessagesDeleted(const std::string
& app_id
) {
215 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
217 ui_thread_
->PostTask(
219 base::Bind(&GCMDriver::MessagesDeleted
, service_
, app_id
));
222 void GCMDriver::IOWorker::OnMessageSendError(
223 const std::string
& app_id
,
224 const GCMClient::SendErrorDetails
& send_error_details
) {
225 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
227 ui_thread_
->PostTask(
229 base::Bind(&GCMDriver::MessageSendError
, service_
, app_id
,
230 send_error_details
));
233 void GCMDriver::IOWorker::OnGCMReady() {
234 ui_thread_
->PostTask(
236 base::Bind(&GCMDriver::GCMClientReady
, service_
));
239 void GCMDriver::IOWorker::OnActivityRecorded() {
240 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
241 // When an activity is recorded, get all the stats and refresh the UI of
242 // gcm-internals page.
243 GetGCMStatistics(false);
246 void GCMDriver::IOWorker::Start(const base::WeakPtr
<GCMDriver
>& service
) {
247 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
250 gcm_client_
->Start();
253 void GCMDriver::IOWorker::Stop() {
254 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
259 void GCMDriver::IOWorker::CheckOut() {
260 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
262 gcm_client_
->CheckOut();
264 // Note that we still need to keep GCMClient instance alive since the
265 // GCMDriver may check in again.
268 void GCMDriver::IOWorker::Register(
269 const std::string
& app_id
,
270 const std::vector
<std::string
>& sender_ids
) {
271 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
273 gcm_client_
->Register(app_id
, sender_ids
);
276 void GCMDriver::IOWorker::Unregister(const std::string
& app_id
) {
277 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
279 gcm_client_
->Unregister(app_id
);
282 void GCMDriver::IOWorker::Send(const std::string
& app_id
,
283 const std::string
& receiver_id
,
284 const GCMClient::OutgoingMessage
& message
) {
285 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
287 gcm_client_
->Send(app_id
, receiver_id
, message
);
290 void GCMDriver::IOWorker::GetGCMStatistics(bool clear_logs
) {
291 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
292 gcm::GCMClient::GCMStatistics stats
;
294 if (gcm_client_
.get()) {
296 gcm_client_
->ClearActivityLogs();
297 stats
= gcm_client_
->GetStatistics();
300 ui_thread_
->PostTask(
302 base::Bind(&GCMDriver::GetGCMStatisticsFinished
, service_
, stats
));
305 void GCMDriver::IOWorker::SetGCMRecording(bool recording
) {
306 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
307 gcm::GCMClient::GCMStatistics stats
;
309 if (gcm_client_
.get()) {
310 gcm_client_
->SetRecording(recording
);
311 stats
= gcm_client_
->GetStatistics();
312 stats
.gcm_client_created
= true;
315 ui_thread_
->PostTask(
317 base::Bind(&GCMDriver::GetGCMStatisticsFinished
, service_
, stats
));
320 GCMDriver::GCMDriver(
321 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
322 scoped_ptr
<IdentityProvider
> identity_provider
,
323 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
324 const base::FilePath
& store_path
,
325 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
326 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
327 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
,
328 const scoped_refptr
<base::SequencedTaskRunner
>& blocking_task_runner
)
329 : gcm_enabled_(true),
330 gcm_client_ready_(false),
331 identity_provider_(identity_provider
.Pass()),
332 ui_thread_(ui_thread
),
333 io_thread_(io_thread
),
334 weak_ptr_factory_(this) {
335 // Get the list of available accounts.
336 std::vector
<std::string
> account_ids
;
337 #if !defined(OS_ANDROID)
338 account_ids
= identity_provider_
->GetTokenService()->GetAccounts();
341 // Create and initialize the GCMClient. Note that this does not initiate the
343 io_worker_
.reset(new IOWorker(ui_thread
, io_thread
));
344 io_thread_
->PostTask(
346 base::Bind(&GCMDriver::IOWorker::Initialize
,
347 base::Unretained(io_worker_
.get()),
348 base::Passed(&gcm_client_factory
),
353 blocking_task_runner
));
355 identity_provider_
->AddObserver(this);
358 GCMDriver::GCMDriver()
359 : gcm_enabled_(true),
360 gcm_client_ready_(false),
361 weak_ptr_factory_(this) {
364 GCMDriver::~GCMDriver() {
367 void GCMDriver::Enable() {
368 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
377 void GCMDriver::Disable() {
378 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
382 gcm_enabled_
= false;
387 void GCMDriver::Stop() {
388 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
390 // No need to stop GCM service if not started yet.
391 if (account_id_
.empty())
396 io_thread_
->PostTask(
398 base::Bind(&GCMDriver::IOWorker::Stop
,
399 base::Unretained(io_worker_
.get())));
402 void GCMDriver::Shutdown() {
403 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
404 identity_provider_
->RemoveObserver(this);
405 for (GCMAppHandlerMap::const_iterator iter
= app_handlers_
.begin();
406 iter
!= app_handlers_
.end(); ++iter
) {
407 iter
->second
->ShutdownHandler();
409 app_handlers_
.clear();
410 io_thread_
->DeleteSoon(FROM_HERE
, io_worker_
.release());
413 void GCMDriver::AddAppHandler(const std::string
& app_id
,
414 GCMAppHandler
* handler
) {
415 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
416 DCHECK(!app_id
.empty());
418 DCHECK(app_handlers_
.find(app_id
) == app_handlers_
.end());
420 app_handlers_
[app_id
] = handler
;
422 // Ensures that the GCM service is started when there is an interest.
426 void GCMDriver::RemoveAppHandler(const std::string
& app_id
) {
427 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
428 DCHECK(!app_id
.empty());
430 app_handlers_
.erase(app_id
);
432 // Stops the GCM service when no app intends to consume it.
433 if (app_handlers_
.empty())
437 void GCMDriver::Register(const std::string
& app_id
,
438 const std::vector
<std::string
>& sender_ids
,
439 const RegisterCallback
& callback
) {
440 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
441 DCHECK(!app_id
.empty());
442 DCHECK(!sender_ids
.empty());
443 DCHECK(!callback
.is_null());
445 GCMClient::Result result
= EnsureStarted();
446 if (result
!= GCMClient::SUCCESS
) {
447 callback
.Run(std::string(), result
);
451 // If previous un/register operation is still in progress, bail out.
452 if (IsAsyncOperationPending(app_id
)) {
453 callback
.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING
);
457 register_callbacks_
[app_id
] = callback
;
459 // Delay the register operation until GCMClient is ready.
460 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
461 delayed_task_controller_
->AddTask(base::Bind(&GCMDriver::DoRegister
,
462 weak_ptr_factory_
.GetWeakPtr(),
468 DoRegister(app_id
, sender_ids
);
471 void GCMDriver::DoRegister(const std::string
& app_id
,
472 const std::vector
<std::string
>& sender_ids
) {
473 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
474 std::map
<std::string
, RegisterCallback
>::iterator callback_iter
=
475 register_callbacks_
.find(app_id
);
476 if (callback_iter
== register_callbacks_
.end()) {
477 // The callback could have been removed when the app is uninstalled.
481 // Normalize the sender IDs by making them sorted.
482 std::vector
<std::string
> normalized_sender_ids
= sender_ids
;
483 std::sort(normalized_sender_ids
.begin(), normalized_sender_ids
.end());
485 io_thread_
->PostTask(
487 base::Bind(&GCMDriver::IOWorker::Register
,
488 base::Unretained(io_worker_
.get()),
490 normalized_sender_ids
));
493 void GCMDriver::Unregister(const std::string
& app_id
,
494 const UnregisterCallback
& callback
) {
495 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
496 DCHECK(!app_id
.empty());
497 DCHECK(!callback
.is_null());
499 GCMClient::Result result
= EnsureStarted();
500 if (result
!= GCMClient::SUCCESS
) {
501 callback
.Run(result
);
505 // If previous un/register operation is still in progress, bail out.
506 if (IsAsyncOperationPending(app_id
)) {
507 callback
.Run(GCMClient::ASYNC_OPERATION_PENDING
);
511 unregister_callbacks_
[app_id
] = callback
;
513 // Delay the unregister operation until GCMClient is ready.
514 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
515 delayed_task_controller_
->AddTask(base::Bind(&GCMDriver::DoUnregister
,
516 weak_ptr_factory_
.GetWeakPtr(),
521 DoUnregister(app_id
);
524 void GCMDriver::DoUnregister(const std::string
& app_id
) {
525 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
527 // Ask the server to unregister it. There could be a small chance that the
528 // unregister request fails. If this occurs, it does not bring any harm since
529 // we simply reject the messages/events received from the server.
530 io_thread_
->PostTask(
532 base::Bind(&GCMDriver::IOWorker::Unregister
,
533 base::Unretained(io_worker_
.get()),
537 void GCMDriver::Send(const std::string
& app_id
,
538 const std::string
& receiver_id
,
539 const GCMClient::OutgoingMessage
& message
,
540 const SendCallback
& callback
) {
541 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
542 DCHECK(!app_id
.empty());
543 DCHECK(!receiver_id
.empty());
544 DCHECK(!callback
.is_null());
546 GCMClient::Result result
= EnsureStarted();
547 if (result
!= GCMClient::SUCCESS
) {
548 callback
.Run(std::string(), result
);
552 // If the message with send ID is still in progress, bail out.
553 std::pair
<std::string
, std::string
> key(app_id
, message
.id
);
554 if (send_callbacks_
.find(key
) != send_callbacks_
.end()) {
555 callback
.Run(message
.id
, GCMClient::INVALID_PARAMETER
);
559 send_callbacks_
[key
] = callback
;
561 // Delay the send operation until all GCMClient is ready.
562 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
563 delayed_task_controller_
->AddTask(base::Bind(&GCMDriver::DoSend
,
564 weak_ptr_factory_
.GetWeakPtr(),
571 DoSend(app_id
, receiver_id
, message
);
574 void GCMDriver::DoSend(const std::string
& app_id
,
575 const std::string
& receiver_id
,
576 const GCMClient::OutgoingMessage
& message
) {
577 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
578 io_thread_
->PostTask(
580 base::Bind(&GCMDriver::IOWorker::Send
,
581 base::Unretained(io_worker_
.get()),
587 GCMClient
* GCMDriver::GetGCMClientForTesting() const {
588 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
589 return io_worker_
? io_worker_
->gcm_client_for_testing() : NULL
;
592 bool GCMDriver::IsStarted() const {
593 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
594 return !account_id_
.empty();
597 bool GCMDriver::IsGCMClientReady() const {
598 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
599 return gcm_client_ready_
;
602 void GCMDriver::GetGCMStatistics(const GetGCMStatisticsCallback
& callback
,
604 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
605 DCHECK(!callback
.is_null());
607 request_gcm_statistics_callback_
= callback
;
608 io_thread_
->PostTask(
610 base::Bind(&GCMDriver::IOWorker::GetGCMStatistics
,
611 base::Unretained(io_worker_
.get()),
615 void GCMDriver::SetGCMRecording(const GetGCMStatisticsCallback
& callback
,
617 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
619 request_gcm_statistics_callback_
= callback
;
620 io_thread_
->PostTask(
622 base::Bind(&GCMDriver::IOWorker::SetGCMRecording
,
623 base::Unretained(io_worker_
.get()),
627 void GCMDriver::OnActiveAccountLogin() {
631 void GCMDriver::OnActiveAccountLogout() {
635 GCMClient::Result
GCMDriver::EnsureStarted() {
636 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
639 return GCMClient::GCM_DISABLED
;
641 // Have any app requested the service?
642 if (app_handlers_
.empty())
643 return GCMClient::UNKNOWN_ERROR
;
645 // Is the user signed in?
646 const std::string account_id
= identity_provider_
->GetActiveAccountId();
647 if (account_id
.empty())
648 return GCMClient::NOT_SIGNED_IN
;
650 // CheckIn could be called more than once when:
651 // 1) The password changes.
652 // 2) Register/send function calls it to ensure CheckIn is done.
653 if (account_id_
== account_id
)
654 return GCMClient::SUCCESS
;
655 account_id_
= account_id
;
657 DCHECK(!delayed_task_controller_
);
658 delayed_task_controller_
.reset(new DelayedTaskController
);
660 // Note that we need to pass weak pointer again since the existing weak
661 // pointer in IOWorker might have been invalidated when check-out occurs.
662 io_thread_
->PostTask(
664 base::Bind(&GCMDriver::IOWorker::Start
,
665 base::Unretained(io_worker_
.get()),
666 weak_ptr_factory_
.GetWeakPtr()));
668 return GCMClient::SUCCESS
;
671 void GCMDriver::RemoveCachedData() {
672 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
673 // Remove all the queued tasks since they no longer make sense after
674 // GCM service is stopped.
675 weak_ptr_factory_
.InvalidateWeakPtrs();
678 gcm_client_ready_
= false;
679 delayed_task_controller_
.reset();
680 register_callbacks_
.clear();
681 send_callbacks_
.clear();
684 void GCMDriver::CheckOut() {
685 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
687 // We still proceed with the check-out logic even if the check-in is not
688 // initiated in the current session. This will make sure that all the
689 // persisted data written previously will get purged.
693 io_thread_
->PostTask(
695 base::Bind(&GCMDriver::IOWorker::CheckOut
,
696 base::Unretained(io_worker_
.get())));
699 bool GCMDriver::IsAsyncOperationPending(const std::string
& app_id
) const {
700 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
701 return register_callbacks_
.find(app_id
) != register_callbacks_
.end() ||
702 unregister_callbacks_
.find(app_id
) != unregister_callbacks_
.end();
705 void GCMDriver::RegisterFinished(const std::string
& app_id
,
706 const std::string
& registration_id
,
707 GCMClient::Result result
) {
708 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
710 std::map
<std::string
, RegisterCallback
>::iterator callback_iter
=
711 register_callbacks_
.find(app_id
);
712 if (callback_iter
== register_callbacks_
.end()) {
713 // The callback could have been removed when the app is uninstalled.
717 RegisterCallback callback
= callback_iter
->second
;
718 register_callbacks_
.erase(callback_iter
);
719 callback
.Run(registration_id
, result
);
722 void GCMDriver::UnregisterFinished(const std::string
& app_id
,
723 GCMClient::Result result
) {
724 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
726 std::map
<std::string
, UnregisterCallback
>::iterator callback_iter
=
727 unregister_callbacks_
.find(app_id
);
728 if (callback_iter
== unregister_callbacks_
.end())
731 UnregisterCallback callback
= callback_iter
->second
;
732 unregister_callbacks_
.erase(callback_iter
);
733 callback
.Run(result
);
736 void GCMDriver::SendFinished(const std::string
& app_id
,
737 const std::string
& message_id
,
738 GCMClient::Result result
) {
739 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
741 std::map
<std::pair
<std::string
, std::string
>, SendCallback
>::iterator
742 callback_iter
= send_callbacks_
.find(
743 std::pair
<std::string
, std::string
>(app_id
, message_id
));
744 if (callback_iter
== send_callbacks_
.end()) {
745 // The callback could have been removed when the app is uninstalled.
749 SendCallback callback
= callback_iter
->second
;
750 send_callbacks_
.erase(callback_iter
);
751 callback
.Run(message_id
, result
);
754 void GCMDriver::MessageReceived(const std::string
& app_id
,
755 GCMClient::IncomingMessage message
) {
756 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
758 // Drop the event if signed out.
759 if (account_id_
.empty())
762 GetAppHandler(app_id
)->OnMessage(app_id
, message
);
765 void GCMDriver::MessagesDeleted(const std::string
& app_id
) {
766 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
768 // Drop the event if signed out.
769 if (account_id_
.empty())
772 GetAppHandler(app_id
)->OnMessagesDeleted(app_id
);
775 void GCMDriver::MessageSendError(
776 const std::string
& app_id
,
777 const GCMClient::SendErrorDetails
& send_error_details
) {
778 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
780 // Drop the event if signed out.
781 if (account_id_
.empty())
784 GetAppHandler(app_id
)->OnSendError(app_id
, send_error_details
);
787 void GCMDriver::GCMClientReady() {
788 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
790 if (gcm_client_ready_
)
792 gcm_client_ready_
= true;
794 delayed_task_controller_
->SetReady();
797 GCMAppHandler
* GCMDriver::GetAppHandler(const std::string
& app_id
) {
798 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
800 std::map
<std::string
, GCMAppHandler
*>::const_iterator iter
=
801 app_handlers_
.find(app_id
);
802 return iter
== app_handlers_
.end() ? &default_app_handler_
: iter
->second
;
805 void GCMDriver::GetGCMStatisticsFinished(GCMClient::GCMStatistics stats
) {
806 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
808 // Normally request_gcm_statistics_callback_ would not be null.
809 if (!request_gcm_statistics_callback_
.is_null())
810 request_gcm_statistics_callback_
.Run(stats
);
812 LOG(WARNING
) << "request_gcm_statistics_callback_ is NULL.";
815 std::string
GCMDriver::SignedInUserName() const {
817 return identity_provider_
->GetActiveUsername();
818 return std::string();