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