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(
54 const std::vector
<AccountMapping
>& account_mappings
) OVERRIDE
;
55 virtual void OnActivityRecorded() OVERRIDE
;
56 virtual void OnConnected(const net::IPEndPoint
& ip_endpoint
) OVERRIDE
;
57 virtual void OnDisconnected() OVERRIDE
;
59 // Called on IO thread.
61 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
62 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
63 const base::FilePath
& store_path
,
64 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
65 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
);
66 void Start(const base::WeakPtr
<GCMDriverDesktop
>& service
);
69 void Register(const std::string
& app_id
,
70 const std::vector
<std::string
>& sender_ids
);
71 void Unregister(const std::string
& app_id
);
72 void Send(const std::string
& app_id
,
73 const std::string
& receiver_id
,
74 const GCMClient::OutgoingMessage
& message
);
75 void GetGCMStatistics(bool clear_logs
);
76 void SetGCMRecording(bool recording
);
78 void SetAccountsForCheckin(
79 const std::map
<std::string
, std::string
>& account_tokens
);
80 void UpdateAccountMapping(const AccountMapping
& account_mapping
);
81 void RemoveAccountMapping(const std::string
& account_id
);
83 // For testing purpose. Can be called from UI thread. Use with care.
84 GCMClient
* gcm_client_for_testing() const { return gcm_client_
.get(); }
87 scoped_refptr
<base::SequencedTaskRunner
> ui_thread_
;
88 scoped_refptr
<base::SequencedTaskRunner
> io_thread_
;
90 base::WeakPtr
<GCMDriverDesktop
> service_
;
92 scoped_ptr
<GCMClient
> gcm_client_
;
94 DISALLOW_COPY_AND_ASSIGN(IOWorker
);
97 GCMDriverDesktop::IOWorker::IOWorker(
98 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
99 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
)
100 : ui_thread_(ui_thread
),
101 io_thread_(io_thread
) {
102 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
105 GCMDriverDesktop::IOWorker::~IOWorker() {
106 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
109 void GCMDriverDesktop::IOWorker::Initialize(
110 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
111 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
112 const base::FilePath
& store_path
,
113 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
114 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
) {
115 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
117 gcm_client_
= gcm_client_factory
->BuildInstance();
119 gcm_client_
->Initialize(chrome_build_info
,
121 blocking_task_runner
,
123 make_scoped_ptr
<Encryptor
>(new SystemEncryptor
),
127 void GCMDriverDesktop::IOWorker::OnRegisterFinished(
128 const std::string
& app_id
,
129 const std::string
& registration_id
,
130 GCMClient::Result result
) {
131 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
133 ui_thread_
->PostTask(
135 base::Bind(&GCMDriverDesktop::RegisterFinished
, service_
, app_id
,
136 registration_id
, result
));
139 void GCMDriverDesktop::IOWorker::OnUnregisterFinished(
140 const std::string
& app_id
,
141 GCMClient::Result result
) {
142 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
144 ui_thread_
->PostTask(FROM_HERE
,
145 base::Bind(&GCMDriverDesktop::UnregisterFinished
,
151 void GCMDriverDesktop::IOWorker::OnSendFinished(const std::string
& app_id
,
152 const std::string
& message_id
,
153 GCMClient::Result result
) {
154 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
156 ui_thread_
->PostTask(
158 base::Bind(&GCMDriverDesktop::SendFinished
, service_
, app_id
, message_id
,
162 void GCMDriverDesktop::IOWorker::OnMessageReceived(
163 const std::string
& app_id
,
164 const GCMClient::IncomingMessage
& message
) {
165 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
167 ui_thread_
->PostTask(
169 base::Bind(&GCMDriverDesktop::MessageReceived
,
175 void GCMDriverDesktop::IOWorker::OnMessagesDeleted(const std::string
& app_id
) {
176 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
178 ui_thread_
->PostTask(
180 base::Bind(&GCMDriverDesktop::MessagesDeleted
, service_
, app_id
));
183 void GCMDriverDesktop::IOWorker::OnMessageSendError(
184 const std::string
& app_id
,
185 const GCMClient::SendErrorDetails
& send_error_details
) {
186 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
188 ui_thread_
->PostTask(
190 base::Bind(&GCMDriverDesktop::MessageSendError
, service_
, app_id
,
191 send_error_details
));
194 void GCMDriverDesktop::IOWorker::OnSendAcknowledged(
195 const std::string
& app_id
,
196 const std::string
& message_id
) {
197 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
199 ui_thread_
->PostTask(
202 &GCMDriverDesktop::SendAcknowledged
, service_
, app_id
, message_id
));
205 void GCMDriverDesktop::IOWorker::OnGCMReady(
206 const std::vector
<AccountMapping
>& account_mappings
) {
207 ui_thread_
->PostTask(
210 &GCMDriverDesktop::GCMClientReady
, service_
, account_mappings
));
213 void GCMDriverDesktop::IOWorker::OnActivityRecorded() {
214 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
215 // When an activity is recorded, get all the stats and refresh the UI of
216 // gcm-internals page.
217 GetGCMStatistics(false);
220 void GCMDriverDesktop::IOWorker::OnConnected(
221 const net::IPEndPoint
& ip_endpoint
) {
222 ui_thread_
->PostTask(FROM_HERE
,
223 base::Bind(&GCMDriverDesktop::OnConnected
,
228 void GCMDriverDesktop::IOWorker::OnDisconnected() {
229 ui_thread_
->PostTask(FROM_HERE
,
230 base::Bind(&GCMDriverDesktop::OnDisconnected
, service_
));
233 void GCMDriverDesktop::IOWorker::Start(
234 const base::WeakPtr
<GCMDriverDesktop
>& service
) {
235 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
238 gcm_client_
->Start();
241 void GCMDriverDesktop::IOWorker::Stop() {
242 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
247 void GCMDriverDesktop::IOWorker::CheckOut() {
248 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
250 gcm_client_
->CheckOut();
252 // Note that we still need to keep GCMClient instance alive since the
253 // GCMDriverDesktop may check in again.
256 void GCMDriverDesktop::IOWorker::Register(
257 const std::string
& app_id
,
258 const std::vector
<std::string
>& sender_ids
) {
259 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
261 gcm_client_
->Register(app_id
, sender_ids
);
264 void GCMDriverDesktop::IOWorker::Unregister(const std::string
& app_id
) {
265 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
267 gcm_client_
->Unregister(app_id
);
270 void GCMDriverDesktop::IOWorker::Send(
271 const std::string
& app_id
,
272 const std::string
& receiver_id
,
273 const GCMClient::OutgoingMessage
& message
) {
274 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
276 gcm_client_
->Send(app_id
, receiver_id
, message
);
279 void GCMDriverDesktop::IOWorker::GetGCMStatistics(bool clear_logs
) {
280 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
281 gcm::GCMClient::GCMStatistics stats
;
283 if (gcm_client_
.get()) {
285 gcm_client_
->ClearActivityLogs();
286 stats
= gcm_client_
->GetStatistics();
289 ui_thread_
->PostTask(
291 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished
, service_
, stats
));
294 void GCMDriverDesktop::IOWorker::SetGCMRecording(bool recording
) {
295 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
296 gcm::GCMClient::GCMStatistics stats
;
298 if (gcm_client_
.get()) {
299 gcm_client_
->SetRecording(recording
);
300 stats
= gcm_client_
->GetStatistics();
301 stats
.gcm_client_created
= true;
304 ui_thread_
->PostTask(
306 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished
, service_
, stats
));
309 void GCMDriverDesktop::IOWorker::SetAccountsForCheckin(
310 const std::map
<std::string
, std::string
>& account_tokens
) {
311 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
313 if (gcm_client_
.get())
314 gcm_client_
->SetAccountsForCheckin(account_tokens
);
317 void GCMDriverDesktop::IOWorker::UpdateAccountMapping(
318 const AccountMapping
& account_mapping
) {
319 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
321 if (gcm_client_
.get())
322 gcm_client_
->UpdateAccountMapping(account_mapping
);
325 void GCMDriverDesktop::IOWorker::RemoveAccountMapping(
326 const std::string
& account_id
) {
327 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
329 if (gcm_client_
.get())
330 gcm_client_
->RemoveAccountMapping(account_id
);
333 GCMDriverDesktop::GCMDriverDesktop(
334 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
335 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
337 const base::FilePath
& store_path
,
338 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
339 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
340 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
,
341 const scoped_refptr
<base::SequencedTaskRunner
>& blocking_task_runner
)
342 : gcm_channel_status_syncer_(
343 new GCMChannelStatusSyncer(this, prefs
, request_context
)),
348 ui_thread_(ui_thread
),
349 io_thread_(io_thread
),
350 weak_ptr_factory_(this) {
351 gcm_enabled_
= gcm_channel_status_syncer_
->gcm_enabled();
353 // Create and initialize the GCMClient. Note that this does not initiate the
355 io_worker_
.reset(new IOWorker(ui_thread
, io_thread
));
356 io_thread_
->PostTask(
358 base::Bind(&GCMDriverDesktop::IOWorker::Initialize
,
359 base::Unretained(io_worker_
.get()),
360 base::Passed(&gcm_client_factory
),
364 blocking_task_runner
));
367 GCMDriverDesktop::~GCMDriverDesktop() {
370 void GCMDriverDesktop::Shutdown() {
371 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
372 GCMDriver::Shutdown();
374 // Dispose the syncer in order to release the reference to
375 // URLRequestContextGetter that needs to be done before IOThread gets
377 gcm_channel_status_syncer_
.reset();
379 io_thread_
->DeleteSoon(FROM_HERE
, io_worker_
.release());
382 void GCMDriverDesktop::OnSignedIn() {
387 void GCMDriverDesktop::OnSignedOut() {
390 // When sign-in enforcement is dropped, we will no longer wipe out the GCM
391 // data when the user signs out.
392 if (!GCMDriver::IsAllowedForAllUsers())
396 void GCMDriverDesktop::Purge() {
397 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
401 io_thread_
->PostTask(FROM_HERE
,
402 base::Bind(&GCMDriverDesktop::IOWorker::CheckOut
,
403 base::Unretained(io_worker_
.get())));
406 void GCMDriverDesktop::AddAppHandler(const std::string
& app_id
,
407 GCMAppHandler
* handler
) {
408 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
409 GCMDriver::AddAppHandler(app_id
, handler
);
411 // Ensures that the GCM service is started when there is an interest.
415 void GCMDriverDesktop::RemoveAppHandler(const std::string
& app_id
) {
416 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
417 GCMDriver::RemoveAppHandler(app_id
);
419 // Stops the GCM service when no app intends to consume it.
420 if (app_handlers().empty())
424 void GCMDriverDesktop::AddConnectionObserver(GCMConnectionObserver
* observer
) {
425 connection_observer_list_
.AddObserver(observer
);
428 void GCMDriverDesktop::RemoveConnectionObserver(
429 GCMConnectionObserver
* observer
) {
430 connection_observer_list_
.RemoveObserver(observer
);
433 void GCMDriverDesktop::Enable() {
434 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
443 void GCMDriverDesktop::Disable() {
444 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
448 gcm_enabled_
= false;
453 void GCMDriverDesktop::Stop() {
454 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
456 // No need to stop GCM service if not started yet.
460 gcm_channel_status_syncer_
->Stop();
464 io_thread_
->PostTask(
466 base::Bind(&GCMDriverDesktop::IOWorker::Stop
,
467 base::Unretained(io_worker_
.get())));
470 void GCMDriverDesktop::RegisterImpl(
471 const std::string
& app_id
,
472 const std::vector
<std::string
>& sender_ids
) {
473 // Delay the register operation until GCMClient is ready.
474 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
475 delayed_task_controller_
->AddTask(base::Bind(&GCMDriverDesktop::DoRegister
,
476 weak_ptr_factory_
.GetWeakPtr(),
482 DoRegister(app_id
, sender_ids
);
485 void GCMDriverDesktop::DoRegister(const std::string
& app_id
,
486 const std::vector
<std::string
>& sender_ids
) {
487 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
488 if (!HasRegisterCallback(app_id
)) {
489 // The callback could have been removed when the app is uninstalled.
493 io_thread_
->PostTask(
495 base::Bind(&GCMDriverDesktop::IOWorker::Register
,
496 base::Unretained(io_worker_
.get()),
501 void GCMDriverDesktop::UnregisterImpl(const std::string
& app_id
) {
502 // Delay the unregister operation until GCMClient is ready.
503 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
504 delayed_task_controller_
->AddTask(
505 base::Bind(&GCMDriverDesktop::DoUnregister
,
506 weak_ptr_factory_
.GetWeakPtr(),
511 DoUnregister(app_id
);
514 void GCMDriverDesktop::DoUnregister(const std::string
& app_id
) {
515 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
517 // Ask the server to unregister it. There could be a small chance that the
518 // unregister request fails. If this occurs, it does not bring any harm since
519 // we simply reject the messages/events received from the server.
520 io_thread_
->PostTask(
522 base::Bind(&GCMDriverDesktop::IOWorker::Unregister
,
523 base::Unretained(io_worker_
.get()),
527 void GCMDriverDesktop::SendImpl(const std::string
& app_id
,
528 const std::string
& receiver_id
,
529 const GCMClient::OutgoingMessage
& message
) {
530 // Delay the send operation until all GCMClient is ready.
531 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
532 delayed_task_controller_
->AddTask(base::Bind(&GCMDriverDesktop::DoSend
,
533 weak_ptr_factory_
.GetWeakPtr(),
540 DoSend(app_id
, receiver_id
, message
);
543 void GCMDriverDesktop::DoSend(const std::string
& app_id
,
544 const std::string
& receiver_id
,
545 const GCMClient::OutgoingMessage
& message
) {
546 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
547 io_thread_
->PostTask(
549 base::Bind(&GCMDriverDesktop::IOWorker::Send
,
550 base::Unretained(io_worker_
.get()),
556 GCMClient
* GCMDriverDesktop::GetGCMClientForTesting() const {
557 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
558 return io_worker_
? io_worker_
->gcm_client_for_testing() : NULL
;
561 bool GCMDriverDesktop::IsStarted() const {
562 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
566 bool GCMDriverDesktop::IsConnected() const {
570 void GCMDriverDesktop::GetGCMStatistics(
571 const GetGCMStatisticsCallback
& callback
,
573 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
574 DCHECK(!callback
.is_null());
576 request_gcm_statistics_callback_
= callback
;
577 io_thread_
->PostTask(
579 base::Bind(&GCMDriverDesktop::IOWorker::GetGCMStatistics
,
580 base::Unretained(io_worker_
.get()),
584 void GCMDriverDesktop::SetGCMRecording(const GetGCMStatisticsCallback
& callback
,
586 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
588 request_gcm_statistics_callback_
= callback
;
589 io_thread_
->PostTask(
591 base::Bind(&GCMDriverDesktop::IOWorker::SetGCMRecording
,
592 base::Unretained(io_worker_
.get()),
596 void GCMDriverDesktop::UpdateAccountMapping(
597 const AccountMapping
& account_mapping
) {
598 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
600 io_thread_
->PostTask(
602 base::Bind(&GCMDriverDesktop::IOWorker::UpdateAccountMapping
,
603 base::Unretained(io_worker_
.get()),
607 void GCMDriverDesktop::RemoveAccountMapping(const std::string
& account_id
) {
608 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
610 io_thread_
->PostTask(
612 base::Bind(&GCMDriverDesktop::IOWorker::RemoveAccountMapping
,
613 base::Unretained(io_worker_
.get()),
617 void GCMDriverDesktop::SetAccountsForCheckin(
618 const std::map
<std::string
, std::string
>& account_tokens
) {
619 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
621 io_thread_
->PostTask(
623 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountsForCheckin
,
624 base::Unretained(io_worker_
.get()),
628 GCMClient::Result
GCMDriverDesktop::EnsureStarted() {
629 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
632 return GCMClient::SUCCESS
;
635 return GCMClient::GCM_DISABLED
;
637 // Have any app requested the service?
638 if (app_handlers().empty())
639 return GCMClient::UNKNOWN_ERROR
;
641 if (!signed_in_
&& !GCMDriver::IsAllowedForAllUsers())
642 return GCMClient::NOT_SIGNED_IN
;
644 DCHECK(!delayed_task_controller_
);
645 delayed_task_controller_
.reset(new GCMDelayedTaskController
);
647 // Polling for channel status is only needed when GCM is supported for all
649 if (GCMDriver::IsAllowedForAllUsers())
650 gcm_channel_status_syncer_
->EnsureStarted();
652 // Note that we need to pass weak pointer again since the existing weak
653 // pointer in IOWorker might have been invalidated when check-out occurs.
654 io_thread_
->PostTask(
656 base::Bind(&GCMDriverDesktop::IOWorker::Start
,
657 base::Unretained(io_worker_
.get()),
658 weak_ptr_factory_
.GetWeakPtr()));
661 return GCMClient::SUCCESS
;
664 void GCMDriverDesktop::RemoveCachedData() {
665 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
666 // Remove all the queued tasks since they no longer make sense after
667 // GCM service is stopped.
668 weak_ptr_factory_
.InvalidateWeakPtrs();
670 gcm_started_
= false;
671 delayed_task_controller_
.reset();
675 void GCMDriverDesktop::MessageReceived(
676 const std::string
& app_id
,
677 const GCMClient::IncomingMessage
& message
) {
678 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
680 // Drop the event if the service has been stopped.
684 GetAppHandler(app_id
)->OnMessage(app_id
, message
);
687 void GCMDriverDesktop::MessagesDeleted(const std::string
& app_id
) {
688 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
690 // Drop the event if the service has been stopped.
694 GetAppHandler(app_id
)->OnMessagesDeleted(app_id
);
697 void GCMDriverDesktop::MessageSendError(
698 const std::string
& app_id
,
699 const GCMClient::SendErrorDetails
& send_error_details
) {
700 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
702 // Drop the event if the service has been stopped.
706 GetAppHandler(app_id
)->OnSendError(app_id
, send_error_details
);
709 void GCMDriverDesktop::SendAcknowledged(const std::string
& app_id
,
710 const std::string
& message_id
) {
711 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
713 // Drop the event if the service has been stopped.
717 GetAppHandler(app_id
)->OnSendAcknowledged(app_id
, message_id
);
720 void GCMDriverDesktop::GCMClientReady(
721 const std::vector
<AccountMapping
>& account_mappings
) {
722 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
724 delayed_task_controller_
->SetReady();
727 void GCMDriverDesktop::OnConnected(const net::IPEndPoint
& ip_endpoint
) {
728 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
732 // Drop the event if the service has been stopped.
736 FOR_EACH_OBSERVER(GCMConnectionObserver
,
737 connection_observer_list_
,
738 OnConnected(ip_endpoint
));
741 void GCMDriverDesktop::OnDisconnected() {
742 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
746 // Drop the event if the service has been stopped.
751 GCMConnectionObserver
, connection_observer_list_
, OnDisconnected());
754 void GCMDriverDesktop::GetGCMStatisticsFinished(
755 const GCMClient::GCMStatistics
& stats
) {
756 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
758 // Normally request_gcm_statistics_callback_ would not be null.
759 if (!request_gcm_statistics_callback_
.is_null())
760 request_gcm_statistics_callback_
.Run(stats
);
762 LOG(WARNING
) << "request_gcm_statistics_callback_ is NULL.";