Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / components / gcm_driver / gcm_driver_desktop.cc
blobb2ab93ae355226a065eeadfd477a0eef433ab262
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 namespace gcm {
29 class GCMDriverDesktop::IOWorker : public GCMClient::Delegate {
30 public:
31 // Called on UI thread.
32 IOWorker(const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
33 const scoped_refptr<base::SequencedTaskRunner>& io_thread);
34 virtual ~IOWorker();
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.
61 void Initialize(
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);
68 void Stop();
69 void CheckOut();
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(); }
88 private:
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,
122 store_path,
123 blocking_task_runner,
124 request_context,
125 make_scoped_ptr<Encryptor>(new SystemEncryptor),
126 this);
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(
136 FROM_HERE,
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,
148 service_,
149 app_id,
150 result));
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(
159 FROM_HERE,
160 base::Bind(&GCMDriverDesktop::SendFinished, service_, app_id, message_id,
161 result));
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(
170 FROM_HERE,
171 base::Bind(&GCMDriverDesktop::MessageReceived,
172 service_,
173 app_id,
174 message));
177 void GCMDriverDesktop::IOWorker::OnMessagesDeleted(const std::string& app_id) {
178 DCHECK(io_thread_->RunsTasksOnCurrentThread());
180 ui_thread_->PostTask(
181 FROM_HERE,
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(
191 FROM_HERE,
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(
202 FROM_HERE,
203 base::Bind(
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,
212 service_,
213 account_mappings,
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,
228 service_,
229 ip_endpoint));
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());
241 service_ = service;
242 gcm_client_->Start();
245 void GCMDriverDesktop::IOWorker::Stop() {
246 DCHECK(io_thread_->RunsTasksOnCurrentThread());
248 gcm_client_->Stop();
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()) {
288 if (clear_logs)
289 gcm_client_->ClearActivityLogs();
290 stats = gcm_client_->GetStatistics();
293 ui_thread_->PostTask(
294 FROM_HERE,
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(
309 FROM_HERE,
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,
349 PrefService* prefs,
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,
357 prefs,
358 channel_status_request_url,
359 user_agent,
360 request_context)),
361 signed_in_(false),
362 gcm_started_(false),
363 gcm_enabled_(true),
364 connected_(false),
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
376 // GCM check-in.
377 io_worker_.reset(new IOWorker(ui_thread, io_thread));
378 io_thread_->PostTask(
379 FROM_HERE,
380 base::Bind(&GCMDriverDesktop::IOWorker::Initialize,
381 base::Unretained(io_worker_.get()),
382 base::Passed(&gcm_client_factory),
383 chrome_build_info,
384 store_path,
385 request_context,
386 blocking_task_runner));
389 GCMDriverDesktop::~GCMDriverDesktop() {
392 void GCMDriverDesktop::Shutdown() {
393 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
395 Stop();
396 GCMDriver::Shutdown();
398 // Dispose the syncer in order to release the reference to
399 // URLRequestContextGetter that needs to be done before IOThread gets
400 // deleted.
401 gcm_channel_status_syncer_.reset();
403 io_thread_->DeleteSoon(FROM_HERE, io_worker_.release());
406 void GCMDriverDesktop::OnSignedIn() {
407 signed_in_ = true;
408 EnsureStarted();
411 void GCMDriverDesktop::OnSignedOut() {
412 signed_in_ = false;
414 // When sign-in enforcement is not dropped, we will stop the GCM connection
415 // when the user signs out.
416 if (!GCMDriver::IsAllowedForAllUsers()) {
417 Stop();
421 void GCMDriverDesktop::Purge() {
422 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
424 RemoveCachedData();
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.
437 EnsureStarted();
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) {
447 Stop();
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());
464 if (gcm_enabled_)
465 return;
466 gcm_enabled_ = true;
468 EnsureStarted();
471 void GCMDriverDesktop::Disable() {
472 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
474 if (!gcm_enabled_)
475 return;
476 gcm_enabled_ = false;
478 Stop();
481 void GCMDriverDesktop::Stop() {
482 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
484 // No need to stop GCM service if not started yet.
485 if (!gcm_started_)
486 return;
488 account_mapper_->ShutdownHandler();
489 GCMDriver::RemoveAppHandler(kGCMAccountMapperAppId);
491 RemoveCachedData();
493 io_thread_->PostTask(
494 FROM_HERE,
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(),
506 app_id,
507 sender_ids));
508 return;
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.
519 return;
522 io_thread_->PostTask(
523 FROM_HERE,
524 base::Bind(&GCMDriverDesktop::IOWorker::Register,
525 base::Unretained(io_worker_.get()),
526 app_id,
527 sender_ids));
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(),
536 app_id));
537 return;
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(
550 FROM_HERE,
551 base::Bind(&GCMDriverDesktop::IOWorker::Unregister,
552 base::Unretained(io_worker_.get()),
553 app_id));
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(),
563 app_id,
564 receiver_id,
565 message));
566 return;
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(
577 FROM_HERE,
578 base::Bind(&GCMDriverDesktop::IOWorker::Send,
579 base::Unretained(io_worker_.get()),
580 app_id,
581 receiver_id,
582 message));
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());
592 return gcm_started_;
595 bool GCMDriverDesktop::IsConnected() const {
596 return connected_;
599 void GCMDriverDesktop::GetGCMStatistics(
600 const GetGCMStatisticsCallback& callback,
601 bool clear_logs) {
602 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
603 DCHECK(!callback.is_null());
605 request_gcm_statistics_callback_ = callback;
606 io_thread_->PostTask(
607 FROM_HERE,
608 base::Bind(&GCMDriverDesktop::IOWorker::GetGCMStatistics,
609 base::Unretained(io_worker_.get()),
610 clear_logs));
613 void GCMDriverDesktop::SetGCMRecording(const GetGCMStatisticsCallback& callback,
614 bool recording) {
615 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
617 request_gcm_statistics_callback_ = callback;
618 io_thread_->PostTask(
619 FROM_HERE,
620 base::Bind(&GCMDriverDesktop::IOWorker::SetGCMRecording,
621 base::Unretained(io_worker_.get()),
622 recording));
625 void GCMDriverDesktop::UpdateAccountMapping(
626 const AccountMapping& account_mapping) {
627 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
629 io_thread_->PostTask(
630 FROM_HERE,
631 base::Bind(&GCMDriverDesktop::IOWorker::UpdateAccountMapping,
632 base::Unretained(io_worker_.get()),
633 account_mapping));
636 void GCMDriverDesktop::RemoveAccountMapping(const std::string& account_id) {
637 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
639 io_thread_->PostTask(
640 FROM_HERE,
641 base::Bind(&GCMDriverDesktop::IOWorker::RemoveAccountMapping,
642 base::Unretained(io_worker_.get()),
643 account_id));
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(
656 FROM_HERE,
657 base::Bind(&GCMDriverDesktop::IOWorker::SetLastTokenFetchTime,
658 base::Unretained(io_worker_.get()),
659 time));
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(
669 FROM_HERE,
670 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountTokens,
671 base::Unretained(io_worker_.get()),
672 account_tokens));
675 GCMClient::Result GCMDriverDesktop::EnsureStarted() {
676 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
678 if (gcm_started_)
679 return GCMClient::SUCCESS;
681 if (!gcm_enabled_) {
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
702 // users.
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(
711 FROM_HERE,
712 base::Bind(&GCMDriverDesktop::IOWorker::Start,
713 base::Unretained(io_worker_.get()),
714 weak_ptr_factory_.GetWeakPtr()));
716 gcm_started_ = true;
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();
728 ClearCallbacks();
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.
737 if (!gcm_started_)
738 return;
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.
747 if (!gcm_started_)
748 return;
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.
759 if (!gcm_started_)
760 return;
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.
770 if (!gcm_started_)
771 return;
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());
792 connected_ = true;
794 // Drop the event if the service has been stopped.
795 if (!gcm_started_)
796 return;
798 FOR_EACH_OBSERVER(GCMConnectionObserver,
799 connection_observer_list_,
800 OnConnected(ip_endpoint));
803 void GCMDriverDesktop::OnDisconnected() {
804 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
806 connected_ = false;
808 // Drop the event if the service has been stopped.
809 if (!gcm_started_)
810 return;
812 FOR_EACH_OBSERVER(
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);
823 else
824 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL.";
827 } // namespace gcm