gcm_driver_desktop.cc revision 1675a649fd7a8b3cb80ffddae2dc181f122353c5
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 26namespace gcm { 27 28class 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 98GCMDriverDesktop::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 106GCMDriverDesktop::IOWorker::~IOWorker() { 107 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 108} 109 110void 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 128void 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 140void 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 152void 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 163void 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 176void 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 184void 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 195void 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 206void 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 214void 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 221void 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 229void GCMDriverDesktop::IOWorker::OnDisconnected() { 230 ui_thread_->PostTask(FROM_HERE, 231 base::Bind(&GCMDriverDesktop::OnDisconnected, service_)); 232} 233 234void GCMDriverDesktop::IOWorker::Start( 235 const base::WeakPtr<GCMDriverDesktop>& service) { 236 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 237 238 service_ = service; 239 gcm_client_->Start(); 240} 241 242void GCMDriverDesktop::IOWorker::Stop() { 243 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 244 245 gcm_client_->Stop(); 246} 247 248void 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 257void 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 265void GCMDriverDesktop::IOWorker::Unregister(const std::string& app_id) { 266 DCHECK(io_thread_->RunsTasksOnCurrentThread()); 267 268 gcm_client_->Unregister(app_id); 269} 270 271void 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 280void 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 295void 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 310void 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 318void 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 326void 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 334GCMDriverDesktop::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 374GCMDriverDesktop::~GCMDriverDesktop() { 375} 376 377void 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 389void GCMDriverDesktop::OnSignedIn() { 390 signed_in_ = true; 391 EnsureStarted(); 392} 393 394void 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 403void 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 413void 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 422void 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 433void GCMDriverDesktop::AddConnectionObserver(GCMConnectionObserver* observer) { 434 connection_observer_list_.AddObserver(observer); 435} 436 437void GCMDriverDesktop::RemoveConnectionObserver( 438 GCMConnectionObserver* observer) { 439 connection_observer_list_.RemoveObserver(observer); 440} 441 442void GCMDriverDesktop::Enable() { 443 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 444 445 if (gcm_enabled_) 446 return; 447 gcm_enabled_ = true; 448 449 EnsureStarted(); 450} 451 452void GCMDriverDesktop::Disable() { 453 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 454 455 if (!gcm_enabled_) 456 return; 457 gcm_enabled_ = false; 458 459 Stop(); 460} 461 462void 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 477void 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 492void 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 508void 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 521void 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 534void 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 550void 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 563GCMClient* GCMDriverDesktop::GetGCMClientForTesting() const { 564 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 565 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL; 566} 567 568bool GCMDriverDesktop::IsStarted() const { 569 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 570 return gcm_started_; 571} 572 573bool GCMDriverDesktop::IsConnected() const { 574 return connected_; 575} 576 577void 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 591void 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 603void 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 614void 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 624void 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 635GCMClient::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 680void 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 691void 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 703void 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 713void 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 725void 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 736void GCMDriverDesktop::GCMClientReady( 737 const std::vector<AccountMapping>& account_mappings) { 738 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 739 740 delayed_task_controller_->SetReady(); 741} 742 743void 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 757void 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 770void 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