Update frame around SAML IdP pages to new GAIA style
[chromium-blink-merge.git] / components / gcm_driver / gcm_driver_desktop.cc
blob7db396d8fdb217cab702bc887bef59eeffdf4a10
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/profiler/scoped_tracker.h"
16 #include "base/sequenced_task_runner.h"
17 #include "base/threading/sequenced_worker_pool.h"
18 #include "components/gcm_driver/gcm_account_mapper.h"
19 #include "components/gcm_driver/gcm_app_handler.h"
20 #include "components/gcm_driver/gcm_channel_status_syncer.h"
21 #include "components/gcm_driver/gcm_client_factory.h"
22 #include "components/gcm_driver/gcm_delayed_task_controller.h"
23 #include "components/gcm_driver/system_encryptor.h"
24 #include "google_apis/gcm/engine/account_mapping.h"
25 #include "net/base/ip_endpoint.h"
26 #include "net/url_request/url_request_context_getter.h"
28 #if defined(OS_CHROMEOS)
29 #include "components/timers/alarm_timer_chromeos.h"
30 #endif
32 namespace gcm {
34 class GCMDriverDesktop::IOWorker : public GCMClient::Delegate {
35 public:
36 // Called on UI thread.
37 IOWorker(const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
38 const scoped_refptr<base::SequencedTaskRunner>& io_thread);
39 virtual ~IOWorker();
41 // Overridden from GCMClient::Delegate:
42 // Called on IO thread.
43 void OnRegisterFinished(const std::string& app_id,
44 const std::string& registration_id,
45 GCMClient::Result result) override;
46 void OnUnregisterFinished(const std::string& app_id,
47 GCMClient::Result result) override;
48 void OnSendFinished(const std::string& app_id,
49 const std::string& message_id,
50 GCMClient::Result result) override;
51 void OnMessageReceived(const std::string& app_id,
52 const GCMClient::IncomingMessage& message) override;
53 void OnMessagesDeleted(const std::string& app_id) override;
54 void OnMessageSendError(
55 const std::string& app_id,
56 const GCMClient::SendErrorDetails& send_error_details) override;
57 void OnSendAcknowledged(const std::string& app_id,
58 const std::string& message_id) override;
59 void OnGCMReady(const std::vector<AccountMapping>& account_mappings,
60 const base::Time& last_token_fetch_time) override;
61 void OnActivityRecorded() override;
62 void OnConnected(const net::IPEndPoint& ip_endpoint) override;
63 void OnDisconnected() override;
65 // Called on IO thread.
66 void Initialize(
67 scoped_ptr<GCMClientFactory> gcm_client_factory,
68 const GCMClient::ChromeBuildInfo& chrome_build_info,
69 const base::FilePath& store_path,
70 const scoped_refptr<net::URLRequestContextGetter>& request_context,
71 const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
72 void Start(GCMClient::StartMode start_mode,
73 const base::WeakPtr<GCMDriverDesktop>& service);
74 void Stop();
75 void Register(const std::string& app_id,
76 const std::vector<std::string>& sender_ids);
77 void Unregister(const std::string& app_id);
78 void Send(const std::string& app_id,
79 const std::string& receiver_id,
80 const GCMClient::OutgoingMessage& message);
81 void GetGCMStatistics(bool clear_logs);
82 void SetGCMRecording(bool recording);
84 void SetAccountTokens(
85 const std::vector<GCMClient::AccountTokenInfo>& account_tokens);
86 void UpdateAccountMapping(const AccountMapping& account_mapping);
87 void RemoveAccountMapping(const std::string& account_id);
88 void SetLastTokenFetchTime(const base::Time& time);
89 void WakeFromSuspendForHeartbeat(bool wake);
91 // For testing purpose. Can be called from UI thread. Use with care.
92 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
94 private:
95 scoped_refptr<base::SequencedTaskRunner> ui_thread_;
96 scoped_refptr<base::SequencedTaskRunner> io_thread_;
98 base::WeakPtr<GCMDriverDesktop> service_;
100 scoped_ptr<GCMClient> gcm_client_;
102 DISALLOW_COPY_AND_ASSIGN(IOWorker);
105 GCMDriverDesktop::IOWorker::IOWorker(
106 const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
107 const scoped_refptr<base::SequencedTaskRunner>& io_thread)
108 : ui_thread_(ui_thread),
109 io_thread_(io_thread) {
110 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
113 GCMDriverDesktop::IOWorker::~IOWorker() {
114 DCHECK(io_thread_->RunsTasksOnCurrentThread());
117 void GCMDriverDesktop::IOWorker::Initialize(
118 scoped_ptr<GCMClientFactory> gcm_client_factory,
119 const GCMClient::ChromeBuildInfo& chrome_build_info,
120 const base::FilePath& store_path,
121 const scoped_refptr<net::URLRequestContextGetter>& request_context,
122 const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
123 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
124 tracked_objects::ScopedTracker tracking_profile(
125 FROM_HERE_WITH_EXPLICIT_FUNCTION(
126 "477117 GCMDriverDesktop::IOWorker::Initialize"));
127 DCHECK(io_thread_->RunsTasksOnCurrentThread());
129 gcm_client_ = gcm_client_factory->BuildInstance();
131 gcm_client_->Initialize(chrome_build_info,
132 store_path,
133 blocking_task_runner,
134 request_context,
135 make_scoped_ptr<Encryptor>(new SystemEncryptor),
136 this);
139 void GCMDriverDesktop::IOWorker::OnRegisterFinished(
140 const std::string& app_id,
141 const std::string& registration_id,
142 GCMClient::Result result) {
143 DCHECK(io_thread_->RunsTasksOnCurrentThread());
145 ui_thread_->PostTask(
146 FROM_HERE,
147 base::Bind(&GCMDriverDesktop::RegisterFinished, service_, app_id,
148 registration_id, result));
151 void GCMDriverDesktop::IOWorker::OnUnregisterFinished(
152 const std::string& app_id,
153 GCMClient::Result result) {
154 DCHECK(io_thread_->RunsTasksOnCurrentThread());
156 ui_thread_->PostTask(FROM_HERE,
157 base::Bind(&GCMDriverDesktop::UnregisterFinished,
158 service_,
159 app_id,
160 result));
163 void GCMDriverDesktop::IOWorker::OnSendFinished(const std::string& app_id,
164 const std::string& message_id,
165 GCMClient::Result result) {
166 DCHECK(io_thread_->RunsTasksOnCurrentThread());
168 ui_thread_->PostTask(
169 FROM_HERE,
170 base::Bind(&GCMDriverDesktop::SendFinished, service_, app_id, message_id,
171 result));
174 void GCMDriverDesktop::IOWorker::OnMessageReceived(
175 const std::string& app_id,
176 const GCMClient::IncomingMessage& message) {
177 DCHECK(io_thread_->RunsTasksOnCurrentThread());
179 ui_thread_->PostTask(
180 FROM_HERE,
181 base::Bind(&GCMDriverDesktop::MessageReceived,
182 service_,
183 app_id,
184 message));
187 void GCMDriverDesktop::IOWorker::OnMessagesDeleted(const std::string& app_id) {
188 DCHECK(io_thread_->RunsTasksOnCurrentThread());
190 ui_thread_->PostTask(
191 FROM_HERE,
192 base::Bind(&GCMDriverDesktop::MessagesDeleted, service_, app_id));
195 void GCMDriverDesktop::IOWorker::OnMessageSendError(
196 const std::string& app_id,
197 const GCMClient::SendErrorDetails& send_error_details) {
198 DCHECK(io_thread_->RunsTasksOnCurrentThread());
200 ui_thread_->PostTask(
201 FROM_HERE,
202 base::Bind(&GCMDriverDesktop::MessageSendError, service_, app_id,
203 send_error_details));
206 void GCMDriverDesktop::IOWorker::OnSendAcknowledged(
207 const std::string& app_id,
208 const std::string& message_id) {
209 DCHECK(io_thread_->RunsTasksOnCurrentThread());
211 ui_thread_->PostTask(
212 FROM_HERE,
213 base::Bind(
214 &GCMDriverDesktop::SendAcknowledged, service_, app_id, message_id));
217 void GCMDriverDesktop::IOWorker::OnGCMReady(
218 const std::vector<AccountMapping>& account_mappings,
219 const base::Time& last_token_fetch_time) {
220 ui_thread_->PostTask(FROM_HERE,
221 base::Bind(&GCMDriverDesktop::GCMClientReady,
222 service_,
223 account_mappings,
224 last_token_fetch_time));
227 void GCMDriverDesktop::IOWorker::OnActivityRecorded() {
228 DCHECK(io_thread_->RunsTasksOnCurrentThread());
229 // When an activity is recorded, get all the stats and refresh the UI of
230 // gcm-internals page.
231 GetGCMStatistics(false);
234 void GCMDriverDesktop::IOWorker::OnConnected(
235 const net::IPEndPoint& ip_endpoint) {
236 ui_thread_->PostTask(FROM_HERE,
237 base::Bind(&GCMDriverDesktop::OnConnected,
238 service_,
239 ip_endpoint));
242 void GCMDriverDesktop::IOWorker::OnDisconnected() {
243 ui_thread_->PostTask(FROM_HERE,
244 base::Bind(&GCMDriverDesktop::OnDisconnected, service_));
247 void GCMDriverDesktop::IOWorker::Start(
248 GCMClient::StartMode start_mode,
249 const base::WeakPtr<GCMDriverDesktop>& service) {
250 DCHECK(io_thread_->RunsTasksOnCurrentThread());
252 service_ = service;
253 gcm_client_->Start(start_mode);
256 void GCMDriverDesktop::IOWorker::Stop() {
257 DCHECK(io_thread_->RunsTasksOnCurrentThread());
259 gcm_client_->Stop();
262 void GCMDriverDesktop::IOWorker::Register(
263 const std::string& app_id,
264 const std::vector<std::string>& sender_ids) {
265 DCHECK(io_thread_->RunsTasksOnCurrentThread());
267 gcm_client_->Register(app_id, sender_ids);
270 void GCMDriverDesktop::IOWorker::Unregister(const std::string& app_id) {
271 DCHECK(io_thread_->RunsTasksOnCurrentThread());
273 gcm_client_->Unregister(app_id);
276 void GCMDriverDesktop::IOWorker::Send(
277 const std::string& app_id,
278 const std::string& receiver_id,
279 const GCMClient::OutgoingMessage& message) {
280 DCHECK(io_thread_->RunsTasksOnCurrentThread());
282 gcm_client_->Send(app_id, receiver_id, message);
285 void GCMDriverDesktop::IOWorker::GetGCMStatistics(bool clear_logs) {
286 DCHECK(io_thread_->RunsTasksOnCurrentThread());
287 gcm::GCMClient::GCMStatistics stats;
289 if (gcm_client_.get()) {
290 if (clear_logs)
291 gcm_client_->ClearActivityLogs();
292 stats = gcm_client_->GetStatistics();
295 ui_thread_->PostTask(
296 FROM_HERE,
297 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished, service_, stats));
300 void GCMDriverDesktop::IOWorker::SetGCMRecording(bool recording) {
301 DCHECK(io_thread_->RunsTasksOnCurrentThread());
302 gcm::GCMClient::GCMStatistics stats;
304 if (gcm_client_.get()) {
305 gcm_client_->SetRecording(recording);
306 stats = gcm_client_->GetStatistics();
307 stats.gcm_client_created = true;
310 ui_thread_->PostTask(
311 FROM_HERE,
312 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished, service_, stats));
315 void GCMDriverDesktop::IOWorker::SetAccountTokens(
316 const std::vector<GCMClient::AccountTokenInfo>& account_tokens) {
317 DCHECK(io_thread_->RunsTasksOnCurrentThread());
319 if (gcm_client_.get())
320 gcm_client_->SetAccountTokens(account_tokens);
323 void GCMDriverDesktop::IOWorker::UpdateAccountMapping(
324 const AccountMapping& account_mapping) {
325 DCHECK(io_thread_->RunsTasksOnCurrentThread());
327 if (gcm_client_.get())
328 gcm_client_->UpdateAccountMapping(account_mapping);
331 void GCMDriverDesktop::IOWorker::RemoveAccountMapping(
332 const std::string& account_id) {
333 DCHECK(io_thread_->RunsTasksOnCurrentThread());
335 if (gcm_client_.get())
336 gcm_client_->RemoveAccountMapping(account_id);
339 void GCMDriverDesktop::IOWorker::SetLastTokenFetchTime(const base::Time& time) {
340 DCHECK(io_thread_->RunsTasksOnCurrentThread());
342 if (gcm_client_.get())
343 gcm_client_->SetLastTokenFetchTime(time);
346 void GCMDriverDesktop::IOWorker::WakeFromSuspendForHeartbeat(bool wake) {
347 #if defined(OS_CHROMEOS)
348 DCHECK(io_thread_->RunsTasksOnCurrentThread());
350 scoped_ptr<base::Timer> timer;
351 if (wake)
352 timer.reset(new timers::SimpleAlarmTimer());
353 else
354 timer.reset(new base::Timer(true, false));
356 gcm_client_->UpdateHeartbeatTimer(timer.Pass());
357 #endif
360 GCMDriverDesktop::GCMDriverDesktop(
361 scoped_ptr<GCMClientFactory> gcm_client_factory,
362 const GCMClient::ChromeBuildInfo& chrome_build_info,
363 const std::string& channel_status_request_url,
364 const std::string& user_agent,
365 PrefService* prefs,
366 const base::FilePath& store_path,
367 const scoped_refptr<net::URLRequestContextGetter>& request_context,
368 const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
369 const scoped_refptr<base::SequencedTaskRunner>& io_thread,
370 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner)
371 : gcm_channel_status_syncer_(
372 new GCMChannelStatusSyncer(this,
373 prefs,
374 channel_status_request_url,
375 user_agent,
376 request_context)),
377 signed_in_(false),
378 gcm_started_(false),
379 gcm_enabled_(true),
380 connected_(false),
381 account_mapper_(new GCMAccountMapper(this)),
382 // Setting to max, to make sure it does not prompt for token reporting
383 // Before reading a reasonable value from the DB, which might be never,
384 // in which case the fetching will be triggered.
385 last_token_fetch_time_(base::Time::Max()),
386 ui_thread_(ui_thread),
387 io_thread_(io_thread),
388 wake_from_suspend_enabled_(false),
389 weak_ptr_factory_(this) {
390 gcm_enabled_ = gcm_channel_status_syncer_->gcm_enabled();
392 // Create and initialize the GCMClient. Note that this does not initiate the
393 // GCM check-in.
394 io_worker_.reset(new IOWorker(ui_thread, io_thread));
395 io_thread_->PostTask(
396 FROM_HERE,
397 base::Bind(&GCMDriverDesktop::IOWorker::Initialize,
398 base::Unretained(io_worker_.get()),
399 base::Passed(&gcm_client_factory),
400 chrome_build_info,
401 store_path,
402 request_context,
403 blocking_task_runner));
406 GCMDriverDesktop::~GCMDriverDesktop() {
409 void GCMDriverDesktop::Shutdown() {
410 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
412 Stop();
413 GCMDriver::Shutdown();
415 // Dispose the syncer in order to release the reference to
416 // URLRequestContextGetter that needs to be done before IOThread gets
417 // deleted.
418 gcm_channel_status_syncer_.reset();
420 io_thread_->DeleteSoon(FROM_HERE, io_worker_.release());
423 void GCMDriverDesktop::OnSignedIn() {
424 signed_in_ = true;
427 void GCMDriverDesktop::OnSignedOut() {
428 signed_in_ = false;
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(GCMClient::DELAYED_START);
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(GCMClient::DELAYED_START);
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::WakeFromSuspendForHeartbeat(bool wake) {
663 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
665 wake_from_suspend_enabled_ = wake;
667 // The GCM service has not been initialized.
668 if (!delayed_task_controller_)
669 return;
671 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
672 // The GCM service was initialized but has not started yet.
673 delayed_task_controller_->AddTask(
674 base::Bind(&GCMDriverDesktop::WakeFromSuspendForHeartbeat,
675 weak_ptr_factory_.GetWeakPtr(),
676 wake_from_suspend_enabled_));
677 return;
680 // The GCMClient is ready so we can go ahead and post this task to the
681 // IOWorker.
682 io_thread_->PostTask(
683 FROM_HERE,
684 base::Bind(&GCMDriverDesktop::IOWorker::WakeFromSuspendForHeartbeat,
685 base::Unretained(io_worker_.get()),
686 wake_from_suspend_enabled_));
689 void GCMDriverDesktop::SetAccountTokens(
690 const std::vector<GCMClient::AccountTokenInfo>& account_tokens) {
691 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
693 account_mapper_->SetAccountTokens(account_tokens);
695 io_thread_->PostTask(
696 FROM_HERE,
697 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountTokens,
698 base::Unretained(io_worker_.get()),
699 account_tokens));
702 GCMClient::Result GCMDriverDesktop::EnsureStarted(
703 GCMClient::StartMode start_mode) {
704 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
706 if (gcm_started_)
707 return GCMClient::SUCCESS;
709 // Have any app requested the service?
710 if (app_handlers().empty())
711 return GCMClient::UNKNOWN_ERROR;
713 // Polling for channel status should be invoked when GCM is being requested,
714 // no matter whether GCM is enabled or nor.
715 gcm_channel_status_syncer_->EnsureStarted();
717 if (!gcm_enabled_)
718 return GCMClient::GCM_DISABLED;
720 if (!delayed_task_controller_)
721 delayed_task_controller_.reset(new GCMDelayedTaskController);
723 // Note that we need to pass weak pointer again since the existing weak
724 // pointer in IOWorker might have been invalidated when GCM is stopped.
725 io_thread_->PostTask(
726 FROM_HERE,
727 base::Bind(&GCMDriverDesktop::IOWorker::Start,
728 base::Unretained(io_worker_.get()),
729 start_mode,
730 weak_ptr_factory_.GetWeakPtr()));
732 return GCMClient::SUCCESS;
735 void GCMDriverDesktop::RemoveCachedData() {
736 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
737 // Remove all the queued tasks since they no longer make sense after
738 // GCM service is stopped.
739 weak_ptr_factory_.InvalidateWeakPtrs();
741 gcm_started_ = false;
742 delayed_task_controller_.reset();
743 ClearCallbacks();
746 void GCMDriverDesktop::MessageReceived(
747 const std::string& app_id,
748 const GCMClient::IncomingMessage& message) {
749 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
751 // Drop the event if the service has been stopped.
752 if (!gcm_started_)
753 return;
755 GetAppHandler(app_id)->OnMessage(app_id, message);
758 void GCMDriverDesktop::MessagesDeleted(const std::string& app_id) {
759 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
761 // Drop the event if the service has been stopped.
762 if (!gcm_started_)
763 return;
765 GetAppHandler(app_id)->OnMessagesDeleted(app_id);
768 void GCMDriverDesktop::MessageSendError(
769 const std::string& app_id,
770 const GCMClient::SendErrorDetails& send_error_details) {
771 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
773 // Drop the event if the service has been stopped.
774 if (!gcm_started_)
775 return;
777 GetAppHandler(app_id)->OnSendError(app_id, send_error_details);
780 void GCMDriverDesktop::SendAcknowledged(const std::string& app_id,
781 const std::string& message_id) {
782 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
784 // Drop the event if the service has been stopped.
785 if (!gcm_started_)
786 return;
788 GetAppHandler(app_id)->OnSendAcknowledged(app_id, message_id);
791 void GCMDriverDesktop::GCMClientReady(
792 const std::vector<AccountMapping>& account_mappings,
793 const base::Time& last_token_fetch_time) {
794 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
796 UMA_HISTOGRAM_BOOLEAN("GCM.UserSignedIn", signed_in_);
798 gcm_started_ = true;
799 if (wake_from_suspend_enabled_)
800 WakeFromSuspendForHeartbeat(wake_from_suspend_enabled_);
802 last_token_fetch_time_ = last_token_fetch_time;
804 GCMDriver::AddAppHandler(kGCMAccountMapperAppId, account_mapper_.get());
805 account_mapper_->Initialize(account_mappings,
806 base::Bind(&GCMDriverDesktop::MessageReceived,
807 weak_ptr_factory_.GetWeakPtr()));
809 delayed_task_controller_->SetReady();
812 void GCMDriverDesktop::OnConnected(const net::IPEndPoint& ip_endpoint) {
813 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
815 connected_ = true;
817 // Drop the event if the service has been stopped.
818 if (!gcm_started_)
819 return;
821 FOR_EACH_OBSERVER(GCMConnectionObserver,
822 connection_observer_list_,
823 OnConnected(ip_endpoint));
826 void GCMDriverDesktop::OnDisconnected() {
827 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
829 connected_ = false;
831 // Drop the event if the service has been stopped.
832 if (!gcm_started_)
833 return;
835 FOR_EACH_OBSERVER(
836 GCMConnectionObserver, connection_observer_list_, OnDisconnected());
839 void GCMDriverDesktop::GetGCMStatisticsFinished(
840 const GCMClient::GCMStatistics& stats) {
841 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
843 // Normally request_gcm_statistics_callback_ would not be null.
844 if (!request_gcm_statistics_callback_.is_null())
845 request_gcm_statistics_callback_.Run(stats);
846 else
847 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL.";
850 } // namespace gcm