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