[sqlite backport] Fix collation dequoting.
[chromium-blink-merge.git] / components / gcm_driver / gcm_driver_desktop.cc
blobe6d04f54db7fe172f7f8132a4f580316e999b37d
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/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.h"
29 #endif
31 namespace gcm {
33 class GCMDriverDesktop::IOWorker : public GCMClient::Delegate {
34 public:
35 // Called on UI thread.
36 IOWorker(const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
37 const scoped_refptr<base::SequencedTaskRunner>& io_thread);
38 virtual ~IOWorker();
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.
65 void Initialize(
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);
73 void Stop();
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(); }
93 private:
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,
127 store_path,
128 blocking_task_runner,
129 request_context,
130 make_scoped_ptr<Encryptor>(new SystemEncryptor),
131 this);
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(
141 FROM_HERE,
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,
153 service_,
154 app_id,
155 result));
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(
164 FROM_HERE,
165 base::Bind(&GCMDriverDesktop::SendFinished, service_, app_id, message_id,
166 result));
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(
175 FROM_HERE,
176 base::Bind(&GCMDriverDesktop::MessageReceived,
177 service_,
178 app_id,
179 message));
182 void GCMDriverDesktop::IOWorker::OnMessagesDeleted(const std::string& app_id) {
183 DCHECK(io_thread_->RunsTasksOnCurrentThread());
185 ui_thread_->PostTask(
186 FROM_HERE,
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(
196 FROM_HERE,
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(
207 FROM_HERE,
208 base::Bind(
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,
217 service_,
218 account_mappings,
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,
233 service_,
234 ip_endpoint));
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());
247 service_ = service;
248 gcm_client_->Start(start_mode);
251 void GCMDriverDesktop::IOWorker::Stop() {
252 DCHECK(io_thread_->RunsTasksOnCurrentThread());
254 gcm_client_->Stop();
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()) {
285 if (clear_logs)
286 gcm_client_->ClearActivityLogs();
287 stats = gcm_client_->GetStatistics();
290 ui_thread_->PostTask(
291 FROM_HERE,
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(
306 FROM_HERE,
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;
346 if (wake)
347 timer.reset(new timers::AlarmTimer(true, false));
348 else
349 timer.reset(new base::Timer(true, false));
351 gcm_client_->UpdateHeartbeatTimer(timer.Pass());
352 #endif
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,
360 PrefService* prefs,
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,
368 prefs,
369 channel_status_request_url,
370 user_agent,
371 request_context)),
372 signed_in_(false),
373 gcm_started_(false),
374 gcm_enabled_(true),
375 connected_(false),
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
388 // GCM check-in.
389 io_worker_.reset(new IOWorker(ui_thread, io_thread));
390 io_thread_->PostTask(
391 FROM_HERE,
392 base::Bind(&GCMDriverDesktop::IOWorker::Initialize,
393 base::Unretained(io_worker_.get()),
394 base::Passed(&gcm_client_factory),
395 chrome_build_info,
396 store_path,
397 request_context,
398 blocking_task_runner));
401 GCMDriverDesktop::~GCMDriverDesktop() {
404 void GCMDriverDesktop::Shutdown() {
405 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
407 Stop();
408 GCMDriver::Shutdown();
410 // Dispose the syncer in order to release the reference to
411 // URLRequestContextGetter that needs to be done before IOThread gets
412 // deleted.
413 gcm_channel_status_syncer_.reset();
415 io_thread_->DeleteSoon(FROM_HERE, io_worker_.release());
418 void GCMDriverDesktop::OnSignedIn() {
419 signed_in_ = true;
422 void GCMDriverDesktop::OnSignedOut() {
423 signed_in_ = false;
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) {
442 Stop();
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());
459 if (gcm_enabled_)
460 return;
461 gcm_enabled_ = true;
463 EnsureStarted(GCMClient::DELAYED_START);
466 void GCMDriverDesktop::Disable() {
467 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
469 if (!gcm_enabled_)
470 return;
471 gcm_enabled_ = false;
473 Stop();
476 void GCMDriverDesktop::Stop() {
477 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
479 // No need to stop GCM service if not started yet.
480 if (!gcm_started_)
481 return;
483 account_mapper_->ShutdownHandler();
484 GCMDriver::RemoveAppHandler(kGCMAccountMapperAppId);
486 RemoveCachedData();
488 io_thread_->PostTask(
489 FROM_HERE,
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(),
501 app_id,
502 sender_ids));
503 return;
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.
514 return;
517 io_thread_->PostTask(
518 FROM_HERE,
519 base::Bind(&GCMDriverDesktop::IOWorker::Register,
520 base::Unretained(io_worker_.get()),
521 app_id,
522 sender_ids));
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(),
531 app_id));
532 return;
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(
545 FROM_HERE,
546 base::Bind(&GCMDriverDesktop::IOWorker::Unregister,
547 base::Unretained(io_worker_.get()),
548 app_id));
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(),
558 app_id,
559 receiver_id,
560 message));
561 return;
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(
572 FROM_HERE,
573 base::Bind(&GCMDriverDesktop::IOWorker::Send,
574 base::Unretained(io_worker_.get()),
575 app_id,
576 receiver_id,
577 message));
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());
587 return gcm_started_;
590 bool GCMDriverDesktop::IsConnected() const {
591 return connected_;
594 void GCMDriverDesktop::GetGCMStatistics(
595 const GetGCMStatisticsCallback& callback,
596 bool clear_logs) {
597 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
598 DCHECK(!callback.is_null());
600 request_gcm_statistics_callback_ = callback;
601 io_thread_->PostTask(
602 FROM_HERE,
603 base::Bind(&GCMDriverDesktop::IOWorker::GetGCMStatistics,
604 base::Unretained(io_worker_.get()),
605 clear_logs));
608 void GCMDriverDesktop::SetGCMRecording(const GetGCMStatisticsCallback& callback,
609 bool recording) {
610 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
612 request_gcm_statistics_callback_ = callback;
613 io_thread_->PostTask(
614 FROM_HERE,
615 base::Bind(&GCMDriverDesktop::IOWorker::SetGCMRecording,
616 base::Unretained(io_worker_.get()),
617 recording));
620 void GCMDriverDesktop::UpdateAccountMapping(
621 const AccountMapping& account_mapping) {
622 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
624 io_thread_->PostTask(
625 FROM_HERE,
626 base::Bind(&GCMDriverDesktop::IOWorker::UpdateAccountMapping,
627 base::Unretained(io_worker_.get()),
628 account_mapping));
631 void GCMDriverDesktop::RemoveAccountMapping(const std::string& account_id) {
632 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
634 io_thread_->PostTask(
635 FROM_HERE,
636 base::Bind(&GCMDriverDesktop::IOWorker::RemoveAccountMapping,
637 base::Unretained(io_worker_.get()),
638 account_id));
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(
651 FROM_HERE,
652 base::Bind(&GCMDriverDesktop::IOWorker::SetLastTokenFetchTime,
653 base::Unretained(io_worker_.get()),
654 time));
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_)
664 return;
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_));
672 return;
675 // The GCMClient is ready so we can go ahead and post this task to the
676 // IOWorker.
677 io_thread_->PostTask(
678 FROM_HERE,
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(
691 FROM_HERE,
692 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountTokens,
693 base::Unretained(io_worker_.get()),
694 account_tokens));
697 GCMClient::Result GCMDriverDesktop::EnsureStarted(
698 GCMClient::StartMode start_mode) {
699 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
701 if (gcm_started_)
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();
712 if (!gcm_enabled_)
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(
721 FROM_HERE,
722 base::Bind(&GCMDriverDesktop::IOWorker::Start,
723 base::Unretained(io_worker_.get()),
724 start_mode,
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();
738 ClearCallbacks();
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.
747 if (!gcm_started_)
748 return;
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.
757 if (!gcm_started_)
758 return;
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.
769 if (!gcm_started_)
770 return;
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.
780 if (!gcm_started_)
781 return;
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_);
793 gcm_started_ = true;
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());
810 connected_ = true;
812 // Drop the event if the service has been stopped.
813 if (!gcm_started_)
814 return;
816 FOR_EACH_OBSERVER(GCMConnectionObserver,
817 connection_observer_list_,
818 OnConnected(ip_endpoint));
821 void GCMDriverDesktop::OnDisconnected() {
822 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
824 connected_ = false;
826 // Drop the event if the service has been stopped.
827 if (!gcm_started_)
828 return;
830 FOR_EACH_OBSERVER(
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);
841 else
842 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL.";
845 } // namespace gcm