gcm_driver_desktop.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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. 4 5#include "components/gcm_driver/gcm_driver_desktop.h" 6 7#include <utility> 8 9#include "base/bind.h" 10#include "base/bind_helpers.h" 11#include "base/files/file_path.h" 12#include "base/location.h" 13#include "base/logging.h" 14#include "base/sequenced_task_runner.h" 15#include "base/threading/sequenced_worker_pool.h" 16#include "components/gcm_driver/gcm_app_handler.h" 17#include "components/gcm_driver/gcm_client_factory.h" 18#include "components/gcm_driver/system_encryptor.h" 19#include "net/base/ip_endpoint.h" 20#include "net/url_request/url_request_context_getter.h" 21 22namespace gcm { 23 24namespace { 25 26// Empty string is reserved for the default app handler. 27const char kDefaultAppHandler[] = ""; 28 29} // namespace 30 31// Helper class to save tasks to run until we're ready to execute them. 32class GCMDriverDesktop::DelayedTaskController { 33 public: 34 DelayedTaskController(); 35 ~DelayedTaskController(); 36 37 // Adds a task that will be invoked once we're ready. 38 void AddTask(const base::Closure& task); 39 40 // Sets ready status. It is ready only when check-in is completed and 41 // the GCMClient is fully initialized. 42 void SetReady(); 43 44 // Returns true if it is ready to perform tasks. 45 bool CanRunTaskWithoutDelay() const; 46 47 private: 48 void RunTasks(); 49 50 // Flag that indicates that GCM is ready. 51 bool ready_; 52 53 std::vector<base::Closure> delayed_tasks_; 54 55 DISALLOW_COPY_AND_ASSIGN(DelayedTaskController); 56}; 57 58GCMDriverDesktop::DelayedTaskController::DelayedTaskController() 59 : ready_(false) { 60} 61 62GCMDriverDesktop::DelayedTaskController::~DelayedTaskController() { 63} 64 65void GCMDriverDesktop::DelayedTaskController::AddTask( 66 const base::Closure& task) { 67 delayed_tasks_.push_back(task); 68} 69 70void GCMDriverDesktop::DelayedTaskController::SetReady() { 71 ready_ = true; 72 RunTasks(); 73} 74 75bool GCMDriverDesktop::DelayedTaskController::CanRunTaskWithoutDelay() const { 76 return ready_; 77} 78 79void GCMDriverDesktop::DelayedTaskController::RunTasks() { 80 DCHECK(ready_); 81 82 for (size_t i = 0; i < delayed_tasks_.size(); ++i) 83 delayed_tasks_[i].Run(); 84 delayed_tasks_.clear(); 85} 86 87class GCMDriverDesktop::IOWorker : public GCMClient::Delegate { 88 public: 89 // Called on UI thread. 90 IOWorker(const scoped_refptr<base::SequencedTaskRunner>& ui_thread, 91 const scoped_refptr<base::SequencedTaskRunner>& io_thread); 92 virtual ~IOWorker(); 93 94 // Overridden from GCMClient::Delegate: 95 // Called on IO thread. 96 virtual void OnRegisterFinished(const std::string& app_id, 97 const std::string& registration_id, 98 GCMClient::Result result) OVERRIDE; 99 virtual void OnUnregisterFinished(const std::string& app_id, 100 GCMClient::Result result) OVERRIDE; 101 virtual void OnSendFinished(const std::string& app_id, 102 const std::string& message_id, 103 GCMClient::Result result) OVERRIDE; 104 virtual void OnMessageReceived( 105 const std::string& app_id, 106 const GCMClient::IncomingMessage& message) OVERRIDE; 107 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE; 108 virtual void OnMessageSendError( 109 const std::string& app_id, 110 const GCMClient::SendErrorDetails& send_error_details) OVERRIDE; 111 virtual void OnGCMReady() OVERRIDE; 112 virtual void OnActivityRecorded() OVERRIDE; 113 virtual void OnConnected(const net::IPEndPoint& ip_endpoint) OVERRIDE; 114 virtual void OnDisconnected() OVERRIDE; 115 116 // Called on IO thread. 117 void 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 void Start(const base::WeakPtr<GCMDriverDesktop>& service); 124 void Stop(); 125 void CheckOut(); 126 void Register(const std::string& app_id, 127 const std::vector<std::string>& sender_ids); 128 void Unregister(const std::string& app_id); 129 void Send(const std::string& app_id, 130 const std::string& receiver_id, 131 const GCMClient::OutgoingMessage& message); 132 void GetGCMStatistics(bool clear_logs); 133 void SetGCMRecording(bool recording); 134 135 void SetAccountsForCheckin( 136 const std::map<std::string, std::string>& account_tokens); 137 138 // For testing purpose. Can be called from UI thread. Use with care. 139 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); } 140 141 private: 142 scoped_refptr<base::SequencedTaskRunner> ui_thread_; 143 scoped_refptr<base::SequencedTaskRunner> io_thread_; 144 145 base::WeakPtr<GCMDriverDesktop> service_; 146 147 scoped_ptr<GCMClient> gcm_client_; 148 149 DISALLOW_COPY_AND_ASSIGN(IOWorker); 150}; 151 152GCMDriverDesktop::IOWorker::IOWorker( 153 const scoped_refptr<base::SequencedTaskRunner>& ui_thread, 154 const scoped_refptr<base::SequencedTaskRunner>& io_thread) 155 : ui_thread_(ui_thread), 156 io_thread_(io_thread) { 157 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 158} 159 160GCMDriverDesktop::IOWorker::~IOWorker() { 161 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 162} 163 164void GCMDriverDesktop::IOWorker::Initialize( 165 scoped_ptr<GCMClientFactory> gcm_client_factory, 166 const GCMClient::ChromeBuildInfo& chrome_build_info, 167 const base::FilePath& store_path, 168 const scoped_refptr<net::URLRequestContextGetter>& request_context, 169 const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { 170 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 171 172 gcm_client_ = gcm_client_factory->BuildInstance(); 173 174 gcm_client_->Initialize(chrome_build_info, 175 store_path, 176 blocking_task_runner, 177 request_context, 178 make_scoped_ptr<Encryptor>(new SystemEncryptor), 179 this); 180} 181 182void GCMDriverDesktop::IOWorker::OnRegisterFinished( 183 const std::string& app_id, 184 const std::string& registration_id, 185 GCMClient::Result result) { 186 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 187 188 ui_thread_->PostTask( 189 FROM_HERE, 190 base::Bind(&GCMDriverDesktop::RegisterFinished, service_, app_id, 191 registration_id, result)); 192} 193 194void GCMDriverDesktop::IOWorker::OnUnregisterFinished( 195 const std::string& app_id, 196 GCMClient::Result result) { 197 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 198 199 ui_thread_->PostTask(FROM_HERE, 200 base::Bind(&GCMDriverDesktop::UnregisterFinished, 201 service_, 202 app_id, 203 result)); 204} 205 206void GCMDriverDesktop::IOWorker::OnSendFinished(const std::string& app_id, 207 const std::string& message_id, 208 GCMClient::Result result) { 209 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 210 211 ui_thread_->PostTask( 212 FROM_HERE, 213 base::Bind(&GCMDriverDesktop::SendFinished, service_, app_id, message_id, 214 result)); 215} 216 217void GCMDriverDesktop::IOWorker::OnMessageReceived( 218 const std::string& app_id, 219 const GCMClient::IncomingMessage& message) { 220 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 221 222 ui_thread_->PostTask( 223 FROM_HERE, 224 base::Bind(&GCMDriverDesktop::MessageReceived, 225 service_, 226 app_id, 227 message)); 228} 229 230void GCMDriverDesktop::IOWorker::OnMessagesDeleted(const std::string& app_id) { 231 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 232 233 ui_thread_->PostTask( 234 FROM_HERE, 235 base::Bind(&GCMDriverDesktop::MessagesDeleted, service_, app_id)); 236} 237 238void GCMDriverDesktop::IOWorker::OnMessageSendError( 239 const std::string& app_id, 240 const GCMClient::SendErrorDetails& send_error_details) { 241 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 242 243 ui_thread_->PostTask( 244 FROM_HERE, 245 base::Bind(&GCMDriverDesktop::MessageSendError, service_, app_id, 246 send_error_details)); 247} 248 249void GCMDriverDesktop::IOWorker::OnGCMReady() { 250 ui_thread_->PostTask( 251 FROM_HERE, 252 base::Bind(&GCMDriverDesktop::GCMClientReady, service_)); 253} 254 255void GCMDriverDesktop::IOWorker::OnActivityRecorded() { 256 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 257 // When an activity is recorded, get all the stats and refresh the UI of 258 // gcm-internals page. 259 GetGCMStatistics(false); 260} 261 262void GCMDriverDesktop::IOWorker::OnConnected( 263 const net::IPEndPoint& ip_endpoint) { 264 ui_thread_->PostTask(FROM_HERE, 265 base::Bind(&GCMDriverDesktop::OnConnected, 266 service_, 267 ip_endpoint)); 268} 269 270void GCMDriverDesktop::IOWorker::OnDisconnected() { 271 ui_thread_->PostTask(FROM_HERE, 272 base::Bind(&GCMDriverDesktop::OnDisconnected, service_)); 273} 274 275void GCMDriverDesktop::IOWorker::Start( 276 const base::WeakPtr<GCMDriverDesktop>& service) { 277 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 278 279 service_ = service; 280 gcm_client_->Start(); 281} 282 283void GCMDriverDesktop::IOWorker::Stop() { 284 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 285 286 gcm_client_->Stop(); 287} 288 289void GCMDriverDesktop::IOWorker::CheckOut() { 290 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 291 292 gcm_client_->CheckOut(); 293 294 // Note that we still need to keep GCMClient instance alive since the 295 // GCMDriverDesktop may check in again. 296} 297 298void GCMDriverDesktop::IOWorker::Register( 299 const std::string& app_id, 300 const std::vector<std::string>& sender_ids) { 301 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 302 303 gcm_client_->Register(app_id, sender_ids); 304} 305 306void GCMDriverDesktop::IOWorker::Unregister(const std::string& app_id) { 307 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 308 309 gcm_client_->Unregister(app_id); 310} 311 312void GCMDriverDesktop::IOWorker::Send( 313 const std::string& app_id, 314 const std::string& receiver_id, 315 const GCMClient::OutgoingMessage& message) { 316 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 317 318 gcm_client_->Send(app_id, receiver_id, message); 319} 320 321void GCMDriverDesktop::IOWorker::GetGCMStatistics(bool clear_logs) { 322 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 323 gcm::GCMClient::GCMStatistics stats; 324 325 if (gcm_client_.get()) { 326 if (clear_logs) 327 gcm_client_->ClearActivityLogs(); 328 stats = gcm_client_->GetStatistics(); 329 } 330 331 ui_thread_->PostTask( 332 FROM_HERE, 333 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished, service_, stats)); 334} 335 336void GCMDriverDesktop::IOWorker::SetGCMRecording(bool recording) { 337 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 338 gcm::GCMClient::GCMStatistics stats; 339 340 if (gcm_client_.get()) { 341 gcm_client_->SetRecording(recording); 342 stats = gcm_client_->GetStatistics(); 343 stats.gcm_client_created = true; 344 } 345 346 ui_thread_->PostTask( 347 FROM_HERE, 348 base::Bind(&GCMDriverDesktop::GetGCMStatisticsFinished, service_, stats)); 349} 350 351void GCMDriverDesktop::IOWorker::SetAccountsForCheckin( 352 const std::map<std::string, std::string>& account_tokens) { 353 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 354 355 if (gcm_client_.get()) 356 gcm_client_->SetAccountsForCheckin(account_tokens); 357} 358 359GCMDriverDesktop::GCMDriverDesktop( 360 scoped_ptr<GCMClientFactory> gcm_client_factory, 361 const GCMClient::ChromeBuildInfo& chrome_build_info, 362 const base::FilePath& store_path, 363 const scoped_refptr<net::URLRequestContextGetter>& request_context, 364 const scoped_refptr<base::SequencedTaskRunner>& ui_thread, 365 const scoped_refptr<base::SequencedTaskRunner>& io_thread, 366 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner) 367 : signed_in_(false), 368 gcm_started_(false), 369 gcm_enabled_(true), 370 connected_(false), 371 ui_thread_(ui_thread), 372 io_thread_(io_thread), 373 weak_ptr_factory_(this) { 374 // Create and initialize the GCMClient. Note that this does not initiate the 375 // GCM check-in. 376 io_worker_.reset(new IOWorker(ui_thread, io_thread)); 377 io_thread_->PostTask( 378 FROM_HERE, 379 base::Bind(&GCMDriverDesktop::IOWorker::Initialize, 380 base::Unretained(io_worker_.get()), 381 base::Passed(&gcm_client_factory), 382 chrome_build_info, 383 store_path, 384 request_context, 385 blocking_task_runner)); 386} 387 388GCMDriverDesktop::~GCMDriverDesktop() { 389} 390 391void GCMDriverDesktop::Shutdown() { 392 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 393 GCMDriver::Shutdown(); 394 io_thread_->DeleteSoon(FROM_HERE, io_worker_.release()); 395} 396 397void GCMDriverDesktop::OnSignedIn() { 398 signed_in_ = true; 399 EnsureStarted(); 400} 401 402void GCMDriverDesktop::Purge() { 403 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 404 405 // We still proceed with the check-out logic even if the check-in is not 406 // initiated in the current session. This will make sure that all the 407 // persisted data written previously will get purged. 408 signed_in_ = false; 409 RemoveCachedData(); 410 411 io_thread_->PostTask(FROM_HERE, 412 base::Bind(&GCMDriverDesktop::IOWorker::CheckOut, 413 base::Unretained(io_worker_.get()))); 414} 415 416void GCMDriverDesktop::AddAppHandler(const std::string& app_id, 417 GCMAppHandler* handler) { 418 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 419 GCMDriver::AddAppHandler(app_id, handler); 420 421 // Ensures that the GCM service is started when there is an interest. 422 EnsureStarted(); 423} 424 425void GCMDriverDesktop::RemoveAppHandler(const std::string& app_id) { 426 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 427 GCMDriver::RemoveAppHandler(app_id); 428 429 // Stops the GCM service when no app intends to consume it. 430 if (app_handlers().empty()) 431 Stop(); 432} 433 434void GCMDriverDesktop::Enable() { 435 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 436 437 if (gcm_enabled_) 438 return; 439 gcm_enabled_ = true; 440 441 EnsureStarted(); 442} 443 444void GCMDriverDesktop::Disable() { 445 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 446 447 if (!gcm_enabled_) 448 return; 449 gcm_enabled_ = false; 450 451 Stop(); 452} 453 454void GCMDriverDesktop::Stop() { 455 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 456 457 // No need to stop GCM service if not started yet. 458 if (!gcm_started_) 459 return; 460 461 RemoveCachedData(); 462 463 io_thread_->PostTask( 464 FROM_HERE, 465 base::Bind(&GCMDriverDesktop::IOWorker::Stop, 466 base::Unretained(io_worker_.get()))); 467} 468 469void GCMDriverDesktop::RegisterImpl( 470 const std::string& app_id, 471 const std::vector<std::string>& sender_ids) { 472 // Delay the register operation until GCMClient is ready. 473 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 474 delayed_task_controller_->AddTask(base::Bind(&GCMDriverDesktop::DoRegister, 475 weak_ptr_factory_.GetWeakPtr(), 476 app_id, 477 sender_ids)); 478 return; 479 } 480 481 DoRegister(app_id, sender_ids); 482} 483 484void GCMDriverDesktop::DoRegister(const std::string& app_id, 485 const std::vector<std::string>& sender_ids) { 486 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 487 if (!HasRegisterCallback(app_id)) { 488 // The callback could have been removed when the app is uninstalled. 489 return; 490 } 491 492 io_thread_->PostTask( 493 FROM_HERE, 494 base::Bind(&GCMDriverDesktop::IOWorker::Register, 495 base::Unretained(io_worker_.get()), 496 app_id, 497 sender_ids)); 498} 499 500void GCMDriverDesktop::UnregisterImpl(const std::string& app_id) { 501 // Delay the unregister operation until GCMClient is ready. 502 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 503 delayed_task_controller_->AddTask( 504 base::Bind(&GCMDriverDesktop::DoUnregister, 505 weak_ptr_factory_.GetWeakPtr(), 506 app_id)); 507 return; 508 } 509 510 DoUnregister(app_id); 511} 512 513void GCMDriverDesktop::DoUnregister(const std::string& app_id) { 514 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 515 516 // Ask the server to unregister it. There could be a small chance that the 517 // unregister request fails. If this occurs, it does not bring any harm since 518 // we simply reject the messages/events received from the server. 519 io_thread_->PostTask( 520 FROM_HERE, 521 base::Bind(&GCMDriverDesktop::IOWorker::Unregister, 522 base::Unretained(io_worker_.get()), 523 app_id)); 524} 525 526void GCMDriverDesktop::SendImpl(const std::string& app_id, 527 const std::string& receiver_id, 528 const GCMClient::OutgoingMessage& message) { 529 // Delay the send operation until all GCMClient is ready. 530 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 531 delayed_task_controller_->AddTask(base::Bind(&GCMDriverDesktop::DoSend, 532 weak_ptr_factory_.GetWeakPtr(), 533 app_id, 534 receiver_id, 535 message)); 536 return; 537 } 538 539 DoSend(app_id, receiver_id, message); 540} 541 542void GCMDriverDesktop::DoSend(const std::string& app_id, 543 const std::string& receiver_id, 544 const GCMClient::OutgoingMessage& message) { 545 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 546 io_thread_->PostTask( 547 FROM_HERE, 548 base::Bind(&GCMDriverDesktop::IOWorker::Send, 549 base::Unretained(io_worker_.get()), 550 app_id, 551 receiver_id, 552 message)); 553} 554 555GCMClient* GCMDriverDesktop::GetGCMClientForTesting() const { 556 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 557 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL; 558} 559 560bool GCMDriverDesktop::IsStarted() const { 561 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 562 return gcm_started_; 563} 564 565bool GCMDriverDesktop::IsConnected() const { 566 return connected_; 567} 568 569void GCMDriverDesktop::GetGCMStatistics( 570 const GetGCMStatisticsCallback& callback, 571 bool clear_logs) { 572 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 573 DCHECK(!callback.is_null()); 574 575 request_gcm_statistics_callback_ = callback; 576 io_thread_->PostTask( 577 FROM_HERE, 578 base::Bind(&GCMDriverDesktop::IOWorker::GetGCMStatistics, 579 base::Unretained(io_worker_.get()), 580 clear_logs)); 581} 582 583void GCMDriverDesktop::SetGCMRecording(const GetGCMStatisticsCallback& callback, 584 bool recording) { 585 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 586 587 request_gcm_statistics_callback_ = callback; 588 io_thread_->PostTask( 589 FROM_HERE, 590 base::Bind(&GCMDriverDesktop::IOWorker::SetGCMRecording, 591 base::Unretained(io_worker_.get()), 592 recording)); 593} 594 595void GCMDriverDesktop::SetAccountsForCheckin( 596 const std::map<std::string, std::string>& account_tokens) { 597 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 598 599 io_thread_->PostTask( 600 FROM_HERE, 601 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountsForCheckin, 602 base::Unretained(io_worker_.get()), 603 account_tokens)); 604} 605 606GCMClient::Result GCMDriverDesktop::EnsureStarted() { 607 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 608 609 if (gcm_started_) 610 return GCMClient::SUCCESS; 611 612 if (!gcm_enabled_) 613 return GCMClient::GCM_DISABLED; 614 615 // Have any app requested the service? 616 if (app_handlers().empty()) 617 return GCMClient::UNKNOWN_ERROR; 618 619 // TODO(jianli): To be removed when sign-in enforcement is dropped. 620 if (!signed_in_ && !GCMDriver::IsAllowedForAllUsers()) 621 return GCMClient::NOT_SIGNED_IN; 622 623 DCHECK(!delayed_task_controller_); 624 delayed_task_controller_.reset(new DelayedTaskController); 625 626 // Note that we need to pass weak pointer again since the existing weak 627 // pointer in IOWorker might have been invalidated when check-out occurs. 628 io_thread_->PostTask( 629 FROM_HERE, 630 base::Bind(&GCMDriverDesktop::IOWorker::Start, 631 base::Unretained(io_worker_.get()), 632 weak_ptr_factory_.GetWeakPtr())); 633 634 gcm_started_ = true; 635 return GCMClient::SUCCESS; 636} 637 638void GCMDriverDesktop::RemoveCachedData() { 639 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 640 // Remove all the queued tasks since they no longer make sense after 641 // GCM service is stopped. 642 weak_ptr_factory_.InvalidateWeakPtrs(); 643 644 gcm_started_ = false; 645 delayed_task_controller_.reset(); 646 ClearCallbacks(); 647} 648 649void GCMDriverDesktop::MessageReceived( 650 const std::string& app_id, 651 const GCMClient::IncomingMessage& message) { 652 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 653 654 // Drop the event if the service has been stopped. 655 if (!gcm_started_) 656 return; 657 658 GetAppHandler(app_id)->OnMessage(app_id, message); 659} 660 661void GCMDriverDesktop::MessagesDeleted(const std::string& app_id) { 662 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 663 664 // Drop the event if the service has been stopped. 665 if (!gcm_started_) 666 return; 667 668 GetAppHandler(app_id)->OnMessagesDeleted(app_id); 669} 670 671void GCMDriverDesktop::MessageSendError( 672 const std::string& app_id, 673 const GCMClient::SendErrorDetails& send_error_details) { 674 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 675 676 // Drop the event if the service has been stopped. 677 if (!gcm_started_) 678 return; 679 680 GetAppHandler(app_id)->OnSendError(app_id, send_error_details); 681} 682 683void GCMDriverDesktop::GCMClientReady() { 684 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 685 686 delayed_task_controller_->SetReady(); 687} 688 689void GCMDriverDesktop::OnConnected(const net::IPEndPoint& ip_endpoint) { 690 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 691 692 connected_ = true; 693 694 // Drop the event if the service has been stopped. 695 if (!gcm_started_) 696 return; 697 698 const GCMAppHandlerMap& app_handler_map = app_handlers(); 699 for (GCMAppHandlerMap::const_iterator iter = app_handler_map.begin(); 700 iter != app_handler_map.end(); ++iter) { 701 iter->second->OnConnected(ip_endpoint); 702 } 703 704 GetAppHandler(kDefaultAppHandler)->OnConnected(ip_endpoint); 705} 706 707void GCMDriverDesktop::OnDisconnected() { 708 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 709 710 connected_ = false; 711 712 // Drop the event if the service has been stopped. 713 if (!gcm_started_) 714 return; 715 716 const GCMAppHandlerMap& app_handler_map = app_handlers(); 717 for (GCMAppHandlerMap::const_iterator iter = app_handler_map.begin(); 718 iter != app_handler_map.end(); ++iter) { 719 iter->second->OnDisconnected(); 720 } 721 722 GetAppHandler(kDefaultAppHandler)->OnDisconnected(); 723} 724 725void GCMDriverDesktop::GetGCMStatisticsFinished( 726 const GCMClient::GCMStatistics& stats) { 727 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 728 729 // Normally request_gcm_statistics_callback_ would not be null. 730 if (!request_gcm_statistics_callback_.is_null()) 731 request_gcm_statistics_callback_.Run(stats); 732 else 733 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL."; 734} 735 736} // namespace gcm 737 738