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"
29 class GCMDriverDesktop::IOWorker
: public GCMClient::Delegate
{
31 // Called on UI thread.
32 IOWorker(const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
33 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
);
36 // Overridden from GCMClient::Delegate:
37 // Called on IO thread.
38 void OnRegisterFinished(const std::string
& app_id
,
39 const std::string
& registration_id
,
40 GCMClient::Result result
) override
;
41 void OnUnregisterFinished(const std::string
& app_id
,
42 GCMClient::Result result
) override
;
43 void OnSendFinished(const std::string
& app_id
,
44 const std::string
& message_id
,
45 GCMClient::Result result
) override
;
46 void OnMessageReceived(const std::string
& app_id
,
47 const GCMClient::IncomingMessage
& message
) override
;
48 void OnMessagesDeleted(const std::string
& app_id
) override
;
49 void OnMessageSendError(
50 const std::string
& app_id
,
51 const GCMClient::SendErrorDetails
& send_error_details
) override
;
52 void OnSendAcknowledged(const std::string
& app_id
,
53 const std::string
& message_id
) override
;
54 void OnGCMReady(const std::vector
<AccountMapping
>& account_mappings
,
55 const base::Time
& last_token_fetch_time
) override
;
56 void OnActivityRecorded() override
;
57 void OnConnected(const net::IPEndPoint
& ip_endpoint
) override
;
58 void OnDisconnected() override
;
60 // Called on IO thread.
62 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
63 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
64 const base::FilePath
& store_path
,
65 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
66 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
);
67 void Start(const base::WeakPtr
<GCMDriverDesktop
>& service
);
70 void Register(const std::string
& app_id
,
71 const std::vector
<std::string
>& sender_ids
);
72 void Unregister(const std::string
& app_id
);
73 void Send(const std::string
& app_id
,
74 const std::string
& receiver_id
,
75 const GCMClient::OutgoingMessage
& message
);
76 void GetGCMStatistics(bool clear_logs
);
77 void SetGCMRecording(bool recording
);
79 void SetAccountTokens(
80 const std::vector
<GCMClient::AccountTokenInfo
>& account_tokens
);
81 void UpdateAccountMapping(const AccountMapping
& account_mapping
);
82 void RemoveAccountMapping(const std::string
& account_id
);
83 void SetLastTokenFetchTime(const base::Time
& time
);
85 // For testing purpose. Can be called from UI thread. Use with care.
86 GCMClient
* gcm_client_for_testing() const { return gcm_client_
.get(); }
89 scoped_refptr
<base::SequencedTaskRunner
> ui_thread_
;
90 scoped_refptr
<base::SequencedTaskRunner
> io_thread_
;
92 base::WeakPtr
<GCMDriverDesktop
> service_
;
94 scoped_ptr
<GCMClient
> gcm_client_
;
96 DISALLOW_COPY_AND_ASSIGN(IOWorker
);
99 GCMDriverDesktop::IOWorker::IOWorker(
100 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
101 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
)
102 : ui_thread_(ui_thread
),
103 io_thread_(io_thread
) {
104 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
107 GCMDriverDesktop::IOWorker::~IOWorker() {
108 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
111 void GCMDriverDesktop::IOWorker::Initialize(
112 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
113 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
114 const base::FilePath
& store_path
,
115 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
116 const scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
) {
117 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
119 gcm_client_
= gcm_client_factory
->BuildInstance();
121 gcm_client_
->Initialize(chrome_build_info
,
123 blocking_task_runner
,
125 make_scoped_ptr
<Encryptor
>(new SystemEncryptor
),
129 void GCMDriverDesktop::IOWorker::OnRegisterFinished(
130 const std::string
& app_id
,
131 const std::string
& registration_id
,
132 GCMClient::Result result
) {
133 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
135 ui_thread_
->PostTask(
137 base::Bind(&GCMDriverDesktop::RegisterFinished
, service_
, app_id
,
138 registration_id
, result
));
141 void GCMDriverDesktop::IOWorker::OnUnregisterFinished(
142 const std::string
& app_id
,
143 GCMClient::Result result
) {
144 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
146 ui_thread_
->PostTask(FROM_HERE
,
147 base::Bind(&GCMDriverDesktop::UnregisterFinished
,
153 void GCMDriverDesktop::IOWorker::OnSendFinished(const std::string
& app_id
,
154 const std::string
& message_id
,
155 GCMClient::Result result
) {
156 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
158 ui_thread_
->PostTask(
160 base::Bind(&GCMDriverDesktop::SendFinished
, service_
, app_id
, message_id
,
164 void GCMDriverDesktop::IOWorker::OnMessageReceived(
165 const std::string
& app_id
,
166 const GCMClient::IncomingMessage
& message
) {
167 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
169 ui_thread_
->PostTask(
171 base::Bind(&GCMDriverDesktop::MessageReceived
,
177 void GCMDriverDesktop::IOWorker::OnMessagesDeleted(const std::string
& app_id
) {
178 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
180 ui_thread_
->PostTask(
182 base::Bind(&GCMDriverDesktop::MessagesDeleted
, service_
, app_id
));
185 void GCMDriverDesktop::IOWorker::OnMessageSendError(
186 const std::string
& app_id
,
187 const GCMClient::SendErrorDetails
& send_error_details
) {
188 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
190 ui_thread_
->PostTask(
192 base::Bind(&GCMDriverDesktop::MessageSendError
, service_
, app_id
,
193 send_error_details
));
196 void GCMDriverDesktop::IOWorker::OnSendAcknowledged(
197 const std::string
& app_id
,
198 const std::string
& message_id
) {
199 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
201 ui_thread_
->PostTask(
204 &GCMDriverDesktop::SendAcknowledged
, service_
, app_id
, message_id
));
207 void GCMDriverDesktop::IOWorker::OnGCMReady(
208 const std::vector
<AccountMapping
>& account_mappings
,
209 const base::Time
& last_token_fetch_time
) {
210 ui_thread_
->PostTask(FROM_HERE
,
211 base::Bind(&GCMDriverDesktop::GCMClientReady
,
214 last_token_fetch_time
));
217 void GCMDriverDesktop::IOWorker::OnActivityRecorded() {
218 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
219 // When an activity is recorded, get all the stats and refresh the UI of
220 // gcm-internals page.
221 GetGCMStatistics(false);
224 void GCMDriverDesktop::IOWorker::OnConnected(
225 const net::IPEndPoint
& ip_endpoint
) {
226 ui_thread_
->PostTask(FROM_HERE
,
227 base::Bind(&GCMDriverDesktop::OnConnected
,
232 void GCMDriverDesktop::IOWorker::OnDisconnected() {
233 ui_thread_
->PostTask(FROM_HERE
,
234 base::Bind(&GCMDriverDesktop::OnDisconnected
, service_
));
237 void GCMDriverDesktop::IOWorker::Start(
238 const base::WeakPtr
<GCMDriverDesktop
>& service
) {
239 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
242 gcm_client_
->Start();
245 void GCMDriverDesktop::IOWorker::Stop() {
246 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
251 void GCMDriverDesktop::IOWorker::CheckOut() {
252 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
254 gcm_client_
->CheckOut();
256 // Note that we still need to keep GCMClient instance alive since the
257 // GCMDriverDesktop may check in again.
260 void GCMDriverDesktop::IOWorker::Register(
261 const std::string
& app_id
,
262 const std::vector
<std::string
>& sender_ids
) {
263 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
265 gcm_client_
->Register(app_id
, sender_ids
);
268 void GCMDriverDesktop::IOWorker::Unregister(const std::string
& app_id
) {
269 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
271 gcm_client_
->Unregister(app_id
);
274 void GCMDriverDesktop::IOWorker::Send(
275 const std::string
& app_id
,
276 const std::string
& receiver_id
,
277 const GCMClient::OutgoingMessage
& message
) {
278 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
280 gcm_client_
->Send(app_id
, receiver_id
, message
);
283 void GCMDriverDesktop::IOWorker::GetGCMStatistics(bool clear_logs
) {
284 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
285 gcm::GCMClient::GCMStatistics stats
;
287 if (gcm_client_
.get()) {
289 gcm_client_
->ClearActivityLogs();
290 stats
= gcm_client_
->GetStatistics();
293 ui_thread_
->PostTask(
295 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished
, service_
, stats
));
298 void GCMDriverDesktop::IOWorker::SetGCMRecording(bool recording
) {
299 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
300 gcm::GCMClient::GCMStatistics stats
;
302 if (gcm_client_
.get()) {
303 gcm_client_
->SetRecording(recording
);
304 stats
= gcm_client_
->GetStatistics();
305 stats
.gcm_client_created
= true;
308 ui_thread_
->PostTask(
310 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished
, service_
, stats
));
313 void GCMDriverDesktop::IOWorker::SetAccountTokens(
314 const std::vector
<GCMClient::AccountTokenInfo
>& account_tokens
) {
315 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
317 if (gcm_client_
.get())
318 gcm_client_
->SetAccountTokens(account_tokens
);
321 void GCMDriverDesktop::IOWorker::UpdateAccountMapping(
322 const AccountMapping
& account_mapping
) {
323 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
325 if (gcm_client_
.get())
326 gcm_client_
->UpdateAccountMapping(account_mapping
);
329 void GCMDriverDesktop::IOWorker::RemoveAccountMapping(
330 const std::string
& account_id
) {
331 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
333 if (gcm_client_
.get())
334 gcm_client_
->RemoveAccountMapping(account_id
);
337 void GCMDriverDesktop::IOWorker::SetLastTokenFetchTime(const base::Time
& time
) {
338 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
340 if (gcm_client_
.get())
341 gcm_client_
->SetLastTokenFetchTime(time
);
344 GCMDriverDesktop::GCMDriverDesktop(
345 scoped_ptr
<GCMClientFactory
> gcm_client_factory
,
346 const GCMClient::ChromeBuildInfo
& chrome_build_info
,
347 const std::string
& channel_status_request_url
,
348 const std::string
& user_agent
,
350 const base::FilePath
& store_path
,
351 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
352 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
353 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
,
354 const scoped_refptr
<base::SequencedTaskRunner
>& blocking_task_runner
)
355 : gcm_channel_status_syncer_(
356 new GCMChannelStatusSyncer(this,
358 channel_status_request_url
,
365 account_mapper_(new GCMAccountMapper(this)),
366 // Setting to max, to make sure it does not prompt for token reporting
367 // Before reading a reasonable value from the DB, which might be never,
368 // in which case the fetching will be triggered.
369 last_token_fetch_time_(base::Time::Max()),
370 ui_thread_(ui_thread
),
371 io_thread_(io_thread
),
372 weak_ptr_factory_(this) {
373 gcm_enabled_
= gcm_channel_status_syncer_
->gcm_enabled();
375 // Create and initialize the GCMClient. Note that this does not initiate the
377 io_worker_
.reset(new IOWorker(ui_thread
, io_thread
));
378 io_thread_
->PostTask(
380 base::Bind(&GCMDriverDesktop::IOWorker::Initialize
,
381 base::Unretained(io_worker_
.get()),
382 base::Passed(&gcm_client_factory
),
386 blocking_task_runner
));
389 GCMDriverDesktop::~GCMDriverDesktop() {
392 void GCMDriverDesktop::Shutdown() {
393 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
396 GCMDriver::Shutdown();
398 // Dispose the syncer in order to release the reference to
399 // URLRequestContextGetter that needs to be done before IOThread gets
401 gcm_channel_status_syncer_
.reset();
403 io_thread_
->DeleteSoon(FROM_HERE
, io_worker_
.release());
406 void GCMDriverDesktop::OnSignedIn() {
411 void GCMDriverDesktop::OnSignedOut() {
414 // When sign-in enforcement is not dropped, we will stop the GCM connection
415 // when the user signs out.
416 if (!GCMDriver::IsAllowedForAllUsers()) {
421 void GCMDriverDesktop::Purge() {
422 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
426 io_thread_
->PostTask(FROM_HERE
,
427 base::Bind(&GCMDriverDesktop::IOWorker::CheckOut
,
428 base::Unretained(io_worker_
.get())));
431 void GCMDriverDesktop::AddAppHandler(const std::string
& app_id
,
432 GCMAppHandler
* handler
) {
433 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
434 GCMDriver::AddAppHandler(app_id
, handler
);
436 // Ensures that the GCM service is started when there is an interest.
440 void GCMDriverDesktop::RemoveAppHandler(const std::string
& app_id
) {
441 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
442 GCMDriver::RemoveAppHandler(app_id
);
444 // Stops the GCM service when no app intends to consume it. Stop function will
445 // remove the last app handler - account mapper.
446 if (app_handlers().size() == 1) {
448 gcm_channel_status_syncer_
->Stop();
452 void GCMDriverDesktop::AddConnectionObserver(GCMConnectionObserver
* observer
) {
453 connection_observer_list_
.AddObserver(observer
);
456 void GCMDriverDesktop::RemoveConnectionObserver(
457 GCMConnectionObserver
* observer
) {
458 connection_observer_list_
.RemoveObserver(observer
);
461 void GCMDriverDesktop::Enable() {
462 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
471 void GCMDriverDesktop::Disable() {
472 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
476 gcm_enabled_
= false;
481 void GCMDriverDesktop::Stop() {
482 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
484 // No need to stop GCM service if not started yet.
488 account_mapper_
->ShutdownHandler();
489 GCMDriver::RemoveAppHandler(kGCMAccountMapperAppId
);
493 io_thread_
->PostTask(
495 base::Bind(&GCMDriverDesktop::IOWorker::Stop
,
496 base::Unretained(io_worker_
.get())));
499 void GCMDriverDesktop::RegisterImpl(
500 const std::string
& app_id
,
501 const std::vector
<std::string
>& sender_ids
) {
502 // Delay the register operation until GCMClient is ready.
503 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
504 delayed_task_controller_
->AddTask(base::Bind(&GCMDriverDesktop::DoRegister
,
505 weak_ptr_factory_
.GetWeakPtr(),
511 DoRegister(app_id
, sender_ids
);
514 void GCMDriverDesktop::DoRegister(const std::string
& app_id
,
515 const std::vector
<std::string
>& sender_ids
) {
516 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
517 if (!HasRegisterCallback(app_id
)) {
518 // The callback could have been removed when the app is uninstalled.
522 io_thread_
->PostTask(
524 base::Bind(&GCMDriverDesktop::IOWorker::Register
,
525 base::Unretained(io_worker_
.get()),
530 void GCMDriverDesktop::UnregisterImpl(const std::string
& app_id
) {
531 // Delay the unregister operation until GCMClient is ready.
532 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
533 delayed_task_controller_
->AddTask(
534 base::Bind(&GCMDriverDesktop::DoUnregister
,
535 weak_ptr_factory_
.GetWeakPtr(),
540 DoUnregister(app_id
);
543 void GCMDriverDesktop::DoUnregister(const std::string
& app_id
) {
544 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
546 // Ask the server to unregister it. There could be a small chance that the
547 // unregister request fails. If this occurs, it does not bring any harm since
548 // we simply reject the messages/events received from the server.
549 io_thread_
->PostTask(
551 base::Bind(&GCMDriverDesktop::IOWorker::Unregister
,
552 base::Unretained(io_worker_
.get()),
556 void GCMDriverDesktop::SendImpl(const std::string
& app_id
,
557 const std::string
& receiver_id
,
558 const GCMClient::OutgoingMessage
& message
) {
559 // Delay the send operation until all GCMClient is ready.
560 if (!delayed_task_controller_
->CanRunTaskWithoutDelay()) {
561 delayed_task_controller_
->AddTask(base::Bind(&GCMDriverDesktop::DoSend
,
562 weak_ptr_factory_
.GetWeakPtr(),
569 DoSend(app_id
, receiver_id
, message
);
572 void GCMDriverDesktop::DoSend(const std::string
& app_id
,
573 const std::string
& receiver_id
,
574 const GCMClient::OutgoingMessage
& message
) {
575 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
576 io_thread_
->PostTask(
578 base::Bind(&GCMDriverDesktop::IOWorker::Send
,
579 base::Unretained(io_worker_
.get()),
585 GCMClient
* GCMDriverDesktop::GetGCMClientForTesting() const {
586 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
587 return io_worker_
? io_worker_
->gcm_client_for_testing() : NULL
;
590 bool GCMDriverDesktop::IsStarted() const {
591 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
595 bool GCMDriverDesktop::IsConnected() const {
599 void GCMDriverDesktop::GetGCMStatistics(
600 const GetGCMStatisticsCallback
& callback
,
602 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
603 DCHECK(!callback
.is_null());
605 request_gcm_statistics_callback_
= callback
;
606 io_thread_
->PostTask(
608 base::Bind(&GCMDriverDesktop::IOWorker::GetGCMStatistics
,
609 base::Unretained(io_worker_
.get()),
613 void GCMDriverDesktop::SetGCMRecording(const GetGCMStatisticsCallback
& callback
,
615 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
617 request_gcm_statistics_callback_
= callback
;
618 io_thread_
->PostTask(
620 base::Bind(&GCMDriverDesktop::IOWorker::SetGCMRecording
,
621 base::Unretained(io_worker_
.get()),
625 void GCMDriverDesktop::UpdateAccountMapping(
626 const AccountMapping
& account_mapping
) {
627 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
629 io_thread_
->PostTask(
631 base::Bind(&GCMDriverDesktop::IOWorker::UpdateAccountMapping
,
632 base::Unretained(io_worker_
.get()),
636 void GCMDriverDesktop::RemoveAccountMapping(const std::string
& account_id
) {
637 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
639 io_thread_
->PostTask(
641 base::Bind(&GCMDriverDesktop::IOWorker::RemoveAccountMapping
,
642 base::Unretained(io_worker_
.get()),
646 base::Time
GCMDriverDesktop::GetLastTokenFetchTime() {
647 return last_token_fetch_time_
;
650 void GCMDriverDesktop::SetLastTokenFetchTime(const base::Time
& time
) {
651 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
653 last_token_fetch_time_
= time
;
655 io_thread_
->PostTask(
657 base::Bind(&GCMDriverDesktop::IOWorker::SetLastTokenFetchTime
,
658 base::Unretained(io_worker_
.get()),
662 void GCMDriverDesktop::SetAccountTokens(
663 const std::vector
<GCMClient::AccountTokenInfo
>& account_tokens
) {
664 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
666 account_mapper_
->SetAccountTokens(account_tokens
);
668 io_thread_
->PostTask(
670 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountTokens
,
671 base::Unretained(io_worker_
.get()),
675 GCMClient::Result
GCMDriverDesktop::EnsureStarted() {
676 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
679 return GCMClient::SUCCESS
;
682 // Poll for channel status in order to find out when it is re-enabled when
683 // GCM is currently disabled.
684 if (GCMDriver::IsAllowedForAllUsers())
685 gcm_channel_status_syncer_
->EnsureStarted();
687 return GCMClient::GCM_DISABLED
;
690 // Have any app requested the service?
691 if (app_handlers().empty())
692 return GCMClient::UNKNOWN_ERROR
;
694 // TODO(jianli): To be removed when sign-in enforcement is dropped.
695 if (!signed_in_
&& !GCMDriver::IsAllowedForAllUsers())
696 return GCMClient::NOT_SIGNED_IN
;
698 DCHECK(!delayed_task_controller_
);
699 delayed_task_controller_
.reset(new GCMDelayedTaskController
);
701 // Polling for channel status is only needed when GCM is supported for all
703 if (GCMDriver::IsAllowedForAllUsers())
704 gcm_channel_status_syncer_
->EnsureStarted();
706 UMA_HISTOGRAM_BOOLEAN("GCM.UserSignedIn", signed_in_
);
708 // Note that we need to pass weak pointer again since the existing weak
709 // pointer in IOWorker might have been invalidated when check-out occurs.
710 io_thread_
->PostTask(
712 base::Bind(&GCMDriverDesktop::IOWorker::Start
,
713 base::Unretained(io_worker_
.get()),
714 weak_ptr_factory_
.GetWeakPtr()));
717 return GCMClient::SUCCESS
;
720 void GCMDriverDesktop::RemoveCachedData() {
721 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
722 // Remove all the queued tasks since they no longer make sense after
723 // GCM service is stopped.
724 weak_ptr_factory_
.InvalidateWeakPtrs();
726 gcm_started_
= false;
727 delayed_task_controller_
.reset();
731 void GCMDriverDesktop::MessageReceived(
732 const std::string
& app_id
,
733 const GCMClient::IncomingMessage
& message
) {
734 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
736 // Drop the event if the service has been stopped.
740 GetAppHandler(app_id
)->OnMessage(app_id
, message
);
743 void GCMDriverDesktop::MessagesDeleted(const std::string
& app_id
) {
744 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
746 // Drop the event if the service has been stopped.
750 GetAppHandler(app_id
)->OnMessagesDeleted(app_id
);
753 void GCMDriverDesktop::MessageSendError(
754 const std::string
& app_id
,
755 const GCMClient::SendErrorDetails
& send_error_details
) {
756 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
758 // Drop the event if the service has been stopped.
762 GetAppHandler(app_id
)->OnSendError(app_id
, send_error_details
);
765 void GCMDriverDesktop::SendAcknowledged(const std::string
& app_id
,
766 const std::string
& message_id
) {
767 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
769 // Drop the event if the service has been stopped.
773 GetAppHandler(app_id
)->OnSendAcknowledged(app_id
, message_id
);
776 void GCMDriverDesktop::GCMClientReady(
777 const std::vector
<AccountMapping
>& account_mappings
,
778 const base::Time
& last_token_fetch_time
) {
779 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
781 last_token_fetch_time_
= last_token_fetch_time
;
783 GCMDriver::AddAppHandler(kGCMAccountMapperAppId
, account_mapper_
.get());
784 account_mapper_
->Initialize(account_mappings
);
786 delayed_task_controller_
->SetReady();
789 void GCMDriverDesktop::OnConnected(const net::IPEndPoint
& ip_endpoint
) {
790 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
794 // Drop the event if the service has been stopped.
798 FOR_EACH_OBSERVER(GCMConnectionObserver
,
799 connection_observer_list_
,
800 OnConnected(ip_endpoint
));
803 void GCMDriverDesktop::OnDisconnected() {
804 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
808 // Drop the event if the service has been stopped.
813 GCMConnectionObserver
, connection_observer_list_
, OnDisconnected());
816 void GCMDriverDesktop::GetGCMStatisticsFinished(
817 const GCMClient::GCMStatistics
& stats
) {
818 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
820 // Normally request_gcm_statistics_callback_ would not be null.
821 if (!request_gcm_statistics_callback_
.is_null())
822 request_gcm_statistics_callback_
.Run(stats
);
824 LOG(WARNING
) << "request_gcm_statistics_callback_ is NULL.";