Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: chrome/browser/services/gcm/gcm_profile_service.cc

Issue 165993005: [GCM] Make sure GCM checkout logic is invoked when the profile is signed out (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix trybots Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/services/gcm/gcm_profile_service.h" 5 #include "chrome/browser/services/gcm/gcm_profile_service.h"
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/path_service.h" 10 #include "base/path_service.h"
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 GCMClient::Result result) OVERRIDE; 253 GCMClient::Result result) OVERRIDE;
254 virtual void OnGCMReady() OVERRIDE; 254 virtual void OnGCMReady() OVERRIDE;
255 255
256 // Called on IO thread. 256 // Called on IO thread.
257 void Initialize( 257 void Initialize(
258 GCMClientFactory* gcm_client_factory, 258 GCMClientFactory* gcm_client_factory,
259 const base::FilePath& store_path, 259 const base::FilePath& store_path,
260 const scoped_refptr<net::URLRequestContextGetter>& 260 const scoped_refptr<net::URLRequestContextGetter>&
261 url_request_context_getter); 261 url_request_context_getter);
262 void Reset(); 262 void Reset();
263 void CheckIn();
263 void CheckOut(); 264 void CheckOut();
264 void Register(const std::string& app_id, 265 void Register(const std::string& app_id,
265 const std::vector<std::string>& sender_ids, 266 const std::vector<std::string>& sender_ids,
266 const std::string& cert); 267 const std::string& cert);
267 void Unregister(const std::string& app_id); 268 void Unregister(const std::string& app_id);
268 void Send(const std::string& app_id, 269 void Send(const std::string& app_id,
269 const std::string& receiver_id, 270 const std::string& receiver_id,
270 const GCMClient::OutgoingMessage& message); 271 const GCMClient::OutgoingMessage& message);
271 272
272 private: 273 private:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 311
311 gcm_client_->Initialize(chrome_build_proto, 312 gcm_client_->Initialize(chrome_build_proto,
312 store_path, 313 store_path,
313 blocking_task_runner, 314 blocking_task_runner,
314 url_request_context_getter, 315 url_request_context_getter,
315 this); 316 this);
316 317
317 content::BrowserThread::PostTask( 318 content::BrowserThread::PostTask(
318 content::BrowserThread::UI, 319 content::BrowserThread::UI,
319 FROM_HERE, 320 FROM_HERE,
320 base::Bind(&GCMProfileService::FinishInitializationOnUI, 321 base::Bind(&GCMProfileService::FinishInitializationOnUI, service_));
321 service_,
322 gcm_client_->IsReady()));
323 } 322 }
324 323
325 void GCMProfileService::IOWorker::Reset() { 324 void GCMProfileService::IOWorker::Reset() {
326 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 325 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
327 326
328 // GCMClient instance must be destroyed from the same thread where it was 327 // GCMClient instance must be destroyed from the same thread where it was
329 // created. 328 // created.
330 gcm_client_.reset(); 329 gcm_client_.reset();
331 } 330 }
332 331
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 } 409 }
411 410
412 void GCMProfileService::IOWorker::OnGCMReady() { 411 void GCMProfileService::IOWorker::OnGCMReady() {
413 content::BrowserThread::PostTask( 412 content::BrowserThread::PostTask(
414 content::BrowserThread::UI, 413 content::BrowserThread::UI,
415 FROM_HERE, 414 FROM_HERE,
416 base::Bind(&GCMProfileService::GCMClientReady, 415 base::Bind(&GCMProfileService::GCMClientReady,
417 service_)); 416 service_));
418 } 417 }
419 418
419 void GCMProfileService::IOWorker::CheckIn() {
420 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
421
422 gcm_client_->CheckIn();
423 }
424
420 void GCMProfileService::IOWorker::CheckOut() { 425 void GCMProfileService::IOWorker::CheckOut() {
421 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 426 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
422 427
423 gcm_client_->CheckOut(); 428 gcm_client_->CheckOut();
424 gcm_client_.reset();
425 } 429 }
426 430
427 void GCMProfileService::IOWorker::Register( 431 void GCMProfileService::IOWorker::Register(
428 const std::string& app_id, 432 const std::string& app_id,
429 const std::vector<std::string>& sender_ids, 433 const std::vector<std::string>& sender_ids,
430 const std::string& cert) { 434 const std::string& cert) {
431 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 435 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
432 436
433 gcm_client_->Register(app_id, cert, sender_ids); 437 gcm_client_->Register(app_id, cert, sender_ids);
434 } 438 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 testing_delegate_(NULL), 502 testing_delegate_(NULL),
499 weak_ptr_factory_(this) { 503 weak_ptr_factory_(this) {
500 DCHECK(!profile->IsOffTheRecord()); 504 DCHECK(!profile->IsOffTheRecord());
501 } 505 }
502 506
503 GCMProfileService::~GCMProfileService() { 507 GCMProfileService::~GCMProfileService() {
504 } 508 }
505 509
506 void GCMProfileService::Initialize( 510 void GCMProfileService::Initialize(
507 scoped_ptr<GCMClientFactory> gcm_client_factory) { 511 scoped_ptr<GCMClientFactory> gcm_client_factory) {
508 gcm_client_factory_ = gcm_client_factory.Pass();
509
510 // This has to be done first since CheckIn depends on it.
511 io_worker_ = new IOWorker(weak_ptr_factory_.GetWeakPtr());
512
513 #if !defined(OS_ANDROID)
514 js_event_router_.reset(new extensions::GcmJsEventRouter(profile_));
515 #endif
516
517 registrar_.Add(this, 512 registrar_.Add(this,
518 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL, 513 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
519 content::Source<Profile>(profile_)); 514 content::Source<Profile>(profile_));
520 registrar_.Add(this, 515 registrar_.Add(this,
521 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, 516 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
522 content::Source<Profile>(profile_)); 517 content::Source<Profile>(profile_));
523 registrar_.Add(this, 518 registrar_.Add(this,
524 chrome::NOTIFICATION_PROFILE_DESTROYED, 519 chrome::NOTIFICATION_PROFILE_DESTROYED,
525 content::Source<Profile>(profile_)); 520 content::Source<Profile>(profile_));
526 // TODO(jianli): move extension specific logic out of GCMProfileService. 521 // TODO(jianli): move extension specific logic out of GCMProfileService.
527 registrar_.Add(this, 522 registrar_.Add(this,
528 chrome:: NOTIFICATION_EXTENSION_UNINSTALLED, 523 chrome:: NOTIFICATION_EXTENSION_UNINSTALLED,
529 content::Source<Profile>(profile_)); 524 content::Source<Profile>(profile_));
530 525
531 // In case that the profile has been signed in before GCMProfileService is 526 // Create and initialize the GCMClient. Note that this does not initiate the
532 // created. 527 // GCM check-in.
533 SigninManagerBase* manager = SigninManagerFactory::GetForProfile(profile_); 528 gcm_client_factory_ = gcm_client_factory.Pass();
534 if (manager) { 529 io_worker_ = new IOWorker(weak_ptr_factory_.GetWeakPtr());
535 std::string username = manager->GetAuthenticatedUsername(); 530 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
536 if (!username.empty()) 531 profile_->GetRequestContext();
537 CheckIn(username); 532 content::BrowserThread::PostTask(
538 } 533 content::BrowserThread::IO,
534 FROM_HERE,
535 base::Bind(&GCMProfileService::IOWorker::Initialize,
536 io_worker_,
537 gcm_client_factory_.get(),
538 profile_->GetPath().Append(chrome::kGCMStoreDirname),
539 url_request_context_getter));
539 } 540 }
540 541
541 void GCMProfileService::Register(const std::string& app_id, 542 void GCMProfileService::Register(const std::string& app_id,
542 const std::vector<std::string>& sender_ids, 543 const std::vector<std::string>& sender_ids,
543 const std::string& cert, 544 const std::string& cert,
544 RegisterCallback callback) { 545 RegisterCallback callback) {
545 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 546 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
546 DCHECK(!app_id.empty() && !sender_ids.empty() && !callback.is_null()); 547 DCHECK(!app_id.empty() && !sender_ids.empty() && !callback.is_null());
547 548
549 // Ensure that check-in has been done.
550 EnsureCheckedIn();
551
548 // If the profile was not signed in, bail out. 552 // If the profile was not signed in, bail out.
549 if (username_.empty()) { 553 if (username_.empty()) {
550 callback.Run(std::string(), GCMClient::NOT_SIGNED_IN); 554 callback.Run(std::string(), GCMClient::NOT_SIGNED_IN);
551 return; 555 return;
552 } 556 }
553 557
554 // If previous register operation is still in progress, bail out. 558 // If previous register operation is still in progress, bail out.
555 if (register_callbacks_.find(app_id) != register_callbacks_.end()) { 559 if (register_callbacks_.find(app_id) != register_callbacks_.end()) {
556 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); 560 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
557 return; 561 return;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 cert)); 627 cert));
624 } 628 }
625 629
626 void GCMProfileService::Send(const std::string& app_id, 630 void GCMProfileService::Send(const std::string& app_id,
627 const std::string& receiver_id, 631 const std::string& receiver_id,
628 const GCMClient::OutgoingMessage& message, 632 const GCMClient::OutgoingMessage& message,
629 SendCallback callback) { 633 SendCallback callback) {
630 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 634 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
631 DCHECK(!app_id.empty() && !receiver_id.empty() && !callback.is_null()); 635 DCHECK(!app_id.empty() && !receiver_id.empty() && !callback.is_null());
632 636
637 // Ensure that check-in has been done.
638 EnsureCheckedIn();
fgorski 2014/02/20 22:18:40 Seems like calling send or receive when will check
jianli 2014/02/21 18:25:11 When a gcm app is running and register/send is cal
639
633 // If the profile was not signed in, bail out. 640 // If the profile was not signed in, bail out.
634 if (username_.empty()) { 641 if (username_.empty()) {
635 callback.Run(std::string(), GCMClient::NOT_SIGNED_IN); 642 callback.Run(std::string(), GCMClient::NOT_SIGNED_IN);
636 return; 643 return;
637 } 644 }
638 645
639 // If the message with send ID is still in progress, bail out. 646 // If the message with send ID is still in progress, bail out.
640 std::pair<std::string, std::string> key(app_id, message.id); 647 std::pair<std::string, std::string> key(app_id, message.id);
641 if (send_callbacks_.find(key) != send_callbacks_.end()) { 648 if (send_callbacks_.find(key) != send_callbacks_.end()) {
642 callback.Run(message.id, GCMClient::INVALID_PARAMETER); 649 callback.Run(message.id, GCMClient::INVALID_PARAMETER);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 message)); 681 message));
675 } 682 }
676 683
677 void GCMProfileService::Observe(int type, 684 void GCMProfileService::Observe(int type,
678 const content::NotificationSource& source, 685 const content::NotificationSource& source,
679 const content::NotificationDetails& details) { 686 const content::NotificationDetails& details) {
680 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 687 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
681 688
682 switch (type) { 689 switch (type) {
683 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { 690 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: {
684 const GoogleServiceSigninSuccessDetails* signin_details = 691 if (IsGCMChannelEnabled())
685 content::Details<GoogleServiceSigninSuccessDetails>(details).ptr(); 692 EnsureCheckedIn();
686 // This could be called multiple times when the password changed.
687 if (username_ != signin_details->username)
688 CheckIn(signin_details->username);
689 break; 693 break;
690 } 694 }
691 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: 695 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
692 CheckOut(); 696 CheckOut();
693 break; 697 break;
694 case chrome::NOTIFICATION_PROFILE_DESTROYED: 698 case chrome::NOTIFICATION_PROFILE_DESTROYED:
695 ResetGCMClient(); 699 ResetGCMClient();
696 break; 700 break;
697 case chrome:: NOTIFICATION_EXTENSION_UNINSTALLED: { 701 case chrome:: NOTIFICATION_EXTENSION_UNINSTALLED:
698 extensions::Extension* extension = 702 if (!username_.empty()) {
699 content::Details<extensions::Extension>(details).ptr(); 703 extensions::Extension* extension =
700 Unregister(extension->id()); 704 content::Details<extensions::Extension>(details).ptr();
705 Unregister(extension->id());
706 }
701 break; 707 break;
702 }
703 default: 708 default:
704 NOTREACHED(); 709 NOTREACHED();
705 } 710 }
706 } 711 }
707 712
708 void GCMProfileService::CheckIn(const std::string& username) { 713 bool GCMProfileService::IsGCMChannelEnabled() const {
709 DCHECK(!username.empty() && username_.empty()); 714 const base::Value* gcm_enabled_value =
715 profile_->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled);
716 bool gcm_enabled = false;
717 return gcm_enabled_value &&
718 gcm_enabled_value->GetAsBoolean(&gcm_enabled) &&
719 gcm_enabled;
720 }
721
722 void GCMProfileService::EnsureCheckedIn() {
723 SigninManagerBase* manager = SigninManagerFactory::GetForProfile(profile_);
724 if (!manager)
725 return;
726 std::string username = manager->GetAuthenticatedUsername();
727 if (username.empty())
728 return;
729
730 // CheckIn could be called more than once when:
731 // 1) The password changes.
732 // 2) Register/send function calls it to ensure CheckIn is done.
733 if (username_ == username)
734 return;
710 username_ = username; 735 username_ = username;
711 736
737 #if !defined(OS_ANDROID)
738 if (!js_event_router_)
739 js_event_router_.reset(new extensions::GcmJsEventRouter(profile_));
740 #endif
741
712 DCHECK(!delayed_task_controller_); 742 DCHECK(!delayed_task_controller_);
713 delayed_task_controller_.reset(new DelayedTaskController); 743 delayed_task_controller_.reset(new DelayedTaskController);
714 744
715 // Load all register apps. 745 // Load all the registered apps.
716 ReadRegisteredAppIDs(); 746 ReadRegisteredAppIDs();
717 747
718 // Let the IO thread create and initialize GCMClient. 748 // Initiate the GCM check-in.
719 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
720 profile_->GetRequestContext();
721 content::BrowserThread::PostTask( 749 content::BrowserThread::PostTask(
722 content::BrowserThread::IO, 750 content::BrowserThread::IO,
723 FROM_HERE, 751 FROM_HERE,
724 base::Bind(&GCMProfileService::IOWorker::Initialize, 752 base::Bind(&GCMProfileService::IOWorker::CheckIn, io_worker_));
725 io_worker_,
726 gcm_client_factory_.get(),
727 profile_->GetPath().Append(chrome::kGCMStoreDirname),
728 url_request_context_getter));
729 } 753 }
730 754
731 void GCMProfileService::CheckOut() { 755 void GCMProfileService::CheckOut() {
732 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 756 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
733 757
734 DCHECK(!username_.empty()); 758 // We still proceed with the check-out logic even if the check-in is not
759 // initiated in the current session. This will make sure that all the
760 // persisted data written previously will get purged.
735 username_.clear(); 761 username_.clear();
736 762
737 // Remove persisted data from app's state store. 763 // Remove persisted data from app's state store.
738 for (RegistrationInfoMap::const_iterator iter = 764 for (RegistrationInfoMap::const_iterator iter =
739 registration_info_map_.begin(); 765 registration_info_map_.begin();
740 iter != registration_info_map_.end(); ++iter) { 766 iter != registration_info_map_.end(); ++iter) {
741 DeleteRegistrationInfo(iter->first); 767 DeleteRegistrationInfo(iter->first);
742 } 768 }
743 769
744 // Remove persisted data from prefs store. 770 // Remove persisted data from prefs store.
745 profile_->GetPrefs()->ClearPref(prefs::kGCMChannelEnabled);
746 profile_->GetPrefs()->ClearPref(prefs::kGCMRegisteredAppIDs); 771 profile_->GetPrefs()->ClearPref(prefs::kGCMRegisteredAppIDs);
747 772
748 gcm_client_ready_ = false; 773 gcm_client_ready_ = false;
749 delayed_task_controller_.reset(); 774 delayed_task_controller_.reset();
750 register_callbacks_.clear(); 775 register_callbacks_.clear();
751 send_callbacks_.clear(); 776 send_callbacks_.clear();
752 registration_info_map_.clear(); 777 registration_info_map_.clear();
753 778
754 content::BrowserThread::PostTask( 779 content::BrowserThread::PostTask(
755 content::BrowserThread::IO, 780 content::BrowserThread::IO,
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 GCMClient::Result result) { 906 GCMClient::Result result) {
882 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 907 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
883 908
884 // Drop the event if signed out. 909 // Drop the event if signed out.
885 if (username_.empty()) 910 if (username_.empty())
886 return; 911 return;
887 912
888 GetEventRouter(app_id)->OnSendError(app_id, message_id, result); 913 GetEventRouter(app_id)->OnSendError(app_id, message_id, result);
889 } 914 }
890 915
891 void GCMProfileService::FinishInitializationOnUI(bool ready) { 916 void GCMProfileService::FinishInitializationOnUI() {
892 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 917 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
893 918
894 gcm_client_ready_ = ready; 919 // Initiates the check-in if the rollout signal indicates yes.
895 if (gcm_client_ready_) 920 if (IsGCMChannelEnabled())
896 delayed_task_controller_->SetGCMReady(); 921 EnsureCheckedIn();
897 } 922 }
898 923
899 void GCMProfileService::GCMClientReady() { 924 void GCMProfileService::GCMClientReady() {
900 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 925 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
901 926
902 if (gcm_client_ready_) 927 if (gcm_client_ready_)
903 return; 928 return;
904 gcm_client_ready_ = true; 929 gcm_client_ready_ = true;
905 930
906 delayed_task_controller_->SetGCMReady(); 931 delayed_task_controller_->SetGCMReady();
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 1053
1029 return true; 1054 return true;
1030 } 1055 }
1031 1056
1032 // static 1057 // static
1033 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() { 1058 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() {
1034 return kRegistrationKey; 1059 return kRegistrationKey;
1035 } 1060 }
1036 1061
1037 } // namespace gcm 1062 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698