Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/prefs/pref_service.h" | 9 #include "base/prefs/pref_service.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 const char kRegistrationKey[] = "gcm.registration"; | 31 const char kRegistrationKey[] = "gcm.registration"; |
| 32 const char kSendersKey[] = "senders"; | 32 const char kSendersKey[] = "senders"; |
| 33 const char kRegistrationIDKey[] = "reg_id"; | 33 const char kRegistrationIDKey[] = "reg_id"; |
| 34 | 34 |
| 35 // Helper class to save tasks to run until we're ready to execute them. | 35 // Helper class to save tasks to run until we're ready to execute them. |
| 36 class GCMProfileService::DelayedTaskController { | 36 class GCMProfileService::DelayedTaskController { |
| 37 public: | 37 public: |
| 38 DelayedTaskController(); | 38 DelayedTaskController(); |
| 39 ~DelayedTaskController(); | 39 ~DelayedTaskController(); |
| 40 | 40 |
| 41 // Adds an app to non-ready list that queue all tasks to invoke until ready. | 41 // Adds an app to the tracking list. It will be first marked as non-ready. |
|
fgorski
2014/01/09 22:06:55
nit: I think "not ready" would be the proper phras
| |
| 42 // Tasks will be queued for delay execution until the app is marked as ready. | |
| 42 void AddApp(const std::string& app_id); | 43 void AddApp(const std::string& app_id); |
| 43 | 44 |
| 45 // Removes the app from the tracking list. | |
| 46 void RemoveApp(const std::string& app_id); | |
| 47 | |
| 44 // Adds a task that will be invoked once we're ready. | 48 // Adds a task that will be invoked once we're ready. |
| 45 void AddTask(const std::string& app_id, base::Closure task); | 49 void AddTask(const std::string& app_id, base::Closure task); |
| 46 | 50 |
| 47 // Marks that GCMClient is ready. | 51 // Marks that GCMClient is ready. |
| 48 void SetGCMClientReady(); | 52 void SetGCMClientReady(); |
| 49 | 53 |
| 50 // Marks that the app is ready to have operations performed. | 54 // Marks that the app is ready to have operations performed. |
| 51 void SetAppReady(const std::string& app_id); | 55 void SetAppReady(const std::string& app_id); |
| 52 | 56 |
| 53 // Returns true if it is ready to perform operations for an app. | 57 // Returns true if it is ready to perform operations for an app. |
| 54 bool CanRunTaskWithoutDelay(const std::string& app_id) const; | 58 bool CanRunTaskWithoutDelay(const std::string& app_id) const; |
| 55 | 59 |
| 60 // Returns true if the app has been tracked for readyness. | |
|
fgorski
2014/01/09 22:06:55
s/readyness/readiness/
| |
| 61 bool IsAppTracked(const std::string& app_id) const; | |
| 62 | |
| 56 private: | 63 private: |
| 57 struct AppTaskQueue { | 64 struct AppTaskQueue { |
| 58 AppTaskQueue(); | 65 AppTaskQueue(); |
| 59 ~AppTaskQueue(); | 66 ~AppTaskQueue(); |
| 60 | 67 |
| 61 // The flag that indicates if GCMProfileService completes loading the | 68 // The flag that indicates if GCMProfileService completes loading the |
| 62 // persistent data for the app. | 69 // persistent data for the app. |
| 63 bool ready; | 70 bool ready; |
| 64 | 71 |
| 65 // Tasks to be invoked upon ready. | 72 // Tasks to be invoked upon ready. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 93 delete iter->second; | 100 delete iter->second; |
| 94 } | 101 } |
| 95 } | 102 } |
| 96 | 103 |
| 97 void GCMProfileService::DelayedTaskController::AddApp( | 104 void GCMProfileService::DelayedTaskController::AddApp( |
| 98 const std::string& app_id) { | 105 const std::string& app_id) { |
| 99 DCHECK(delayed_task_map_.find(app_id) == delayed_task_map_.end()); | 106 DCHECK(delayed_task_map_.find(app_id) == delayed_task_map_.end()); |
| 100 delayed_task_map_[app_id] = new AppTaskQueue; | 107 delayed_task_map_[app_id] = new AppTaskQueue; |
| 101 } | 108 } |
| 102 | 109 |
| 110 void GCMProfileService::DelayedTaskController::RemoveApp( | |
| 111 const std::string& app_id) { | |
| 112 delayed_task_map_.erase(app_id); | |
| 113 } | |
| 114 | |
| 103 void GCMProfileService::DelayedTaskController::AddTask( | 115 void GCMProfileService::DelayedTaskController::AddTask( |
| 104 const std::string& app_id, base::Closure task) { | 116 const std::string& app_id, base::Closure task) { |
| 105 DelayedTaskMap::const_iterator iter = delayed_task_map_.find(app_id); | 117 DelayedTaskMap::const_iterator iter = delayed_task_map_.find(app_id); |
| 106 DCHECK(iter != delayed_task_map_.end()); | 118 DCHECK(iter != delayed_task_map_.end()); |
| 107 iter->second->tasks.push_back(task); | 119 iter->second->tasks.push_back(task); |
| 108 } | 120 } |
| 109 | 121 |
| 110 void GCMProfileService::DelayedTaskController::SetGCMClientReady() { | 122 void GCMProfileService::DelayedTaskController::SetGCMClientReady() { |
| 111 gcm_client_ready_ = true; | 123 gcm_client_ready_ = true; |
| 112 | 124 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 142 bool GCMProfileService::DelayedTaskController::CanRunTaskWithoutDelay( | 154 bool GCMProfileService::DelayedTaskController::CanRunTaskWithoutDelay( |
| 143 const std::string& app_id) const { | 155 const std::string& app_id) const { |
| 144 if (!gcm_client_ready_) | 156 if (!gcm_client_ready_) |
| 145 return false; | 157 return false; |
| 146 DelayedTaskMap::const_iterator iter = delayed_task_map_.find(app_id); | 158 DelayedTaskMap::const_iterator iter = delayed_task_map_.find(app_id); |
| 147 if (iter == delayed_task_map_.end()) | 159 if (iter == delayed_task_map_.end()) |
| 148 return true; | 160 return true; |
| 149 return iter->second->ready; | 161 return iter->second->ready; |
| 150 } | 162 } |
| 151 | 163 |
| 164 bool GCMProfileService::DelayedTaskController::IsAppTracked( | |
| 165 const std::string& app_id) const { | |
| 166 return delayed_task_map_.find(app_id) != delayed_task_map_.end(); | |
| 167 } | |
| 168 | |
| 152 void GCMProfileService::DelayedTaskController::RunTasks( | 169 void GCMProfileService::DelayedTaskController::RunTasks( |
| 153 AppTaskQueue* task_queue) { | 170 AppTaskQueue* task_queue) { |
| 154 DCHECK(gcm_client_ready_ && task_queue->ready); | 171 DCHECK(gcm_client_ready_ && task_queue->ready); |
| 155 | 172 |
| 156 for (size_t i = 0; i < task_queue->tasks.size(); ++i) | 173 for (size_t i = 0; i < task_queue->tasks.size(); ++i) |
| 157 task_queue->tasks[i].Run(); | 174 task_queue->tasks[i].Run(); |
| 158 task_queue->tasks.clear(); | 175 task_queue->tasks.clear(); |
| 159 } | 176 } |
| 160 | 177 |
| 161 class GCMProfileService::IOWorker | 178 class GCMProfileService::IOWorker |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 407 GCMProfileService::RegistrationInfo::~RegistrationInfo() { | 424 GCMProfileService::RegistrationInfo::~RegistrationInfo() { |
| 408 } | 425 } |
| 409 | 426 |
| 410 bool GCMProfileService::RegistrationInfo::IsValid() const { | 427 bool GCMProfileService::RegistrationInfo::IsValid() const { |
| 411 return !sender_ids.empty() && !registration_id.empty(); | 428 return !sender_ids.empty() && !registration_id.empty(); |
| 412 } | 429 } |
| 413 | 430 |
| 414 bool GCMProfileService::enable_gcm_for_testing_ = false; | 431 bool GCMProfileService::enable_gcm_for_testing_ = false; |
| 415 | 432 |
| 416 // static | 433 // static |
| 417 bool GCMProfileService::IsGCMEnabled() { | 434 bool GCMProfileService::IsGCMEnabled(Profile* profile) { |
| 435 // GCM is not enabled in incognito mode. | |
| 436 if (profile->IsOffTheRecord()) | |
| 437 return false; | |
| 438 | |
| 418 if (enable_gcm_for_testing_) | 439 if (enable_gcm_for_testing_) |
| 419 return true; | 440 return true; |
| 420 | 441 |
| 421 // GCM support is only enabled for Canary/Dev builds. | 442 // GCM support is only enabled for Canary/Dev builds. |
| 422 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); | 443 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); |
| 423 return channel == chrome::VersionInfo::CHANNEL_UNKNOWN || | 444 return channel == chrome::VersionInfo::CHANNEL_UNKNOWN || |
| 424 channel == chrome::VersionInfo::CHANNEL_CANARY || | 445 channel == chrome::VersionInfo::CHANNEL_CANARY || |
| 425 channel == chrome::VersionInfo::CHANNEL_DEV; | 446 channel == chrome::VersionInfo::CHANNEL_DEV; |
| 426 } | 447 } |
| 427 | 448 |
| 428 // static | 449 // static |
| 429 void GCMProfileService::RegisterProfilePrefs( | 450 void GCMProfileService::RegisterProfilePrefs( |
| 430 user_prefs::PrefRegistrySyncable* registry) { | 451 user_prefs::PrefRegistrySyncable* registry) { |
| 431 registry->RegisterUint64Pref( | 452 registry->RegisterUint64Pref( |
| 432 prefs::kGCMUserAccountID, | 453 prefs::kGCMUserAccountID, |
| 433 0, | 454 0, |
| 434 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 455 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 435 registry->RegisterStringPref( | 456 registry->RegisterStringPref( |
| 436 prefs::kGCMUserToken, | 457 prefs::kGCMUserToken, |
| 437 "", | 458 "", |
| 438 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 459 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 439 } | 460 } |
| 440 | 461 |
| 441 GCMProfileService::GCMProfileService(Profile* profile) | 462 GCMProfileService::GCMProfileService(Profile* profile) |
| 442 : profile_(profile), | 463 : profile_(profile), |
| 443 testing_delegate_(NULL), | 464 testing_delegate_(NULL), |
| 444 weak_ptr_factory_(this) { | 465 weak_ptr_factory_(this) { |
| 466 DCHECK(!profile->IsOffTheRecord()); | |
| 445 Init(); | 467 Init(); |
| 446 } | 468 } |
| 447 | 469 |
| 448 GCMProfileService::GCMProfileService(Profile* profile, | 470 GCMProfileService::GCMProfileService(Profile* profile, |
| 449 TestingDelegate* testing_delegate) | 471 TestingDelegate* testing_delegate) |
| 450 : profile_(profile), | 472 : profile_(profile), |
| 451 testing_delegate_(testing_delegate), | 473 testing_delegate_(testing_delegate), |
| 452 weak_ptr_factory_(this) { | 474 weak_ptr_factory_(this) { |
| 453 Init(); | 475 Init(); |
| 454 } | 476 } |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 717 // ask the server to unregister it. | 739 // ask the server to unregister it. |
| 718 RegistrationInfoMap::iterator registration_info_iter = | 740 RegistrationInfoMap::iterator registration_info_iter = |
| 719 registration_info_map_.find(app_id); | 741 registration_info_map_.find(app_id); |
| 720 if (registration_info_iter == registration_info_map_.end()) | 742 if (registration_info_iter == registration_info_map_.end()) |
| 721 return; | 743 return; |
| 722 registration_info_map_.erase(registration_info_iter); | 744 registration_info_map_.erase(registration_info_iter); |
| 723 | 745 |
| 724 // Remove the persisted registration info. | 746 // Remove the persisted registration info. |
| 725 DeleteRegistrationInfo(app_id); | 747 DeleteRegistrationInfo(app_id); |
| 726 | 748 |
| 749 // No need to track the app any more. | |
| 750 delayed_task_controller_->RemoveApp(app_id); | |
| 751 | |
| 727 // Ask the server to unregister it. There could be a small chance that the | 752 // Ask the server to unregister it. There could be a small chance that the |
| 728 // unregister request fails. If this occurs, it does not bring any harm since | 753 // unregister request fails. If this occurs, it does not bring any harm since |
| 729 // we simply reject the messages/events received from the server. | 754 // we simply reject the messages/events received from the server. |
| 730 content::BrowserThread::PostTask( | 755 content::BrowserThread::PostTask( |
| 731 content::BrowserThread::IO, | 756 content::BrowserThread::IO, |
| 732 FROM_HERE, | 757 FROM_HERE, |
| 733 base::Bind(&GCMProfileService::IOWorker::Unregister, | 758 base::Bind(&GCMProfileService::IOWorker::Unregister, |
| 734 io_worker_, | 759 io_worker_, |
| 735 app_id)); | 760 app_id)); |
| 736 } | 761 } |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 879 new base::DictionaryValue()); | 904 new base::DictionaryValue()); |
| 880 registration_info_dict->Set(kSendersKey, senders_list.release()); | 905 registration_info_dict->Set(kSendersKey, senders_list.release()); |
| 881 registration_info_dict->SetString(kRegistrationIDKey, | 906 registration_info_dict->SetString(kRegistrationIDKey, |
| 882 registration_info.registration_id); | 907 registration_info.registration_id); |
| 883 | 908 |
| 884 storage->SetExtensionValue( | 909 storage->SetExtensionValue( |
| 885 app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>()); | 910 app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>()); |
| 886 } | 911 } |
| 887 | 912 |
| 888 void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) { | 913 void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) { |
| 914 // This function can be called more than once when the app is allowed in | |
| 915 // incognito and the extension service reloads the app. | |
| 916 if (delayed_task_controller_->IsAppTracked(app_id)) | |
| 917 return; | |
| 918 | |
| 919 delayed_task_controller_->AddApp(app_id); | |
| 920 | |
| 889 extensions::StateStore* storage = | 921 extensions::StateStore* storage = |
| 890 extensions::ExtensionSystem::Get(profile_)->state_store(); | 922 extensions::ExtensionSystem::Get(profile_)->state_store(); |
| 891 DCHECK(storage); | 923 DCHECK(storage); |
| 892 | |
| 893 delayed_task_controller_->AddApp(app_id); | |
| 894 | |
| 895 storage->GetExtensionValue( | 924 storage->GetExtensionValue( |
| 896 app_id, | 925 app_id, |
| 897 kRegistrationKey, | 926 kRegistrationKey, |
| 898 base::Bind( | 927 base::Bind( |
| 899 &GCMProfileService::ReadRegistrationInfoFinished, | 928 &GCMProfileService::ReadRegistrationInfoFinished, |
| 900 weak_ptr_factory_.GetWeakPtr(), | 929 weak_ptr_factory_.GetWeakPtr(), |
| 901 app_id)); | 930 app_id)); |
| 902 } | 931 } |
| 903 | 932 |
| 904 void GCMProfileService::ReadRegistrationInfoFinished( | 933 void GCMProfileService::ReadRegistrationInfoFinished( |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 939 | 968 |
| 940 return true; | 969 return true; |
| 941 } | 970 } |
| 942 | 971 |
| 943 // static | 972 // static |
| 944 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() { | 973 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() { |
| 945 return kRegistrationKey; | 974 return kRegistrationKey; |
| 946 } | 975 } |
| 947 | 976 |
| 948 } // namespace gcm | 977 } // namespace gcm |
| OLD | NEW |