gcm_driver_desktop.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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 PrefService* prefs, 338 const base::FilePath& store_path, 339 const scoped_refptr<net::URLRequestContextGetter>& request_context, 340 const scoped_refptr<base::SequencedTaskRunner>& ui_thread, 341 const scoped_refptr<base::SequencedTaskRunner>& io_thread, 342 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner) 343 : gcm_channel_status_syncer_( 344 new GCMChannelStatusSyncer(this, prefs, request_context)), 345 signed_in_(false), 346 gcm_started_(false), 347 gcm_enabled_(true), 348 connected_(false), 349 ui_thread_(ui_thread), 350 io_thread_(io_thread), 351 weak_ptr_factory_(this) { 352 gcm_enabled_ = gcm_channel_status_syncer_->gcm_enabled(); 353 354 // Create and initialize the GCMClient. Note that this does not initiate the 355 // GCM check-in. 356 io_worker_.reset(new IOWorker(ui_thread, io_thread)); 357 io_thread_->PostTask( 358 FROM_HERE, 359 base::Bind(&GCMDriverDesktop::IOWorker::Initialize, 360 base::Unretained(io_worker_.get()), 361 base::Passed(&gcm_client_factory), 362 chrome_build_info, 363 store_path, 364 request_context, 365 blocking_task_runner)); 366} 367 368GCMDriverDesktop::~GCMDriverDesktop() { 369} 370 371void GCMDriverDesktop::Shutdown() { 372 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 373 GCMDriver::Shutdown(); 374 375 // Dispose the syncer in order to release the reference to 376 // URLRequestContextGetter that needs to be done before IOThread gets 377 // deleted. 378 gcm_channel_status_syncer_.reset(); 379 380 io_thread_->DeleteSoon(FROM_HERE, io_worker_.release()); 381} 382 383void GCMDriverDesktop::OnSignedIn() { 384 signed_in_ = true; 385 EnsureStarted(); 386} 387 388void GCMDriverDesktop::Purge() { 389 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 390 391 // We still proceed with the check-out logic even if the check-in is not 392 // initiated in the current session. This will make sure that all the 393 // persisted data written previously will get purged. 394 signed_in_ = false; 395 RemoveCachedData(); 396 397 io_thread_->PostTask(FROM_HERE, 398 base::Bind(&GCMDriverDesktop::IOWorker::CheckOut, 399 base::Unretained(io_worker_.get()))); 400} 401 402void GCMDriverDesktop::AddAppHandler(const std::string& app_id, 403 GCMAppHandler* handler) { 404 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 405 GCMDriver::AddAppHandler(app_id, handler); 406 407 // Ensures that the GCM service is started when there is an interest. 408 EnsureStarted(); 409} 410 411void GCMDriverDesktop::RemoveAppHandler(const std::string& app_id) { 412 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 413 GCMDriver::RemoveAppHandler(app_id); 414 415 // Stops the GCM service when no app intends to consume it. 416 if (app_handlers().empty()) 417 Stop(); 418} 419 420void GCMDriverDesktop::AddConnectionObserver(GCMConnectionObserver* observer) { 421 connection_observer_list_.AddObserver(observer); 422} 423 424void GCMDriverDesktop::RemoveConnectionObserver( 425 GCMConnectionObserver* observer) { 426 connection_observer_list_.RemoveObserver(observer); 427} 428 429void GCMDriverDesktop::Enable() { 430 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 431 432 if (gcm_enabled_) 433 return; 434 gcm_enabled_ = true; 435 436 EnsureStarted(); 437} 438 439void GCMDriverDesktop::Disable() { 440 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 441 442 if (!gcm_enabled_) 443 return; 444 gcm_enabled_ = false; 445 446 Stop(); 447} 448 449void GCMDriverDesktop::Stop() { 450 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 451 452 // No need to stop GCM service if not started yet. 453 if (!gcm_started_) 454 return; 455 456 gcm_channel_status_syncer_->Stop(); 457 458 RemoveCachedData(); 459 460 io_thread_->PostTask( 461 FROM_HERE, 462 base::Bind(&GCMDriverDesktop::IOWorker::Stop, 463 base::Unretained(io_worker_.get()))); 464} 465 466void GCMDriverDesktop::RegisterImpl( 467 const std::string& app_id, 468 const std::vector<std::string>& sender_ids) { 469 // Delay the register operation until GCMClient is ready. 470 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 471 delayed_task_controller_->AddTask(base::Bind(&GCMDriverDesktop::DoRegister, 472 weak_ptr_factory_.GetWeakPtr(), 473 app_id, 474 sender_ids)); 475 return; 476 } 477 478 DoRegister(app_id, sender_ids); 479} 480 481void GCMDriverDesktop::DoRegister(const std::string& app_id, 482 const std::vector<std::string>& sender_ids) { 483 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 484 if (!HasRegisterCallback(app_id)) { 485 // The callback could have been removed when the app is uninstalled. 486 return; 487 } 488 489 io_thread_->PostTask( 490 FROM_HERE, 491 base::Bind(&GCMDriverDesktop::IOWorker::Register, 492 base::Unretained(io_worker_.get()), 493 app_id, 494 sender_ids)); 495} 496 497void GCMDriverDesktop::UnregisterImpl(const std::string& app_id) { 498 // Delay the unregister operation until GCMClient is ready. 499 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 500 delayed_task_controller_->AddTask( 501 base::Bind(&GCMDriverDesktop::DoUnregister, 502 weak_ptr_factory_.GetWeakPtr(), 503 app_id)); 504 return; 505 } 506 507 DoUnregister(app_id); 508} 509 510void GCMDriverDesktop::DoUnregister(const std::string& app_id) { 511 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 512 513 // Ask the server to unregister it. There could be a small chance that the 514 // unregister request fails. If this occurs, it does not bring any harm since 515 // we simply reject the messages/events received from the server. 516 io_thread_->PostTask( 517 FROM_HERE, 518 base::Bind(&GCMDriverDesktop::IOWorker::Unregister, 519 base::Unretained(io_worker_.get()), 520 app_id)); 521} 522 523void GCMDriverDesktop::SendImpl(const std::string& app_id, 524 const std::string& receiver_id, 525 const GCMClient::OutgoingMessage& message) { 526 // Delay the send operation until all GCMClient is ready. 527 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 528 delayed_task_controller_->AddTask(base::Bind(&GCMDriverDesktop::DoSend, 529 weak_ptr_factory_.GetWeakPtr(), 530 app_id, 531 receiver_id, 532 message)); 533 return; 534 } 535 536 DoSend(app_id, receiver_id, message); 537} 538 539void GCMDriverDesktop::DoSend(const std::string& app_id, 540 const std::string& receiver_id, 541 const GCMClient::OutgoingMessage& message) { 542 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 543 io_thread_->PostTask( 544 FROM_HERE, 545 base::Bind(&GCMDriverDesktop::IOWorker::Send, 546 base::Unretained(io_worker_.get()), 547 app_id, 548 receiver_id, 549 message)); 550} 551 552GCMClient* GCMDriverDesktop::GetGCMClientForTesting() const { 553 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 554 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL; 555} 556 557bool GCMDriverDesktop::IsStarted() const { 558 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 559 return gcm_started_; 560} 561 562bool GCMDriverDesktop::IsConnected() const { 563 return connected_; 564} 565 566void GCMDriverDesktop::GetGCMStatistics( 567 const GetGCMStatisticsCallback& callback, 568 bool clear_logs) { 569 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 570 DCHECK(!callback.is_null()); 571 572 request_gcm_statistics_callback_ = callback; 573 io_thread_->PostTask( 574 FROM_HERE, 575 base::Bind(&GCMDriverDesktop::IOWorker::GetGCMStatistics, 576 base::Unretained(io_worker_.get()), 577 clear_logs)); 578} 579 580void GCMDriverDesktop::SetGCMRecording(const GetGCMStatisticsCallback& callback, 581 bool recording) { 582 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 583 584 request_gcm_statistics_callback_ = callback; 585 io_thread_->PostTask( 586 FROM_HERE, 587 base::Bind(&GCMDriverDesktop::IOWorker::SetGCMRecording, 588 base::Unretained(io_worker_.get()), 589 recording)); 590} 591 592void GCMDriverDesktop::UpdateAccountMapping( 593 const AccountMapping& account_mapping) { 594 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 595 596 io_thread_->PostTask( 597 FROM_HERE, 598 base::Bind(&GCMDriverDesktop::IOWorker::UpdateAccountMapping, 599 base::Unretained(io_worker_.get()), 600 account_mapping)); 601} 602 603void GCMDriverDesktop::RemoveAccountMapping(const std::string& account_id) { 604 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 605 606 io_thread_->PostTask( 607 FROM_HERE, 608 base::Bind(&GCMDriverDesktop::IOWorker::RemoveAccountMapping, 609 base::Unretained(io_worker_.get()), 610 account_id)); 611} 612 613void GCMDriverDesktop::SetAccountsForCheckin( 614 const std::map<std::string, std::string>& account_tokens) { 615 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 616 617 io_thread_->PostTask( 618 FROM_HERE, 619 base::Bind(&GCMDriverDesktop::IOWorker::SetAccountsForCheckin, 620 base::Unretained(io_worker_.get()), 621 account_tokens)); 622} 623 624GCMClient::Result GCMDriverDesktop::EnsureStarted() { 625 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 626 627 if (gcm_started_) 628 return GCMClient::SUCCESS; 629 630 if (!gcm_enabled_) 631 return GCMClient::GCM_DISABLED; 632 633 // Have any app requested the service? 634 if (app_handlers().empty()) 635 return GCMClient::UNKNOWN_ERROR; 636 637 // TODO(jianli): To be removed when sign-in enforcement is dropped. 638 if (!signed_in_ && !GCMDriver::IsAllowedForAllUsers()) 639 return GCMClient::NOT_SIGNED_IN; 640 641 DCHECK(!delayed_task_controller_); 642 delayed_task_controller_.reset(new GCMDelayedTaskController); 643 644 // Polling for channel status is only needed when GCM is supported for all 645 // users. 646 if (GCMDriver::IsAllowedForAllUsers()) 647 gcm_channel_status_syncer_->EnsureStarted(); 648 649 UMA_HISTOGRAM_BOOLEAN("GCM.UserSignedIn", signed_in_); 650 651 // Note that we need to pass weak pointer again since the existing weak 652 // pointer in IOWorker might have been invalidated when check-out occurs. 653 io_thread_->PostTask( 654 FROM_HERE, 655 base::Bind(&GCMDriverDesktop::IOWorker::Start, 656 base::Unretained(io_worker_.get()), 657 weak_ptr_factory_.GetWeakPtr())); 658 659 gcm_started_ = true; 660 return GCMClient::SUCCESS; 661} 662 663void GCMDriverDesktop::RemoveCachedData() { 664 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 665 // Remove all the queued tasks since they no longer make sense after 666 // GCM service is stopped. 667 weak_ptr_factory_.InvalidateWeakPtrs(); 668 669 gcm_started_ = false; 670 delayed_task_controller_.reset(); 671 ClearCallbacks(); 672} 673 674void GCMDriverDesktop::MessageReceived( 675 const std::string& app_id, 676 const GCMClient::IncomingMessage& message) { 677 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 678 679 // Drop the event if the service has been stopped. 680 if (!gcm_started_) 681 return; 682 683 GetAppHandler(app_id)->OnMessage(app_id, message); 684} 685 686void GCMDriverDesktop::MessagesDeleted(const std::string& app_id) { 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)->OnMessagesDeleted(app_id); 694} 695 696void GCMDriverDesktop::MessageSendError( 697 const std::string& app_id, 698 const GCMClient::SendErrorDetails& send_error_details) { 699 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 700 701 // Drop the event if the service has been stopped. 702 if (!gcm_started_) 703 return; 704 705 GetAppHandler(app_id)->OnSendError(app_id, send_error_details); 706} 707 708void GCMDriverDesktop::SendAcknowledged(const std::string& app_id, 709 const std::string& message_id) { 710 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 711 712 // Drop the event if the service has been stopped. 713 if (!gcm_started_) 714 return; 715 716 GetAppHandler(app_id)->OnSendAcknowledged(app_id, message_id); 717} 718 719void GCMDriverDesktop::GCMClientReady( 720 const std::vector<AccountMapping>& account_mappings) { 721 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 722 723 delayed_task_controller_->SetReady(); 724} 725 726void GCMDriverDesktop::OnConnected(const net::IPEndPoint& ip_endpoint) { 727 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 728 729 connected_ = true; 730 731 // Drop the event if the service has been stopped. 732 if (!gcm_started_) 733 return; 734 735 FOR_EACH_OBSERVER(GCMConnectionObserver, 736 connection_observer_list_, 737 OnConnected(ip_endpoint)); 738} 739 740void GCMDriverDesktop::OnDisconnected() { 741 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 742 743 connected_ = false; 744 745 // Drop the event if the service has been stopped. 746 if (!gcm_started_) 747 return; 748 749 FOR_EACH_OBSERVER( 750 GCMConnectionObserver, connection_observer_list_, OnDisconnected()); 751} 752 753void GCMDriverDesktop::GetGCMStatisticsFinished( 754 const GCMClient::GCMStatistics& stats) { 755 DCHECK(ui_thread_->RunsTasksOnCurrentThread()); 756 757 // Normally request_gcm_statistics_callback_ would not be null. 758 if (!request_gcm_statistics_callback_.is_null()) 759 request_gcm_statistics_callback_.Run(stats); 760 else 761 LOG(WARNING) << "request_gcm_statistics_callback_ is NULL."; 762} 763 764} // namespace gcm 765 766