Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / components / gcm_driver / gcm_driver_desktop.cc
blob001b0183f8304cc051177294ebb8e14dfa020877
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"
7 #include <utility>
9 #include "base/bind.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"
23 namespace gcm {
25 // Helper class to save tasks to run until we're ready to execute them.
26 class GCMDriverDesktop::DelayedTaskController {
27 public:
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.
36 void SetReady();
38 // Returns true if it is ready to perform tasks.
39 bool CanRunTaskWithoutDelay() const;
41 private:
42 void RunTasks();
44 // Flag that indicates that GCM is ready.
45 bool ready_;
47 std::vector<base::Closure> delayed_tasks_;
49 DISALLOW_COPY_AND_ASSIGN(DelayedTaskController);
52 GCMDriverDesktop::DelayedTaskController::DelayedTaskController()
53 : ready_(false) {
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() {
65 ready_ = true;
66 RunTasks();
69 bool GCMDriverDesktop::DelayedTaskController::CanRunTaskWithoutDelay() const {
70 return ready_;
73 void GCMDriverDesktop::DelayedTaskController::RunTasks() {
74 DCHECK(ready_);
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 {
82 public:
83 // Called on UI thread.
84 IOWorker(const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
85 const scoped_refptr<base::SequencedTaskRunner>& io_thread);
86 virtual ~IOWorker();
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.
113 void Initialize(
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);
120 void Stop();
121 void CheckOut();
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(); }
139 private:
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,
173 store_path,
174 blocking_task_runner,
175 request_context,
176 make_scoped_ptr<Encryptor>(new SystemEncryptor),
177 this);
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(
187 FROM_HERE,
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,
199 service_,
200 app_id,
201 result));
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(
210 FROM_HERE,
211 base::Bind(&GCMDriverDesktop::SendFinished, service_, app_id, message_id,
212 result));
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(
221 FROM_HERE,
222 base::Bind(&GCMDriverDesktop::MessageReceived,
223 service_,
224 app_id,
225 message));
228 void GCMDriverDesktop::IOWorker::OnMessagesDeleted(const std::string& app_id) {
229 DCHECK(io_thread_->RunsTasksOnCurrentThread());
231 ui_thread_->PostTask(
232 FROM_HERE,
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(
242 FROM_HERE,
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(
253 FROM_HERE,
254 base::Bind(
255 &GCMDriverDesktop::SendAcknowledged, service_, app_id, message_id));
258 void GCMDriverDesktop::IOWorker::OnGCMReady() {
259 ui_thread_->PostTask(
260 FROM_HERE,
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,
275 service_,
276 ip_endpoint));
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());
288 service_ = service;
289 gcm_client_->Start();
292 void GCMDriverDesktop::IOWorker::Stop() {
293 DCHECK(io_thread_->RunsTasksOnCurrentThread());
295 gcm_client_->Stop();
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()) {
335 if (clear_logs)
336 gcm_client_->ClearActivityLogs();
337 stats = gcm_client_->GetStatistics();
340 ui_thread_->PostTask(
341 FROM_HERE,
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(
356 FROM_HERE,
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)
392 : signed_in_(false),
393 gcm_started_(false),
394 gcm_enabled_(true),
395 connected_(false),
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
400 // GCM check-in.
401 io_worker_.reset(new IOWorker(ui_thread, io_thread));
402 io_thread_->PostTask(
403 FROM_HERE,
404 base::Bind(&GCMDriverDesktop::IOWorker::Initialize,
405 base::Unretained(io_worker_.get()),
406 base::Passed(&gcm_client_factory),
407 chrome_build_info,
408 store_path,
409 request_context,
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() {
423 signed_in_ = true;
424 EnsureStarted();
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.
433 signed_in_ = false;
434 RemoveCachedData();
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.
447 EnsureStarted();
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())
456 Stop();
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());
471 if (gcm_enabled_)
472 return;
473 gcm_enabled_ = true;
475 EnsureStarted();
478 void GCMDriverDesktop::Disable() {
479 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
481 if (!gcm_enabled_)
482 return;
483 gcm_enabled_ = false;
485 Stop();
488 void GCMDriverDesktop::Stop() {
489 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
491 // No need to stop GCM service if not started yet.
492 if (!gcm_started_)
493 return;
495 RemoveCachedData();
497 io_thread_->PostTask(
498 FROM_HERE,
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(),
510 app_id,
511 sender_ids));
512 return;
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.
523 return;
526 io_thread_->PostTask(
527 FROM_HERE,
528 base::Bind(&GCMDriverDesktop::IOWorker::Register,
529 base::Unretained(io_worker_.get()),
530 app_id,
531 sender_ids));
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(),
540 app_id));
541 return;
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(
554 FROM_HERE,
555 base::Bind(&GCMDriverDesktop::IOWorker::Unregister,
556 base::Unretained(io_worker_.get()),
557 app_id));
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(),
567 app_id,
568 receiver_id,
569 message));
570 return;
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(
581 FROM_HERE,
582 base::Bind(&GCMDriverDesktop::IOWorker::Send,
583 base::Unretained(io_worker_.get()),
584 app_id,
585 receiver_id,
586 message));
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());
596 return gcm_started_;
599 bool GCMDriverDesktop::IsConnected() const {
600 return connected_;
603 void GCMDriverDesktop::GetGCMStatistics(
604 const GetGCMStatisticsCallback& callback,
605 bool clear_logs) {
606 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
607 DCHECK(!callback.is_null());
609 request_gcm_statistics_callback_ = callback;
610 io_thread_->PostTask(
611 FROM_HERE,
612 base::Bind(&GCMDriverDesktop::IOWorker::GetGCMStatistics,
613 base::Unretained(io_worker_.get()),
614 clear_logs));
617 void GCMDriverDesktop::SetGCMRecording(const GetGCMStatisticsCallback& callback,
618 bool recording) {
619 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
621 request_gcm_statistics_callback_ = callback;
622 io_thread_->PostTask(
623 FROM_HERE,
624 base::Bind(&GCMDriverDesktop::IOWorker::SetGCMRecording,
625 base::Unretained(io_worker_.get()),
626 recording));
629 void GCMDriverDesktop::UpdateAccountMapping(
630 const AccountMapping& account_mapping) {
631 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
633 io_thread_->PostTask(
634 FROM_HERE,
635 base::Bind(&GCMDriverDesktop::IOWorker::UpdateAccountMapping,
636 base::Unretained(io_worker_.get()),
637 account_mapping));
640 void GCMDriverDesktop::RemoveAccountMapping(const std::string& account_id) {
641 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
643 io_thread_->PostTask(
644 FROM_HERE,
645 base::Bind(&GCMDriverDesktop::IOWorker::RemoveAccountMapping,
646 base::Unretained(io_worker_.get()),
647 account_id));
650 void GCMDriverDesktop::SetAccountsForCheckin(
651 const std::map<std::string, std::string>& account_tokens) {
652 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
654 io_thread_->PostTask(
655 FROM_HERE,
656 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountsForCheckin,
657 base::Unretained(io_worker_.get()),
658 account_tokens));
661 GCMClient::Result GCMDriverDesktop::EnsureStarted() {
662 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
664 if (gcm_started_)
665 return GCMClient::SUCCESS;
667 if (!gcm_enabled_)
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(
684 FROM_HERE,
685 base::Bind(&GCMDriverDesktop::IOWorker::Start,
686 base::Unretained(io_worker_.get()),
687 weak_ptr_factory_.GetWeakPtr()));
689 gcm_started_ = true;
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();
701 ClearCallbacks();
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.
710 if (!gcm_started_)
711 return;
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.
720 if (!gcm_started_)
721 return;
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.
732 if (!gcm_started_)
733 return;
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.
743 if (!gcm_started_)
744 return;
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());
758 connected_ = true;
760 // Drop the event if the service has been stopped.
761 if (!gcm_started_)
762 return;
764 FOR_EACH_OBSERVER(GCMConnectionObserver,
765 connection_observer_list_,
766 OnConnected(ip_endpoint));
769 void GCMDriverDesktop::OnDisconnected() {
770 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
772 connected_ = false;
774 // Drop the event if the service has been stopped.
775 if (!gcm_started_)
776 return;
778 FOR_EACH_OBSERVER(
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);
789 else
790 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL.";
793 } // namespace gcm