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::AddHeartbeatInterval(const std::string& scope, | 605 void GCMClientImpl::AddHeartbeatInterval(const std::string& scope, |
560 int interval_ms) { | 606 int interval_ms) { |
561 DCHECK(mcs_client_); | 607 DCHECK(mcs_client_); |
562 mcs_client_->AddHeartbeatInterval(scope, interval_ms); | 608 mcs_client_->AddHeartbeatInterval(scope, interval_ms); |
563 } | 609 } |
564 | 610 |
565 void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) { | 611 void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) { |
566 DCHECK(mcs_client_); | 612 DCHECK(mcs_client_); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 delegate_->OnDisconnected(); | 760 delegate_->OnDisconnected(); |
715 mcs_client_.reset(); | 761 mcs_client_.reset(); |
716 checkin_request_.reset(); | 762 checkin_request_.reset(); |
717 // Delete all of the pending registration and unregistration requests. | 763 // Delete all of the pending registration and unregistration requests. |
718 STLDeleteValues(&pending_registration_requests_); | 764 STLDeleteValues(&pending_registration_requests_); |
719 STLDeleteValues(&pending_unregistration_requests_); | 765 STLDeleteValues(&pending_unregistration_requests_); |
720 state_ = INITIALIZED; | 766 state_ = INITIALIZED; |
721 gcm_store_->Close(); | 767 gcm_store_->Close(); |
722 } | 768 } |
723 | 769 |
724 void GCMClientImpl::Register(const std::string& app_id, | 770 void GCMClientImpl::Register( |
725 const std::vector<std::string>& sender_ids) { | 771 const linked_ptr<RegistrationInfo>& registration_info) { |
726 DCHECK_EQ(state_, READY); | 772 DCHECK_EQ(state_, READY); |
727 | 773 |
728 // If the same sender ids is provided, return the cached registration ID | 774 // Find and use the cached registration ID. |
729 // directly. | |
730 RegistrationInfoMap::const_iterator registrations_iter = | 775 RegistrationInfoMap::const_iterator registrations_iter = |
731 registrations_.find(app_id); | 776 registrations_.find(registration_info); |
732 if (registrations_iter != registrations_.end() && | 777 if (registrations_iter != registrations_.end()) { |
733 registrations_iter->second->sender_ids == sender_ids) { | 778 bool matched = true; |
734 delegate_->OnRegisterFinished( | 779 |
735 app_id, registrations_iter->second->registration_id, SUCCESS); | 780 // For GCM registration, we also match the sender IDs since multiple |
736 return; | 781 // registrations are not supported. |
| 782 const GCMRegistrationInfo* gcm_registration_info = |
| 783 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get()); |
| 784 if (gcm_registration_info) { |
| 785 const GCMRegistrationInfo* cached_gcm_registration_info = |
| 786 GCMRegistrationInfo::FromRegistrationInfo( |
| 787 registrations_iter->first.get()); |
| 788 DCHECK(cached_gcm_registration_info); |
| 789 if (cached_gcm_registration_info && |
| 790 gcm_registration_info->sender_ids != |
| 791 cached_gcm_registration_info->sender_ids) { |
| 792 matched = false; |
| 793 } |
| 794 } |
| 795 |
| 796 if (matched) { |
| 797 delegate_->OnRegisterFinished( |
| 798 registration_info, registrations_iter->second, SUCCESS); |
| 799 return; |
| 800 } |
737 } | 801 } |
738 | 802 |
739 RegistrationRequest::RequestInfo request_info( | |
740 device_checkin_info_.android_id, | |
741 device_checkin_info_.secret, | |
742 app_id, | |
743 sender_ids); | |
744 DCHECK_EQ(0u, pending_registration_requests_.count(app_id)); | |
745 | |
746 RegistrationRequest* registration_request = | 803 RegistrationRequest* registration_request = |
747 new RegistrationRequest(gservices_settings_.GetRegistrationURL(), | 804 new RegistrationRequest( |
748 request_info, | 805 gservices_settings_.GetRegistrationURL(), |
749 GetGCMBackoffPolicy(), | 806 BuildRegistrationRequestInfo(*registration_info).Pass(), |
750 base::Bind(&GCMClientImpl::OnRegisterCompleted, | 807 GetGCMBackoffPolicy(), |
751 weak_ptr_factory_.GetWeakPtr(), | 808 base::Bind(&GCMClientImpl::OnRegisterCompleted, |
752 app_id, | 809 weak_ptr_factory_.GetWeakPtr(), |
753 sender_ids), | 810 registration_info), |
754 kMaxRegistrationRetries, | 811 kMaxRegistrationRetries, |
755 url_request_context_getter_, | 812 url_request_context_getter_, |
756 &recorder_); | 813 &recorder_); |
757 pending_registration_requests_[app_id] = registration_request; | 814 pending_registration_requests_[registration_info] = registration_request; |
758 registration_request->Start(); | 815 registration_request->Start(); |
759 } | 816 } |
760 | 817 |
761 void GCMClientImpl::OnRegisterCompleted( | 818 void GCMClientImpl::OnRegisterCompleted( |
762 const std::string& app_id, | 819 const linked_ptr<RegistrationInfo>& registration_info, |
763 const std::vector<std::string>& sender_ids, | |
764 RegistrationRequest::Status status, | 820 RegistrationRequest::Status status, |
765 const std::string& registration_id) { | 821 const std::string& registration_id) { |
766 DCHECK(delegate_); | 822 DCHECK(delegate_); |
767 | 823 |
768 Result result; | 824 Result result; |
769 PendingRegistrationRequests::iterator iter = | 825 PendingRegistrationRequests::iterator iter = |
770 pending_registration_requests_.find(app_id); | 826 pending_registration_requests_.find(registration_info); |
771 if (iter == pending_registration_requests_.end()) | 827 if (iter == pending_registration_requests_.end()) |
772 result = UNKNOWN_ERROR; | 828 result = UNKNOWN_ERROR; |
773 else if (status == RegistrationRequest::INVALID_SENDER) | 829 else if (status == RegistrationRequest::INVALID_SENDER) |
774 result = INVALID_PARAMETER; | 830 result = INVALID_PARAMETER; |
775 else if (registration_id.empty()) | 831 else if (registration_id.empty()) |
776 result = SERVER_ERROR; | 832 result = SERVER_ERROR; |
777 else | 833 else |
778 result = SUCCESS; | 834 result = SUCCESS; |
779 | 835 |
780 if (result == SUCCESS) { | 836 if (result == SUCCESS) { |
781 // Cache it. | 837 // Cache it. |
782 linked_ptr<RegistrationInfo> registration(new RegistrationInfo); | 838 registrations_[registration_info] = registration_id; |
783 registration->sender_ids = sender_ids; | |
784 registration->registration_id = registration_id; | |
785 registrations_[app_id] = registration; | |
786 | 839 |
787 // Save it in the persistent store. | 840 // Save it in the persistent store. |
788 gcm_store_->AddRegistration( | 841 gcm_store_->AddRegistration( |
789 app_id, | 842 registration_info->GetSerializedKey(), |
790 registration, | 843 registration_info->GetSerializedValue(registration_id), |
791 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, | 844 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
792 weak_ptr_factory_.GetWeakPtr())); | 845 weak_ptr_factory_.GetWeakPtr())); |
793 } | 846 } |
794 | 847 |
795 delegate_->OnRegisterFinished( | 848 delegate_->OnRegisterFinished( |
796 app_id, result == SUCCESS ? registration_id : std::string(), result); | 849 registration_info, |
| 850 result == SUCCESS ? registration_id : std::string(), |
| 851 result); |
797 | 852 |
798 if (iter != pending_registration_requests_.end()) { | 853 if (iter != pending_registration_requests_.end()) { |
799 delete iter->second; | 854 delete iter->second; |
800 pending_registration_requests_.erase(iter); | 855 pending_registration_requests_.erase(iter); |
801 } | 856 } |
802 } | 857 } |
803 | 858 |
804 void GCMClientImpl::Unregister(const std::string& app_id) { | 859 void GCMClientImpl::Unregister( |
| 860 const linked_ptr<RegistrationInfo>& registration_info) { |
805 DCHECK_EQ(state_, READY); | 861 DCHECK_EQ(state_, READY); |
806 if (pending_unregistration_requests_.count(app_id) == 1) | 862 if (pending_unregistration_requests_.count(registration_info) == 1) |
807 return; | 863 return; |
808 | 864 |
809 // Remove from the cache and persistent store. | 865 // Remove from the cache and persistent store. |
810 registrations_.erase(app_id); | 866 registrations_.erase(registration_info); |
811 gcm_store_->RemoveRegistration( | 867 gcm_store_->RemoveRegistration( |
812 app_id, | 868 registration_info->GetSerializedKey(), |
813 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, | 869 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
814 weak_ptr_factory_.GetWeakPtr())); | 870 weak_ptr_factory_.GetWeakPtr())); |
815 | 871 |
816 UnregistrationRequest::RequestInfo request_info( | |
817 device_checkin_info_.android_id, | |
818 device_checkin_info_.secret, | |
819 app_id); | |
820 | |
821 UnregistrationRequest* unregistration_request = new UnregistrationRequest( | 872 UnregistrationRequest* unregistration_request = new UnregistrationRequest( |
822 gservices_settings_.GetRegistrationURL(), | 873 gservices_settings_.GetRegistrationURL(), |
823 request_info, | 874 BuildUnregistrationRequestInfo(*registration_info).Pass(), |
824 GetGCMBackoffPolicy(), | 875 GetGCMBackoffPolicy(), |
825 base::Bind(&GCMClientImpl::OnUnregisterCompleted, | 876 base::Bind(&GCMClientImpl::OnUnregisterCompleted, |
826 weak_ptr_factory_.GetWeakPtr(), | 877 weak_ptr_factory_.GetWeakPtr(), |
827 app_id), | 878 registration_info), |
828 url_request_context_getter_, | 879 url_request_context_getter_, |
829 &recorder_); | 880 &recorder_); |
830 pending_unregistration_requests_[app_id] = unregistration_request; | 881 pending_unregistration_requests_[registration_info] = unregistration_request; |
831 unregistration_request->Start(); | 882 unregistration_request->Start(); |
832 } | 883 } |
833 | 884 |
834 void GCMClientImpl::OnUnregisterCompleted( | 885 void GCMClientImpl::OnUnregisterCompleted( |
835 const std::string& app_id, | 886 const linked_ptr<RegistrationInfo>& registration_info, |
836 UnregistrationRequest::Status status) { | 887 UnregistrationRequest::Status status) { |
837 DVLOG(1) << "Unregister completed for app: " << app_id | 888 DVLOG(1) << "Unregister completed for app: " << registration_info->app_id |
838 << " with " << (status ? "success." : "failure."); | 889 << " with " << (status ? "success." : "failure."); |
839 delegate_->OnUnregisterFinished( | 890 delegate_->OnUnregisterFinished( |
840 app_id, | 891 registration_info, |
841 status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR); | 892 status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR); |
842 | 893 |
843 PendingUnregistrationRequests::iterator iter = | 894 PendingUnregistrationRequests::iterator iter = |
844 pending_unregistration_requests_.find(app_id); | 895 pending_unregistration_requests_.find(registration_info); |
845 if (iter == pending_unregistration_requests_.end()) | 896 if (iter == pending_unregistration_requests_.end()) |
846 return; | 897 return; |
847 | 898 |
848 delete iter->second; | 899 delete iter->second; |
849 pending_unregistration_requests_.erase(iter); | 900 pending_unregistration_requests_.erase(iter); |
850 } | 901 } |
851 | 902 |
852 void GCMClientImpl::OnGCMStoreDestroyed(bool success) { | 903 void GCMClientImpl::OnGCMStoreDestroyed(bool success) { |
853 DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!"; | 904 DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!"; |
854 UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success); | 905 UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
896 case GCMClientImpl::INITIAL_DEVICE_CHECKIN: | 947 case GCMClientImpl::INITIAL_DEVICE_CHECKIN: |
897 return "INITIAL_DEVICE_CHECKIN"; | 948 return "INITIAL_DEVICE_CHECKIN"; |
898 case GCMClientImpl::READY: | 949 case GCMClientImpl::READY: |
899 return "READY"; | 950 return "READY"; |
900 default: | 951 default: |
901 NOTREACHED(); | 952 NOTREACHED(); |
902 return std::string(); | 953 return std::string(); |
903 } | 954 } |
904 } | 955 } |
905 | 956 |
| 957 scoped_ptr<RegistrationRequest::RequestInfo> |
| 958 GCMClientImpl::BuildRegistrationRequestInfo( |
| 959 const RegistrationInfo& registration_info) const { |
| 960 scoped_ptr<RegistrationRequest::RequestInfo> request_info; |
| 961 |
| 962 const GCMRegistrationInfo* gcm_registration_info = |
| 963 GCMRegistrationInfo::FromRegistrationInfo(®istration_info); |
| 964 if (gcm_registration_info) { |
| 965 scoped_ptr<RegistrationRequest::GCMRequestInfo> gcm_request_info( |
| 966 new RegistrationRequest::GCMRequestInfo); |
| 967 gcm_request_info->set_sender_ids(gcm_registration_info->sender_ids); |
| 968 request_info = gcm_request_info.Pass(); |
| 969 } |
| 970 |
| 971 const InstanceIDTokenInfo* instance_id_token_info = |
| 972 InstanceIDTokenInfo::FromRegistrationInfo(®istration_info); |
| 973 if (instance_id_token_info) { |
| 974 auto instance_id_iter = instance_id_data_.find(registration_info.app_id); |
| 975 DCHECK(instance_id_iter != instance_id_data_.end()); |
| 976 |
| 977 scoped_ptr<RegistrationRequest::InstanceIDRequestInfo> |
| 978 instance_id_token_request_info( |
| 979 new RegistrationRequest::InstanceIDRequestInfo); |
| 980 instance_id_token_request_info->set_instance_id(instance_id_iter->first); |
| 981 instance_id_token_request_info->set_authorized_entity( |
| 982 instance_id_token_info->authorized_entity); |
| 983 instance_id_token_request_info->set_scope(instance_id_token_info->scope); |
| 984 instance_id_token_request_info->set_options( |
| 985 instance_id_token_info->options); |
| 986 request_info = instance_id_token_request_info.Pass(); |
| 987 } |
| 988 |
| 989 DCHECK(request_info.get()); |
| 990 |
| 991 request_info->set_chrome_version(chrome_build_info_.version); |
| 992 request_info->set_android_id(device_checkin_info_.android_id); |
| 993 request_info->set_security_token(device_checkin_info_.secret); |
| 994 request_info->set_app_id(registration_info.app_id); |
| 995 return request_info.Pass(); |
| 996 } |
| 997 |
| 998 scoped_ptr<UnregistrationRequest::RequestInfo> |
| 999 GCMClientImpl::BuildUnregistrationRequestInfo( |
| 1000 const RegistrationInfo& registration_info) const { |
| 1001 scoped_ptr<UnregistrationRequest::RequestInfo> request_info; |
| 1002 |
| 1003 const GCMRegistrationInfo* gcm_registration_info = |
| 1004 GCMRegistrationInfo::FromRegistrationInfo(®istration_info); |
| 1005 if (gcm_registration_info) |
| 1006 request_info.reset(new UnregistrationRequest::GCMRequestInfo); |
| 1007 |
| 1008 const InstanceIDTokenInfo* instance_id_token_info = |
| 1009 InstanceIDTokenInfo::FromRegistrationInfo(®istration_info); |
| 1010 if (instance_id_token_info) { |
| 1011 auto instance_id_iter = instance_id_data_.find(registration_info.app_id); |
| 1012 DCHECK(instance_id_iter != instance_id_data_.end()); |
| 1013 |
| 1014 scoped_ptr<UnregistrationRequest::InstanceIDRequestInfo> |
| 1015 instance_id_token_request_info( |
| 1016 new UnregistrationRequest::InstanceIDRequestInfo); |
| 1017 instance_id_token_request_info->set_instance_id(instance_id_iter->first); |
| 1018 instance_id_token_request_info->set_authorized_entity( |
| 1019 instance_id_token_info->authorized_entity); |
| 1020 instance_id_token_request_info->set_scope(instance_id_token_info->scope); |
| 1021 request_info = instance_id_token_request_info.Pass(); |
| 1022 } |
| 1023 |
| 1024 DCHECK(request_info.get()); |
| 1025 |
| 1026 request_info->set_chrome_version(chrome_build_info_.version); |
| 1027 request_info->set_android_id(device_checkin_info_.android_id); |
| 1028 request_info->set_security_token(device_checkin_info_.secret); |
| 1029 request_info->set_app_id(registration_info.app_id); |
| 1030 return request_info.Pass(); |
| 1031 } |
| 1032 |
906 void GCMClientImpl::SetRecording(bool recording) { | 1033 void GCMClientImpl::SetRecording(bool recording) { |
907 recorder_.SetRecording(recording); | 1034 recorder_.SetRecording(recording); |
908 } | 1035 } |
909 | 1036 |
910 void GCMClientImpl::ClearActivityLogs() { | 1037 void GCMClientImpl::ClearActivityLogs() { |
911 recorder_.Clear(); | 1038 recorder_.Clear(); |
912 } | 1039 } |
913 | 1040 |
914 GCMClient::GCMStatistics GCMClientImpl::GetStatistics() const { | 1041 GCMClient::GCMStatistics GCMClientImpl::GetStatistics() const { |
915 GCMClient::GCMStatistics stats; | 1042 GCMClient::GCMStatistics stats; |
916 stats.gcm_client_created = true; | 1043 stats.gcm_client_created = true; |
917 stats.is_recording = recorder_.is_recording(); | 1044 stats.is_recording = recorder_.is_recording(); |
918 stats.gcm_client_state = GetStateString(); | 1045 stats.gcm_client_state = GetStateString(); |
919 stats.connection_client_created = mcs_client_.get() != NULL; | 1046 stats.connection_client_created = mcs_client_.get() != NULL; |
920 if (connection_factory_.get()) | 1047 if (connection_factory_.get()) |
921 stats.connection_state = connection_factory_->GetConnectionStateString(); | 1048 stats.connection_state = connection_factory_->GetConnectionStateString(); |
922 if (mcs_client_.get()) { | 1049 if (mcs_client_.get()) { |
923 stats.send_queue_size = mcs_client_->GetSendQueueSize(); | 1050 stats.send_queue_size = mcs_client_->GetSendQueueSize(); |
924 stats.resend_queue_size = mcs_client_->GetResendQueueSize(); | 1051 stats.resend_queue_size = mcs_client_->GetResendQueueSize(); |
925 } | 1052 } |
926 if (device_checkin_info_.android_id > 0) | 1053 if (device_checkin_info_.android_id > 0) |
927 stats.android_id = device_checkin_info_.android_id; | 1054 stats.android_id = device_checkin_info_.android_id; |
928 recorder_.CollectActivities(&stats.recorded_activities); | 1055 recorder_.CollectActivities(&stats.recorded_activities); |
929 | 1056 |
930 for (RegistrationInfoMap::const_iterator it = registrations_.begin(); | 1057 for (RegistrationInfoMap::const_iterator it = registrations_.begin(); |
931 it != registrations_.end(); ++it) { | 1058 it != registrations_.end(); ++it) { |
932 stats.registered_app_ids.push_back(it->first); | 1059 stats.registered_app_ids.push_back(it->first->app_id); |
933 } | 1060 } |
934 return stats; | 1061 return stats; |
935 } | 1062 } |
936 | 1063 |
937 void GCMClientImpl::OnActivityRecorded() { | 1064 void GCMClientImpl::OnActivityRecorded() { |
938 delegate_->OnActivityRecorded(); | 1065 delegate_->OnActivityRecorded(); |
939 } | 1066 } |
940 | 1067 |
941 void GCMClientImpl::OnConnected(const GURL& current_server, | 1068 void GCMClientImpl::OnConnected(const GURL& current_server, |
942 const net::IPEndPoint& ip_endpoint) { | 1069 const net::IPEndPoint& ip_endpoint) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 DVLOG(1) << "Unknown message_type received. Message ignored. " | 1167 DVLOG(1) << "Unknown message_type received. Message ignored. " |
1041 << "App ID: " << data_message_stanza.category() << "."; | 1168 << "App ID: " << data_message_stanza.category() << "."; |
1042 break; | 1169 break; |
1043 } | 1170 } |
1044 } | 1171 } |
1045 | 1172 |
1046 void GCMClientImpl::HandleIncomingDataMessage( | 1173 void GCMClientImpl::HandleIncomingDataMessage( |
1047 const mcs_proto::DataMessageStanza& data_message_stanza, | 1174 const mcs_proto::DataMessageStanza& data_message_stanza, |
1048 MessageData& message_data) { | 1175 MessageData& message_data) { |
1049 std::string app_id = data_message_stanza.category(); | 1176 std::string app_id = data_message_stanza.category(); |
| 1177 std::string sender = data_message_stanza.from(); |
1050 | 1178 |
1051 // Drop the message when the app is not registered for the sender of the | 1179 // Drop the message when the app is not registered for the sender of the |
1052 // message. | 1180 // message. |
1053 RegistrationInfoMap::iterator iter = registrations_.find(app_id); | 1181 bool registered = false; |
1054 bool not_registered = | 1182 |
1055 iter == registrations_.end() || | 1183 // First, find among all GCM registrations. |
1056 std::find(iter->second->sender_ids.begin(), | 1184 scoped_ptr<GCMRegistrationInfo> gcm_registration(new GCMRegistrationInfo); |
1057 iter->second->sender_ids.end(), | 1185 gcm_registration->app_id = app_id; |
1058 data_message_stanza.from()) == iter->second->sender_ids.end(); | 1186 auto gcm_registration_iter = registrations_.find( |
1059 recorder_.RecordDataMessageReceived(app_id, data_message_stanza.from(), | 1187 make_linked_ptr<RegistrationInfo>(gcm_registration.release())); |
1060 data_message_stanza.ByteSize(), !not_registered, | 1188 if (gcm_registration_iter != registrations_.end()) { |
| 1189 GCMRegistrationInfo* cached_gcm_registration = |
| 1190 GCMRegistrationInfo::FromRegistrationInfo( |
| 1191 gcm_registration_iter->first.get()); |
| 1192 if (cached_gcm_registration && |
| 1193 std::find(cached_gcm_registration->sender_ids.begin(), |
| 1194 cached_gcm_registration->sender_ids.end(), |
| 1195 sender) != cached_gcm_registration->sender_ids.end()) { |
| 1196 registered = true; |
| 1197 } |
| 1198 } |
| 1199 |
| 1200 // Then, find among all InstanceID registrations. |
| 1201 if (!registered) { |
| 1202 scoped_ptr<InstanceIDTokenInfo> instance_id_token(new InstanceIDTokenInfo); |
| 1203 instance_id_token->app_id = app_id; |
| 1204 instance_id_token->authorized_entity = sender; |
| 1205 instance_id_token->scope = kGCMScope; |
| 1206 auto instance_id_token_iter = registrations_.find( |
| 1207 make_linked_ptr<RegistrationInfo>(instance_id_token.release())); |
| 1208 if (instance_id_token_iter != registrations_.end()) |
| 1209 registered = true; |
| 1210 } |
| 1211 |
| 1212 recorder_.RecordDataMessageReceived(app_id, sender, |
| 1213 data_message_stanza.ByteSize(), registered, |
1061 GCMStatsRecorder::DATA_MESSAGE); | 1214 GCMStatsRecorder::DATA_MESSAGE); |
1062 if (not_registered) { | 1215 if (!registered) |
1063 return; | 1216 return; |
1064 } | |
1065 | 1217 |
1066 IncomingMessage incoming_message; | 1218 IncomingMessage incoming_message; |
1067 incoming_message.sender_id = data_message_stanza.from(); | 1219 incoming_message.sender_id = data_message_stanza.from(); |
1068 if (data_message_stanza.has_token()) | 1220 if (data_message_stanza.has_token()) |
1069 incoming_message.collapse_key = data_message_stanza.token(); | 1221 incoming_message.collapse_key = data_message_stanza.token(); |
1070 incoming_message.data = message_data; | 1222 incoming_message.data = message_data; |
1071 delegate_->OnMessageReceived(app_id, incoming_message); | 1223 delegate_->OnMessageReceived(app_id, incoming_message); |
1072 } | 1224 } |
1073 | 1225 |
1074 void GCMClientImpl::HandleIncomingSendError( | 1226 void GCMClientImpl::HandleIncomingSendError( |
(...skipping 17 matching lines...) Expand all Loading... |
1092 delegate_->OnMessageSendError(data_message_stanza.category(), | 1244 delegate_->OnMessageSendError(data_message_stanza.category(), |
1093 send_error_details); | 1245 send_error_details); |
1094 } | 1246 } |
1095 | 1247 |
1096 bool GCMClientImpl::HasStandaloneRegisteredApp() const { | 1248 bool GCMClientImpl::HasStandaloneRegisteredApp() const { |
1097 if (registrations_.empty()) | 1249 if (registrations_.empty()) |
1098 return false; | 1250 return false; |
1099 // Note that account mapper is not counted as a standalone app since it is | 1251 // Note that account mapper is not counted as a standalone app since it is |
1100 // automatically started when other app uses GCM. | 1252 // automatically started when other app uses GCM. |
1101 return registrations_.size() > 1 || | 1253 return registrations_.size() > 1 || |
1102 !registrations_.count(kGCMAccountMapperAppId); | 1254 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId); |
1103 } | 1255 } |
1104 | 1256 |
1105 } // namespace gcm | 1257 } // namespace gcm |
OLD | NEW |