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