| 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 not ready. |
| 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 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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 GCMProfileService::RegistrationInfo::~RegistrationInfo() { | 425 GCMProfileService::RegistrationInfo::~RegistrationInfo() { |
| 409 } | 426 } |
| 410 | 427 |
| 411 bool GCMProfileService::RegistrationInfo::IsValid() const { | 428 bool GCMProfileService::RegistrationInfo::IsValid() const { |
| 412 return !sender_ids.empty() && !registration_id.empty(); | 429 return !sender_ids.empty() && !registration_id.empty(); |
| 413 } | 430 } |
| 414 | 431 |
| 415 bool GCMProfileService::enable_gcm_for_testing_ = false; | 432 bool GCMProfileService::enable_gcm_for_testing_ = false; |
| 416 | 433 |
| 417 // static | 434 // static |
| 418 bool GCMProfileService::IsGCMEnabled() { | 435 bool GCMProfileService::IsGCMEnabled(Profile* profile) { |
| 436 // GCM is not enabled in incognito mode. |
| 437 if (profile->IsOffTheRecord()) |
| 438 return false; |
| 439 |
| 419 if (enable_gcm_for_testing_) | 440 if (enable_gcm_for_testing_) |
| 420 return true; | 441 return true; |
| 421 | 442 |
| 422 // GCM support is only enabled for Canary/Dev builds. | 443 // GCM support is only enabled for Canary/Dev builds. |
| 423 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); | 444 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); |
| 424 return channel == chrome::VersionInfo::CHANNEL_UNKNOWN || | 445 return channel == chrome::VersionInfo::CHANNEL_UNKNOWN || |
| 425 channel == chrome::VersionInfo::CHANNEL_CANARY || | 446 channel == chrome::VersionInfo::CHANNEL_CANARY || |
| 426 channel == chrome::VersionInfo::CHANNEL_DEV; | 447 channel == chrome::VersionInfo::CHANNEL_DEV; |
| 427 } | 448 } |
| 428 | 449 |
| 429 // static | 450 // static |
| 430 void GCMProfileService::RegisterProfilePrefs( | 451 void GCMProfileService::RegisterProfilePrefs( |
| 431 user_prefs::PrefRegistrySyncable* registry) { | 452 user_prefs::PrefRegistrySyncable* registry) { |
| 432 registry->RegisterUint64Pref( | 453 registry->RegisterUint64Pref( |
| 433 prefs::kGCMUserAccountID, | 454 prefs::kGCMUserAccountID, |
| 434 0, | 455 0, |
| 435 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 456 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 436 registry->RegisterStringPref( | 457 registry->RegisterStringPref( |
| 437 prefs::kGCMUserToken, | 458 prefs::kGCMUserToken, |
| 438 "", | 459 "", |
| 439 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 460 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 440 } | 461 } |
| 441 | 462 |
| 442 GCMProfileService::GCMProfileService(Profile* profile) | 463 GCMProfileService::GCMProfileService(Profile* profile) |
| 443 : profile_(profile), | 464 : profile_(profile), |
| 444 testing_delegate_(NULL), | 465 testing_delegate_(NULL), |
| 445 weak_ptr_factory_(this) { | 466 weak_ptr_factory_(this) { |
| 467 DCHECK(!profile->IsOffTheRecord()); |
| 446 Init(); | 468 Init(); |
| 447 } | 469 } |
| 448 | 470 |
| 449 GCMProfileService::GCMProfileService(Profile* profile, | 471 GCMProfileService::GCMProfileService(Profile* profile, |
| 450 TestingDelegate* testing_delegate) | 472 TestingDelegate* testing_delegate) |
| 451 : profile_(profile), | 473 : profile_(profile), |
| 452 testing_delegate_(testing_delegate), | 474 testing_delegate_(testing_delegate), |
| 453 weak_ptr_factory_(this) { | 475 weak_ptr_factory_(this) { |
| 454 Init(); | 476 Init(); |
| 455 } | 477 } |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 // ask the server to unregister it. | 740 // ask the server to unregister it. |
| 719 RegistrationInfoMap::iterator registration_info_iter = | 741 RegistrationInfoMap::iterator registration_info_iter = |
| 720 registration_info_map_.find(app_id); | 742 registration_info_map_.find(app_id); |
| 721 if (registration_info_iter == registration_info_map_.end()) | 743 if (registration_info_iter == registration_info_map_.end()) |
| 722 return; | 744 return; |
| 723 registration_info_map_.erase(registration_info_iter); | 745 registration_info_map_.erase(registration_info_iter); |
| 724 | 746 |
| 725 // Remove the persisted registration info. | 747 // Remove the persisted registration info. |
| 726 DeleteRegistrationInfo(app_id); | 748 DeleteRegistrationInfo(app_id); |
| 727 | 749 |
| 750 // No need to track the app any more. |
| 751 delayed_task_controller_->RemoveApp(app_id); |
| 752 |
| 728 // Ask the server to unregister it. There could be a small chance that the | 753 // Ask the server to unregister it. There could be a small chance that the |
| 729 // unregister request fails. If this occurs, it does not bring any harm since | 754 // unregister request fails. If this occurs, it does not bring any harm since |
| 730 // we simply reject the messages/events received from the server. | 755 // we simply reject the messages/events received from the server. |
| 731 content::BrowserThread::PostTask( | 756 content::BrowserThread::PostTask( |
| 732 content::BrowserThread::IO, | 757 content::BrowserThread::IO, |
| 733 FROM_HERE, | 758 FROM_HERE, |
| 734 base::Bind(&GCMProfileService::IOWorker::Unregister, | 759 base::Bind(&GCMProfileService::IOWorker::Unregister, |
| 735 io_worker_, | 760 io_worker_, |
| 736 app_id)); | 761 app_id)); |
| 737 } | 762 } |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 new base::DictionaryValue()); | 905 new base::DictionaryValue()); |
| 881 registration_info_dict->Set(kSendersKey, senders_list.release()); | 906 registration_info_dict->Set(kSendersKey, senders_list.release()); |
| 882 registration_info_dict->SetString(kRegistrationIDKey, | 907 registration_info_dict->SetString(kRegistrationIDKey, |
| 883 registration_info.registration_id); | 908 registration_info.registration_id); |
| 884 | 909 |
| 885 storage->SetExtensionValue( | 910 storage->SetExtensionValue( |
| 886 app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>()); | 911 app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>()); |
| 887 } | 912 } |
| 888 | 913 |
| 889 void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) { | 914 void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) { |
| 915 // This function can be called more than once when the app is allowed in |
| 916 // incognito and the extension service reloads the app. |
| 917 if (delayed_task_controller_->IsAppTracked(app_id)) |
| 918 return; |
| 919 |
| 920 delayed_task_controller_->AddApp(app_id); |
| 921 |
| 890 extensions::StateStore* storage = | 922 extensions::StateStore* storage = |
| 891 extensions::ExtensionSystem::Get(profile_)->state_store(); | 923 extensions::ExtensionSystem::Get(profile_)->state_store(); |
| 892 DCHECK(storage); | 924 DCHECK(storage); |
| 893 | |
| 894 delayed_task_controller_->AddApp(app_id); | |
| 895 | |
| 896 storage->GetExtensionValue( | 925 storage->GetExtensionValue( |
| 897 app_id, | 926 app_id, |
| 898 kRegistrationKey, | 927 kRegistrationKey, |
| 899 base::Bind( | 928 base::Bind( |
| 900 &GCMProfileService::ReadRegistrationInfoFinished, | 929 &GCMProfileService::ReadRegistrationInfoFinished, |
| 901 weak_ptr_factory_.GetWeakPtr(), | 930 weak_ptr_factory_.GetWeakPtr(), |
| 902 app_id)); | 931 app_id)); |
| 903 } | 932 } |
| 904 | 933 |
| 905 void GCMProfileService::ReadRegistrationInfoFinished( | 934 void GCMProfileService::ReadRegistrationInfoFinished( |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 | 969 |
| 941 return true; | 970 return true; |
| 942 } | 971 } |
| 943 | 972 |
| 944 // static | 973 // static |
| 945 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() { | 974 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() { |
| 946 return kRegistrationKey; | 975 return kRegistrationKey; |
| 947 } | 976 } |
| 948 | 977 |
| 949 } // namespace gcm | 978 } // namespace gcm |
| OLD | NEW |