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