Make sure webrtc::VideoSource is released when WebRtcVideoTrackAdapter is destroyed.
[chromium-blink-merge.git] / components / gcm_driver / gcm_driver.cc
blobe41972e944770856d073a93788f2713687cfca58
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.h"
7 #include <algorithm>
8 #include <utility>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/files/file_path.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/threading/sequenced_worker_pool.h"
17 #include "components/gcm_driver/gcm_app_handler.h"
18 #include "components/gcm_driver/gcm_client_factory.h"
19 #include "components/gcm_driver/system_encryptor.h"
20 #include "google_apis/gaia/oauth2_token_service.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 GCMDriver::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 GCMDriver::DelayedTaskController::DelayedTaskController() : ready_(false) {
55 GCMDriver::DelayedTaskController::~DelayedTaskController() {
58 void GCMDriver::DelayedTaskController::AddTask(const base::Closure& task) {
59 delayed_tasks_.push_back(task);
62 void GCMDriver::DelayedTaskController::SetReady() {
63 ready_ = true;
64 RunTasks();
67 bool GCMDriver::DelayedTaskController::CanRunTaskWithoutDelay() const {
68 return ready_;
71 void GCMDriver::DelayedTaskController::RunTasks() {
72 DCHECK(ready_);
74 for (size_t i = 0; i < delayed_tasks_.size(); ++i)
75 delayed_tasks_[i].Run();
76 delayed_tasks_.clear();
79 class GCMDriver::IOWorker : public GCMClient::Delegate {
80 public:
81 // Called on UI thread.
82 IOWorker(const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
83 const scoped_refptr<base::SequencedTaskRunner>& io_thread);
84 virtual ~IOWorker();
86 // Overridden from GCMClient::Delegate:
87 // Called on IO thread.
88 virtual void OnRegisterFinished(const std::string& app_id,
89 const std::string& registration_id,
90 GCMClient::Result result) OVERRIDE;
91 virtual void OnUnregisterFinished(const std::string& app_id,
92 GCMClient::Result result) OVERRIDE;
93 virtual void OnSendFinished(const std::string& app_id,
94 const std::string& message_id,
95 GCMClient::Result result) OVERRIDE;
96 virtual void OnMessageReceived(
97 const std::string& app_id,
98 const GCMClient::IncomingMessage& message) OVERRIDE;
99 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
100 virtual void OnMessageSendError(
101 const std::string& app_id,
102 const GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
103 virtual void OnGCMReady() OVERRIDE;
104 virtual void OnActivityRecorded() OVERRIDE;
106 // Called on IO thread.
107 void Initialize(
108 scoped_ptr<GCMClientFactory> gcm_client_factory,
109 const GCMClient::ChromeBuildInfo& chrome_build_info,
110 const base::FilePath& store_path,
111 const std::vector<std::string>& account_ids,
112 const scoped_refptr<net::URLRequestContextGetter>& request_context,
113 const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
114 void Start(const base::WeakPtr<GCMDriver>& service);
115 void Stop();
116 void CheckOut();
117 void Register(const std::string& app_id,
118 const std::vector<std::string>& sender_ids);
119 void Unregister(const std::string& app_id);
120 void Send(const std::string& app_id,
121 const std::string& receiver_id,
122 const GCMClient::OutgoingMessage& message);
123 void GetGCMStatistics(bool clear_logs);
124 void SetGCMRecording(bool recording);
126 // For testing purpose. Can be called from UI thread. Use with care.
127 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
129 private:
130 scoped_refptr<base::SequencedTaskRunner> ui_thread_;
131 scoped_refptr<base::SequencedTaskRunner> io_thread_;
133 base::WeakPtr<GCMDriver> service_;
135 scoped_ptr<GCMClient> gcm_client_;
137 DISALLOW_COPY_AND_ASSIGN(IOWorker);
140 GCMDriver::IOWorker::IOWorker(
141 const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
142 const scoped_refptr<base::SequencedTaskRunner>& io_thread)
143 : ui_thread_(ui_thread),
144 io_thread_(io_thread) {
145 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
148 GCMDriver::IOWorker::~IOWorker() {
149 DCHECK(io_thread_->RunsTasksOnCurrentThread());
152 void GCMDriver::IOWorker::Initialize(
153 scoped_ptr<GCMClientFactory> gcm_client_factory,
154 const GCMClient::ChromeBuildInfo& chrome_build_info,
155 const base::FilePath& store_path,
156 const std::vector<std::string>& account_ids,
157 const scoped_refptr<net::URLRequestContextGetter>& request_context,
158 const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
159 DCHECK(io_thread_->RunsTasksOnCurrentThread());
161 gcm_client_ = gcm_client_factory->BuildInstance();
163 gcm_client_->Initialize(chrome_build_info,
164 store_path,
165 account_ids,
166 blocking_task_runner,
167 request_context,
168 make_scoped_ptr<Encryptor>(new SystemEncryptor),
169 this);
172 void GCMDriver::IOWorker::OnRegisterFinished(
173 const std::string& app_id,
174 const std::string& registration_id,
175 GCMClient::Result result) {
176 DCHECK(io_thread_->RunsTasksOnCurrentThread());
178 ui_thread_->PostTask(
179 FROM_HERE,
180 base::Bind(&GCMDriver::RegisterFinished, service_, app_id,
181 registration_id, result));
184 void GCMDriver::IOWorker::OnUnregisterFinished(const std::string& app_id,
185 GCMClient::Result result) {
186 DCHECK(io_thread_->RunsTasksOnCurrentThread());
188 ui_thread_->PostTask(
189 FROM_HERE,
190 base::Bind(&GCMDriver::UnregisterFinished, service_, app_id, result));
193 void GCMDriver::IOWorker::OnSendFinished(const std::string& app_id,
194 const std::string& message_id,
195 GCMClient::Result result) {
196 DCHECK(io_thread_->RunsTasksOnCurrentThread());
198 ui_thread_->PostTask(
199 FROM_HERE,
200 base::Bind(&GCMDriver::SendFinished, service_, app_id, message_id,
201 result));
204 void GCMDriver::IOWorker::OnMessageReceived(
205 const std::string& app_id,
206 const GCMClient::IncomingMessage& message) {
207 DCHECK(io_thread_->RunsTasksOnCurrentThread());
209 ui_thread_->PostTask(
210 FROM_HERE,
211 base::Bind(&GCMDriver::MessageReceived, service_, app_id, message));
214 void GCMDriver::IOWorker::OnMessagesDeleted(const std::string& app_id) {
215 DCHECK(io_thread_->RunsTasksOnCurrentThread());
217 ui_thread_->PostTask(
218 FROM_HERE,
219 base::Bind(&GCMDriver::MessagesDeleted, service_, app_id));
222 void GCMDriver::IOWorker::OnMessageSendError(
223 const std::string& app_id,
224 const GCMClient::SendErrorDetails& send_error_details) {
225 DCHECK(io_thread_->RunsTasksOnCurrentThread());
227 ui_thread_->PostTask(
228 FROM_HERE,
229 base::Bind(&GCMDriver::MessageSendError, service_, app_id,
230 send_error_details));
233 void GCMDriver::IOWorker::OnGCMReady() {
234 ui_thread_->PostTask(
235 FROM_HERE,
236 base::Bind(&GCMDriver::GCMClientReady, service_));
239 void GCMDriver::IOWorker::OnActivityRecorded() {
240 DCHECK(io_thread_->RunsTasksOnCurrentThread());
241 // When an activity is recorded, get all the stats and refresh the UI of
242 // gcm-internals page.
243 GetGCMStatistics(false);
246 void GCMDriver::IOWorker::Start(const base::WeakPtr<GCMDriver>& service) {
247 DCHECK(io_thread_->RunsTasksOnCurrentThread());
249 service_ = service;
250 gcm_client_->Start();
253 void GCMDriver::IOWorker::Stop() {
254 DCHECK(io_thread_->RunsTasksOnCurrentThread());
256 gcm_client_->Stop();
259 void GCMDriver::IOWorker::CheckOut() {
260 DCHECK(io_thread_->RunsTasksOnCurrentThread());
262 gcm_client_->CheckOut();
264 // Note that we still need to keep GCMClient instance alive since the
265 // GCMDriver may check in again.
268 void GCMDriver::IOWorker::Register(
269 const std::string& app_id,
270 const std::vector<std::string>& sender_ids) {
271 DCHECK(io_thread_->RunsTasksOnCurrentThread());
273 gcm_client_->Register(app_id, sender_ids);
276 void GCMDriver::IOWorker::Unregister(const std::string& app_id) {
277 DCHECK(io_thread_->RunsTasksOnCurrentThread());
279 gcm_client_->Unregister(app_id);
282 void GCMDriver::IOWorker::Send(const std::string& app_id,
283 const std::string& receiver_id,
284 const GCMClient::OutgoingMessage& message) {
285 DCHECK(io_thread_->RunsTasksOnCurrentThread());
287 gcm_client_->Send(app_id, receiver_id, message);
290 void GCMDriver::IOWorker::GetGCMStatistics(bool clear_logs) {
291 DCHECK(io_thread_->RunsTasksOnCurrentThread());
292 gcm::GCMClient::GCMStatistics stats;
294 if (gcm_client_.get()) {
295 if (clear_logs)
296 gcm_client_->ClearActivityLogs();
297 stats = gcm_client_->GetStatistics();
300 ui_thread_->PostTask(
301 FROM_HERE,
302 base::Bind(&GCMDriver::GetGCMStatisticsFinished, service_, stats));
305 void GCMDriver::IOWorker::SetGCMRecording(bool recording) {
306 DCHECK(io_thread_->RunsTasksOnCurrentThread());
307 gcm::GCMClient::GCMStatistics stats;
309 if (gcm_client_.get()) {
310 gcm_client_->SetRecording(recording);
311 stats = gcm_client_->GetStatistics();
312 stats.gcm_client_created = true;
315 ui_thread_->PostTask(
316 FROM_HERE,
317 base::Bind(&GCMDriver::GetGCMStatisticsFinished, service_, stats));
320 GCMDriver::GCMDriver(
321 scoped_ptr<GCMClientFactory> gcm_client_factory,
322 scoped_ptr<IdentityProvider> identity_provider,
323 const GCMClient::ChromeBuildInfo& chrome_build_info,
324 const base::FilePath& store_path,
325 const scoped_refptr<net::URLRequestContextGetter>& request_context,
326 const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
327 const scoped_refptr<base::SequencedTaskRunner>& io_thread,
328 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner)
329 : gcm_enabled_(true),
330 gcm_client_ready_(false),
331 identity_provider_(identity_provider.Pass()),
332 ui_thread_(ui_thread),
333 io_thread_(io_thread),
334 weak_ptr_factory_(this) {
335 // Get the list of available accounts.
336 std::vector<std::string> account_ids;
337 #if !defined(OS_ANDROID)
338 account_ids = identity_provider_->GetTokenService()->GetAccounts();
339 #endif
341 // Create and initialize the GCMClient. Note that this does not initiate the
342 // GCM check-in.
343 io_worker_.reset(new IOWorker(ui_thread, io_thread));
344 io_thread_->PostTask(
345 FROM_HERE,
346 base::Bind(&GCMDriver::IOWorker::Initialize,
347 base::Unretained(io_worker_.get()),
348 base::Passed(&gcm_client_factory),
349 chrome_build_info,
350 store_path,
351 account_ids,
352 request_context,
353 blocking_task_runner));
355 identity_provider_->AddObserver(this);
358 GCMDriver::GCMDriver()
359 : gcm_enabled_(true),
360 gcm_client_ready_(false),
361 weak_ptr_factory_(this) {
364 GCMDriver::~GCMDriver() {
367 void GCMDriver::Enable() {
368 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
370 if (gcm_enabled_)
371 return;
372 gcm_enabled_ = true;
374 EnsureStarted();
377 void GCMDriver::Disable() {
378 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
380 if (!gcm_enabled_)
381 return;
382 gcm_enabled_ = false;
384 Stop();
387 void GCMDriver::Stop() {
388 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
390 // No need to stop GCM service if not started yet.
391 if (account_id_.empty())
392 return;
394 RemoveCachedData();
396 io_thread_->PostTask(
397 FROM_HERE,
398 base::Bind(&GCMDriver::IOWorker::Stop,
399 base::Unretained(io_worker_.get())));
402 void GCMDriver::Shutdown() {
403 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
404 identity_provider_->RemoveObserver(this);
405 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
406 iter != app_handlers_.end(); ++iter) {
407 iter->second->ShutdownHandler();
409 app_handlers_.clear();
410 io_thread_->DeleteSoon(FROM_HERE, io_worker_.release());
413 void GCMDriver::AddAppHandler(const std::string& app_id,
414 GCMAppHandler* handler) {
415 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
416 DCHECK(!app_id.empty());
417 DCHECK(handler);
418 DCHECK(app_handlers_.find(app_id) == app_handlers_.end());
420 app_handlers_[app_id] = handler;
422 // Ensures that the GCM service is started when there is an interest.
423 EnsureStarted();
426 void GCMDriver::RemoveAppHandler(const std::string& app_id) {
427 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
428 DCHECK(!app_id.empty());
430 app_handlers_.erase(app_id);
432 // Stops the GCM service when no app intends to consume it.
433 if (app_handlers_.empty())
434 Stop();
437 void GCMDriver::Register(const std::string& app_id,
438 const std::vector<std::string>& sender_ids,
439 const RegisterCallback& callback) {
440 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
441 DCHECK(!app_id.empty());
442 DCHECK(!sender_ids.empty());
443 DCHECK(!callback.is_null());
445 GCMClient::Result result = EnsureStarted();
446 if (result != GCMClient::SUCCESS) {
447 callback.Run(std::string(), result);
448 return;
451 // If previous un/register operation is still in progress, bail out.
452 if (IsAsyncOperationPending(app_id)) {
453 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
454 return;
457 register_callbacks_[app_id] = callback;
459 // Delay the register operation until GCMClient is ready.
460 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
461 delayed_task_controller_->AddTask(base::Bind(&GCMDriver::DoRegister,
462 weak_ptr_factory_.GetWeakPtr(),
463 app_id,
464 sender_ids));
465 return;
468 DoRegister(app_id, sender_ids);
471 void GCMDriver::DoRegister(const std::string& app_id,
472 const std::vector<std::string>& sender_ids) {
473 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
474 std::map<std::string, RegisterCallback>::iterator callback_iter =
475 register_callbacks_.find(app_id);
476 if (callback_iter == register_callbacks_.end()) {
477 // The callback could have been removed when the app is uninstalled.
478 return;
481 // Normalize the sender IDs by making them sorted.
482 std::vector<std::string> normalized_sender_ids = sender_ids;
483 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
485 io_thread_->PostTask(
486 FROM_HERE,
487 base::Bind(&GCMDriver::IOWorker::Register,
488 base::Unretained(io_worker_.get()),
489 app_id,
490 normalized_sender_ids));
493 void GCMDriver::Unregister(const std::string& app_id,
494 const UnregisterCallback& callback) {
495 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
496 DCHECK(!app_id.empty());
497 DCHECK(!callback.is_null());
499 GCMClient::Result result = EnsureStarted();
500 if (result != GCMClient::SUCCESS) {
501 callback.Run(result);
502 return;
505 // If previous un/register operation is still in progress, bail out.
506 if (IsAsyncOperationPending(app_id)) {
507 callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
508 return;
511 unregister_callbacks_[app_id] = callback;
513 // Delay the unregister operation until GCMClient is ready.
514 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
515 delayed_task_controller_->AddTask(base::Bind(&GCMDriver::DoUnregister,
516 weak_ptr_factory_.GetWeakPtr(),
517 app_id));
518 return;
521 DoUnregister(app_id);
524 void GCMDriver::DoUnregister(const std::string& app_id) {
525 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
527 // Ask the server to unregister it. There could be a small chance that the
528 // unregister request fails. If this occurs, it does not bring any harm since
529 // we simply reject the messages/events received from the server.
530 io_thread_->PostTask(
531 FROM_HERE,
532 base::Bind(&GCMDriver::IOWorker::Unregister,
533 base::Unretained(io_worker_.get()),
534 app_id));
537 void GCMDriver::Send(const std::string& app_id,
538 const std::string& receiver_id,
539 const GCMClient::OutgoingMessage& message,
540 const SendCallback& callback) {
541 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
542 DCHECK(!app_id.empty());
543 DCHECK(!receiver_id.empty());
544 DCHECK(!callback.is_null());
546 GCMClient::Result result = EnsureStarted();
547 if (result != GCMClient::SUCCESS) {
548 callback.Run(std::string(), result);
549 return;
552 // If the message with send ID is still in progress, bail out.
553 std::pair<std::string, std::string> key(app_id, message.id);
554 if (send_callbacks_.find(key) != send_callbacks_.end()) {
555 callback.Run(message.id, GCMClient::INVALID_PARAMETER);
556 return;
559 send_callbacks_[key] = callback;
561 // Delay the send operation until all GCMClient is ready.
562 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
563 delayed_task_controller_->AddTask(base::Bind(&GCMDriver::DoSend,
564 weak_ptr_factory_.GetWeakPtr(),
565 app_id,
566 receiver_id,
567 message));
568 return;
571 DoSend(app_id, receiver_id, message);
574 void GCMDriver::DoSend(const std::string& app_id,
575 const std::string& receiver_id,
576 const GCMClient::OutgoingMessage& message) {
577 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
578 io_thread_->PostTask(
579 FROM_HERE,
580 base::Bind(&GCMDriver::IOWorker::Send,
581 base::Unretained(io_worker_.get()),
582 app_id,
583 receiver_id,
584 message));
587 GCMClient* GCMDriver::GetGCMClientForTesting() const {
588 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
589 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL;
592 bool GCMDriver::IsStarted() const {
593 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
594 return !account_id_.empty();
597 bool GCMDriver::IsGCMClientReady() const {
598 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
599 return gcm_client_ready_;
602 void GCMDriver::GetGCMStatistics(const GetGCMStatisticsCallback& callback,
603 bool clear_logs) {
604 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
605 DCHECK(!callback.is_null());
607 request_gcm_statistics_callback_ = callback;
608 io_thread_->PostTask(
609 FROM_HERE,
610 base::Bind(&GCMDriver::IOWorker::GetGCMStatistics,
611 base::Unretained(io_worker_.get()),
612 clear_logs));
615 void GCMDriver::SetGCMRecording(const GetGCMStatisticsCallback& callback,
616 bool recording) {
617 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
619 request_gcm_statistics_callback_ = callback;
620 io_thread_->PostTask(
621 FROM_HERE,
622 base::Bind(&GCMDriver::IOWorker::SetGCMRecording,
623 base::Unretained(io_worker_.get()),
624 recording));
627 void GCMDriver::OnActiveAccountLogin() {
628 EnsureStarted();
631 void GCMDriver::OnActiveAccountLogout() {
632 CheckOut();
635 GCMClient::Result GCMDriver::EnsureStarted() {
636 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
638 if (!gcm_enabled_)
639 return GCMClient::GCM_DISABLED;
641 // Have any app requested the service?
642 if (app_handlers_.empty())
643 return GCMClient::UNKNOWN_ERROR;
645 // Is the user signed in?
646 const std::string account_id = identity_provider_->GetActiveAccountId();
647 if (account_id.empty())
648 return GCMClient::NOT_SIGNED_IN;
650 // CheckIn could be called more than once when:
651 // 1) The password changes.
652 // 2) Register/send function calls it to ensure CheckIn is done.
653 if (account_id_ == account_id)
654 return GCMClient::SUCCESS;
655 account_id_ = account_id;
657 DCHECK(!delayed_task_controller_);
658 delayed_task_controller_.reset(new DelayedTaskController);
660 // Note that we need to pass weak pointer again since the existing weak
661 // pointer in IOWorker might have been invalidated when check-out occurs.
662 io_thread_->PostTask(
663 FROM_HERE,
664 base::Bind(&GCMDriver::IOWorker::Start,
665 base::Unretained(io_worker_.get()),
666 weak_ptr_factory_.GetWeakPtr()));
668 return GCMClient::SUCCESS;
671 void GCMDriver::RemoveCachedData() {
672 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
673 // Remove all the queued tasks since they no longer make sense after
674 // GCM service is stopped.
675 weak_ptr_factory_.InvalidateWeakPtrs();
677 account_id_.clear();
678 gcm_client_ready_ = false;
679 delayed_task_controller_.reset();
680 register_callbacks_.clear();
681 send_callbacks_.clear();
684 void GCMDriver::CheckOut() {
685 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
687 // We still proceed with the check-out logic even if the check-in is not
688 // initiated in the current session. This will make sure that all the
689 // persisted data written previously will get purged.
691 RemoveCachedData();
693 io_thread_->PostTask(
694 FROM_HERE,
695 base::Bind(&GCMDriver::IOWorker::CheckOut,
696 base::Unretained(io_worker_.get())));
699 bool GCMDriver::IsAsyncOperationPending(const std::string& app_id) const {
700 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
701 return register_callbacks_.find(app_id) != register_callbacks_.end() ||
702 unregister_callbacks_.find(app_id) != unregister_callbacks_.end();
705 void GCMDriver::RegisterFinished(const std::string& app_id,
706 const std::string& registration_id,
707 GCMClient::Result result) {
708 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
710 std::map<std::string, RegisterCallback>::iterator callback_iter =
711 register_callbacks_.find(app_id);
712 if (callback_iter == register_callbacks_.end()) {
713 // The callback could have been removed when the app is uninstalled.
714 return;
717 RegisterCallback callback = callback_iter->second;
718 register_callbacks_.erase(callback_iter);
719 callback.Run(registration_id, result);
722 void GCMDriver::UnregisterFinished(const std::string& app_id,
723 GCMClient::Result result) {
724 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
726 std::map<std::string, UnregisterCallback>::iterator callback_iter =
727 unregister_callbacks_.find(app_id);
728 if (callback_iter == unregister_callbacks_.end())
729 return;
731 UnregisterCallback callback = callback_iter->second;
732 unregister_callbacks_.erase(callback_iter);
733 callback.Run(result);
736 void GCMDriver::SendFinished(const std::string& app_id,
737 const std::string& message_id,
738 GCMClient::Result result) {
739 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
741 std::map<std::pair<std::string, std::string>, SendCallback>::iterator
742 callback_iter = send_callbacks_.find(
743 std::pair<std::string, std::string>(app_id, message_id));
744 if (callback_iter == send_callbacks_.end()) {
745 // The callback could have been removed when the app is uninstalled.
746 return;
749 SendCallback callback = callback_iter->second;
750 send_callbacks_.erase(callback_iter);
751 callback.Run(message_id, result);
754 void GCMDriver::MessageReceived(const std::string& app_id,
755 GCMClient::IncomingMessage message) {
756 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
758 // Drop the event if signed out.
759 if (account_id_.empty())
760 return;
762 GetAppHandler(app_id)->OnMessage(app_id, message);
765 void GCMDriver::MessagesDeleted(const std::string& app_id) {
766 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
768 // Drop the event if signed out.
769 if (account_id_.empty())
770 return;
772 GetAppHandler(app_id)->OnMessagesDeleted(app_id);
775 void GCMDriver::MessageSendError(
776 const std::string& app_id,
777 const GCMClient::SendErrorDetails& send_error_details) {
778 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
780 // Drop the event if signed out.
781 if (account_id_.empty())
782 return;
784 GetAppHandler(app_id)->OnSendError(app_id, send_error_details);
787 void GCMDriver::GCMClientReady() {
788 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
790 if (gcm_client_ready_)
791 return;
792 gcm_client_ready_ = true;
794 delayed_task_controller_->SetReady();
797 GCMAppHandler* GCMDriver::GetAppHandler(const std::string& app_id) {
798 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
800 std::map<std::string, GCMAppHandler*>::const_iterator iter =
801 app_handlers_.find(app_id);
802 return iter == app_handlers_.end() ? &default_app_handler_ : iter->second;
805 void GCMDriver::GetGCMStatisticsFinished(GCMClient::GCMStatistics stats) {
806 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
808 // Normally request_gcm_statistics_callback_ would not be null.
809 if (!request_gcm_statistics_callback_.is_null())
810 request_gcm_statistics_callback_.Run(stats);
811 else
812 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL.";
815 std::string GCMDriver::SignedInUserName() const {
816 if (IsStarted())
817 return identity_provider_->GetActiveUsername();
818 return std::string();
821 } // namespace gcm