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_channel_status_syncer.h"
18 #include "components/gcm_driver/gcm_client_factory.h"
19 #include "components/gcm_driver/gcm_delayed_task_controller.h"
20 #include "components/gcm_driver/system_encryptor.h"
21 #include "google_apis/gcm/engine/account_mapping.h"
22 #include "net/base/ip_endpoint.h"
23 #include "net/url_request/url_request_context_getter.h"
27 class GCMDriverDesktop::IOWorker
: public GCMClient::Delegate
{
29 // Called on UI thread.
30 IOWorker(const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
31 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
);
34 // Overridden from GCMClient::Delegate:
35 // Called on IO thread.
36 virtual void OnRegisterFinished(const std::string
& app_id
,
37 const std::string
& registration_id
,
38 GCMClient::Result result
) OVERRIDE
;
39 virtual void OnUnregisterFinished(const std::string
& app_id
,
40 GCMClient::Result result
) OVERRIDE
;
41 virtual void OnSendFinished(const std::string
& app_id
,
42 const std::string
& message_id
,
43 GCMClient::Result result
) OVERRIDE
;
44 virtual void OnMessageReceived(
45 const std::string
& app_id
,
46 const GCMClient::IncomingMessage
& message
) OVERRIDE
;
47 virtual void OnMessagesDeleted(const std::string
& app_id
) OVERRIDE
;
48 virtual void OnMessageSendError(
49 const std::string
& app_id
,
50 const GCMClient::SendErrorDetails
& send_error_details
) OVERRIDE
;
51 virtual void OnSendAcknowledged(const std::string
& app_id
,
52 const std::string
& message_id
) OVERRIDE
;
53 virtual void OnGCMReady() OVERRIDE
;
54 virtual void OnActivityRecorded() OVERRIDE
;
55 virtual void OnConnected(const net::IPEndPoint
& ip_endpoint
) OVERRIDE
;
56 virtual void OnDisconnected() OVERRIDE
;
58 // Called on IO thread.
60 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
61 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
62 const base::FilePath
& store_path
,
63 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
64 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
);
65 void Start(const base::WeakPtr
<GCMDriverDesktop
>& service
);
68 void Register(const std::string
& app_id
,
69 const std::vector
<std::string
>& sender_ids
);
70 void Unregister(const std::string
& app_id
);
71 void Send(const std::string
& app_id
,
72 const std::string
& receiver_id
,
73 const GCMClient::OutgoingMessage
& message
);
74 void GetGCMStatistics(bool clear_logs
);
75 void SetGCMRecording(bool recording
);
77 void SetAccountsForCheckin(
78 const std::map
<std::string
, std::string
>& account_tokens
);
79 void UpdateAccountMapping(const AccountMapping
& account_mapping
);
80 void RemoveAccountMapping(const std::string
& account_id
);
82 // For testing purpose. Can be called from UI thread. Use with care.
83 GCMClient
* gcm_client_for_testing() const { return gcm_client_
.get(); }
86 scoped_refptr
<base::SequencedTaskRunner
> ui_thread_
;
87 scoped_refptr
<base::SequencedTaskRunner
> io_thread_
;
89 base::WeakPtr
<GCMDriverDesktop
> service_
;
91 scoped_ptr
<GCMClient
> gcm_client_
;
93 DISALLOW_COPY_AND_ASSIGN(IOWorker
);
96 GCMDriverDesktop::IOWorker::IOWorker(
97 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
98 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
)
99 : ui_thread_(ui_thread
),
100 io_thread_(io_thread
) {
101 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
104 GCMDriverDesktop::IOWorker::~IOWorker() {
105 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
108 void GCMDriverDesktop::IOWorker::Initialize(
109 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
110 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
111 const base::FilePath
& store_path
,
112 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
113 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
) {
114 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
116 gcm_client_
= gcm_client_factory
->BuildInstance();
118 gcm_client_
->Initialize(chrome_build_info
,
120 blocking_task_runner
,
122 make_scoped_ptr
<Encryptor
>(new SystemEncryptor
),
126 void GCMDriverDesktop::IOWorker::OnRegisterFinished(
127 const std::string
& app_id
,
128 const std::string
& registration_id
,
129 GCMClient::Result result
) {
130 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
132 ui_thread_
->PostTask(
134 base::Bind(&GCMDriverDesktop::RegisterFinished
, service_
, app_id
,
135 registration_id
, result
));
138 void GCMDriverDesktop::IOWorker::OnUnregisterFinished(
139 const std::string
& app_id
,
140 GCMClient::Result result
) {
141 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
143 ui_thread_
->PostTask(FROM_HERE
,
144 base::Bind(&GCMDriverDesktop::UnregisterFinished
,
150 void GCMDriverDesktop::IOWorker::OnSendFinished(const std::string
& app_id
,
151 const std::string
& message_id
,
152 GCMClient::Result result
) {
153 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
155 ui_thread_
->PostTask(
157 base::Bind(&GCMDriverDesktop::SendFinished
, service_
, app_id
, message_id
,
161 void GCMDriverDesktop::IOWorker::OnMessageReceived(
162 const std::string
& app_id
,
163 const GCMClient::IncomingMessage
& message
) {
164 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
166 ui_thread_
->PostTask(
168 base::Bind(&GCMDriverDesktop::MessageReceived
,
174 void GCMDriverDesktop::IOWorker::OnMessagesDeleted(const std::string
& app_id
) {
175 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
177 ui_thread_
->PostTask(
179 base::Bind(&GCMDriverDesktop::MessagesDeleted
, service_
, app_id
));
182 void GCMDriverDesktop::IOWorker::OnMessageSendError(
183 const std::string
& app_id
,
184 const GCMClient::SendErrorDetails
& send_error_details
) {
185 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
187 ui_thread_
->PostTask(
189 base::Bind(&GCMDriverDesktop::MessageSendError
, service_
, app_id
,
190 send_error_details
));
193 void GCMDriverDesktop::IOWorker::OnSendAcknowledged(
194 const std::string
& app_id
,
195 const std::string
& message_id
) {
196 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
198 ui_thread_
->PostTask(
201 &GCMDriverDesktop::SendAcknowledged
, service_
, app_id
, message_id
));
204 void GCMDriverDesktop::IOWorker::OnGCMReady() {
205 ui_thread_
->PostTask(
207 base::Bind(&GCMDriverDesktop::GCMClientReady
, service_
));
210 void GCMDriverDesktop::IOWorker::OnActivityRecorded() {
211 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
212 // When an activity is recorded, get all the stats and refresh the UI of
213 // gcm-internals page.
214 GetGCMStatistics(false);
217 void GCMDriverDesktop::IOWorker::OnConnected(
218 const net::IPEndPoint
& ip_endpoint
) {
219 ui_thread_
->PostTask(FROM_HERE
,
220 base::Bind(&GCMDriverDesktop::OnConnected
,
225 void GCMDriverDesktop::IOWorker::OnDisconnected() {
226 ui_thread_
->PostTask(FROM_HERE
,
227 base::Bind(&GCMDriverDesktop::OnDisconnected
, service_
));
230 void GCMDriverDesktop::IOWorker::Start(
231 const base::WeakPtr
<GCMDriverDesktop
>& service
) {
232 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
235 gcm_client_
->Start();
238 void GCMDriverDesktop::IOWorker::Stop() {
239 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
244 void GCMDriverDesktop::IOWorker::CheckOut() {
245 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
247 gcm_client_
->CheckOut();
249 // Note that we still need to keep GCMClient instance alive since the
250 // GCMDriverDesktop may check in again.
253 void GCMDriverDesktop::IOWorker::Register(
254 const std::string
& app_id
,
255 const std::vector
<std::string
>& sender_ids
) {
256 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
258 gcm_client_
->Register(app_id
, sender_ids
);
261 void GCMDriverDesktop::IOWorker::Unregister(const std::string
& app_id
) {
262 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
264 gcm_client_
->Unregister(app_id
);
267 void GCMDriverDesktop::IOWorker::Send(
268 const std::string
& app_id
,
269 const std::string
& receiver_id
,
270 const GCMClient::OutgoingMessage
& message
) {
271 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
273 gcm_client_
->Send(app_id
, receiver_id
, message
);
276 void GCMDriverDesktop::IOWorker::GetGCMStatistics(bool clear_logs
) {
277 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
278 gcm::GCMClient::GCMStatistics stats
;
280 if (gcm_client_
.get()) {
282 gcm_client_
->ClearActivityLogs();
283 stats
= gcm_client_
->GetStatistics();
286 ui_thread_
->PostTask(
288 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished
, service_
, stats
));
291 void GCMDriverDesktop::IOWorker::SetGCMRecording(bool recording
) {
292 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
293 gcm::GCMClient::GCMStatistics stats
;
295 if (gcm_client_
.get()) {
296 gcm_client_
->SetRecording(recording
);
297 stats
= gcm_client_
->GetStatistics();
298 stats
.gcm_client_created
= true;
301 ui_thread_
->PostTask(
303 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished
, service_
, stats
));
306 void GCMDriverDesktop::IOWorker::SetAccountsForCheckin(
307 const std::map
<std::string
, std::string
>& account_tokens
) {
308 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
310 if (gcm_client_
.get())
311 gcm_client_
->SetAccountsForCheckin(account_tokens
);
314 void GCMDriverDesktop::IOWorker::UpdateAccountMapping(
315 const AccountMapping
& account_mapping
) {
316 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
318 if (gcm_client_
.get())
319 gcm_client_
->UpdateAccountMapping(account_mapping
);
322 void GCMDriverDesktop::IOWorker::RemoveAccountMapping(
323 const std::string
& account_id
) {
324 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
326 if (gcm_client_
.get())
327 gcm_client_
->RemoveAccountMapping(account_id
);
330 GCMDriverDesktop::GCMDriverDesktop(
331 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
332 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
334 const base::FilePath
& store_path
,
335 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
336 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
337 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
,
338 const scoped_refptr
<base::SequencedTaskRunner
>& blocking_task_runner
)
339 : gcm_channel_status_syncer_(
340 new GCMChannelStatusSyncer(this, prefs
, request_context
)),
345 ui_thread_(ui_thread
),
346 io_thread_(io_thread
),
347 weak_ptr_factory_(this) {
348 gcm_enabled_
= gcm_channel_status_syncer_
->gcm_enabled();
350 // Create and initialize the GCMClient. Note that this does not initiate the
352 io_worker_
.reset(new IOWorker(ui_thread
, io_thread
));
353 io_thread_
->PostTask(
355 base::Bind(&GCMDriverDesktop::IOWorker::Initialize
,
356 base::Unretained(io_worker_
.get()),
357 base::Passed(&gcm_client_factory
),
361 blocking_task_runner
));
364 GCMDriverDesktop::~GCMDriverDesktop() {
367 void GCMDriverDesktop::Shutdown() {
368 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
369 GCMDriver::Shutdown();
371 // Dispose the syncer in order to release the reference to
372 // URLRequestContextGetter that needs to be done before IOThread gets
374 gcm_channel_status_syncer_
.reset();
376 io_thread_
->DeleteSoon(FROM_HERE
, io_worker_
.release());
379 void GCMDriverDesktop::OnSignedIn() {
384 void GCMDriverDesktop::OnSignedOut() {
387 // When sign-in enforcement is dropped, we will no longer wipe out the GCM
388 // data when the user signs out.
389 if (!GCMDriver::IsAllowedForAllUsers())
393 void GCMDriverDesktop::Purge() {
394 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
398 io_thread_
->PostTask(FROM_HERE
,
399 base::Bind(&GCMDriverDesktop::IOWorker::CheckOut
,
400 base::Unretained(io_worker_
.get())));
403 void GCMDriverDesktop::AddAppHandler(const std::string
& app_id
,
404 GCMAppHandler
* handler
) {
405 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
406 GCMDriver::AddAppHandler(app_id
, handler
);
408 // Ensures that the GCM service is started when there is an interest.
412 void GCMDriverDesktop::RemoveAppHandler(const std::string
& app_id
) {
413 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
414 GCMDriver::RemoveAppHandler(app_id
);
416 // Stops the GCM service when no app intends to consume it.
417 if (app_handlers().empty())
421 void GCMDriverDesktop::AddConnectionObserver(GCMConnectionObserver
* observer
) {
422 connection_observer_list_
.AddObserver(observer
);
425 void GCMDriverDesktop::RemoveConnectionObserver(
426 GCMConnectionObserver
* observer
) {
427 connection_observer_list_
.RemoveObserver(observer
);
430 void GCMDriverDesktop::Enable() {
431 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
440 void GCMDriverDesktop::Disable() {
441 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
445 gcm_enabled_
= false;
450 void GCMDriverDesktop::Stop() {
451 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
453 // No need to stop GCM service if not started yet.
457 gcm_channel_status_syncer_
->Stop();
461 io_thread_
->PostTask(
463 base::Bind(&GCMDriverDesktop::IOWorker::Stop
,
464 base::Unretained(io_worker_
.get())));
467 void GCMDriverDesktop::RegisterImpl(
468 const std::string
& app_id
,
469 const std::vector
<std::string
>& sender_ids
) {
470 // Delay the register operation until GCMClient is ready.
471 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
472 delayed_task_controller_
->AddTask(base::Bind(&GCMDriverDesktop::DoRegister
,
473 weak_ptr_factory_
.GetWeakPtr(),
479 DoRegister(app_id
, sender_ids
);
482 void GCMDriverDesktop::DoRegister(const std::string
& app_id
,
483 const std::vector
<std::string
>& sender_ids
) {
484 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
485 if (!HasRegisterCallback(app_id
)) {
486 // The callback could have been removed when the app is uninstalled.
490 io_thread_
->PostTask(
492 base::Bind(&GCMDriverDesktop::IOWorker::Register
,
493 base::Unretained(io_worker_
.get()),
498 void GCMDriverDesktop::UnregisterImpl(const std::string
& app_id
) {
499 // Delay the unregister operation until GCMClient is ready.
500 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
501 delayed_task_controller_
->AddTask(
502 base::Bind(&GCMDriverDesktop::DoUnregister
,
503 weak_ptr_factory_
.GetWeakPtr(),
508 DoUnregister(app_id
);
511 void GCMDriverDesktop::DoUnregister(const std::string
& app_id
) {
512 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
514 // Ask the server to unregister it. There could be a small chance that the
515 // unregister request fails. If this occurs, it does not bring any harm since
516 // we simply reject the messages/events received from the server.
517 io_thread_
->PostTask(
519 base::Bind(&GCMDriverDesktop::IOWorker::Unregister
,
520 base::Unretained(io_worker_
.get()),
524 void GCMDriverDesktop::SendImpl(const std::string
& app_id
,
525 const std::string
& receiver_id
,
526 const GCMClient::OutgoingMessage
& message
) {
527 // Delay the send operation until all GCMClient is ready.
528 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
529 delayed_task_controller_
->AddTask(base::Bind(&GCMDriverDesktop::DoSend
,
530 weak_ptr_factory_
.GetWeakPtr(),
537 DoSend(app_id
, receiver_id
, message
);
540 void GCMDriverDesktop::DoSend(const std::string
& app_id
,
541 const std::string
& receiver_id
,
542 const GCMClient::OutgoingMessage
& message
) {
543 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
544 io_thread_
->PostTask(
546 base::Bind(&GCMDriverDesktop::IOWorker::Send
,
547 base::Unretained(io_worker_
.get()),
553 GCMClient
* GCMDriverDesktop::GetGCMClientForTesting() const {
554 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
555 return io_worker_
? io_worker_
->gcm_client_for_testing() : NULL
;
558 bool GCMDriverDesktop::IsStarted() const {
559 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
563 bool GCMDriverDesktop::IsConnected() const {
567 void GCMDriverDesktop::GetGCMStatistics(
568 const GetGCMStatisticsCallback
& callback
,
570 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
571 DCHECK(!callback
.is_null());
573 request_gcm_statistics_callback_
= callback
;
574 io_thread_
->PostTask(
576 base::Bind(&GCMDriverDesktop::IOWorker::GetGCMStatistics
,
577 base::Unretained(io_worker_
.get()),
581 void GCMDriverDesktop::SetGCMRecording(const GetGCMStatisticsCallback
& callback
,
583 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
585 request_gcm_statistics_callback_
= callback
;
586 io_thread_
->PostTask(
588 base::Bind(&GCMDriverDesktop::IOWorker::SetGCMRecording
,
589 base::Unretained(io_worker_
.get()),
593 void GCMDriverDesktop::UpdateAccountMapping(
594 const AccountMapping
& account_mapping
) {
595 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
597 io_thread_
->PostTask(
599 base::Bind(&GCMDriverDesktop::IOWorker::UpdateAccountMapping
,
600 base::Unretained(io_worker_
.get()),
604 void GCMDriverDesktop::RemoveAccountMapping(const std::string
& account_id
) {
605 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
607 io_thread_
->PostTask(
609 base::Bind(&GCMDriverDesktop::IOWorker::RemoveAccountMapping
,
610 base::Unretained(io_worker_
.get()),
614 void GCMDriverDesktop::SetAccountsForCheckin(
615 const std::map
<std::string
, std::string
>& account_tokens
) {
616 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
618 io_thread_
->PostTask(
620 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountsForCheckin
,
621 base::Unretained(io_worker_
.get()),
625 GCMClient::Result
GCMDriverDesktop::EnsureStarted() {
626 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
629 return GCMClient::SUCCESS
;
632 return GCMClient::GCM_DISABLED
;
634 // Have any app requested the service?
635 if (app_handlers().empty())
636 return GCMClient::UNKNOWN_ERROR
;
638 if (!signed_in_
&& !GCMDriver::IsAllowedForAllUsers())
639 return GCMClient::NOT_SIGNED_IN
;
641 DCHECK(!delayed_task_controller_
);
642 delayed_task_controller_
.reset(new GCMDelayedTaskController
);
644 // Polling for channel status is only needed when GCM is supported for all
646 if (GCMDriver::IsAllowedForAllUsers())
647 gcm_channel_status_syncer_
->EnsureStarted();
649 // Note that we need to pass weak pointer again since the existing weak
650 // pointer in IOWorker might have been invalidated when check-out occurs.
651 io_thread_
->PostTask(
653 base::Bind(&GCMDriverDesktop::IOWorker::Start
,
654 base::Unretained(io_worker_
.get()),
655 weak_ptr_factory_
.GetWeakPtr()));
658 return GCMClient::SUCCESS
;
661 void GCMDriverDesktop::RemoveCachedData() {
662 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
663 // Remove all the queued tasks since they no longer make sense after
664 // GCM service is stopped.
665 weak_ptr_factory_
.InvalidateWeakPtrs();
667 gcm_started_
= false;
668 delayed_task_controller_
.reset();
672 void GCMDriverDesktop::MessageReceived(
673 const std::string
& app_id
,
674 const GCMClient::IncomingMessage
& message
) {
675 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
677 // Drop the event if the service has been stopped.
681 GetAppHandler(app_id
)->OnMessage(app_id
, message
);
684 void GCMDriverDesktop::MessagesDeleted(const std::string
& app_id
) {
685 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
687 // Drop the event if the service has been stopped.
691 GetAppHandler(app_id
)->OnMessagesDeleted(app_id
);
694 void GCMDriverDesktop::MessageSendError(
695 const std::string
& app_id
,
696 const GCMClient::SendErrorDetails
& send_error_details
) {
697 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
699 // Drop the event if the service has been stopped.
703 GetAppHandler(app_id
)->OnSendError(app_id
, send_error_details
);
706 void GCMDriverDesktop::SendAcknowledged(const std::string
& app_id
,
707 const std::string
& message_id
) {
708 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
710 // Drop the event if the service has been stopped.
714 GetAppHandler(app_id
)->OnSendAcknowledged(app_id
, message_id
);
717 void GCMDriverDesktop::GCMClientReady() {
718 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
720 delayed_task_controller_
->SetReady();
723 void GCMDriverDesktop::OnConnected(const net::IPEndPoint
& ip_endpoint
) {
724 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
728 // Drop the event if the service has been stopped.
732 FOR_EACH_OBSERVER(GCMConnectionObserver
,
733 connection_observer_list_
,
734 OnConnected(ip_endpoint
));
737 void GCMDriverDesktop::OnDisconnected() {
738 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
742 // Drop the event if the service has been stopped.
747 GCMConnectionObserver
, connection_observer_list_
, OnDisconnected());
750 void GCMDriverDesktop::GetGCMStatisticsFinished(
751 const GCMClient::GCMStatistics
& stats
) {
752 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
754 // Normally request_gcm_statistics_callback_ would not be null.
755 if (!request_gcm_statistics_callback_
.is_null())
756 request_gcm_statistics_callback_
.Run(stats
);
758 LOG(WARNING
) << "request_gcm_statistics_callback_ is NULL.";