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 <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 39 #include "google_apis/gcm/protocol/android_checkin.pb.h" | 39 #include "google_apis/gcm/protocol/android_checkin.pb.h" |
| 40 #include "net/url_request/url_request_context_getter.h" | 40 #include "net/url_request/url_request_context_getter.h" |
| 41 | 41 |
| 42 using extensions::Extension; | 42 using extensions::Extension; |
| 43 | 43 |
| 44 namespace gcm { | 44 namespace gcm { |
| 45 | 45 |
| 46 namespace { | 46 namespace { |
| 47 | 47 |
| 48 const char kRegistrationKey[] = "gcm.registration"; | 48 const char kRegistrationKey[] = "gcm.registration"; |
| 49 const char kSendersKey[] = "senders"; | 49 const char kSenderKey[] = "sender"; |
| 50 const char kRegistrationIDKey[] = "reg_id"; | 50 const char kRegistrationIDKey[] = "reg_id"; |
| 51 | 51 |
| 52 checkin_proto::ChromeBuildProto_Platform GetPlatform() { | 52 checkin_proto::ChromeBuildProto_Platform GetPlatform() { |
| 53 #if defined(OS_WIN) | 53 #if defined(OS_WIN) |
| 54 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN; | 54 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN; |
| 55 #elif defined(OS_MACOSX) | 55 #elif defined(OS_MACOSX) |
| 56 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_MAC; | 56 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_MAC; |
| 57 #elif defined(OS_CHROMEOS) | 57 #elif defined(OS_CHROMEOS) |
| 58 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_CROS; | 58 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_CROS; |
| 59 #elif defined(OS_LINUX) | 59 #elif defined(OS_LINUX) |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 260 // Called on IO thread. | 260 // Called on IO thread. |
| 261 void Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory, | 261 void Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory, |
| 262 const base::FilePath& store_path, | 262 const base::FilePath& store_path, |
| 263 const std::vector<std::string>& account_ids, | 263 const std::vector<std::string>& account_ids, |
| 264 const scoped_refptr<net::URLRequestContextGetter>& | 264 const scoped_refptr<net::URLRequestContextGetter>& |
| 265 url_request_context_getter); | 265 url_request_context_getter); |
| 266 void Reset(); | 266 void Reset(); |
| 267 void Load(const base::WeakPtr<GCMProfileService>& service); | 267 void Load(const base::WeakPtr<GCMProfileService>& service); |
| 268 void CheckOut(); | 268 void CheckOut(); |
| 269 void Register(const std::string& app_id, | 269 void Register(const std::string& app_id, |
| 270 const std::vector<std::string>& sender_ids, | 270 const std::string& sender_id, |
| 271 const std::string& cert); | 271 const std::string& cert); |
| 272 void Unregister(const std::string& app_id); | 272 void Unregister(const std::string& app_id); |
| 273 void Send(const std::string& app_id, | 273 void Send(const std::string& app_id, |
| 274 const std::string& receiver_id, | 274 const std::string& receiver_id, |
| 275 const GCMClient::OutgoingMessage& message); | 275 const GCMClient::OutgoingMessage& message); |
| 276 | 276 |
| 277 // For testing purpose. Can be called from UI thread. Use with care. | 277 // For testing purpose. Can be called from UI thread. Use with care. |
| 278 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); } | 278 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); } |
| 279 | 279 |
| 280 private: | 280 private: |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 430 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 430 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 431 | 431 |
| 432 gcm_client_->CheckOut(); | 432 gcm_client_->CheckOut(); |
| 433 | 433 |
| 434 // Note that we still need to keep GCMClient instance alive since the profile | 434 // Note that we still need to keep GCMClient instance alive since the profile |
| 435 // might be signed in again. | 435 // might be signed in again. |
| 436 } | 436 } |
| 437 | 437 |
| 438 void GCMProfileService::IOWorker::Register( | 438 void GCMProfileService::IOWorker::Register( |
| 439 const std::string& app_id, | 439 const std::string& app_id, |
| 440 const std::vector<std::string>& sender_ids, | 440 const std::string& sender_id, |
| 441 const std::string& cert) { | 441 const std::string& cert) { |
| 442 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 442 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 443 | 443 |
| 444 gcm_client_->Register(app_id, cert, sender_ids); | 444 gcm_client_->Register(app_id, cert, sender_id); |
| 445 } | 445 } |
| 446 | 446 |
| 447 void GCMProfileService::IOWorker::Unregister(const std::string& app_id) { | 447 void GCMProfileService::IOWorker::Unregister(const std::string& app_id) { |
| 448 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 448 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 449 | 449 |
| 450 gcm_client_->Unregister(app_id); | 450 gcm_client_->Unregister(app_id); |
| 451 } | 451 } |
| 452 | 452 |
| 453 void GCMProfileService::IOWorker::Send( | 453 void GCMProfileService::IOWorker::Send( |
| 454 const std::string& app_id, | 454 const std::string& app_id, |
| 455 const std::string& receiver_id, | 455 const std::string& receiver_id, |
| 456 const GCMClient::OutgoingMessage& message) { | 456 const GCMClient::OutgoingMessage& message) { |
| 457 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 457 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 458 | 458 |
| 459 gcm_client_->Send(app_id, receiver_id, message); | 459 gcm_client_->Send(app_id, receiver_id, message); |
| 460 } | 460 } |
| 461 | 461 |
| 462 GCMProfileService::RegistrationInfo::RegistrationInfo() { | 462 GCMProfileService::RegistrationInfo::RegistrationInfo() { |
| 463 } | 463 } |
| 464 | 464 |
| 465 GCMProfileService::RegistrationInfo::~RegistrationInfo() { | 465 GCMProfileService::RegistrationInfo::~RegistrationInfo() { |
| 466 } | 466 } |
| 467 | 467 |
| 468 bool GCMProfileService::RegistrationInfo::IsValid() const { | 468 bool GCMProfileService::RegistrationInfo::IsValid() const { |
| 469 return !sender_ids.empty() && !registration_id.empty(); | 469 return !sender_id.empty() && !registration_id.empty(); |
| 470 } | 470 } |
| 471 | 471 |
| 472 // static | 472 // static |
| 473 GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState( | 473 GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState( |
| 474 Profile* profile) { | 474 Profile* profile) { |
| 475 const base::Value* gcm_enabled_value = | 475 const base::Value* gcm_enabled_value = |
| 476 profile->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled); | 476 profile->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled); |
| 477 if (!gcm_enabled_value) | 477 if (!gcm_enabled_value) |
| 478 return ENABLED_FOR_APPS; | 478 return ENABLED_FOR_APPS; |
| 479 | 479 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 account_ids, | 553 account_ids, |
| 554 url_request_context_getter)); | 554 url_request_context_getter)); |
| 555 | 555 |
| 556 // Load from the GCM store and initiate the GCM check-in if the rollout signal | 556 // Load from the GCM store and initiate the GCM check-in if the rollout signal |
| 557 // indicates yes. | 557 // indicates yes. |
| 558 if (GetGCMEnabledState(profile_) == ALWAYS_ENABLED) | 558 if (GetGCMEnabledState(profile_) == ALWAYS_ENABLED) |
| 559 EnsureLoaded(); | 559 EnsureLoaded(); |
| 560 } | 560 } |
| 561 | 561 |
| 562 void GCMProfileService::Register(const std::string& app_id, | 562 void GCMProfileService::Register(const std::string& app_id, |
| 563 const std::vector<std::string>& sender_ids, | 563 const std::string& sender_id, |
| 564 const std::string& cert, | 564 const std::string& cert, |
| 565 RegisterCallback callback) { | 565 RegisterCallback callback) { |
| 566 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 566 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 567 DCHECK(!app_id.empty() && !sender_ids.empty() && !callback.is_null()); | 567 DCHECK(!app_id.empty() && !sender_id.empty() && !callback.is_null()); |
| 568 | 568 |
| 569 // Ensure that check-in has been done. | 569 // Ensure that check-in has been done. |
| 570 EnsureLoaded(); | 570 EnsureLoaded(); |
| 571 | 571 |
| 572 // If the profile was not signed in, bail out. | 572 // If the profile was not signed in, bail out. |
| 573 if (username_.empty()) { | 573 if (username_.empty()) { |
| 574 callback.Run(std::string(), GCMClient::NOT_SIGNED_IN); | 574 callback.Run(std::string(), GCMClient::NOT_SIGNED_IN); |
| 575 return; | 575 return; |
| 576 } | 576 } |
| 577 | 577 |
| 578 // If previous register operation is still in progress, bail out. | 578 // If previous register operation is still in progress, bail out. |
| 579 if (register_callbacks_.find(app_id) != register_callbacks_.end()) { | 579 if (register_callbacks_.find(app_id) != register_callbacks_.end()) { |
| 580 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); | 580 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); |
| 581 return; | 581 return; |
| 582 } | 582 } |
| 583 | 583 |
| 584 register_callbacks_[app_id] = callback; | 584 register_callbacks_[app_id] = callback; |
| 585 | 585 |
| 586 EnsureAppReady(app_id); | 586 EnsureAppReady(app_id); |
| 587 | 587 |
| 588 // Delay the register operation until GCMClient is ready. | 588 // Delay the register operation until GCMClient is ready. |
| 589 if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) { | 589 if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) { |
| 590 delayed_task_controller_->AddTask( | 590 delayed_task_controller_->AddTask( |
| 591 app_id, | 591 app_id, |
| 592 base::Bind(&GCMProfileService::DoRegister, | 592 base::Bind(&GCMProfileService::DoRegister, |
| 593 weak_ptr_factory_.GetWeakPtr(), | 593 weak_ptr_factory_.GetWeakPtr(), |
| 594 app_id, | 594 app_id, |
| 595 sender_ids, | 595 sender_id, |
| 596 cert)); | 596 cert)); |
| 597 return; | 597 return; |
| 598 } | 598 } |
| 599 | 599 |
| 600 DoRegister(app_id, sender_ids, cert); | 600 DoRegister(app_id, sender_id, cert); |
| 601 } | 601 } |
| 602 | 602 |
| 603 void GCMProfileService::DoRegister(const std::string& app_id, | 603 void GCMProfileService::DoRegister(const std::string& app_id, |
| 604 const std::vector<std::string>& sender_ids, | 604 const std::string& sender_id, |
| 605 const std::string& cert) { | 605 const std::string& cert) { |
| 606 std::map<std::string, RegisterCallback>::iterator callback_iter = | 606 std::map<std::string, RegisterCallback>::iterator callback_iter = |
| 607 register_callbacks_.find(app_id); | 607 register_callbacks_.find(app_id); |
| 608 if (callback_iter == register_callbacks_.end()) { | 608 if (callback_iter == register_callbacks_.end()) { |
| 609 // The callback could have been removed when the app is uninstalled. | 609 // The callback could have been removed when the app is uninstalled. |
| 610 return; | 610 return; |
| 611 } | 611 } |
| 612 | 612 |
| 613 // Normalize the sender IDs by making them sorted. | |
| 614 std::vector<std::string> normalized_sender_ids = sender_ids; | |
| 615 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end()); | |
| 616 | |
| 617 // If the same sender ids is provided, return the cached registration ID | 613 // If the same sender ids is provided, return the cached registration ID |
| 618 // directly. | 614 // directly. |
| 619 RegistrationInfoMap::const_iterator registration_info_iter = | 615 RegistrationInfoMap::const_iterator registration_info_iter = |
| 620 registration_info_map_.find(app_id); | 616 registration_info_map_.find(app_id); |
| 621 if (registration_info_iter != registration_info_map_.end() && | 617 if (registration_info_iter != registration_info_map_.end() && |
| 622 registration_info_iter->second.sender_ids == normalized_sender_ids) { | 618 registration_info_iter->second.sender_id == sender_id) { |
| 623 RegisterCallback callback = callback_iter->second; | 619 RegisterCallback callback = callback_iter->second; |
| 624 register_callbacks_.erase(callback_iter); | 620 register_callbacks_.erase(callback_iter); |
| 625 callback.Run(registration_info_iter->second.registration_id, | 621 callback.Run(registration_info_iter->second.registration_id, |
| 626 GCMClient::SUCCESS); | 622 GCMClient::SUCCESS); |
| 627 return; | 623 return; |
| 628 } | 624 } |
| 629 | 625 |
| 630 // Cache the sender IDs. The registration ID will be filled when the | 626 // Cache the sender IDs. The registration ID will be filled when the |
| 631 // registration completes. | 627 // registration completes. |
| 632 RegistrationInfo registration_info; | 628 RegistrationInfo registration_info; |
| 633 registration_info.sender_ids = normalized_sender_ids; | 629 registration_info.sender_id = sender_id; |
| 634 registration_info_map_[app_id] = registration_info; | 630 registration_info_map_[app_id] = registration_info; |
| 635 | 631 |
| 636 // Save the IDs of all registered apps such that we know what to remove from | 632 // Save the IDs of all registered apps such that we know what to remove from |
| 637 // the the app's state store when the profile is signed out. | 633 // the the app's state store when the profile is signed out. |
| 638 WriteRegisteredAppIDs(); | 634 WriteRegisteredAppIDs(); |
| 639 | 635 |
| 640 content::BrowserThread::PostTask( | 636 content::BrowserThread::PostTask( |
| 641 content::BrowserThread::IO, | 637 content::BrowserThread::IO, |
| 642 FROM_HERE, | 638 FROM_HERE, |
| 643 base::Bind(&GCMProfileService::IOWorker::Register, | 639 base::Bind(&GCMProfileService::IOWorker::Register, |
| 644 io_worker_, | 640 io_worker_, |
| 645 app_id, | 641 app_id, |
| 646 normalized_sender_ids, | 642 sender_id, |
| 647 cert)); | 643 cert)); |
| 648 } | 644 } |
| 649 | 645 |
| 650 void GCMProfileService::Send(const std::string& app_id, | 646 void GCMProfileService::Send(const std::string& app_id, |
| 651 const std::string& receiver_id, | 647 const std::string& receiver_id, |
| 652 const GCMClient::OutgoingMessage& message, | 648 const GCMClient::OutgoingMessage& message, |
| 653 SendCallback callback) { | 649 SendCallback callback) { |
| 654 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 650 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 655 DCHECK(!app_id.empty() && !receiver_id.empty() && !callback.is_null()); | 651 DCHECK(!app_id.empty() && !receiver_id.empty() && !callback.is_null()); |
| 656 | 652 |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 989 | 985 |
| 990 void GCMProfileService::WriteRegistrationInfo(const std::string& app_id) { | 986 void GCMProfileService::WriteRegistrationInfo(const std::string& app_id) { |
| 991 extensions::StateStore* storage = | 987 extensions::StateStore* storage = |
| 992 extensions::ExtensionSystem::Get(profile_)->state_store(); | 988 extensions::ExtensionSystem::Get(profile_)->state_store(); |
| 993 DCHECK(storage); | 989 DCHECK(storage); |
| 994 | 990 |
| 995 RegistrationInfoMap::const_iterator registration_info_iter = | 991 RegistrationInfoMap::const_iterator registration_info_iter = |
| 996 registration_info_map_.find(app_id); | 992 registration_info_map_.find(app_id); |
| 997 if (registration_info_iter == registration_info_map_.end()) | 993 if (registration_info_iter == registration_info_map_.end()) |
| 998 return; | 994 return; |
| 995 | |
| 999 const RegistrationInfo& registration_info = registration_info_iter->second; | 996 const RegistrationInfo& registration_info = registration_info_iter->second; |
| 1000 | |
| 1001 scoped_ptr<base::ListValue> senders_list(new base::ListValue()); | |
| 1002 for (std::vector<std::string>::const_iterator senders_iter = | |
| 1003 registration_info.sender_ids.begin(); | |
| 1004 senders_iter != registration_info.sender_ids.end(); | |
| 1005 ++senders_iter) { | |
| 1006 senders_list->AppendString(*senders_iter); | |
| 1007 } | |
| 1008 | |
| 1009 scoped_ptr<base::DictionaryValue> registration_info_dict( | 997 scoped_ptr<base::DictionaryValue> registration_info_dict( |
| 1010 new base::DictionaryValue()); | 998 new base::DictionaryValue()); |
| 1011 registration_info_dict->Set(kSendersKey, senders_list.release()); | 999 registration_info_dict->SetString(kSenderKey, |
|
jianli
2014/03/03 21:29:31
Do we want to make it be compatible with future mu
fgorski
2014/03/03 23:14:16
Done. Modified the write and read code to simply s
| |
| 1000 registration_info.sender_id); | |
| 1012 registration_info_dict->SetString(kRegistrationIDKey, | 1001 registration_info_dict->SetString(kRegistrationIDKey, |
| 1013 registration_info.registration_id); | 1002 registration_info.registration_id); |
| 1014 | 1003 |
| 1015 storage->SetExtensionValue( | 1004 storage->SetExtensionValue( |
| 1016 app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>()); | 1005 app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>()); |
| 1017 } | 1006 } |
| 1018 | 1007 |
| 1019 void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) { | 1008 void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) { |
| 1020 delayed_task_controller_->AddApp(app_id); | 1009 delayed_task_controller_->AddApp(app_id); |
| 1021 | 1010 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 1050 bool GCMProfileService::ParsePersistedRegistrationInfo( | 1039 bool GCMProfileService::ParsePersistedRegistrationInfo( |
| 1051 scoped_ptr<base::Value> value, | 1040 scoped_ptr<base::Value> value, |
| 1052 RegistrationInfo* registration_info) { | 1041 RegistrationInfo* registration_info) { |
| 1053 base::DictionaryValue* dict = NULL; | 1042 base::DictionaryValue* dict = NULL; |
| 1054 if (!value.get() || !value->GetAsDictionary(&dict)) | 1043 if (!value.get() || !value->GetAsDictionary(&dict)) |
| 1055 return false; | 1044 return false; |
| 1056 | 1045 |
| 1057 if (!dict->GetString(kRegistrationIDKey, ®istration_info->registration_id)) | 1046 if (!dict->GetString(kRegistrationIDKey, ®istration_info->registration_id)) |
| 1058 return false; | 1047 return false; |
| 1059 | 1048 |
| 1060 const base::ListValue* senders_list = NULL; | 1049 if (!dict->GetString(kSenderKey, ®istration_info->sender_id)) |
| 1061 if (!dict->GetList(kSendersKey, &senders_list) || !senders_list->GetSize()) | |
| 1062 return false; | 1050 return false; |
| 1063 for (size_t i = 0; i < senders_list->GetSize(); ++i) { | |
| 1064 std::string sender; | |
| 1065 if (!senders_list->GetString(i, &sender)) | |
| 1066 return false; | |
| 1067 registration_info->sender_ids.push_back(sender); | |
| 1068 } | |
| 1069 | 1051 |
| 1070 return true; | 1052 return true; |
| 1071 } | 1053 } |
| 1072 | 1054 |
| 1073 // static | 1055 // static |
| 1074 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() { | 1056 const char* GCMProfileService::GetPersistentRegisterKeyForTesting() { |
| 1075 return kRegistrationKey; | 1057 return kRegistrationKey; |
| 1076 } | 1058 } |
| 1077 | 1059 |
| 1078 } // namespace gcm | 1060 } // namespace gcm |
| OLD | NEW |