| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/base64.h" | 11 #include "base/base64.h" |
| 12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/path_service.h" | 14 #include "base/path_service.h" |
| 15 #include "base/prefs/pref_service.h" | 15 #include "base/prefs/pref_service.h" |
| 16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/threading/sequenced_worker_pool.h" | 17 #include "base/threading/sequenced_worker_pool.h" |
| 18 #include "chrome/browser/chrome_notification_types.h" | 18 #include "chrome/browser/chrome_notification_types.h" |
| 19 #include "chrome/browser/extensions/state_store.h" | |
| 20 #include "chrome/browser/services/gcm/gcm_app_handler.h" | 19 #include "chrome/browser/services/gcm/gcm_app_handler.h" |
| 21 #include "chrome/browser/services/gcm/gcm_client_factory.h" | 20 #include "chrome/browser/services/gcm/gcm_client_factory.h" |
| 22 #include "chrome/browser/signin/profile_oauth2_token_service.h" | 21 #include "chrome/browser/signin/profile_oauth2_token_service.h" |
| 23 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" | 22 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" |
| 24 #include "chrome/browser/signin/signin_manager.h" | 23 #include "chrome/browser/signin/signin_manager.h" |
| 25 #include "chrome/browser/signin/signin_manager_factory.h" | 24 #include "chrome/browser/signin/signin_manager_factory.h" |
| 26 #include "chrome/common/chrome_constants.h" | 25 #include "chrome/common/chrome_constants.h" |
| 27 #include "chrome/common/chrome_paths.h" | 26 #include "chrome/common/chrome_paths.h" |
| 28 #include "chrome/common/chrome_version_info.h" | 27 #include "chrome/common/chrome_version_info.h" |
| 29 #include "chrome/common/pref_names.h" | 28 #include "chrome/common/pref_names.h" |
| 30 #include "components/user_prefs/pref_registry_syncable.h" | 29 #include "components/user_prefs/pref_registry_syncable.h" |
| 31 #include "content/public/browser/browser_thread.h" | 30 #include "content/public/browser/browser_thread.h" |
| 32 #include "content/public/browser/notification_details.h" | 31 #include "content/public/browser/notification_details.h" |
| 33 #include "content/public/browser/notification_source.h" | 32 #include "content/public/browser/notification_source.h" |
| 34 #include "extensions/browser/extension_system.h" | |
| 35 #include "google_apis/gcm/protocol/android_checkin.pb.h" | 33 #include "google_apis/gcm/protocol/android_checkin.pb.h" |
| 36 #include "net/url_request/url_request_context_getter.h" | 34 #include "net/url_request/url_request_context_getter.h" |
| 37 | 35 |
| 38 namespace gcm { | 36 namespace gcm { |
| 39 | 37 |
| 40 namespace { | 38 namespace { |
| 41 | 39 |
| 42 const char kRegistrationKey[] = "gcm.registration"; | |
| 43 const char kSendersKey[] = "senders"; | |
| 44 const char kRegistrationIDKey[] = "reg_id"; | |
| 45 | |
| 46 checkin_proto::ChromeBuildProto_Platform GetPlatform() { | 40 checkin_proto::ChromeBuildProto_Platform GetPlatform() { |
| 47 #if defined(OS_WIN) | 41 #if defined(OS_WIN) |
| 48 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN; | 42 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN; |
| 49 #elif defined(OS_MACOSX) | 43 #elif defined(OS_MACOSX) |
| 50 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_MAC; | 44 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_MAC; |
| 51 #elif defined(OS_CHROMEOS) | 45 #elif defined(OS_CHROMEOS) |
| 52 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_CROS; | 46 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_CROS; |
| 53 #elif defined(OS_LINUX) | 47 #elif defined(OS_LINUX) |
| 54 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_LINUX; | 48 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_LINUX; |
| 55 #else | 49 #else |
| (...skipping 27 matching lines...) Expand all Loading... |
| 83 } | 77 } |
| 84 | 78 |
| 85 } // namespace | 79 } // namespace |
| 86 | 80 |
| 87 // Helper class to save tasks to run until we're ready to execute them. | 81 // Helper class to save tasks to run until we're ready to execute them. |
| 88 class GCMProfileService::DelayedTaskController { | 82 class GCMProfileService::DelayedTaskController { |
| 89 public: | 83 public: |
| 90 DelayedTaskController(); | 84 DelayedTaskController(); |
| 91 ~DelayedTaskController(); | 85 ~DelayedTaskController(); |
| 92 | 86 |
| 93 // Adds an app to the tracking list. It will be first marked as not ready. | 87 // Adds a task that will be invoked once we're ready. |
| 94 // Tasks will be queued for delay execution until the app is marked as ready. | 88 void AddTask(base::Closure task); |
| 95 void AddApp(const std::string& app_id); | |
| 96 | 89 |
| 97 // Removes the app from the tracking list. | 90 // Sets ready status. It is ready only when check-in is completed and |
| 98 void RemoveApp(const std::string& app_id); | 91 // the GCMClient is fully initialized. |
| 92 void SetReady(); |
| 99 | 93 |
| 100 // Adds a task that will be invoked once we're ready. | 94 // Returns true if it is ready to perform tasks. |
| 101 void AddTask(const std::string& app_id, base::Closure task); | 95 bool CanRunTaskWithoutDelay() const; |
| 102 | |
| 103 // Sets GCM ready status. GCM is ready only when check-in is completed and | |
| 104 // the GCMClient is fully initialized. If it is set to ready for the first | |
| 105 // time, all the pending tasks for any ready apps will be run. | |
| 106 void SetGCMReady(); | |
| 107 | |
| 108 // Sets ready status for the app. If GCM is already ready, all the pending | |
| 109 // tasks for this app will be run. | |
| 110 void SetAppReady(const std::string& app_id); | |
| 111 | |
| 112 // Returns true if it is ready to perform operations for an app. | |
| 113 bool CanRunTaskWithoutDelay(const std::string& app_id) const; | |
| 114 | |
| 115 // Returns true if the app has been tracked for readiness. | |
| 116 bool IsAppTracked(const std::string& app_id) const; | |
| 117 | 96 |
| 118 private: | 97 private: |
| 119 struct AppTaskQueue { | 98 void RunTasks(); |
| 120 AppTaskQueue(); | |
| 121 ~AppTaskQueue(); | |
| 122 | 99 |
| 123 // The flag that indicates if GCMClient is ready. | 100 // Flag that indicates that GCM is ready. |
| 124 bool ready; | 101 bool ready_; |
| 125 | 102 |
| 126 // Tasks to be invoked upon ready. | 103 std::vector<base::Closure> delayed_tasks_; |
| 127 std::vector<base::Closure> tasks; | |
| 128 }; | |
| 129 | |
| 130 void RunTasks(AppTaskQueue* task_queue); | |
| 131 | |
| 132 // Flag that indicates that GCM is done. | |
| 133 bool gcm_ready_; | |
| 134 | |
| 135 // Map from app_id to AppTaskQueue storing the tasks that will be invoked | |
| 136 // when both GCM and the app get ready. | |
| 137 typedef std::map<std::string, AppTaskQueue*> DelayedTaskMap; | |
| 138 DelayedTaskMap delayed_task_map_; | |
| 139 }; | 104 }; |
| 140 | 105 |
| 141 GCMProfileService::DelayedTaskController::AppTaskQueue::AppTaskQueue() | |
| 142 : ready(false) { | |
| 143 } | |
| 144 | |
| 145 GCMProfileService::DelayedTaskController::AppTaskQueue::~AppTaskQueue() { | |
| 146 } | |
| 147 | |
| 148 GCMProfileService::DelayedTaskController::DelayedTaskController() | 106 GCMProfileService::DelayedTaskController::DelayedTaskController() |
| 149 : gcm_ready_(false) { | 107 : ready_(false) { |
| 150 } | 108 } |
| 151 | 109 |
| 152 GCMProfileService::DelayedTaskController::~DelayedTaskController() { | 110 GCMProfileService::DelayedTaskController::~DelayedTaskController() { |
| 153 for (DelayedTaskMap::const_iterator iter = delayed_task_map_.begin(); | |
| 154 iter != delayed_task_map_.end(); ++iter) { | |
| 155 delete iter->second; | |
| 156 } | |
| 157 } | 111 } |
| 158 | 112 |
| 159 void GCMProfileService::DelayedTaskController::AddApp( | 113 void GCMProfileService::DelayedTaskController::AddTask(base::Closure task) { |
| 160 const std::string& app_id) { | 114 delayed_tasks_.push_back(task); |
| 161 DCHECK(delayed_task_map_.find(app_id) == delayed_task_map_.end()); | |
| 162 delayed_task_map_[app_id] = new AppTaskQueue; | |
| 163 } | 115 } |
| 164 | 116 |
| 165 void GCMProfileService::DelayedTaskController::RemoveApp( | 117 void GCMProfileService::DelayedTaskController::SetReady() { |
| 166 const std::string& app_id) { | 118 ready_ = true; |
| 167 DelayedTaskMap::iterator iter = delayed_task_map_.find(app_id); | 119 RunTasks(); |
| 168 if (iter == delayed_task_map_.end()) | |
| 169 return; | |
| 170 delete iter->second; | |
| 171 delayed_task_map_.erase(iter); | |
| 172 } | 120 } |
| 173 | 121 |
| 174 void GCMProfileService::DelayedTaskController::AddTask( | 122 bool GCMProfileService::DelayedTaskController::CanRunTaskWithoutDelay() const { |
| 175 const std::string& app_id, base::Closure task) { | 123 return ready_; |
| 176 DelayedTaskMap::const_iterator iter = delayed_task_map_.find(app_id); | |
| 177 DCHECK(iter != delayed_task_map_.end()); | |
| 178 iter->second->tasks.push_back(task); | |
| 179 } | 124 } |
| 180 | 125 |
| 181 void GCMProfileService::DelayedTaskController::SetGCMReady() { | 126 void GCMProfileService::DelayedTaskController::RunTasks() { |
| 182 gcm_ready_ = true; | 127 DCHECK(ready_); |
| 183 | 128 |
| 184 for (DelayedTaskMap::iterator iter = delayed_task_map_.begin(); | 129 for (size_t i = 0; i < delayed_tasks_.size(); ++i) |
| 185 iter != delayed_task_map_.end(); ++iter) { | 130 delayed_tasks_[i].Run(); |
| 186 if (iter->second->ready) | 131 delayed_tasks_.clear(); |
| 187 RunTasks(iter->second); | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 void GCMProfileService::DelayedTaskController::SetAppReady( | |
| 192 const std::string& app_id) { | |
| 193 DelayedTaskMap::iterator iter = delayed_task_map_.find(app_id); | |
| 194 DCHECK(iter != delayed_task_map_.end()); | |
| 195 | |
| 196 AppTaskQueue* task_queue = iter->second; | |
| 197 DCHECK(task_queue); | |
| 198 task_queue->ready = true; | |
| 199 | |
| 200 if (gcm_ready_) | |
| 201 RunTasks(task_queue); | |
| 202 } | |
| 203 | |
| 204 bool GCMProfileService::DelayedTaskController::CanRunTaskWithoutDelay( | |
| 205 const std::string& app_id) const { | |
| 206 if (!gcm_ready_) | |
| 207 return false; | |
| 208 DelayedTaskMap::const_iterator iter = delayed_task_map_.find(app_id); | |
| 209 if (iter == delayed_task_map_.end()) | |
| 210 return true; | |
| 211 return iter->second->ready; | |
| 212 } | |
| 213 | |
| 214 bool GCMProfileService::DelayedTaskController::IsAppTracked( | |
| 215 const std::string& app_id) const { | |
| 216 return delayed_task_map_.find(app_id) != delayed_task_map_.end(); | |
| 217 } | |
| 218 | |
| 219 void GCMProfileService::DelayedTaskController::RunTasks( | |
| 220 AppTaskQueue* task_queue) { | |
| 221 DCHECK(gcm_ready_ && task_queue->ready); | |
| 222 | |
| 223 for (size_t i = 0; i < task_queue->tasks.size(); ++i) | |
| 224 task_queue->tasks[i].Run(); | |
| 225 task_queue->tasks.clear(); | |
| 226 } | 132 } |
| 227 | 133 |
| 228 class GCMProfileService::IOWorker | 134 class GCMProfileService::IOWorker |
| 229 : public GCMClient::Delegate, | 135 : public GCMClient::Delegate, |
| 230 public base::RefCountedThreadSafe<GCMProfileService::IOWorker>{ | 136 public base::RefCountedThreadSafe<GCMProfileService::IOWorker>{ |
| 231 public: | 137 public: |
| 232 // Called on UI thread. | 138 // Called on UI thread. |
| 233 IOWorker(); | 139 IOWorker(); |
| 234 | 140 |
| 235 // Overridden from GCMClient::Delegate: | 141 // Overridden from GCMClient::Delegate: |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 case GCMProfileService::ENABLED_FOR_APPS: | 393 case GCMProfileService::ENABLED_FOR_APPS: |
| 488 return "ENABLED_FOR_APPS"; | 394 return "ENABLED_FOR_APPS"; |
| 489 case GCMProfileService::ALWAYS_DISABLED: | 395 case GCMProfileService::ALWAYS_DISABLED: |
| 490 return "ALWAYS_DISABLED"; | 396 return "ALWAYS_DISABLED"; |
| 491 default: | 397 default: |
| 492 NOTREACHED(); | 398 NOTREACHED(); |
| 493 return std::string(); | 399 return std::string(); |
| 494 } | 400 } |
| 495 } | 401 } |
| 496 | 402 |
| 497 GCMProfileService::RegistrationInfo::RegistrationInfo() { | |
| 498 } | |
| 499 | |
| 500 GCMProfileService::RegistrationInfo::~RegistrationInfo() { | |
| 501 } | |
| 502 | |
| 503 bool GCMProfileService::RegistrationInfo::IsValid() const { | |
| 504 return !sender_ids.empty() && !registration_id.empty(); | |
| 505 } | |
| 506 | |
| 507 // static | 403 // static |
| 508 GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState( | 404 GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState( |
| 509 Profile* profile) { | 405 Profile* profile) { |
| 510 const base::Value* gcm_enabled_value = | 406 const base::Value* gcm_enabled_value = |
| 511 profile->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled); | 407 profile->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled); |
| 512 if (!gcm_enabled_value) | 408 if (!gcm_enabled_value) |
| 513 return ENABLED_FOR_APPS; | 409 return ENABLED_FOR_APPS; |
| 514 | 410 |
| 515 bool gcm_enabled = false; | 411 bool gcm_enabled = false; |
| 516 if (!gcm_enabled_value->GetAsBoolean(&gcm_enabled)) | 412 if (!gcm_enabled_value->GetAsBoolean(&gcm_enabled)) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 527 bool on_by_default = false; | 423 bool on_by_default = false; |
| 528 if (channel == chrome::VersionInfo::CHANNEL_UNKNOWN || | 424 if (channel == chrome::VersionInfo::CHANNEL_UNKNOWN || |
| 529 channel == chrome::VersionInfo::CHANNEL_CANARY || | 425 channel == chrome::VersionInfo::CHANNEL_CANARY || |
| 530 channel == chrome::VersionInfo::CHANNEL_DEV) { | 426 channel == chrome::VersionInfo::CHANNEL_DEV) { |
| 531 on_by_default = true; | 427 on_by_default = true; |
| 532 } | 428 } |
| 533 registry->RegisterBooleanPref( | 429 registry->RegisterBooleanPref( |
| 534 prefs::kGCMChannelEnabled, | 430 prefs::kGCMChannelEnabled, |
| 535 on_by_default, | 431 on_by_default, |
| 536 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 432 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 537 registry->RegisterListPref( | |
| 538 prefs::kGCMRegisteredAppIDs, | |
| 539 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
| 540 } | 433 } |
| 541 | 434 |
| 542 GCMProfileService::GCMProfileService(Profile* profile) | 435 GCMProfileService::GCMProfileService(Profile* profile) |
| 543 : profile_(profile), | 436 : profile_(profile), |
| 544 gcm_client_ready_(false), | 437 gcm_client_ready_(false), |
| 545 weak_ptr_factory_(this) { | 438 weak_ptr_factory_(this) { |
| 546 DCHECK(!profile->IsOffTheRecord()); | 439 DCHECK(!profile->IsOffTheRecord()); |
| 547 } | 440 } |
| 548 | 441 |
| 549 GCMProfileService::~GCMProfileService() { | 442 GCMProfileService::~GCMProfileService() { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 | 538 |
| 646 // If previous un/register operation is still in progress, bail out. | 539 // If previous un/register operation is still in progress, bail out. |
| 647 if (IsAsyncOperationPending(app_id)) { | 540 if (IsAsyncOperationPending(app_id)) { |
| 648 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); | 541 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); |
| 649 return; | 542 return; |
| 650 } | 543 } |
| 651 | 544 |
| 652 register_callbacks_[app_id] = callback; | 545 register_callbacks_[app_id] = callback; |
| 653 | 546 |
| 654 // Delay the register operation until GCMClient is ready. | 547 // Delay the register operation until GCMClient is ready. |
| 655 if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) { | 548 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { |
| 656 delayed_task_controller_->AddTask( | 549 delayed_task_controller_->AddTask( |
| 657 app_id, | |
| 658 base::Bind(&GCMProfileService::DoRegister, | 550 base::Bind(&GCMProfileService::DoRegister, |
| 659 weak_ptr_factory_.GetWeakPtr(), | 551 weak_ptr_factory_.GetWeakPtr(), |
| 660 app_id, | 552 app_id, |
| 661 sender_ids)); | 553 sender_ids)); |
| 662 return; | 554 return; |
| 663 } | 555 } |
| 664 | 556 |
| 665 DoRegister(app_id, sender_ids); | 557 DoRegister(app_id, sender_ids); |
| 666 } | 558 } |
| 667 | 559 |
| 668 void GCMProfileService::DoRegister(const std::string& app_id, | 560 void GCMProfileService::DoRegister(const std::string& app_id, |
| 669 const std::vector<std::string>& sender_ids) { | 561 const std::vector<std::string>& sender_ids) { |
| 670 std::map<std::string, RegisterCallback>::iterator callback_iter = | 562 std::map<std::string, RegisterCallback>::iterator callback_iter = |
| 671 register_callbacks_.find(app_id); | 563 register_callbacks_.find(app_id); |
| 672 if (callback_iter == register_callbacks_.end()) { | 564 if (callback_iter == register_callbacks_.end()) { |
| 673 // The callback could have been removed when the app is uninstalled. | 565 // The callback could have been removed when the app is uninstalled. |
| 674 return; | 566 return; |
| 675 } | 567 } |
| 676 | 568 |
| 677 // Normalize the sender IDs by making them sorted. | 569 // Normalize the sender IDs by making them sorted. |
| 678 std::vector<std::string> normalized_sender_ids = sender_ids; | 570 std::vector<std::string> normalized_sender_ids = sender_ids; |
| 679 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end()); | 571 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end()); |
| 680 | 572 |
| 681 // If the same sender ids is provided, return the cached registration ID | |
| 682 // directly. | |
| 683 RegistrationInfoMap::const_iterator registration_info_iter = | |
| 684 registration_info_map_.find(app_id); | |
| 685 if (registration_info_iter != registration_info_map_.end() && | |
| 686 registration_info_iter->second.sender_ids == normalized_sender_ids) { | |
| 687 RegisterCallback callback = callback_iter->second; | |
| 688 register_callbacks_.erase(callback_iter); | |
| 689 callback.Run(registration_info_iter->second.registration_id, | |
| 690 GCMClient::SUCCESS); | |
| 691 return; | |
| 692 } | |
| 693 | |
| 694 // Cache the sender IDs. The registration ID will be filled when the | |
| 695 // registration completes. | |
| 696 RegistrationInfo registration_info; | |
| 697 registration_info.sender_ids = normalized_sender_ids; | |
| 698 registration_info_map_[app_id] = registration_info; | |
| 699 | |
| 700 // Save the IDs of all registered apps such that we know what to remove from | |
| 701 // the the app's state store when the profile is signed out. | |
| 702 WriteRegisteredAppIDs(); | |
| 703 | |
| 704 content::BrowserThread::PostTask( | 573 content::BrowserThread::PostTask( |
| 705 content::BrowserThread::IO, | 574 content::BrowserThread::IO, |
| 706 FROM_HERE, | 575 FROM_HERE, |
| 707 base::Bind(&GCMProfileService::IOWorker::Register, | 576 base::Bind(&GCMProfileService::IOWorker::Register, |
| 708 io_worker_, | 577 io_worker_, |
| 709 app_id, | 578 app_id, |
| 710 normalized_sender_ids)); | 579 normalized_sender_ids)); |
| 711 } | 580 } |
| 712 | 581 |
| 713 void GCMProfileService::Unregister(const std::string& app_id, | 582 void GCMProfileService::Unregister(const std::string& app_id, |
| 714 UnregisterCallback callback) { | 583 UnregisterCallback callback) { |
| 715 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 584 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 716 DCHECK(!app_id.empty() && !callback.is_null()); | 585 DCHECK(!app_id.empty() && !callback.is_null()); |
| 717 | 586 |
| 718 GCMClient::Result result = EnsureAppReady(app_id); | 587 GCMClient::Result result = EnsureAppReady(app_id); |
| 719 if (result != GCMClient::SUCCESS) { | 588 if (result != GCMClient::SUCCESS) { |
| 720 callback.Run(result); | 589 callback.Run(result); |
| 721 return; | 590 return; |
| 722 } | 591 } |
| 723 | 592 |
| 724 // If previous un/register operation is still in progress, bail out. | 593 // If previous un/register operation is still in progress, bail out. |
| 725 if (IsAsyncOperationPending(app_id)) { | 594 if (IsAsyncOperationPending(app_id)) { |
| 726 callback.Run(GCMClient::ASYNC_OPERATION_PENDING); | 595 callback.Run(GCMClient::ASYNC_OPERATION_PENDING); |
| 727 return; | 596 return; |
| 728 } | 597 } |
| 729 | 598 |
| 730 unregister_callbacks_[app_id] = callback; | 599 unregister_callbacks_[app_id] = callback; |
| 731 | 600 |
| 732 // Delay the unregister operation until GCMClient is ready. | 601 // Delay the unregister operation until GCMClient is ready. |
| 733 if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) { | 602 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { |
| 734 delayed_task_controller_->AddTask( | 603 delayed_task_controller_->AddTask( |
| 735 app_id, | |
| 736 base::Bind(&GCMProfileService::DoUnregister, | 604 base::Bind(&GCMProfileService::DoUnregister, |
| 737 weak_ptr_factory_.GetWeakPtr(), | 605 weak_ptr_factory_.GetWeakPtr(), |
| 738 app_id)); | 606 app_id)); |
| 739 return; | 607 return; |
| 740 } | 608 } |
| 741 | 609 |
| 742 DoUnregister(app_id); | 610 DoUnregister(app_id); |
| 743 } | 611 } |
| 744 | 612 |
| 745 void GCMProfileService::DoUnregister(const std::string& app_id) { | 613 void GCMProfileService::DoUnregister(const std::string& app_id) { |
| 746 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 614 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 747 | 615 |
| 748 // Unregister might be triggered in response to a message that is missing | |
| 749 // recipient and in that case there will not be an entry in the map. | |
| 750 RegistrationInfoMap::iterator registration_info_iter = | |
| 751 registration_info_map_.find(app_id); | |
| 752 if (registration_info_iter != registration_info_map_.end()) { | |
| 753 registration_info_map_.erase(registration_info_iter); | |
| 754 | |
| 755 // Update the persisted IDs of registered apps. | |
| 756 WriteRegisteredAppIDs(); | |
| 757 | |
| 758 // Remove the persisted registration info. | |
| 759 DeleteRegistrationInfo(app_id); | |
| 760 | |
| 761 // No need to track the app any more. | |
| 762 delayed_task_controller_->RemoveApp(app_id); | |
| 763 } | |
| 764 | |
| 765 // Ask the server to unregister it. There could be a small chance that the | 616 // Ask the server to unregister it. There could be a small chance that the |
| 766 // unregister request fails. If this occurs, it does not bring any harm since | 617 // unregister request fails. If this occurs, it does not bring any harm since |
| 767 // we simply reject the messages/events received from the server. | 618 // we simply reject the messages/events received from the server. |
| 768 content::BrowserThread::PostTask( | 619 content::BrowserThread::PostTask( |
| 769 content::BrowserThread::IO, | 620 content::BrowserThread::IO, |
| 770 FROM_HERE, | 621 FROM_HERE, |
| 771 base::Bind(&GCMProfileService::IOWorker::Unregister, | 622 base::Bind(&GCMProfileService::IOWorker::Unregister, |
| 772 io_worker_, | 623 io_worker_, |
| 773 app_id)); | 624 app_id)); |
| 774 } | 625 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 789 // If the message with send ID is still in progress, bail out. | 640 // If the message with send ID is still in progress, bail out. |
| 790 std::pair<std::string, std::string> key(app_id, message.id); | 641 std::pair<std::string, std::string> key(app_id, message.id); |
| 791 if (send_callbacks_.find(key) != send_callbacks_.end()) { | 642 if (send_callbacks_.find(key) != send_callbacks_.end()) { |
| 792 callback.Run(message.id, GCMClient::INVALID_PARAMETER); | 643 callback.Run(message.id, GCMClient::INVALID_PARAMETER); |
| 793 return; | 644 return; |
| 794 } | 645 } |
| 795 | 646 |
| 796 send_callbacks_[key] = callback; | 647 send_callbacks_[key] = callback; |
| 797 | 648 |
| 798 // Delay the send operation until all GCMClient is ready. | 649 // Delay the send operation until all GCMClient is ready. |
| 799 if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) { | 650 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { |
| 800 delayed_task_controller_->AddTask( | 651 delayed_task_controller_->AddTask( |
| 801 app_id, | |
| 802 base::Bind(&GCMProfileService::DoSend, | 652 base::Bind(&GCMProfileService::DoSend, |
| 803 weak_ptr_factory_.GetWeakPtr(), | 653 weak_ptr_factory_.GetWeakPtr(), |
| 804 app_id, | 654 app_id, |
| 805 receiver_id, | 655 receiver_id, |
| 806 message)); | 656 message)); |
| 807 return; | 657 return; |
| 808 } | 658 } |
| 809 | 659 |
| 810 DoSend(app_id, receiver_id, message); | 660 DoSend(app_id, receiver_id, message); |
| 811 } | 661 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 883 // CheckIn could be called more than once when: | 733 // CheckIn could be called more than once when: |
| 884 // 1) The password changes. | 734 // 1) The password changes. |
| 885 // 2) Register/send function calls it to ensure CheckIn is done. | 735 // 2) Register/send function calls it to ensure CheckIn is done. |
| 886 if (username_ == username) | 736 if (username_ == username) |
| 887 return; | 737 return; |
| 888 username_ = username; | 738 username_ = username; |
| 889 | 739 |
| 890 DCHECK(!delayed_task_controller_); | 740 DCHECK(!delayed_task_controller_); |
| 891 delayed_task_controller_.reset(new DelayedTaskController); | 741 delayed_task_controller_.reset(new DelayedTaskController); |
| 892 | 742 |
| 893 // Load all the registered apps. | |
| 894 ReadRegisteredAppIDs(); | |
| 895 | |
| 896 // This will load the data from the gcm store and trigger the check-in if | 743 // This will load the data from the gcm store and trigger the check-in if |
| 897 // the persisted check-in info is not found. | 744 // the persisted check-in info is not found. |
| 898 // Note that we need to pass weak pointer again since the existing weak | 745 // Note that we need to pass weak pointer again since the existing weak |
| 899 // pointer in IOWorker might have been invalidated when check-out occurs. | 746 // pointer in IOWorker might have been invalidated when check-out occurs. |
| 900 content::BrowserThread::PostTask( | 747 content::BrowserThread::PostTask( |
| 901 content::BrowserThread::IO, | 748 content::BrowserThread::IO, |
| 902 FROM_HERE, | 749 FROM_HERE, |
| 903 base::Bind(&GCMProfileService::IOWorker::Load, | 750 base::Bind(&GCMProfileService::IOWorker::Load, |
| 904 io_worker_, | 751 io_worker_, |
| 905 weak_ptr_factory_.GetWeakPtr())); | 752 weak_ptr_factory_.GetWeakPtr())); |
| 906 } | 753 } |
| 907 | 754 |
| 908 void GCMProfileService::RemoveCachedData() { | 755 void GCMProfileService::RemoveCachedData() { |
| 909 // Remove all the queued tasks since they no longer make sense after | 756 // Remove all the queued tasks since they no longer make sense after |
| 910 // GCM service is stopped. | 757 // GCM service is stopped. |
| 911 weak_ptr_factory_.InvalidateWeakPtrs(); | 758 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 912 | 759 |
| 913 username_.clear(); | 760 username_.clear(); |
| 914 gcm_client_ready_ = false; | 761 gcm_client_ready_ = false; |
| 915 delayed_task_controller_.reset(); | 762 delayed_task_controller_.reset(); |
| 916 register_callbacks_.clear(); | 763 register_callbacks_.clear(); |
| 917 send_callbacks_.clear(); | 764 send_callbacks_.clear(); |
| 918 registration_info_map_.clear(); | |
| 919 } | |
| 920 | |
| 921 void GCMProfileService::RemovePersistedData() { | |
| 922 // Remove persisted data from app's state store. | |
| 923 for (RegistrationInfoMap::const_iterator iter = | |
| 924 registration_info_map_.begin(); | |
| 925 iter != registration_info_map_.end(); ++iter) { | |
| 926 DeleteRegistrationInfo(iter->first); | |
| 927 } | |
| 928 | |
| 929 // Remove persisted data from prefs store. | |
| 930 profile_->GetPrefs()->ClearPref(prefs::kGCMRegisteredAppIDs); | |
| 931 } | 765 } |
| 932 | 766 |
| 933 void GCMProfileService::CheckOut() { | 767 void GCMProfileService::CheckOut() { |
| 934 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 768 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 935 | 769 |
| 936 // We still proceed with the check-out logic even if the check-in is not | 770 // We still proceed with the check-out logic even if the check-in is not |
| 937 // initiated in the current session. This will make sure that all the | 771 // initiated in the current session. This will make sure that all the |
| 938 // persisted data written previously will get purged. | 772 // persisted data written previously will get purged. |
| 939 | 773 |
| 940 // This has to be done before removing the cached data since we need to do | |
| 941 // the lookup based on the cached data. | |
| 942 RemovePersistedData(); | |
| 943 | |
| 944 RemoveCachedData(); | 774 RemoveCachedData(); |
| 945 | 775 |
| 946 content::BrowserThread::PostTask( | 776 content::BrowserThread::PostTask( |
| 947 content::BrowserThread::IO, | 777 content::BrowserThread::IO, |
| 948 FROM_HERE, | 778 FROM_HERE, |
| 949 base::Bind(&GCMProfileService::IOWorker::CheckOut, io_worker_)); | 779 base::Bind(&GCMProfileService::IOWorker::CheckOut, io_worker_)); |
| 950 } | 780 } |
| 951 | 781 |
| 952 void GCMProfileService::ResetGCMClient() { | 782 void GCMProfileService::ResetGCMClient() { |
| 953 content::BrowserThread::PostTask( | 783 content::BrowserThread::PostTask( |
| 954 content::BrowserThread::IO, | 784 content::BrowserThread::IO, |
| 955 FROM_HERE, | 785 FROM_HERE, |
| 956 base::Bind(&GCMProfileService::IOWorker::Reset, io_worker_)); | 786 base::Bind(&GCMProfileService::IOWorker::Reset, io_worker_)); |
| 957 } | 787 } |
| 958 | 788 |
| 959 GCMClient::Result GCMProfileService::EnsureAppReady(const std::string& app_id) { | 789 GCMClient::Result GCMProfileService::EnsureAppReady(const std::string& app_id) { |
| 960 // Ensure that check-in has been done. | 790 // Ensure that check-in has been done. |
| 961 EnsureLoaded(); | 791 EnsureLoaded(); |
| 962 | 792 |
| 963 // If the profile was not signed in, bail out. | 793 // If the profile was not signed in, bail out. |
| 964 if (username_.empty()) | 794 if (username_.empty()) |
| 965 return GCMClient::NOT_SIGNED_IN; | 795 return GCMClient::NOT_SIGNED_IN; |
| 966 | 796 |
| 967 // Ensure that app registration information was read. | |
| 968 if (!delayed_task_controller_->IsAppTracked(app_id)) | |
| 969 ReadRegistrationInfo(app_id); | |
| 970 | |
| 971 return GCMClient::SUCCESS; | 797 return GCMClient::SUCCESS; |
| 972 } | 798 } |
| 973 | 799 |
| 974 bool GCMProfileService::IsAsyncOperationPending( | 800 bool GCMProfileService::IsAsyncOperationPending( |
| 975 const std::string& app_id) const { | 801 const std::string& app_id) const { |
| 976 return register_callbacks_.find(app_id) != register_callbacks_.end() || | 802 return register_callbacks_.find(app_id) != register_callbacks_.end() || |
| 977 unregister_callbacks_.find(app_id) != unregister_callbacks_.end(); | 803 unregister_callbacks_.find(app_id) != unregister_callbacks_.end(); |
| 978 } | 804 } |
| 979 | 805 |
| 980 void GCMProfileService::RegisterFinished(const std::string& app_id, | 806 void GCMProfileService::RegisterFinished(const std::string& app_id, |
| 981 const std::string& registration_id, | 807 const std::string& registration_id, |
| 982 GCMClient::Result result) { | 808 GCMClient::Result result) { |
| 983 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 809 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 984 | 810 |
| 985 std::map<std::string, RegisterCallback>::iterator callback_iter = | 811 std::map<std::string, RegisterCallback>::iterator callback_iter = |
| 986 register_callbacks_.find(app_id); | 812 register_callbacks_.find(app_id); |
| 987 if (callback_iter == register_callbacks_.end()) { | 813 if (callback_iter == register_callbacks_.end()) { |
| 988 // The callback could have been removed when the app is uninstalled. | 814 // The callback could have been removed when the app is uninstalled. |
| 989 return; | 815 return; |
| 990 } | 816 } |
| 991 | 817 |
| 992 // Cache the registration ID if the registration succeeds. Otherwise, | |
| 993 // removed the cached info. | |
| 994 RegistrationInfoMap::iterator registration_info_iter = | |
| 995 registration_info_map_.find(app_id); | |
| 996 // This is unlikely to happen because the app will not be uninstalled before | |
| 997 // the asynchronous extension function completes. | |
| 998 DCHECK(registration_info_iter != registration_info_map_.end()); | |
| 999 if (result == GCMClient::SUCCESS) { | |
| 1000 registration_info_iter->second.registration_id = registration_id; | |
| 1001 WriteRegistrationInfo(app_id); | |
| 1002 } else { | |
| 1003 registration_info_map_.erase(registration_info_iter); | |
| 1004 } | |
| 1005 | |
| 1006 RegisterCallback callback = callback_iter->second; | 818 RegisterCallback callback = callback_iter->second; |
| 1007 register_callbacks_.erase(callback_iter); | 819 register_callbacks_.erase(callback_iter); |
| 1008 callback.Run(registration_id, result); | 820 callback.Run(registration_id, result); |
| 1009 } | 821 } |
| 1010 | 822 |
| 1011 void GCMProfileService::UnregisterFinished(const std::string& app_id, | 823 void GCMProfileService::UnregisterFinished(const std::string& app_id, |
| 1012 GCMClient::Result result) { | 824 GCMClient::Result result) { |
| 1013 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 825 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 1014 | 826 |
| 1015 std::map<std::string, UnregisterCallback>::iterator callback_iter = | 827 std::map<std::string, UnregisterCallback>::iterator callback_iter = |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1041 } | 853 } |
| 1042 | 854 |
| 1043 void GCMProfileService::MessageReceived(const std::string& app_id, | 855 void GCMProfileService::MessageReceived(const std::string& app_id, |
| 1044 GCMClient::IncomingMessage message) { | 856 GCMClient::IncomingMessage message) { |
| 1045 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 857 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 1046 | 858 |
| 1047 // Drop the event if signed out. | 859 // Drop the event if signed out. |
| 1048 if (username_.empty()) | 860 if (username_.empty()) |
| 1049 return; | 861 return; |
| 1050 | 862 |
| 1051 // Dropping the message when application does not have a registration entry | |
| 1052 // or the app is not registered for the sender of the message. | |
| 1053 RegistrationInfoMap::iterator iter = registration_info_map_.find(app_id); | |
| 1054 if (iter == registration_info_map_.end() || | |
| 1055 std::find(iter->second.sender_ids.begin(), | |
| 1056 iter->second.sender_ids.end(), | |
| 1057 message.sender_id) == iter->second.sender_ids.end()) { | |
| 1058 return; | |
| 1059 } | |
| 1060 | |
| 1061 GetAppHandler(app_id)->OnMessage(app_id, message); | 863 GetAppHandler(app_id)->OnMessage(app_id, message); |
| 1062 } | 864 } |
| 1063 | 865 |
| 1064 void GCMProfileService::MessagesDeleted(const std::string& app_id) { | 866 void GCMProfileService::MessagesDeleted(const std::string& app_id) { |
| 1065 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 867 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 1066 | 868 |
| 1067 // Drop the event if signed out. | 869 // Drop the event if signed out. |
| 1068 if (username_.empty()) | 870 if (username_.empty()) |
| 1069 return; | 871 return; |
| 1070 | 872 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1083 GetAppHandler(app_id)->OnSendError(app_id, send_error_details); | 885 GetAppHandler(app_id)->OnSendError(app_id, send_error_details); |
| 1084 } | 886 } |
| 1085 | 887 |
| 1086 void GCMProfileService::GCMClientReady() { | 888 void GCMProfileService::GCMClientReady() { |
| 1087 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 889 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 1088 | 890 |
| 1089 if (gcm_client_ready_) | 891 if (gcm_client_ready_) |
| 1090 return; | 892 return; |
| 1091 gcm_client_ready_ = true; | 893 gcm_client_ready_ = true; |
| 1092 | 894 |
| 1093 delayed_task_controller_->SetGCMReady(); | 895 delayed_task_controller_->SetReady(); |
| 1094 } | 896 } |
| 1095 | 897 |
| 1096 GCMAppHandler* GCMProfileService::GetAppHandler(const std::string& app_id) { | 898 GCMAppHandler* GCMProfileService::GetAppHandler(const std::string& app_id) { |
| 1097 std::map<std::string, GCMAppHandler*>::const_iterator iter = | 899 std::map<std::string, GCMAppHandler*>::const_iterator iter = |
| 1098 app_handlers_.find(app_id); | 900 app_handlers_.find(app_id); |
| 1099 return iter == app_handlers_.end() ? &default_app_handler_ : iter->second; | 901 return iter == app_handlers_.end() ? &default_app_handler_ : iter->second; |
| 1100 } | 902 } |
| 1101 | 903 |
| 1102 void GCMProfileService::ReadRegisteredAppIDs() { | |
| 1103 const base::ListValue* app_id_list = | |
| 1104 profile_->GetPrefs()->GetList(prefs::kGCMRegisteredAppIDs); | |
| 1105 for (size_t i = 0; i < app_id_list->GetSize(); ++i) { | |
| 1106 std::string app_id; | |
| 1107 if (!app_id_list->GetString(i, &app_id)) | |
| 1108 continue; | |
| 1109 ReadRegistrationInfo(app_id); | |
| 1110 } | |
| 1111 } | |
| 1112 | |
| 1113 void GCMProfileService::WriteRegisteredAppIDs() { | |
| 1114 base::ListValue apps; | |
| 1115 for (RegistrationInfoMap::const_iterator iter = | |
| 1116 registration_info_map_.begin(); | |
| 1117 iter != registration_info_map_.end(); ++iter) { | |
| 1118 apps.Append(new base::StringValue(iter->first)); | |
| 1119 } | |
| 1120 profile_->GetPrefs()->Set(prefs::kGCMRegisteredAppIDs, apps); | |
| 1121 } | |
| 1122 | |
| 1123 void GCMProfileService::DeleteRegistrationInfo(const std::string& app_id) { | |
| 1124 extensions::StateStore* storage = | |
| 1125 extensions::ExtensionSystem::Get(profile_)->state_store(); | |
| 1126 DCHECK(storage); | |
| 1127 | |
| 1128 storage->RemoveExtensionValue(app_id, kRegistrationKey); | |
| 1129 } | |
| 1130 | |
| 1131 void GCMProfileService::WriteRegistrationInfo(const std::string& app_id) { | |
| 1132 extensions::StateStore* storage = | |
| 1133 extensions::ExtensionSystem::Get(profile_)->state_store(); | |
| 1134 DCHECK(storage); | |
| 1135 | |
| 1136 RegistrationInfoMap::const_iterator registration_info_iter = | |
| 1137 registration_info_map_.find(app_id); | |
| 1138 if (registration_info_iter == registration_info_map_.end()) | |
| 1139 return; | |
| 1140 const RegistrationInfo& registration_info = registration_info_iter->second; | |
| 1141 | |
| 1142 scoped_ptr<base::ListValue> senders_list(new base::ListValue()); | |
| 1143 for (std::vector<std::string>::const_iterator senders_iter = | |
| 1144 registration_info.sender_ids.begin(); | |
| 1145 senders_iter != registration_info.sender_ids.end(); | |
| 1146 ++senders_iter) { | |
| 1147 senders_list->AppendString(*senders_iter); | |
| 1148 } | |
| 1149 | |
| 1150 scoped_ptr<base::DictionaryValue> registration_info_dict( | |
| 1151 new base::DictionaryValue()); | |
| 1152 registration_info_dict->Set(kSendersKey, senders_list.release()); | |
| 1153 registration_info_dict->SetString(kRegistrationIDKey, | |
| 1154 registration_info.registration_id); | |
| 1155 | |
| 1156 storage->SetExtensionValue( | |
| 1157 app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>()); | |
| 1158 } | |
| 1159 | |
| 1160 void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) { | |
| 1161 delayed_task_controller_->AddApp(app_id); | |
| 1162 | |
| 1163 extensions::StateStore* storage = | |
| 1164 extensions::ExtensionSystem::Get(profile_)->state_store(); | |
| 1165 DCHECK(storage); | |
| 1166 storage->GetExtensionValue( | |
| 1167 app_id, | |
| 1168 kRegistrationKey, | |
| 1169 base::Bind( | |
| 1170 &GCMProfileService::ReadRegistrationInfoFinished, | |
| 1171 weak_ptr_factory_.GetWeakPtr(), | |
| 1172 app_id)); | |
| 1173 } | |
| 1174 | |
| 1175 void GCMProfileService::ReadRegistrationInfoFinished( | |
| 1176 const std::string& app_id, | |
| 1177 scoped_ptr<base::Value> value) { | |
| 1178 RegistrationInfo registration_info; | |
| 1179 if (value && | |
| 1180 !ParsePersistedRegistrationInfo(value.Pass(), ®istration_info)) { | |
| 1181 // Delete the persisted data if it is corrupted. | |
| 1182 DeleteRegistrationInfo(app_id); | |
| 1183 } | |
| 1184 | |
| 1185 if (registration_info.IsValid()) | |
| 1186 registration_info_map_[app_id] = registration_info; | |
| 1187 | |
| 1188 delayed_task_controller_->SetAppReady(app_id); | |
| 1189 } | |
| 1190 | |
| 1191 bool GCMProfileService::ParsePersistedRegistrationInfo( | |
| 1192 scoped_ptr<base::Value> value, | |
| 1193 RegistrationInfo* registration_info) { | |
| 1194 base::DictionaryValue* dict = NULL; | |
| 1195 if (!value.get() || !value->GetAsDictionary(&dict)) | |
| 1196 return false; | |
| 1197 | |
| 1198 if (!dict->GetString(kRegistrationIDKey, ®istration_info->registration_id)) | |
| 1199 return false; | |
| 1200 | |
| 1201 const base::ListValue* senders_list = NULL; | |
| 1202 if (!dict->GetList(kSendersKey, &senders_list) || !senders_list->GetSize()) | |
| 1203 return false; | |
| 1204 for (size_t i = 0; i < senders_list->GetSize(); ++i) { | |
| 1205 std::string sender; | |
| 1206 if (!senders_list->GetString(i, &sender)) | |
| 1207 return false; | |
| 1208 registration_info->sender_ids.push_back(sender); | |
| 1209 } | |
| 1210 | |
| 1211 return true; | |
| 1212 } | |
| 1213 | |
| 1214 void GCMProfileService::RequestGCMStatisticsFinished( | 904 void GCMProfileService::RequestGCMStatisticsFinished( |
| 1215 GCMClient::GCMStatistics stats) { | 905 GCMClient::GCMStatistics stats) { |
| 1216 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 906 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 1217 | 907 |
| 1218 request_gcm_statistics_callback_.Run(stats); | 908 request_gcm_statistics_callback_.Run(stats); |
| 1219 } | 909 } |
| 1220 | 910 |
| 1221 // static | |
| 1222 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() { | |
| 1223 return kRegistrationKey; | |
| 1224 } | |
| 1225 | |
| 1226 } // namespace gcm | 911 } // namespace gcm |
| OLD | NEW |