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/metrics/histogram.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/threading/sequenced_worker_pool.h"
17 #include "components/gcm_driver/gcm_account_mapper.h"
18 #include "components/gcm_driver/gcm_app_handler.h"
19 #include "components/gcm_driver/gcm_channel_status_syncer.h"
20 #include "components/gcm_driver/gcm_client_factory.h"
21 #include "components/gcm_driver/gcm_delayed_task_controller.h"
22 #include "components/gcm_driver/system_encryptor.h"
23 #include "google_apis/gcm/engine/account_mapping.h"
24 #include "net/base/ip_endpoint.h"
25 #include "net/url_request/url_request_context_getter.h"
27 #if defined(OS_CHROMEOS)
28 #include "components/timers/alarm_timer_chromeos.h"
33 class GCMDriverDesktop::IOWorker
: public GCMClient::Delegate
{
35 // Called on UI thread.
36 IOWorker(const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
37 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
);
40 // Overridden from GCMClient::Delegate:
41 // Called on IO thread.
42 void OnRegisterFinished(const std::string
& app_id
,
43 const std::string
& registration_id
,
44 GCMClient::Result result
) override
;
45 void OnUnregisterFinished(const std::string
& app_id
,
46 GCMClient::Result result
) override
;
47 void OnSendFinished(const std::string
& app_id
,
48 const std::string
& message_id
,
49 GCMClient::Result result
) override
;
50 void OnMessageReceived(const std::string
& app_id
,
51 const GCMClient::IncomingMessage
& message
) override
;
52 void OnMessagesDeleted(const std::string
& app_id
) override
;
53 void OnMessageSendError(
54 const std::string
& app_id
,
55 const GCMClient::SendErrorDetails
& send_error_details
) override
;
56 void OnSendAcknowledged(const std::string
& app_id
,
57 const std::string
& message_id
) override
;
58 void OnGCMReady(const std::vector
<AccountMapping
>& account_mappings
,
59 const base::Time
& last_token_fetch_time
) override
;
60 void OnActivityRecorded() override
;
61 void OnConnected(const net::IPEndPoint
& ip_endpoint
) override
;
62 void OnDisconnected() override
;
64 // Called on IO thread.
66 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
67 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
68 const base::FilePath
& store_path
,
69 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
70 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
);
71 void Start(GCMClient::StartMode start_mode
,
72 const base::WeakPtr
<GCMDriverDesktop
>& service
);
74 void Register(const std::string
& app_id
,
75 const std::vector
<std::string
>& sender_ids
);
76 void Unregister(const std::string
& app_id
);
77 void Send(const std::string
& app_id
,
78 const std::string
& receiver_id
,
79 const GCMClient::OutgoingMessage
& message
);
80 void GetGCMStatistics(bool clear_logs
);
81 void SetGCMRecording(bool recording
);
83 void SetAccountTokens(
84 const std::vector
<GCMClient::AccountTokenInfo
>& account_tokens
);
85 void UpdateAccountMapping(const AccountMapping
& account_mapping
);
86 void RemoveAccountMapping(const std::string
& account_id
);
87 void SetLastTokenFetchTime(const base::Time
& time
);
88 void WakeFromSuspendForHeartbeat(bool wake
);
90 // For testing purpose. Can be called from UI thread. Use with care.
91 GCMClient
* gcm_client_for_testing() const { return gcm_client_
.get(); }
94 scoped_refptr
<base::SequencedTaskRunner
> ui_thread_
;
95 scoped_refptr
<base::SequencedTaskRunner
> io_thread_
;
97 base::WeakPtr
<GCMDriverDesktop
> service_
;
99 scoped_ptr
<GCMClient
> gcm_client_
;
101 DISALLOW_COPY_AND_ASSIGN(IOWorker
);
104 GCMDriverDesktop::IOWorker::IOWorker(
105 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
106 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
)
107 : ui_thread_(ui_thread
),
108 io_thread_(io_thread
) {
109 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
112 GCMDriverDesktop::IOWorker::~IOWorker() {
113 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
116 void GCMDriverDesktop::IOWorker::Initialize(
117 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
118 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
119 const base::FilePath
& store_path
,
120 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
121 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
) {
122 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
124 gcm_client_
= gcm_client_factory
->BuildInstance();
126 gcm_client_
->Initialize(chrome_build_info
,
128 blocking_task_runner
,
130 make_scoped_ptr
<Encryptor
>(new SystemEncryptor
),
134 void GCMDriverDesktop::IOWorker::OnRegisterFinished(
135 const std::string
& app_id
,
136 const std::string
& registration_id
,
137 GCMClient::Result result
) {
138 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
140 ui_thread_
->PostTask(
142 base::Bind(&GCMDriverDesktop::RegisterFinished
, service_
, app_id
,
143 registration_id
, result
));
146 void GCMDriverDesktop::IOWorker::OnUnregisterFinished(
147 const std::string
& app_id
,
148 GCMClient::Result result
) {
149 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
151 ui_thread_
->PostTask(FROM_HERE
,
152 base::Bind(&GCMDriverDesktop::UnregisterFinished
,
158 void GCMDriverDesktop::IOWorker::OnSendFinished(const std::string
& app_id
,
159 const std::string
& message_id
,
160 GCMClient::Result result
) {
161 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
163 ui_thread_
->PostTask(
165 base::Bind(&GCMDriverDesktop::SendFinished
, service_
, app_id
, message_id
,
169 void GCMDriverDesktop::IOWorker::OnMessageReceived(
170 const std::string
& app_id
,
171 const GCMClient::IncomingMessage
& message
) {
172 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
174 ui_thread_
->PostTask(
176 base::Bind(&GCMDriverDesktop::MessageReceived
,
182 void GCMDriverDesktop::IOWorker::OnMessagesDeleted(const std::string
& app_id
) {
183 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
185 ui_thread_
->PostTask(
187 base::Bind(&GCMDriverDesktop::MessagesDeleted
, service_
, app_id
));
190 void GCMDriverDesktop::IOWorker::OnMessageSendError(
191 const std::string
& app_id
,
192 const GCMClient::SendErrorDetails
& send_error_details
) {
193 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
195 ui_thread_
->PostTask(
197 base::Bind(&GCMDriverDesktop::MessageSendError
, service_
, app_id
,
198 send_error_details
));
201 void GCMDriverDesktop::IOWorker::OnSendAcknowledged(
202 const std::string
& app_id
,
203 const std::string
& message_id
) {
204 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
206 ui_thread_
->PostTask(
209 &GCMDriverDesktop::SendAcknowledged
, service_
, app_id
, message_id
));
212 void GCMDriverDesktop::IOWorker::OnGCMReady(
213 const std::vector
<AccountMapping
>& account_mappings
,
214 const base::Time
& last_token_fetch_time
) {
215 ui_thread_
->PostTask(FROM_HERE
,
216 base::Bind(&GCMDriverDesktop::GCMClientReady
,
219 last_token_fetch_time
));
222 void GCMDriverDesktop::IOWorker::OnActivityRecorded() {
223 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
224 // When an activity is recorded, get all the stats and refresh the UI of
225 // gcm-internals page.
226 GetGCMStatistics(false);
229 void GCMDriverDesktop::IOWorker::OnConnected(
230 const net::IPEndPoint
& ip_endpoint
) {
231 ui_thread_
->PostTask(FROM_HERE
,
232 base::Bind(&GCMDriverDesktop::OnConnected
,
237 void GCMDriverDesktop::IOWorker::OnDisconnected() {
238 ui_thread_
->PostTask(FROM_HERE
,
239 base::Bind(&GCMDriverDesktop::OnDisconnected
, service_
));
242 void GCMDriverDesktop::IOWorker::Start(
243 GCMClient::StartMode start_mode
,
244 const base::WeakPtr
<GCMDriverDesktop
>& service
) {
245 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
248 gcm_client_
->Start(start_mode
);
251 void GCMDriverDesktop::IOWorker::Stop() {
252 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
257 void GCMDriverDesktop::IOWorker::Register(
258 const std::string
& app_id
,
259 const std::vector
<std::string
>& sender_ids
) {
260 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
262 gcm_client_
->Register(app_id
, sender_ids
);
265 void GCMDriverDesktop::IOWorker::Unregister(const std::string
& app_id
) {
266 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
268 gcm_client_
->Unregister(app_id
);
271 void GCMDriverDesktop::IOWorker::Send(
272 const std::string
& app_id
,
273 const std::string
& receiver_id
,
274 const GCMClient::OutgoingMessage
& message
) {
275 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
277 gcm_client_
->Send(app_id
, receiver_id
, message
);
280 void GCMDriverDesktop::IOWorker::GetGCMStatistics(bool clear_logs
) {
281 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
282 gcm::GCMClient::GCMStatistics stats
;
284 if (gcm_client_
.get()) {
286 gcm_client_
->ClearActivityLogs();
287 stats
= gcm_client_
->GetStatistics();
290 ui_thread_
->PostTask(
292 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished
, service_
, stats
));
295 void GCMDriverDesktop::IOWorker::SetGCMRecording(bool recording
) {
296 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
297 gcm::GCMClient::GCMStatistics stats
;
299 if (gcm_client_
.get()) {
300 gcm_client_
->SetRecording(recording
);
301 stats
= gcm_client_
->GetStatistics();
302 stats
.gcm_client_created
= true;
305 ui_thread_
->PostTask(
307 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished
, service_
, stats
));
310 void GCMDriverDesktop::IOWorker::SetAccountTokens(
311 const std::vector
<GCMClient::AccountTokenInfo
>& account_tokens
) {
312 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
314 if (gcm_client_
.get())
315 gcm_client_
->SetAccountTokens(account_tokens
);
318 void GCMDriverDesktop::IOWorker::UpdateAccountMapping(
319 const AccountMapping
& account_mapping
) {
320 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
322 if (gcm_client_
.get())
323 gcm_client_
->UpdateAccountMapping(account_mapping
);
326 void GCMDriverDesktop::IOWorker::RemoveAccountMapping(
327 const std::string
& account_id
) {
328 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
330 if (gcm_client_
.get())
331 gcm_client_
->RemoveAccountMapping(account_id
);
334 void GCMDriverDesktop::IOWorker::SetLastTokenFetchTime(const base::Time
& time
) {
335 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
337 if (gcm_client_
.get())
338 gcm_client_
->SetLastTokenFetchTime(time
);
341 void GCMDriverDesktop::IOWorker::WakeFromSuspendForHeartbeat(bool wake
) {
342 #if defined(OS_CHROMEOS)
343 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
345 scoped_ptr
<base::Timer
> timer
;
347 timer
.reset(new timers::SimpleAlarmTimer());
349 timer
.reset(new base::Timer(true, false));
351 gcm_client_
->UpdateHeartbeatTimer(timer
.Pass());
355 GCMDriverDesktop::GCMDriverDesktop(
356 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
357 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
358 const std::string
& channel_status_request_url
,
359 const std::string
& user_agent
,
361 const base::FilePath
& store_path
,
362 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
363 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
364 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
,
365 const scoped_refptr
<base::SequencedTaskRunner
>& blocking_task_runner
)
366 : gcm_channel_status_syncer_(
367 new GCMChannelStatusSyncer(this,
369 channel_status_request_url
,
376 account_mapper_(new GCMAccountMapper(this)),
377 // Setting to max, to make sure it does not prompt for token reporting
378 // Before reading a reasonable value from the DB, which might be never,
379 // in which case the fetching will be triggered.
380 last_token_fetch_time_(base::Time::Max()),
381 ui_thread_(ui_thread
),
382 io_thread_(io_thread
),
383 wake_from_suspend_enabled_(false),
384 weak_ptr_factory_(this) {
385 gcm_enabled_
= gcm_channel_status_syncer_
->gcm_enabled();
387 // Create and initialize the GCMClient. Note that this does not initiate the
389 io_worker_
.reset(new IOWorker(ui_thread
, io_thread
));
390 io_thread_
->PostTask(
392 base::Bind(&GCMDriverDesktop::IOWorker::Initialize
,
393 base::Unretained(io_worker_
.get()),
394 base::Passed(&gcm_client_factory
),
398 blocking_task_runner
));
401 GCMDriverDesktop::~GCMDriverDesktop() {
404 void GCMDriverDesktop::Shutdown() {
405 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
408 GCMDriver::Shutdown();
410 // Dispose the syncer in order to release the reference to
411 // URLRequestContextGetter that needs to be done before IOThread gets
413 gcm_channel_status_syncer_
.reset();
415 io_thread_
->DeleteSoon(FROM_HERE
, io_worker_
.release());
418 void GCMDriverDesktop::OnSignedIn() {
422 void GCMDriverDesktop::OnSignedOut() {
426 void GCMDriverDesktop::AddAppHandler(const std::string
& app_id
,
427 GCMAppHandler
* handler
) {
428 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
429 GCMDriver::AddAppHandler(app_id
, handler
);
431 // Ensures that the GCM service is started when there is an interest.
432 EnsureStarted(GCMClient::DELAYED_START
);
435 void GCMDriverDesktop::RemoveAppHandler(const std::string
& app_id
) {
436 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
437 GCMDriver::RemoveAppHandler(app_id
);
439 // Stops the GCM service when no app intends to consume it. Stop function will
440 // remove the last app handler - account mapper.
441 if (app_handlers().size() == 1) {
443 gcm_channel_status_syncer_
->Stop();
447 void GCMDriverDesktop::AddConnectionObserver(GCMConnectionObserver
* observer
) {
448 connection_observer_list_
.AddObserver(observer
);
451 void GCMDriverDesktop::RemoveConnectionObserver(
452 GCMConnectionObserver
* observer
) {
453 connection_observer_list_
.RemoveObserver(observer
);
456 void GCMDriverDesktop::Enable() {
457 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
463 EnsureStarted(GCMClient::DELAYED_START
);
466 void GCMDriverDesktop::Disable() {
467 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
471 gcm_enabled_
= false;
476 void GCMDriverDesktop::Stop() {
477 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
479 // No need to stop GCM service if not started yet.
483 account_mapper_
->ShutdownHandler();
484 GCMDriver::RemoveAppHandler(kGCMAccountMapperAppId
);
488 io_thread_
->PostTask(
490 base::Bind(&GCMDriverDesktop::IOWorker::Stop
,
491 base::Unretained(io_worker_
.get())));
494 void GCMDriverDesktop::RegisterImpl(
495 const std::string
& app_id
,
496 const std::vector
<std::string
>& sender_ids
) {
497 // Delay the register operation until GCMClient is ready.
498 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
499 delayed_task_controller_
->AddTask(base::Bind(&GCMDriverDesktop::DoRegister
,
500 weak_ptr_factory_
.GetWeakPtr(),
506 DoRegister(app_id
, sender_ids
);
509 void GCMDriverDesktop::DoRegister(const std::string
& app_id
,
510 const std::vector
<std::string
>& sender_ids
) {
511 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
512 if (!HasRegisterCallback(app_id
)) {
513 // The callback could have been removed when the app is uninstalled.
517 io_thread_
->PostTask(
519 base::Bind(&GCMDriverDesktop::IOWorker::Register
,
520 base::Unretained(io_worker_
.get()),
525 void GCMDriverDesktop::UnregisterImpl(const std::string
& app_id
) {
526 // Delay the unregister operation until GCMClient is ready.
527 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
528 delayed_task_controller_
->AddTask(
529 base::Bind(&GCMDriverDesktop::DoUnregister
,
530 weak_ptr_factory_
.GetWeakPtr(),
535 DoUnregister(app_id
);
538 void GCMDriverDesktop::DoUnregister(const std::string
& app_id
) {
539 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
541 // Ask the server to unregister it. There could be a small chance that the
542 // unregister request fails. If this occurs, it does not bring any harm since
543 // we simply reject the messages/events received from the server.
544 io_thread_
->PostTask(
546 base::Bind(&GCMDriverDesktop::IOWorker::Unregister
,
547 base::Unretained(io_worker_
.get()),
551 void GCMDriverDesktop::SendImpl(const std::string
& app_id
,
552 const std::string
& receiver_id
,
553 const GCMClient::OutgoingMessage
& message
) {
554 // Delay the send operation until all GCMClient is ready.
555 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
556 delayed_task_controller_
->AddTask(base::Bind(&GCMDriverDesktop::DoSend
,
557 weak_ptr_factory_
.GetWeakPtr(),
564 DoSend(app_id
, receiver_id
, message
);
567 void GCMDriverDesktop::DoSend(const std::string
& app_id
,
568 const std::string
& receiver_id
,
569 const GCMClient::OutgoingMessage
& message
) {
570 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
571 io_thread_
->PostTask(
573 base::Bind(&GCMDriverDesktop::IOWorker::Send
,
574 base::Unretained(io_worker_
.get()),
580 GCMClient
* GCMDriverDesktop::GetGCMClientForTesting() const {
581 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
582 return io_worker_
? io_worker_
->gcm_client_for_testing() : NULL
;
585 bool GCMDriverDesktop::IsStarted() const {
586 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
590 bool GCMDriverDesktop::IsConnected() const {
594 void GCMDriverDesktop::GetGCMStatistics(
595 const GetGCMStatisticsCallback
& callback
,
597 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
598 DCHECK(!callback
.is_null());
600 request_gcm_statistics_callback_
= callback
;
601 io_thread_
->PostTask(
603 base::Bind(&GCMDriverDesktop::IOWorker::GetGCMStatistics
,
604 base::Unretained(io_worker_
.get()),
608 void GCMDriverDesktop::SetGCMRecording(const GetGCMStatisticsCallback
& callback
,
610 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
612 request_gcm_statistics_callback_
= callback
;
613 io_thread_
->PostTask(
615 base::Bind(&GCMDriverDesktop::IOWorker::SetGCMRecording
,
616 base::Unretained(io_worker_
.get()),
620 void GCMDriverDesktop::UpdateAccountMapping(
621 const AccountMapping
& account_mapping
) {
622 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
624 io_thread_
->PostTask(
626 base::Bind(&GCMDriverDesktop::IOWorker::UpdateAccountMapping
,
627 base::Unretained(io_worker_
.get()),
631 void GCMDriverDesktop::RemoveAccountMapping(const std::string
& account_id
) {
632 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
634 io_thread_
->PostTask(
636 base::Bind(&GCMDriverDesktop::IOWorker::RemoveAccountMapping
,
637 base::Unretained(io_worker_
.get()),
641 base::Time
GCMDriverDesktop::GetLastTokenFetchTime() {
642 return last_token_fetch_time_
;
645 void GCMDriverDesktop::SetLastTokenFetchTime(const base::Time
& time
) {
646 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
648 last_token_fetch_time_
= time
;
650 io_thread_
->PostTask(
652 base::Bind(&GCMDriverDesktop::IOWorker::SetLastTokenFetchTime
,
653 base::Unretained(io_worker_
.get()),
657 void GCMDriverDesktop::WakeFromSuspendForHeartbeat(bool wake
) {
658 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
660 wake_from_suspend_enabled_
= wake
;
662 // The GCM service has not been initialized.
663 if (!delayed_task_controller_
)
666 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
667 // The GCM service was initialized but has not started yet.
668 delayed_task_controller_
->AddTask(
669 base::Bind(&GCMDriverDesktop::WakeFromSuspendForHeartbeat
,
670 weak_ptr_factory_
.GetWeakPtr(),
671 wake_from_suspend_enabled_
));
675 // The GCMClient is ready so we can go ahead and post this task to the
677 io_thread_
->PostTask(
679 base::Bind(&GCMDriverDesktop::IOWorker::WakeFromSuspendForHeartbeat
,
680 base::Unretained(io_worker_
.get()),
681 wake_from_suspend_enabled_
));
684 void GCMDriverDesktop::SetAccountTokens(
685 const std::vector
<GCMClient::AccountTokenInfo
>& account_tokens
) {
686 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
688 account_mapper_
->SetAccountTokens(account_tokens
);
690 io_thread_
->PostTask(
692 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountTokens
,
693 base::Unretained(io_worker_
.get()),
697 GCMClient::Result
GCMDriverDesktop::EnsureStarted(
698 GCMClient::StartMode start_mode
) {
699 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
702 return GCMClient::SUCCESS
;
704 // Have any app requested the service?
705 if (app_handlers().empty())
706 return GCMClient::UNKNOWN_ERROR
;
708 // Polling for channel status should be invoked when GCM is being requested,
709 // no matter whether GCM is enabled or nor.
710 gcm_channel_status_syncer_
->EnsureStarted();
713 return GCMClient::GCM_DISABLED
;
715 if (!delayed_task_controller_
)
716 delayed_task_controller_
.reset(new GCMDelayedTaskController
);
718 // Note that we need to pass weak pointer again since the existing weak
719 // pointer in IOWorker might have been invalidated when GCM is stopped.
720 io_thread_
->PostTask(
722 base::Bind(&GCMDriverDesktop::IOWorker::Start
,
723 base::Unretained(io_worker_
.get()),
725 weak_ptr_factory_
.GetWeakPtr()));
727 return GCMClient::SUCCESS
;
730 void GCMDriverDesktop::RemoveCachedData() {
731 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
732 // Remove all the queued tasks since they no longer make sense after
733 // GCM service is stopped.
734 weak_ptr_factory_
.InvalidateWeakPtrs();
736 gcm_started_
= false;
737 delayed_task_controller_
.reset();
741 void GCMDriverDesktop::MessageReceived(
742 const std::string
& app_id
,
743 const GCMClient::IncomingMessage
& message
) {
744 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
746 // Drop the event if the service has been stopped.
750 GetAppHandler(app_id
)->OnMessage(app_id
, message
);
753 void GCMDriverDesktop::MessagesDeleted(const std::string
& app_id
) {
754 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
756 // Drop the event if the service has been stopped.
760 GetAppHandler(app_id
)->OnMessagesDeleted(app_id
);
763 void GCMDriverDesktop::MessageSendError(
764 const std::string
& app_id
,
765 const GCMClient::SendErrorDetails
& send_error_details
) {
766 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
768 // Drop the event if the service has been stopped.
772 GetAppHandler(app_id
)->OnSendError(app_id
, send_error_details
);
775 void GCMDriverDesktop::SendAcknowledged(const std::string
& app_id
,
776 const std::string
& message_id
) {
777 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
779 // Drop the event if the service has been stopped.
783 GetAppHandler(app_id
)->OnSendAcknowledged(app_id
, message_id
);
786 void GCMDriverDesktop::GCMClientReady(
787 const std::vector
<AccountMapping
>& account_mappings
,
788 const base::Time
& last_token_fetch_time
) {
789 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
791 UMA_HISTOGRAM_BOOLEAN("GCM.UserSignedIn", signed_in_
);
794 if (wake_from_suspend_enabled_
)
795 WakeFromSuspendForHeartbeat(wake_from_suspend_enabled_
);
797 last_token_fetch_time_
= last_token_fetch_time
;
799 GCMDriver::AddAppHandler(kGCMAccountMapperAppId
, account_mapper_
.get());
800 account_mapper_
->Initialize(account_mappings
,
801 base::Bind(&GCMDriverDesktop::MessageReceived
,
802 weak_ptr_factory_
.GetWeakPtr()));
804 delayed_task_controller_
->SetReady();
807 void GCMDriverDesktop::OnConnected(const net::IPEndPoint
& ip_endpoint
) {
808 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
812 // Drop the event if the service has been stopped.
816 FOR_EACH_OBSERVER(GCMConnectionObserver
,
817 connection_observer_list_
,
818 OnConnected(ip_endpoint
));
821 void GCMDriverDesktop::OnDisconnected() {
822 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
826 // Drop the event if the service has been stopped.
831 GCMConnectionObserver
, connection_observer_list_
, OnDisconnected());
834 void GCMDriverDesktop::GetGCMStatisticsFinished(
835 const GCMClient::GCMStatistics
& stats
) {
836 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
838 // Normally request_gcm_statistics_callback_ would not be null.
839 if (!request_gcm_statistics_callback_
.is_null())
840 request_gcm_statistics_callback_
.Run(stats
);
842 LOG(WARNING
) << "request_gcm_statistics_callback_ is NULL.";