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_desktop.h"
10 #include "base/bind_helpers.h"
11 #include "base/files/file_path.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "components/gcm_driver/gcm_app_handler.h"
17 #include "components/gcm_driver/gcm_client_factory.h"
18 #include "components/gcm_driver/system_encryptor.h"
19 #include "google_apis/gcm/engine/account_mapping.h"
20 #include "net/base/ip_endpoint.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 GCMDriverDesktop::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 GCMDriverDesktop::DelayedTaskController::DelayedTaskController()
56 GCMDriverDesktop::DelayedTaskController::~DelayedTaskController() {
59 void GCMDriverDesktop::DelayedTaskController::AddTask(
60 const base::Closure
& task
) {
61 delayed_tasks_
.push_back(task
);
64 void GCMDriverDesktop::DelayedTaskController::SetReady() {
69 bool GCMDriverDesktop::DelayedTaskController::CanRunTaskWithoutDelay() const {
73 void GCMDriverDesktop::DelayedTaskController::RunTasks() {
76 for (size_t i
= 0; i
< delayed_tasks_
.size(); ++i
)
77 delayed_tasks_
[i
].Run();
78 delayed_tasks_
.clear();
81 class GCMDriverDesktop::IOWorker
: public GCMClient::Delegate
{
83 // Called on UI thread.
84 IOWorker(const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
85 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
);
88 // Overridden from GCMClient::Delegate:
89 // Called on IO thread.
90 virtual void OnRegisterFinished(const std::string
& app_id
,
91 const std::string
& registration_id
,
92 GCMClient::Result result
) OVERRIDE
;
93 virtual void OnUnregisterFinished(const std::string
& app_id
,
94 GCMClient::Result result
) OVERRIDE
;
95 virtual void OnSendFinished(const std::string
& app_id
,
96 const std::string
& message_id
,
97 GCMClient::Result result
) OVERRIDE
;
98 virtual void OnMessageReceived(
99 const std::string
& app_id
,
100 const GCMClient::IncomingMessage
& message
) OVERRIDE
;
101 virtual void OnMessagesDeleted(const std::string
& app_id
) OVERRIDE
;
102 virtual void OnMessageSendError(
103 const std::string
& app_id
,
104 const GCMClient::SendErrorDetails
& send_error_details
) OVERRIDE
;
105 virtual void OnSendAcknowledged(const std::string
& app_id
,
106 const std::string
& message_id
) OVERRIDE
;
107 virtual void OnGCMReady() OVERRIDE
;
108 virtual void OnActivityRecorded() OVERRIDE
;
109 virtual void OnConnected(const net::IPEndPoint
& ip_endpoint
) OVERRIDE
;
110 virtual void OnDisconnected() OVERRIDE
;
112 // Called on IO thread.
114 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
115 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
116 const base::FilePath
& store_path
,
117 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
118 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
);
119 void Start(const base::WeakPtr
<GCMDriverDesktop
>& service
);
122 void Register(const std::string
& app_id
,
123 const std::vector
<std::string
>& sender_ids
);
124 void Unregister(const std::string
& app_id
);
125 void Send(const std::string
& app_id
,
126 const std::string
& receiver_id
,
127 const GCMClient::OutgoingMessage
& message
);
128 void GetGCMStatistics(bool clear_logs
);
129 void SetGCMRecording(bool recording
);
131 void SetAccountsForCheckin(
132 const std::map
<std::string
, std::string
>& account_tokens
);
133 void UpdateAccountMapping(const AccountMapping
& account_mapping
);
134 void RemoveAccountMapping(const std::string
& account_id
);
136 // For testing purpose. Can be called from UI thread. Use with care.
137 GCMClient
* gcm_client_for_testing() const { return gcm_client_
.get(); }
140 scoped_refptr
<base::SequencedTaskRunner
> ui_thread_
;
141 scoped_refptr
<base::SequencedTaskRunner
> io_thread_
;
143 base::WeakPtr
<GCMDriverDesktop
> service_
;
145 scoped_ptr
<GCMClient
> gcm_client_
;
147 DISALLOW_COPY_AND_ASSIGN(IOWorker
);
150 GCMDriverDesktop::IOWorker::IOWorker(
151 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
152 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
)
153 : ui_thread_(ui_thread
),
154 io_thread_(io_thread
) {
155 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
158 GCMDriverDesktop::IOWorker::~IOWorker() {
159 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
162 void GCMDriverDesktop::IOWorker::Initialize(
163 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
164 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
165 const base::FilePath
& store_path
,
166 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
167 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
) {
168 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
170 gcm_client_
= gcm_client_factory
->BuildInstance();
172 gcm_client_
->Initialize(chrome_build_info
,
174 blocking_task_runner
,
176 make_scoped_ptr
<Encryptor
>(new SystemEncryptor
),
180 void GCMDriverDesktop::IOWorker::OnRegisterFinished(
181 const std::string
& app_id
,
182 const std::string
& registration_id
,
183 GCMClient::Result result
) {
184 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
186 ui_thread_
->PostTask(
188 base::Bind(&GCMDriverDesktop::RegisterFinished
, service_
, app_id
,
189 registration_id
, result
));
192 void GCMDriverDesktop::IOWorker::OnUnregisterFinished(
193 const std::string
& app_id
,
194 GCMClient::Result result
) {
195 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
197 ui_thread_
->PostTask(FROM_HERE
,
198 base::Bind(&GCMDriverDesktop::UnregisterFinished
,
204 void GCMDriverDesktop::IOWorker::OnSendFinished(const std::string
& app_id
,
205 const std::string
& message_id
,
206 GCMClient::Result result
) {
207 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
209 ui_thread_
->PostTask(
211 base::Bind(&GCMDriverDesktop::SendFinished
, service_
, app_id
, message_id
,
215 void GCMDriverDesktop::IOWorker::OnMessageReceived(
216 const std::string
& app_id
,
217 const GCMClient::IncomingMessage
& message
) {
218 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
220 ui_thread_
->PostTask(
222 base::Bind(&GCMDriverDesktop::MessageReceived
,
228 void GCMDriverDesktop::IOWorker::OnMessagesDeleted(const std::string
& app_id
) {
229 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
231 ui_thread_
->PostTask(
233 base::Bind(&GCMDriverDesktop::MessagesDeleted
, service_
, app_id
));
236 void GCMDriverDesktop::IOWorker::OnMessageSendError(
237 const std::string
& app_id
,
238 const GCMClient::SendErrorDetails
& send_error_details
) {
239 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
241 ui_thread_
->PostTask(
243 base::Bind(&GCMDriverDesktop::MessageSendError
, service_
, app_id
,
244 send_error_details
));
247 void GCMDriverDesktop::IOWorker::OnSendAcknowledged(
248 const std::string
& app_id
,
249 const std::string
& message_id
) {
250 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
252 ui_thread_
->PostTask(
255 &GCMDriverDesktop::SendAcknowledged
, service_
, app_id
, message_id
));
258 void GCMDriverDesktop::IOWorker::OnGCMReady() {
259 ui_thread_
->PostTask(
261 base::Bind(&GCMDriverDesktop::GCMClientReady
, service_
));
264 void GCMDriverDesktop::IOWorker::OnActivityRecorded() {
265 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
266 // When an activity is recorded, get all the stats and refresh the UI of
267 // gcm-internals page.
268 GetGCMStatistics(false);
271 void GCMDriverDesktop::IOWorker::OnConnected(
272 const net::IPEndPoint
& ip_endpoint
) {
273 ui_thread_
->PostTask(FROM_HERE
,
274 base::Bind(&GCMDriverDesktop::OnConnected
,
279 void GCMDriverDesktop::IOWorker::OnDisconnected() {
280 ui_thread_
->PostTask(FROM_HERE
,
281 base::Bind(&GCMDriverDesktop::OnDisconnected
, service_
));
284 void GCMDriverDesktop::IOWorker::Start(
285 const base::WeakPtr
<GCMDriverDesktop
>& service
) {
286 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
289 gcm_client_
->Start();
292 void GCMDriverDesktop::IOWorker::Stop() {
293 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
298 void GCMDriverDesktop::IOWorker::CheckOut() {
299 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
301 gcm_client_
->CheckOut();
303 // Note that we still need to keep GCMClient instance alive since the
304 // GCMDriverDesktop may check in again.
307 void GCMDriverDesktop::IOWorker::Register(
308 const std::string
& app_id
,
309 const std::vector
<std::string
>& sender_ids
) {
310 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
312 gcm_client_
->Register(app_id
, sender_ids
);
315 void GCMDriverDesktop::IOWorker::Unregister(const std::string
& app_id
) {
316 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
318 gcm_client_
->Unregister(app_id
);
321 void GCMDriverDesktop::IOWorker::Send(
322 const std::string
& app_id
,
323 const std::string
& receiver_id
,
324 const GCMClient::OutgoingMessage
& message
) {
325 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
327 gcm_client_
->Send(app_id
, receiver_id
, message
);
330 void GCMDriverDesktop::IOWorker::GetGCMStatistics(bool clear_logs
) {
331 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
332 gcm::GCMClient::GCMStatistics stats
;
334 if (gcm_client_
.get()) {
336 gcm_client_
->ClearActivityLogs();
337 stats
= gcm_client_
->GetStatistics();
340 ui_thread_
->PostTask(
342 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished
, service_
, stats
));
345 void GCMDriverDesktop::IOWorker::SetGCMRecording(bool recording
) {
346 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
347 gcm::GCMClient::GCMStatistics stats
;
349 if (gcm_client_
.get()) {
350 gcm_client_
->SetRecording(recording
);
351 stats
= gcm_client_
->GetStatistics();
352 stats
.gcm_client_created
= true;
355 ui_thread_
->PostTask(
357 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished
, service_
, stats
));
360 void GCMDriverDesktop::IOWorker::SetAccountsForCheckin(
361 const std::map
<std::string
, std::string
>& account_tokens
) {
362 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
364 if (gcm_client_
.get())
365 gcm_client_
->SetAccountsForCheckin(account_tokens
);
368 void GCMDriverDesktop::IOWorker::UpdateAccountMapping(
369 const AccountMapping
& account_mapping
) {
370 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
372 if (gcm_client_
.get())
373 gcm_client_
->UpdateAccountMapping(account_mapping
);
376 void GCMDriverDesktop::IOWorker::RemoveAccountMapping(
377 const std::string
& account_id
) {
378 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
380 if (gcm_client_
.get())
381 gcm_client_
->RemoveAccountMapping(account_id
);
384 GCMDriverDesktop::GCMDriverDesktop(
385 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
386 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
387 const base::FilePath
& store_path
,
388 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
389 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
390 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
,
391 const scoped_refptr
<base::SequencedTaskRunner
>& blocking_task_runner
)
396 ui_thread_(ui_thread
),
397 io_thread_(io_thread
),
398 weak_ptr_factory_(this) {
399 // Create and initialize the GCMClient. Note that this does not initiate the
401 io_worker_
.reset(new IOWorker(ui_thread
, io_thread
));
402 io_thread_
->PostTask(
404 base::Bind(&GCMDriverDesktop::IOWorker::Initialize
,
405 base::Unretained(io_worker_
.get()),
406 base::Passed(&gcm_client_factory
),
410 blocking_task_runner
));
413 GCMDriverDesktop::~GCMDriverDesktop() {
416 void GCMDriverDesktop::Shutdown() {
417 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
418 GCMDriver::Shutdown();
419 io_thread_
->DeleteSoon(FROM_HERE
, io_worker_
.release());
422 void GCMDriverDesktop::OnSignedIn() {
427 void GCMDriverDesktop::Purge() {
428 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
430 // We still proceed with the check-out logic even if the check-in is not
431 // initiated in the current session. This will make sure that all the
432 // persisted data written previously will get purged.
436 io_thread_
->PostTask(FROM_HERE
,
437 base::Bind(&GCMDriverDesktop::IOWorker::CheckOut
,
438 base::Unretained(io_worker_
.get())));
441 void GCMDriverDesktop::AddAppHandler(const std::string
& app_id
,
442 GCMAppHandler
* handler
) {
443 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
444 GCMDriver::AddAppHandler(app_id
, handler
);
446 // Ensures that the GCM service is started when there is an interest.
450 void GCMDriverDesktop::RemoveAppHandler(const std::string
& app_id
) {
451 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
452 GCMDriver::RemoveAppHandler(app_id
);
454 // Stops the GCM service when no app intends to consume it.
455 if (app_handlers().empty())
459 void GCMDriverDesktop::AddConnectionObserver(GCMConnectionObserver
* observer
) {
460 connection_observer_list_
.AddObserver(observer
);
463 void GCMDriverDesktop::RemoveConnectionObserver(
464 GCMConnectionObserver
* observer
) {
465 connection_observer_list_
.RemoveObserver(observer
);
468 void GCMDriverDesktop::Enable() {
469 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
478 void GCMDriverDesktop::Disable() {
479 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
483 gcm_enabled_
= false;
488 void GCMDriverDesktop::Stop() {
489 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
491 // No need to stop GCM service if not started yet.
497 io_thread_
->PostTask(
499 base::Bind(&GCMDriverDesktop::IOWorker::Stop
,
500 base::Unretained(io_worker_
.get())));
503 void GCMDriverDesktop::RegisterImpl(
504 const std::string
& app_id
,
505 const std::vector
<std::string
>& sender_ids
) {
506 // Delay the register operation until GCMClient is ready.
507 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
508 delayed_task_controller_
->AddTask(base::Bind(&GCMDriverDesktop::DoRegister
,
509 weak_ptr_factory_
.GetWeakPtr(),
515 DoRegister(app_id
, sender_ids
);
518 void GCMDriverDesktop::DoRegister(const std::string
& app_id
,
519 const std::vector
<std::string
>& sender_ids
) {
520 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
521 if (!HasRegisterCallback(app_id
)) {
522 // The callback could have been removed when the app is uninstalled.
526 io_thread_
->PostTask(
528 base::Bind(&GCMDriverDesktop::IOWorker::Register
,
529 base::Unretained(io_worker_
.get()),
534 void GCMDriverDesktop::UnregisterImpl(const std::string
& app_id
) {
535 // Delay the unregister operation until GCMClient is ready.
536 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
537 delayed_task_controller_
->AddTask(
538 base::Bind(&GCMDriverDesktop::DoUnregister
,
539 weak_ptr_factory_
.GetWeakPtr(),
544 DoUnregister(app_id
);
547 void GCMDriverDesktop::DoUnregister(const std::string
& app_id
) {
548 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
550 // Ask the server to unregister it. There could be a small chance that the
551 // unregister request fails. If this occurs, it does not bring any harm since
552 // we simply reject the messages/events received from the server.
553 io_thread_
->PostTask(
555 base::Bind(&GCMDriverDesktop::IOWorker::Unregister
,
556 base::Unretained(io_worker_
.get()),
560 void GCMDriverDesktop::SendImpl(const std::string
& app_id
,
561 const std::string
& receiver_id
,
562 const GCMClient::OutgoingMessage
& message
) {
563 // Delay the send operation until all GCMClient is ready.
564 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
565 delayed_task_controller_
->AddTask(base::Bind(&GCMDriverDesktop::DoSend
,
566 weak_ptr_factory_
.GetWeakPtr(),
573 DoSend(app_id
, receiver_id
, message
);
576 void GCMDriverDesktop::DoSend(const std::string
& app_id
,
577 const std::string
& receiver_id
,
578 const GCMClient::OutgoingMessage
& message
) {
579 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
580 io_thread_
->PostTask(
582 base::Bind(&GCMDriverDesktop::IOWorker::Send
,
583 base::Unretained(io_worker_
.get()),
589 GCMClient
* GCMDriverDesktop::GetGCMClientForTesting() const {
590 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
591 return io_worker_
? io_worker_
->gcm_client_for_testing() : NULL
;
594 bool GCMDriverDesktop::IsStarted() const {
595 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
599 bool GCMDriverDesktop::IsConnected() const {
603 void GCMDriverDesktop::GetGCMStatistics(
604 const GetGCMStatisticsCallback
& callback
,
606 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
607 DCHECK(!callback
.is_null());
609 request_gcm_statistics_callback_
= callback
;
610 io_thread_
->PostTask(
612 base::Bind(&GCMDriverDesktop::IOWorker::GetGCMStatistics
,
613 base::Unretained(io_worker_
.get()),
617 void GCMDriverDesktop::SetGCMRecording(const GetGCMStatisticsCallback
& callback
,
619 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
621 request_gcm_statistics_callback_
= callback
;
622 io_thread_
->PostTask(
624 base::Bind(&GCMDriverDesktop::IOWorker::SetGCMRecording
,
625 base::Unretained(io_worker_
.get()),
629 void GCMDriverDesktop::UpdateAccountMapping(
630 const AccountMapping
& account_mapping
) {
631 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
633 io_thread_
->PostTask(
635 base::Bind(&GCMDriverDesktop::IOWorker::UpdateAccountMapping
,
636 base::Unretained(io_worker_
.get()),
640 void GCMDriverDesktop::RemoveAccountMapping(const std::string
& account_id
) {
641 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
643 io_thread_
->PostTask(
645 base::Bind(&GCMDriverDesktop::IOWorker::RemoveAccountMapping
,
646 base::Unretained(io_worker_
.get()),
650 void GCMDriverDesktop::SetAccountsForCheckin(
651 const std::map
<std::string
, std::string
>& account_tokens
) {
652 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
654 io_thread_
->PostTask(
656 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountsForCheckin
,
657 base::Unretained(io_worker_
.get()),
661 GCMClient::Result
GCMDriverDesktop::EnsureStarted() {
662 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
665 return GCMClient::SUCCESS
;
668 return GCMClient::GCM_DISABLED
;
670 // Have any app requested the service?
671 if (app_handlers().empty())
672 return GCMClient::UNKNOWN_ERROR
;
674 // TODO(jianli): To be removed when sign-in enforcement is dropped.
675 if (!signed_in_
&& !GCMDriver::IsAllowedForAllUsers())
676 return GCMClient::NOT_SIGNED_IN
;
678 DCHECK(!delayed_task_controller_
);
679 delayed_task_controller_
.reset(new DelayedTaskController
);
681 // Note that we need to pass weak pointer again since the existing weak
682 // pointer in IOWorker might have been invalidated when check-out occurs.
683 io_thread_
->PostTask(
685 base::Bind(&GCMDriverDesktop::IOWorker::Start
,
686 base::Unretained(io_worker_
.get()),
687 weak_ptr_factory_
.GetWeakPtr()));
690 return GCMClient::SUCCESS
;
693 void GCMDriverDesktop::RemoveCachedData() {
694 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
695 // Remove all the queued tasks since they no longer make sense after
696 // GCM service is stopped.
697 weak_ptr_factory_
.InvalidateWeakPtrs();
699 gcm_started_
= false;
700 delayed_task_controller_
.reset();
704 void GCMDriverDesktop::MessageReceived(
705 const std::string
& app_id
,
706 const GCMClient::IncomingMessage
& message
) {
707 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
709 // Drop the event if the service has been stopped.
713 GetAppHandler(app_id
)->OnMessage(app_id
, message
);
716 void GCMDriverDesktop::MessagesDeleted(const std::string
& app_id
) {
717 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
719 // Drop the event if the service has been stopped.
723 GetAppHandler(app_id
)->OnMessagesDeleted(app_id
);
726 void GCMDriverDesktop::MessageSendError(
727 const std::string
& app_id
,
728 const GCMClient::SendErrorDetails
& send_error_details
) {
729 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
731 // Drop the event if the service has been stopped.
735 GetAppHandler(app_id
)->OnSendError(app_id
, send_error_details
);
738 void GCMDriverDesktop::SendAcknowledged(const std::string
& app_id
,
739 const std::string
& message_id
) {
740 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
742 // Drop the event if the service has been stopped.
746 GetAppHandler(app_id
)->OnSendAcknowledged(app_id
, message_id
);
749 void GCMDriverDesktop::GCMClientReady() {
750 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
752 delayed_task_controller_
->SetReady();
755 void GCMDriverDesktop::OnConnected(const net::IPEndPoint
& ip_endpoint
) {
756 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
760 // Drop the event if the service has been stopped.
764 FOR_EACH_OBSERVER(GCMConnectionObserver
,
765 connection_observer_list_
,
766 OnConnected(ip_endpoint
));
769 void GCMDriverDesktop::OnDisconnected() {
770 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
774 // Drop the event if the service has been stopped.
779 GCMConnectionObserver
, connection_observer_list_
, OnDisconnected());
782 void GCMDriverDesktop::GetGCMStatisticsFinished(
783 const GCMClient::GCMStatistics
& stats
) {
784 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
786 // Normally request_gcm_statistics_callback_ would not be null.
787 if (!request_gcm_statistics_callback_
.is_null())
788 request_gcm_statistics_callback_
.Run(stats
);
790 LOG(WARNING
) << "request_gcm_statistics_callback_ is NULL.";