| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/gcm_driver/gcm_client_impl.h" | 5 #include "components/gcm_driver/gcm_client_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 | 60 |
| 61 enum ResetStoreError { | 61 enum ResetStoreError { |
| 62 DESTROYING_STORE_FAILED, | 62 DESTROYING_STORE_FAILED, |
| 63 INFINITE_STORE_RESET, | 63 INFINITE_STORE_RESET, |
| 64 // NOTE: always keep this entry at the end. Add new value only immediately | 64 // NOTE: always keep this entry at the end. Add new value only immediately |
| 65 // above this line. Make sure to update the corresponding histogram enum | 65 // above this line. Make sure to update the corresponding histogram enum |
| 66 // accordingly. | 66 // accordingly. |
| 67 RESET_STORE_ERROR_COUNT | 67 RESET_STORE_ERROR_COUNT |
| 68 }; | 68 }; |
| 69 | 69 |
| 70 const char kGCMScope[] = "GCM"; |
| 70 const int kMaxRegistrationRetries = 5; | 71 const int kMaxRegistrationRetries = 5; |
| 71 const char kMessageTypeDataMessage[] = "gcm"; | 72 const char kMessageTypeDataMessage[] = "gcm"; |
| 72 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; | 73 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; |
| 73 const char kMessageTypeKey[] = "message_type"; | 74 const char kMessageTypeKey[] = "message_type"; |
| 74 const char kMessageTypeSendErrorKey[] = "send_error"; | 75 const char kMessageTypeSendErrorKey[] = "send_error"; |
| 75 const char kSendErrorMessageIdKey[] = "google.message_id"; | 76 const char kSendErrorMessageIdKey[] = "google.message_id"; |
| 76 const char kSendMessageFromValue[] = "gcm@chrome.com"; | 77 const char kSendMessageFromValue[] = "gcm@chrome.com"; |
| 77 const int64 kDefaultUserSerialNumber = 0LL; | 78 const int64 kDefaultUserSerialNumber = 0LL; |
| 78 | 79 |
| 79 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { | 80 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 MessageType DecodeMessageType(const std::string& value) { | 163 MessageType DecodeMessageType(const std::string& value) { |
| 163 if (kMessageTypeDeletedMessagesKey == value) | 164 if (kMessageTypeDeletedMessagesKey == value) |
| 164 return DELETED_MESSAGES; | 165 return DELETED_MESSAGES; |
| 165 if (kMessageTypeSendErrorKey == value) | 166 if (kMessageTypeSendErrorKey == value) |
| 166 return SEND_ERROR; | 167 return SEND_ERROR; |
| 167 if (kMessageTypeDataMessage == value) | 168 if (kMessageTypeDataMessage == value) |
| 168 return DATA_MESSAGE; | 169 return DATA_MESSAGE; |
| 169 return UNKNOWN; | 170 return UNKNOWN; |
| 170 } | 171 } |
| 171 | 172 |
| 173 std::string SerializeInstanceIDData(const std::string& instance_id, |
| 174 const std::string& extra_data) { |
| 175 DCHECK(!instance_id.empty() && !extra_data.empty()); |
| 176 DCHECK(instance_id.find(',') == std::string::npos); |
| 177 return instance_id + "," + extra_data; |
| 178 } |
| 179 |
| 180 bool DeserializeInstanceIDData(const std::string& serialized_data, |
| 181 std::string* instance_id, |
| 182 std::string* extra_data) { |
| 183 DCHECK(instance_id && extra_data); |
| 184 std::size_t pos = serialized_data.find(','); |
| 185 if (pos == std::string::npos) |
| 186 return false; |
| 187 *instance_id = serialized_data.substr(0, pos); |
| 188 *extra_data = serialized_data.substr(pos + 1); |
| 189 return !instance_id->empty() && !extra_data->empty(); |
| 190 } |
| 191 |
| 172 void RecordOutgoingMessageToUMA( | 192 void RecordOutgoingMessageToUMA( |
| 173 const gcm::GCMClient::OutgoingMessage& message) { | 193 const gcm::GCMClient::OutgoingMessage& message) { |
| 174 OutgoingMessageTTLCategory ttl_category; | 194 OutgoingMessageTTLCategory ttl_category; |
| 175 if (message.time_to_live == 0) | 195 if (message.time_to_live == 0) |
| 176 ttl_category = TTL_ZERO; | 196 ttl_category = TTL_ZERO; |
| 177 else if (message.time_to_live <= 60 ) | 197 else if (message.time_to_live <= 60 ) |
| 178 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE; | 198 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE; |
| 179 else if (message.time_to_live <= 60 * 60) | 199 else if (message.time_to_live <= 60 * 60) |
| 180 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR; | 200 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR; |
| 181 else if (message.time_to_live <= 24 * 60 * 60) | 201 else if (message.time_to_live <= 24 * 60 * 60) |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 | 348 |
| 329 void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { | 349 void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { |
| 330 DCHECK_EQ(LOADING, state_); | 350 DCHECK_EQ(LOADING, state_); |
| 331 | 351 |
| 332 if (!result->success) { | 352 if (!result->success) { |
| 333 ResetStore(); | 353 ResetStore(); |
| 334 return; | 354 return; |
| 335 } | 355 } |
| 336 gcm_store_reset_ = false; | 356 gcm_store_reset_ = false; |
| 337 | 357 |
| 338 registrations_ = result->registrations; | |
| 339 device_checkin_info_.android_id = result->device_android_id; | 358 device_checkin_info_.android_id = result->device_android_id; |
| 340 device_checkin_info_.secret = result->device_security_token; | 359 device_checkin_info_.secret = result->device_security_token; |
| 341 device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts; | 360 device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts; |
| 342 // A case where there were previously no accounts reported with checkin is | 361 // A case where there were previously no accounts reported with checkin is |
| 343 // considered to be the same as when the list of accounts is empty. It enables | 362 // considered to be the same as when the list of accounts is empty. It enables |
| 344 // scheduling a periodic checkin for devices with no signed in users | 363 // scheduling a periodic checkin for devices with no signed in users |
| 345 // immediately after restart, while keeping |accounts_set == false| delays the | 364 // immediately after restart, while keeping |accounts_set == false| delays the |
| 346 // checkin until the list of accounts is set explicitly. | 365 // checkin until the list of accounts is set explicitly. |
| 347 if (result->last_checkin_accounts.size() == 0) | 366 if (result->last_checkin_accounts.size() == 0) |
| 348 device_checkin_info_.accounts_set = true; | 367 device_checkin_info_.accounts_set = true; |
| 349 last_checkin_time_ = result->last_checkin_time; | 368 last_checkin_time_ = result->last_checkin_time; |
| 350 gservices_settings_.UpdateFromLoadResult(*result); | 369 gservices_settings_.UpdateFromLoadResult(*result); |
| 351 instance_id_data_ = result->instance_id_data; | 370 |
| 371 for (auto iter = result->registrations.begin(); |
| 372 iter != result->registrations.end(); |
| 373 ++iter) { |
| 374 std::string registration_id; |
| 375 scoped_ptr<RegistrationInfo> registration = |
| 376 RegistrationInfo::BuildFromString( |
| 377 iter->first, iter->second, ®istration_id); |
| 378 // TODO(jianli): Add UMA to track the error case. |
| 379 if (registration.get()) |
| 380 registrations_[make_linked_ptr(registration.release())] = registration_id; |
| 381 } |
| 382 |
| 383 for (auto iter = result->instance_id_data.begin(); |
| 384 iter != result->instance_id_data.end(); |
| 385 ++iter) { |
| 386 std::string instance_id; |
| 387 std::string extra_data; |
| 388 if (DeserializeInstanceIDData(iter->second, &instance_id, &extra_data)) |
| 389 instance_id_data_[iter->first] = std::make_pair(instance_id, extra_data); |
| 390 } |
| 391 |
| 352 load_result_ = result.Pass(); | 392 load_result_ = result.Pass(); |
| 353 state_ = LOADED; | 393 state_ = LOADED; |
| 354 | 394 |
| 355 // Don't initiate the GCM connection when GCM is in delayed start mode and | 395 // Don't initiate the GCM connection when GCM is in delayed start mode and |
| 356 // not any standalone app has registered GCM yet. | 396 // not any standalone app has registered GCM yet. |
| 357 if (start_mode_ == DELAYED_START && !HasStandaloneRegisteredApp()) | 397 if (start_mode_ == DELAYED_START && !HasStandaloneRegisteredApp()) |
| 358 return; | 398 return; |
| 359 | 399 |
| 360 StartGCM(); | 400 StartGCM(); |
| 361 } | 401 } |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, | 565 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, |
| 526 weak_ptr_factory_.GetWeakPtr())); | 566 weak_ptr_factory_.GetWeakPtr())); |
| 527 } | 567 } |
| 528 | 568 |
| 529 void GCMClientImpl::UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) { | 569 void GCMClientImpl::UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) { |
| 530 DCHECK(mcs_client_); | 570 DCHECK(mcs_client_); |
| 531 mcs_client_->UpdateHeartbeatTimer(timer.Pass()); | 571 mcs_client_->UpdateHeartbeatTimer(timer.Pass()); |
| 532 } | 572 } |
| 533 | 573 |
| 534 void GCMClientImpl::AddInstanceIDData(const std::string& app_id, | 574 void GCMClientImpl::AddInstanceIDData(const std::string& app_id, |
| 535 const std::string& instance_id_data) { | 575 const std::string& instance_id, |
| 536 instance_id_data_[app_id] = instance_id_data; | 576 const std::string& extra_data) { |
| 577 instance_id_data_[app_id] = std::make_pair(instance_id, extra_data); |
| 537 gcm_store_->AddInstanceIDData( | 578 gcm_store_->AddInstanceIDData( |
| 538 app_id, | 579 app_id, |
| 539 instance_id_data, | 580 SerializeInstanceIDData(instance_id, extra_data), |
| 540 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, | 581 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, |
| 541 weak_ptr_factory_.GetWeakPtr())); | 582 weak_ptr_factory_.GetWeakPtr())); |
| 542 } | 583 } |
| 543 | 584 |
| 544 void GCMClientImpl::RemoveInstanceIDData(const std::string& app_id) { | 585 void GCMClientImpl::RemoveInstanceIDData(const std::string& app_id) { |
| 545 instance_id_data_.erase(app_id); | 586 instance_id_data_.erase(app_id); |
| 546 gcm_store_->RemoveInstanceIDData( | 587 gcm_store_->RemoveInstanceIDData( |
| 547 app_id, | 588 app_id, |
| 548 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, | 589 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, |
| 549 weak_ptr_factory_.GetWeakPtr())); | 590 weak_ptr_factory_.GetWeakPtr())); |
| 550 } | 591 } |
| 551 | 592 |
| 552 std::string GCMClientImpl::GetInstanceIDData(const std::string& app_id) { | 593 void GCMClientImpl::GetInstanceIDData(const std::string& app_id, |
| 594 std::string* instance_id, |
| 595 std::string* extra_data) { |
| 596 DCHECK(instance_id && extra_data); |
| 597 |
| 553 auto iter = instance_id_data_.find(app_id); | 598 auto iter = instance_id_data_.find(app_id); |
| 554 if (iter == instance_id_data_.end()) | 599 if (iter == instance_id_data_.end()) |
| 555 return std::string(); | 600 return; |
| 556 return iter->second; | 601 *instance_id = iter->second.first; |
| 602 *extra_data = iter->second.second; |
| 557 } | 603 } |
| 558 | 604 |
| 559 void GCMClientImpl::StartCheckin() { | 605 void GCMClientImpl::StartCheckin() { |
| 560 // Make sure no checkin is in progress. | 606 // Make sure no checkin is in progress. |
| 561 if (checkin_request_.get()) | 607 if (checkin_request_.get()) |
| 562 return; | 608 return; |
| 563 | 609 |
| 564 checkin_proto::ChromeBuildProto chrome_build_proto; | 610 checkin_proto::ChromeBuildProto chrome_build_proto; |
| 565 ToCheckinProtoVersion(chrome_build_info_, &chrome_build_proto); | 611 ToCheckinProtoVersion(chrome_build_info_, &chrome_build_proto); |
| 566 CheckinRequest::RequestInfo request_info(device_checkin_info_.android_id, | 612 CheckinRequest::RequestInfo request_info(device_checkin_info_.android_id, |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 delegate_->OnDisconnected(); | 749 delegate_->OnDisconnected(); |
| 704 mcs_client_.reset(); | 750 mcs_client_.reset(); |
| 705 checkin_request_.reset(); | 751 checkin_request_.reset(); |
| 706 // Delete all of the pending registration and unregistration requests. | 752 // Delete all of the pending registration and unregistration requests. |
| 707 STLDeleteValues(&pending_registration_requests_); | 753 STLDeleteValues(&pending_registration_requests_); |
| 708 STLDeleteValues(&pending_unregistration_requests_); | 754 STLDeleteValues(&pending_unregistration_requests_); |
| 709 state_ = INITIALIZED; | 755 state_ = INITIALIZED; |
| 710 gcm_store_->Close(); | 756 gcm_store_->Close(); |
| 711 } | 757 } |
| 712 | 758 |
| 713 void GCMClientImpl::Register(const std::string& app_id, | 759 void GCMClientImpl::Register( |
| 714 const std::vector<std::string>& sender_ids) { | 760 const linked_ptr<RegistrationInfo>& registration_info) { |
| 715 DCHECK_EQ(state_, READY); | 761 DCHECK_EQ(state_, READY); |
| 716 | 762 |
| 717 // If the same sender ids is provided, return the cached registration ID | 763 // Find and use the cached registration ID. |
| 718 // directly. | |
| 719 RegistrationInfoMap::const_iterator registrations_iter = | 764 RegistrationInfoMap::const_iterator registrations_iter = |
| 720 registrations_.find(app_id); | 765 registrations_.find(registration_info); |
| 721 if (registrations_iter != registrations_.end() && | 766 if (registrations_iter != registrations_.end()) { |
| 722 registrations_iter->second->sender_ids == sender_ids) { | 767 bool matched = true; |
| 723 delegate_->OnRegisterFinished( | 768 |
| 724 app_id, registrations_iter->second->registration_id, SUCCESS); | 769 // For GCM registration, we also match the sender IDs since multiple |
| 725 return; | 770 // registrations are not supported. |
| 771 const GCMRegistrationInfo* gcm_registration_info = |
| 772 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get()); |
| 773 if (gcm_registration_info) { |
| 774 const GCMRegistrationInfo* cached_gcm_registration_info = |
| 775 GCMRegistrationInfo::FromRegistrationInfo( |
| 776 registrations_iter->first.get()); |
| 777 DCHECK(cached_gcm_registration_info); |
| 778 if (cached_gcm_registration_info && |
| 779 gcm_registration_info->sender_ids != |
| 780 cached_gcm_registration_info->sender_ids) { |
| 781 matched = false; |
| 782 } |
| 783 } |
| 784 |
| 785 if (matched) { |
| 786 delegate_->OnRegisterFinished( |
| 787 registration_info, registrations_iter->second, SUCCESS); |
| 788 return; |
| 789 } |
| 726 } | 790 } |
| 727 | 791 |
| 728 RegistrationRequest::RequestInfo request_info( | |
| 729 device_checkin_info_.android_id, | |
| 730 device_checkin_info_.secret, | |
| 731 app_id, | |
| 732 sender_ids); | |
| 733 DCHECK_EQ(0u, pending_registration_requests_.count(app_id)); | |
| 734 | |
| 735 RegistrationRequest* registration_request = | 792 RegistrationRequest* registration_request = |
| 736 new RegistrationRequest(gservices_settings_.GetRegistrationURL(), | 793 new RegistrationRequest( |
| 737 request_info, | 794 gservices_settings_.GetRegistrationURL(), |
| 738 GetGCMBackoffPolicy(), | 795 BuildRegistrationRequestInfo(*registration_info).Pass(), |
| 739 base::Bind(&GCMClientImpl::OnRegisterCompleted, | 796 GetGCMBackoffPolicy(), |
| 740 weak_ptr_factory_.GetWeakPtr(), | 797 base::Bind(&GCMClientImpl::OnRegisterCompleted, |
| 741 app_id, | 798 weak_ptr_factory_.GetWeakPtr(), |
| 742 sender_ids), | 799 registration_info), |
| 743 kMaxRegistrationRetries, | 800 kMaxRegistrationRetries, |
| 744 url_request_context_getter_, | 801 url_request_context_getter_, |
| 745 &recorder_); | 802 &recorder_); |
| 746 pending_registration_requests_[app_id] = registration_request; | 803 pending_registration_requests_[registration_info] = registration_request; |
| 747 registration_request->Start(); | 804 registration_request->Start(); |
| 748 } | 805 } |
| 749 | 806 |
| 750 void GCMClientImpl::OnRegisterCompleted( | 807 void GCMClientImpl::OnRegisterCompleted( |
| 751 const std::string& app_id, | 808 const linked_ptr<RegistrationInfo>& registration_info, |
| 752 const std::vector<std::string>& sender_ids, | |
| 753 RegistrationRequest::Status status, | 809 RegistrationRequest::Status status, |
| 754 const std::string& registration_id) { | 810 const std::string& registration_id) { |
| 755 DCHECK(delegate_); | 811 DCHECK(delegate_); |
| 756 | 812 |
| 757 Result result; | 813 Result result; |
| 758 PendingRegistrationRequests::iterator iter = | 814 PendingRegistrationRequests::iterator iter = |
| 759 pending_registration_requests_.find(app_id); | 815 pending_registration_requests_.find(registration_info); |
| 760 if (iter == pending_registration_requests_.end()) | 816 if (iter == pending_registration_requests_.end()) |
| 761 result = UNKNOWN_ERROR; | 817 result = UNKNOWN_ERROR; |
| 762 else if (status == RegistrationRequest::INVALID_SENDER) | 818 else if (status == RegistrationRequest::INVALID_SENDER) |
| 763 result = INVALID_PARAMETER; | 819 result = INVALID_PARAMETER; |
| 764 else if (registration_id.empty()) | 820 else if (registration_id.empty()) |
| 765 result = SERVER_ERROR; | 821 result = SERVER_ERROR; |
| 766 else | 822 else |
| 767 result = SUCCESS; | 823 result = SUCCESS; |
| 768 | 824 |
| 769 if (result == SUCCESS) { | 825 if (result == SUCCESS) { |
| 770 // Cache it. | 826 // Cache it. |
| 771 linked_ptr<RegistrationInfo> registration(new RegistrationInfo); | 827 registrations_[registration_info] = registration_id; |
| 772 registration->sender_ids = sender_ids; | |
| 773 registration->registration_id = registration_id; | |
| 774 registrations_[app_id] = registration; | |
| 775 | 828 |
| 776 // Save it in the persistent store. | 829 // Save it in the persistent store. |
| 777 gcm_store_->AddRegistration( | 830 gcm_store_->AddRegistration( |
| 778 app_id, | 831 registration_info->GetSerializedKey(), |
| 779 registration, | 832 registration_info->GetSerializedValue(registration_id), |
| 780 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, | 833 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
| 781 weak_ptr_factory_.GetWeakPtr())); | 834 weak_ptr_factory_.GetWeakPtr())); |
| 782 } | 835 } |
| 783 | 836 |
| 784 delegate_->OnRegisterFinished( | 837 delegate_->OnRegisterFinished( |
| 785 app_id, result == SUCCESS ? registration_id : std::string(), result); | 838 registration_info, |
| 839 result == SUCCESS ? registration_id : std::string(), |
| 840 result); |
| 786 | 841 |
| 787 if (iter != pending_registration_requests_.end()) { | 842 if (iter != pending_registration_requests_.end()) { |
| 788 delete iter->second; | 843 delete iter->second; |
| 789 pending_registration_requests_.erase(iter); | 844 pending_registration_requests_.erase(iter); |
| 790 } | 845 } |
| 791 } | 846 } |
| 792 | 847 |
| 793 void GCMClientImpl::Unregister(const std::string& app_id) { | 848 void GCMClientImpl::Unregister( |
| 849 const linked_ptr<RegistrationInfo>& registration_info) { |
| 794 DCHECK_EQ(state_, READY); | 850 DCHECK_EQ(state_, READY); |
| 795 if (pending_unregistration_requests_.count(app_id) == 1) | 851 if (pending_unregistration_requests_.count(registration_info) == 1) |
| 796 return; | 852 return; |
| 797 | 853 |
| 798 // Remove from the cache and persistent store. | 854 // Remove from the cache and persistent store. |
| 799 registrations_.erase(app_id); | 855 registrations_.erase(registration_info); |
| 800 gcm_store_->RemoveRegistration( | 856 gcm_store_->RemoveRegistration( |
| 801 app_id, | 857 registration_info->GetSerializedKey(), |
| 802 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, | 858 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
| 803 weak_ptr_factory_.GetWeakPtr())); | 859 weak_ptr_factory_.GetWeakPtr())); |
| 804 | 860 |
| 805 UnregistrationRequest::RequestInfo request_info( | |
| 806 device_checkin_info_.android_id, | |
| 807 device_checkin_info_.secret, | |
| 808 app_id); | |
| 809 | |
| 810 UnregistrationRequest* unregistration_request = new UnregistrationRequest( | 861 UnregistrationRequest* unregistration_request = new UnregistrationRequest( |
| 811 gservices_settings_.GetRegistrationURL(), | 862 gservices_settings_.GetRegistrationURL(), |
| 812 request_info, | 863 BuildUnregistrationRequestInfo(*registration_info).Pass(), |
| 813 GetGCMBackoffPolicy(), | 864 GetGCMBackoffPolicy(), |
| 814 base::Bind(&GCMClientImpl::OnUnregisterCompleted, | 865 base::Bind(&GCMClientImpl::OnUnregisterCompleted, |
| 815 weak_ptr_factory_.GetWeakPtr(), | 866 weak_ptr_factory_.GetWeakPtr(), |
| 816 app_id), | 867 registration_info), |
| 817 url_request_context_getter_, | 868 url_request_context_getter_, |
| 818 &recorder_); | 869 &recorder_); |
| 819 pending_unregistration_requests_[app_id] = unregistration_request; | 870 pending_unregistration_requests_[registration_info] = unregistration_request; |
| 820 unregistration_request->Start(); | 871 unregistration_request->Start(); |
| 821 } | 872 } |
| 822 | 873 |
| 823 void GCMClientImpl::OnUnregisterCompleted( | 874 void GCMClientImpl::OnUnregisterCompleted( |
| 824 const std::string& app_id, | 875 const linked_ptr<RegistrationInfo>& registration_info, |
| 825 UnregistrationRequest::Status status) { | 876 UnregistrationRequest::Status status) { |
| 826 DVLOG(1) << "Unregister completed for app: " << app_id | 877 DVLOG(1) << "Unregister completed for app: " << registration_info->app_id |
| 827 << " with " << (status ? "success." : "failure."); | 878 << " with " << (status ? "success." : "failure."); |
| 828 delegate_->OnUnregisterFinished( | 879 delegate_->OnUnregisterFinished( |
| 829 app_id, | 880 registration_info, |
| 830 status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR); | 881 status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR); |
| 831 | 882 |
| 832 PendingUnregistrationRequests::iterator iter = | 883 PendingUnregistrationRequests::iterator iter = |
| 833 pending_unregistration_requests_.find(app_id); | 884 pending_unregistration_requests_.find(registration_info); |
| 834 if (iter == pending_unregistration_requests_.end()) | 885 if (iter == pending_unregistration_requests_.end()) |
| 835 return; | 886 return; |
| 836 | 887 |
| 837 delete iter->second; | 888 delete iter->second; |
| 838 pending_unregistration_requests_.erase(iter); | 889 pending_unregistration_requests_.erase(iter); |
| 839 } | 890 } |
| 840 | 891 |
| 841 void GCMClientImpl::OnGCMStoreDestroyed(bool success) { | 892 void GCMClientImpl::OnGCMStoreDestroyed(bool success) { |
| 842 DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!"; | 893 DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!"; |
| 843 UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success); | 894 UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 885 case GCMClientImpl::INITIAL_DEVICE_CHECKIN: | 936 case GCMClientImpl::INITIAL_DEVICE_CHECKIN: |
| 886 return "INITIAL_DEVICE_CHECKIN"; | 937 return "INITIAL_DEVICE_CHECKIN"; |
| 887 case GCMClientImpl::READY: | 938 case GCMClientImpl::READY: |
| 888 return "READY"; | 939 return "READY"; |
| 889 default: | 940 default: |
| 890 NOTREACHED(); | 941 NOTREACHED(); |
| 891 return std::string(); | 942 return std::string(); |
| 892 } | 943 } |
| 893 } | 944 } |
| 894 | 945 |
| 946 scoped_ptr<RegistrationRequest::RequestInfo> |
| 947 GCMClientImpl::BuildRegistrationRequestInfo( |
| 948 const RegistrationInfo& registration_info) const { |
| 949 const GCMRegistrationInfo* gcm_registration_info = |
| 950 GCMRegistrationInfo::FromRegistrationInfo(®istration_info); |
| 951 if (gcm_registration_info) { |
| 952 scoped_ptr<RegistrationRequest::GCMRequestInfo> request_info( |
| 953 new RegistrationRequest::GCMRequestInfo); |
| 954 request_info->chrome_version = chrome_build_info_.version; |
| 955 request_info->android_id = device_checkin_info_.android_id; |
| 956 request_info->security_token = device_checkin_info_.secret; |
| 957 request_info->app_id = registration_info.app_id; |
| 958 request_info->sender_ids = gcm_registration_info->sender_ids; |
| 959 return request_info.Pass(); |
| 960 } |
| 961 |
| 962 const InstanceIDTokenInfo* instance_id_token_info = |
| 963 InstanceIDTokenInfo::FromRegistrationInfo(®istration_info); |
| 964 if (!instance_id_token_info) |
| 965 return scoped_ptr<RegistrationRequest::RequestInfo>(); |
| 966 |
| 967 auto instance_id_iter = instance_id_data_.find(registration_info.app_id); |
| 968 if (instance_id_iter == instance_id_data_.end()) |
| 969 return scoped_ptr<RegistrationRequest::RequestInfo>(); |
| 970 |
| 971 scoped_ptr<RegistrationRequest::InstanceIDRequestInfo> request_info( |
| 972 new RegistrationRequest::InstanceIDRequestInfo); |
| 973 request_info->chrome_version = chrome_build_info_.version; |
| 974 request_info->android_id = device_checkin_info_.android_id; |
| 975 request_info->security_token = device_checkin_info_.secret; |
| 976 request_info->app_id = registration_info.app_id; |
| 977 request_info->instance_id = instance_id_iter->first; |
| 978 request_info->authorized_entity = instance_id_token_info->authorized_entity; |
| 979 request_info->scope = instance_id_token_info->scope; |
| 980 request_info->options = instance_id_token_info->options; |
| 981 return request_info.Pass(); |
| 982 } |
| 983 |
| 984 scoped_ptr<UnregistrationRequest::RequestInfo> |
| 985 GCMClientImpl::BuildUnregistrationRequestInfo( |
| 986 const RegistrationInfo& registration_info) const { |
| 987 const GCMRegistrationInfo* gcm_registration_info = |
| 988 GCMRegistrationInfo::FromRegistrationInfo(®istration_info); |
| 989 if (gcm_registration_info) { |
| 990 scoped_ptr<UnregistrationRequest::GCMRequestInfo> request_info( |
| 991 new UnregistrationRequest::GCMRequestInfo); |
| 992 request_info->chrome_version = chrome_build_info_.version; |
| 993 request_info->android_id = device_checkin_info_.android_id; |
| 994 request_info->security_token = device_checkin_info_.secret; |
| 995 request_info->app_id = registration_info.app_id; |
| 996 return request_info.Pass(); |
| 997 } |
| 998 |
| 999 const InstanceIDTokenInfo* instance_id_token_info = |
| 1000 InstanceIDTokenInfo::FromRegistrationInfo(®istration_info); |
| 1001 if (!instance_id_token_info) |
| 1002 return scoped_ptr<UnregistrationRequest::RequestInfo>(); |
| 1003 |
| 1004 auto instance_id_iter = instance_id_data_.find(registration_info.app_id); |
| 1005 if (instance_id_iter == instance_id_data_.end()) |
| 1006 return scoped_ptr<UnregistrationRequest::RequestInfo>(); |
| 1007 |
| 1008 scoped_ptr<UnregistrationRequest::InstanceIDRequestInfo> request_info( |
| 1009 new UnregistrationRequest::InstanceIDRequestInfo); |
| 1010 request_info->chrome_version = chrome_build_info_.version; |
| 1011 request_info->android_id = device_checkin_info_.android_id; |
| 1012 request_info->security_token = device_checkin_info_.secret; |
| 1013 request_info->app_id = registration_info.app_id; |
| 1014 request_info->instance_id = instance_id_iter->first; |
| 1015 request_info->authorized_entity = instance_id_token_info->authorized_entity; |
| 1016 request_info->scope = instance_id_token_info->scope; |
| 1017 return request_info.Pass(); |
| 1018 } |
| 1019 |
| 895 void GCMClientImpl::SetRecording(bool recording) { | 1020 void GCMClientImpl::SetRecording(bool recording) { |
| 896 recorder_.SetRecording(recording); | 1021 recorder_.SetRecording(recording); |
| 897 } | 1022 } |
| 898 | 1023 |
| 899 void GCMClientImpl::ClearActivityLogs() { | 1024 void GCMClientImpl::ClearActivityLogs() { |
| 900 recorder_.Clear(); | 1025 recorder_.Clear(); |
| 901 } | 1026 } |
| 902 | 1027 |
| 903 GCMClient::GCMStatistics GCMClientImpl::GetStatistics() const { | 1028 GCMClient::GCMStatistics GCMClientImpl::GetStatistics() const { |
| 904 GCMClient::GCMStatistics stats; | 1029 GCMClient::GCMStatistics stats; |
| 905 stats.gcm_client_created = true; | 1030 stats.gcm_client_created = true; |
| 906 stats.is_recording = recorder_.is_recording(); | 1031 stats.is_recording = recorder_.is_recording(); |
| 907 stats.gcm_client_state = GetStateString(); | 1032 stats.gcm_client_state = GetStateString(); |
| 908 stats.connection_client_created = mcs_client_.get() != NULL; | 1033 stats.connection_client_created = mcs_client_.get() != NULL; |
| 909 if (connection_factory_.get()) | 1034 if (connection_factory_.get()) |
| 910 stats.connection_state = connection_factory_->GetConnectionStateString(); | 1035 stats.connection_state = connection_factory_->GetConnectionStateString(); |
| 911 if (mcs_client_.get()) { | 1036 if (mcs_client_.get()) { |
| 912 stats.send_queue_size = mcs_client_->GetSendQueueSize(); | 1037 stats.send_queue_size = mcs_client_->GetSendQueueSize(); |
| 913 stats.resend_queue_size = mcs_client_->GetResendQueueSize(); | 1038 stats.resend_queue_size = mcs_client_->GetResendQueueSize(); |
| 914 } | 1039 } |
| 915 if (device_checkin_info_.android_id > 0) | 1040 if (device_checkin_info_.android_id > 0) |
| 916 stats.android_id = device_checkin_info_.android_id; | 1041 stats.android_id = device_checkin_info_.android_id; |
| 917 recorder_.CollectActivities(&stats.recorded_activities); | 1042 recorder_.CollectActivities(&stats.recorded_activities); |
| 918 | 1043 |
| 919 for (RegistrationInfoMap::const_iterator it = registrations_.begin(); | 1044 for (RegistrationInfoMap::const_iterator it = registrations_.begin(); |
| 920 it != registrations_.end(); ++it) { | 1045 it != registrations_.end(); ++it) { |
| 921 stats.registered_app_ids.push_back(it->first); | 1046 stats.registered_app_ids.push_back(it->first->app_id); |
| 922 } | 1047 } |
| 923 return stats; | 1048 return stats; |
| 924 } | 1049 } |
| 925 | 1050 |
| 926 void GCMClientImpl::OnActivityRecorded() { | 1051 void GCMClientImpl::OnActivityRecorded() { |
| 927 delegate_->OnActivityRecorded(); | 1052 delegate_->OnActivityRecorded(); |
| 928 } | 1053 } |
| 929 | 1054 |
| 930 void GCMClientImpl::OnConnected(const GURL& current_server, | 1055 void GCMClientImpl::OnConnected(const GURL& current_server, |
| 931 const net::IPEndPoint& ip_endpoint) { | 1056 const net::IPEndPoint& ip_endpoint) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1029 DVLOG(1) << "Unknown message_type received. Message ignored. " | 1154 DVLOG(1) << "Unknown message_type received. Message ignored. " |
| 1030 << "App ID: " << data_message_stanza.category() << "."; | 1155 << "App ID: " << data_message_stanza.category() << "."; |
| 1031 break; | 1156 break; |
| 1032 } | 1157 } |
| 1033 } | 1158 } |
| 1034 | 1159 |
| 1035 void GCMClientImpl::HandleIncomingDataMessage( | 1160 void GCMClientImpl::HandleIncomingDataMessage( |
| 1036 const mcs_proto::DataMessageStanza& data_message_stanza, | 1161 const mcs_proto::DataMessageStanza& data_message_stanza, |
| 1037 MessageData& message_data) { | 1162 MessageData& message_data) { |
| 1038 std::string app_id = data_message_stanza.category(); | 1163 std::string app_id = data_message_stanza.category(); |
| 1164 std::string sender = data_message_stanza.from(); |
| 1039 | 1165 |
| 1040 // Drop the message when the app is not registered for the sender of the | 1166 // Drop the message when the app is not registered for the sender of the |
| 1041 // message. | 1167 // message. |
| 1042 RegistrationInfoMap::iterator iter = registrations_.find(app_id); | 1168 bool registered = false; |
| 1043 bool not_registered = | 1169 |
| 1044 iter == registrations_.end() || | 1170 // First, find among all GCM registrations. |
| 1045 std::find(iter->second->sender_ids.begin(), | 1171 scoped_ptr<GCMRegistrationInfo> gcm_registration(new GCMRegistrationInfo); |
| 1046 iter->second->sender_ids.end(), | 1172 gcm_registration->app_id = app_id; |
| 1047 data_message_stanza.from()) == iter->second->sender_ids.end(); | 1173 auto gcm_registration_iter = registrations_.find( |
| 1048 recorder_.RecordDataMessageReceived(app_id, data_message_stanza.from(), | 1174 make_linked_ptr<RegistrationInfo>(gcm_registration.release())); |
| 1049 data_message_stanza.ByteSize(), !not_registered, | 1175 if (gcm_registration_iter != registrations_.end()) { |
| 1176 GCMRegistrationInfo* cached_gcm_registration = |
| 1177 GCMRegistrationInfo::FromRegistrationInfo( |
| 1178 gcm_registration_iter->first.get()); |
| 1179 if (cached_gcm_registration && |
| 1180 std::find(cached_gcm_registration->sender_ids.begin(), |
| 1181 cached_gcm_registration->sender_ids.end(), |
| 1182 sender) != cached_gcm_registration->sender_ids.end()) { |
| 1183 registered = true; |
| 1184 } |
| 1185 } |
| 1186 |
| 1187 // Then, find among all InstanceID registrations. |
| 1188 if (!registered) { |
| 1189 scoped_ptr<InstanceIDTokenInfo> instance_id_token(new InstanceIDTokenInfo); |
| 1190 instance_id_token->app_id = app_id; |
| 1191 instance_id_token->authorized_entity = sender; |
| 1192 instance_id_token->scope = kGCMScope; |
| 1193 auto instance_id_token_iter = registrations_.find( |
| 1194 make_linked_ptr<RegistrationInfo>(instance_id_token.release())); |
| 1195 if (instance_id_token_iter != registrations_.end()) |
| 1196 registered = true; |
| 1197 } |
| 1198 |
| 1199 recorder_.RecordDataMessageReceived(app_id, sender, |
| 1200 data_message_stanza.ByteSize(), registered, |
| 1050 GCMStatsRecorder::DATA_MESSAGE); | 1201 GCMStatsRecorder::DATA_MESSAGE); |
| 1051 if (not_registered) { | 1202 if (!registered) |
| 1052 return; | 1203 return; |
| 1053 } | |
| 1054 | 1204 |
| 1055 IncomingMessage incoming_message; | 1205 IncomingMessage incoming_message; |
| 1056 incoming_message.sender_id = data_message_stanza.from(); | 1206 incoming_message.sender_id = data_message_stanza.from(); |
| 1057 if (data_message_stanza.has_token()) | 1207 if (data_message_stanza.has_token()) |
| 1058 incoming_message.collapse_key = data_message_stanza.token(); | 1208 incoming_message.collapse_key = data_message_stanza.token(); |
| 1059 incoming_message.data = message_data; | 1209 incoming_message.data = message_data; |
| 1060 delegate_->OnMessageReceived(app_id, incoming_message); | 1210 delegate_->OnMessageReceived(app_id, incoming_message); |
| 1061 } | 1211 } |
| 1062 | 1212 |
| 1063 void GCMClientImpl::HandleIncomingSendError( | 1213 void GCMClientImpl::HandleIncomingSendError( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1081 delegate_->OnMessageSendError(data_message_stanza.category(), | 1231 delegate_->OnMessageSendError(data_message_stanza.category(), |
| 1082 send_error_details); | 1232 send_error_details); |
| 1083 } | 1233 } |
| 1084 | 1234 |
| 1085 bool GCMClientImpl::HasStandaloneRegisteredApp() const { | 1235 bool GCMClientImpl::HasStandaloneRegisteredApp() const { |
| 1086 if (registrations_.empty()) | 1236 if (registrations_.empty()) |
| 1087 return false; | 1237 return false; |
| 1088 // Note that account mapper is not counted as a standalone app since it is | 1238 // Note that account mapper is not counted as a standalone app since it is |
| 1089 // automatically started when other app uses GCM. | 1239 // automatically started when other app uses GCM. |
| 1090 return registrations_.size() > 1 || | 1240 return registrations_.size() > 1 || |
| 1091 !registrations_.count(kGCMAccountMapperAppId); | 1241 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId); |
| 1092 } | 1242 } |
| 1093 | 1243 |
| 1094 } // namespace gcm | 1244 } // namespace gcm |
| OLD | NEW |