Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: components/gcm_driver/gcm_client_impl.cc

Issue 1137463003: Support getting and deleting token for Instance ID. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix trybots Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
12 #include "base/metrics/histogram_macros.h" 12 #include "base/metrics/histogram_macros.h"
13 #include "base/sequenced_task_runner.h" 13 #include "base/sequenced_task_runner.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
17 #include "base/time/default_clock.h" 17 #include "base/time/default_clock.h"
18 #include "base/timer/timer.h" 18 #include "base/timer/timer.h"
19 #include "components/gcm_driver/gcm_account_mapper.h" 19 #include "components/gcm_driver/gcm_account_mapper.h"
20 #include "components/gcm_driver/gcm_backoff_policy.h" 20 #include "components/gcm_driver/gcm_backoff_policy.h"
21 #include "google_apis/gcm/base/encryptor.h" 21 #include "google_apis/gcm/base/encryptor.h"
22 #include "google_apis/gcm/base/mcs_message.h" 22 #include "google_apis/gcm/base/mcs_message.h"
23 #include "google_apis/gcm/base/mcs_util.h" 23 #include "google_apis/gcm/base/mcs_util.h"
24 #include "google_apis/gcm/engine/checkin_request.h" 24 #include "google_apis/gcm/engine/checkin_request.h"
25 #include "google_apis/gcm/engine/connection_factory_impl.h" 25 #include "google_apis/gcm/engine/connection_factory_impl.h"
26 #include "google_apis/gcm/engine/gcm_registration_request.h"
26 #include "google_apis/gcm/engine/gcm_store_impl.h" 27 #include "google_apis/gcm/engine/gcm_store_impl.h"
28 #include "google_apis/gcm/engine/gcm_unregistration_request.h"
29 #include "google_apis/gcm/engine/instance_id_delete_token_request.h"
30 #include "google_apis/gcm/engine/instance_id_get_token_request.h"
27 #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" 31 #include "google_apis/gcm/monitoring/gcm_stats_recorder.h"
28 #include "google_apis/gcm/protocol/checkin.pb.h" 32 #include "google_apis/gcm/protocol/checkin.pb.h"
29 #include "google_apis/gcm/protocol/mcs.pb.h" 33 #include "google_apis/gcm/protocol/mcs.pb.h"
30 #include "net/http/http_network_session.h" 34 #include "net/http/http_network_session.h"
31 #include "net/http/http_transaction_factory.h" 35 #include "net/http/http_transaction_factory.h"
32 #include "net/url_request/url_request_context.h" 36 #include "net/url_request/url_request_context.h"
33 #include "url/gurl.h" 37 #include "url/gurl.h"
34 38
35 namespace gcm { 39 namespace gcm {
36 40
(...skipping 23 matching lines...) Expand all
60 64
61 enum ResetStoreError { 65 enum ResetStoreError {
62 DESTROYING_STORE_FAILED, 66 DESTROYING_STORE_FAILED,
63 INFINITE_STORE_RESET, 67 INFINITE_STORE_RESET,
64 // NOTE: always keep this entry at the end. Add new value only immediately 68 // 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 69 // above this line. Make sure to update the corresponding histogram enum
66 // accordingly. 70 // accordingly.
67 RESET_STORE_ERROR_COUNT 71 RESET_STORE_ERROR_COUNT
68 }; 72 };
69 73
74 const char kGCMScope[] = "GCM";
70 const int kMaxRegistrationRetries = 5; 75 const int kMaxRegistrationRetries = 5;
71 const char kMessageTypeDataMessage[] = "gcm"; 76 const char kMessageTypeDataMessage[] = "gcm";
72 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; 77 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages";
73 const char kMessageTypeKey[] = "message_type"; 78 const char kMessageTypeKey[] = "message_type";
74 const char kMessageTypeSendErrorKey[] = "send_error"; 79 const char kMessageTypeSendErrorKey[] = "send_error";
75 const char kSendErrorMessageIdKey[] = "google.message_id"; 80 const char kSendErrorMessageIdKey[] = "google.message_id";
76 const char kSendMessageFromValue[] = "gcm@chrome.com"; 81 const char kSendMessageFromValue[] = "gcm@chrome.com";
77 const int64 kDefaultUserSerialNumber = 0LL; 82 const int64 kDefaultUserSerialNumber = 0LL;
78 83
79 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { 84 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 MessageType DecodeMessageType(const std::string& value) { 167 MessageType DecodeMessageType(const std::string& value) {
163 if (kMessageTypeDeletedMessagesKey == value) 168 if (kMessageTypeDeletedMessagesKey == value)
164 return DELETED_MESSAGES; 169 return DELETED_MESSAGES;
165 if (kMessageTypeSendErrorKey == value) 170 if (kMessageTypeSendErrorKey == value)
166 return SEND_ERROR; 171 return SEND_ERROR;
167 if (kMessageTypeDataMessage == value) 172 if (kMessageTypeDataMessage == value)
168 return DATA_MESSAGE; 173 return DATA_MESSAGE;
169 return UNKNOWN; 174 return UNKNOWN;
170 } 175 }
171 176
177 int ConstructGCMVersion(const std::string& chrome_version) {
178 // Major Chrome version is passed as GCM version.
179 size_t pos = chrome_version.find('.');
180 if (pos == std::string::npos) {
181 NOTREACHED();
182 return 0;
183 }
184
185 int gcm_version = 0;
186 base::StringToInt(
187 base::StringPiece(chrome_version.c_str(), pos), &gcm_version);
188 return gcm_version;
189 }
190
191 std::string SerializeInstanceIDData(const std::string& instance_id,
192 const std::string& extra_data) {
193 DCHECK(!instance_id.empty() && !extra_data.empty());
194 DCHECK(instance_id.find(',') == std::string::npos);
195 return instance_id + "," + extra_data;
196 }
197
198 bool DeserializeInstanceIDData(const std::string& serialized_data,
199 std::string* instance_id,
200 std::string* extra_data) {
201 DCHECK(instance_id && extra_data);
202 std::size_t pos = serialized_data.find(',');
203 if (pos == std::string::npos)
204 return false;
205 *instance_id = serialized_data.substr(0, pos);
206 *extra_data = serialized_data.substr(pos + 1);
207 return !instance_id->empty() && !extra_data->empty();
208 }
209
172 void RecordOutgoingMessageToUMA( 210 void RecordOutgoingMessageToUMA(
173 const gcm::GCMClient::OutgoingMessage& message) { 211 const gcm::GCMClient::OutgoingMessage& message) {
174 OutgoingMessageTTLCategory ttl_category; 212 OutgoingMessageTTLCategory ttl_category;
175 if (message.time_to_live == 0) 213 if (message.time_to_live == 0)
176 ttl_category = TTL_ZERO; 214 ttl_category = TTL_ZERO;
177 else if (message.time_to_live <= 60 ) 215 else if (message.time_to_live <= 60 )
178 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE; 216 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE;
179 else if (message.time_to_live <= 60 * 60) 217 else if (message.time_to_live <= 60 * 60)
180 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR; 218 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR;
181 else if (message.time_to_live <= 24 * 60 * 60) 219 else if (message.time_to_live <= 24 * 60 * 60)
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 366
329 void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { 367 void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) {
330 DCHECK_EQ(LOADING, state_); 368 DCHECK_EQ(LOADING, state_);
331 369
332 if (!result->success) { 370 if (!result->success) {
333 ResetStore(); 371 ResetStore();
334 return; 372 return;
335 } 373 }
336 gcm_store_reset_ = false; 374 gcm_store_reset_ = false;
337 375
338 registrations_ = result->registrations;
339 device_checkin_info_.android_id = result->device_android_id; 376 device_checkin_info_.android_id = result->device_android_id;
340 device_checkin_info_.secret = result->device_security_token; 377 device_checkin_info_.secret = result->device_security_token;
341 device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts; 378 device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts;
342 // A case where there were previously no accounts reported with checkin is 379 // 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 380 // 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 381 // scheduling a periodic checkin for devices with no signed in users
345 // immediately after restart, while keeping |accounts_set == false| delays the 382 // immediately after restart, while keeping |accounts_set == false| delays the
346 // checkin until the list of accounts is set explicitly. 383 // checkin until the list of accounts is set explicitly.
347 if (result->last_checkin_accounts.size() == 0) 384 if (result->last_checkin_accounts.size() == 0)
348 device_checkin_info_.accounts_set = true; 385 device_checkin_info_.accounts_set = true;
349 last_checkin_time_ = result->last_checkin_time; 386 last_checkin_time_ = result->last_checkin_time;
350 gservices_settings_.UpdateFromLoadResult(*result); 387 gservices_settings_.UpdateFromLoadResult(*result);
351 instance_id_data_ = result->instance_id_data; 388
389 for (auto iter = result->registrations.begin();
390 iter != result->registrations.end();
391 ++iter) {
392 std::string registration_id;
393 scoped_ptr<RegistrationInfo> registration =
394 RegistrationInfo::BuildFromString(
395 iter->first, iter->second, &registration_id);
396 // TODO(jianli): Add UMA to track the error case.
397 if (registration.get())
398 registrations_[make_linked_ptr(registration.release())] = registration_id;
399 }
400
401 for (auto iter = result->instance_id_data.begin();
402 iter != result->instance_id_data.end();
403 ++iter) {
404 std::string instance_id;
405 std::string extra_data;
406 if (DeserializeInstanceIDData(iter->second, &instance_id, &extra_data))
407 instance_id_data_[iter->first] = std::make_pair(instance_id, extra_data);
408 }
409
352 load_result_ = result.Pass(); 410 load_result_ = result.Pass();
353 state_ = LOADED; 411 state_ = LOADED;
354 412
355 // Don't initiate the GCM connection when GCM is in delayed start mode and 413 // Don't initiate the GCM connection when GCM is in delayed start mode and
356 // not any standalone app has registered GCM yet. 414 // not any standalone app has registered GCM yet.
357 if (start_mode_ == DELAYED_START && !HasStandaloneRegisteredApp()) 415 if (start_mode_ == DELAYED_START && !HasStandaloneRegisteredApp())
358 return; 416 return;
359 417
360 StartGCM(); 418 StartGCM();
361 } 419 }
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, 583 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback,
526 weak_ptr_factory_.GetWeakPtr())); 584 weak_ptr_factory_.GetWeakPtr()));
527 } 585 }
528 586
529 void GCMClientImpl::UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) { 587 void GCMClientImpl::UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) {
530 DCHECK(mcs_client_); 588 DCHECK(mcs_client_);
531 mcs_client_->UpdateHeartbeatTimer(timer.Pass()); 589 mcs_client_->UpdateHeartbeatTimer(timer.Pass());
532 } 590 }
533 591
534 void GCMClientImpl::AddInstanceIDData(const std::string& app_id, 592 void GCMClientImpl::AddInstanceIDData(const std::string& app_id,
535 const std::string& instance_id_data) { 593 const std::string& instance_id,
536 instance_id_data_[app_id] = instance_id_data; 594 const std::string& extra_data) {
595 instance_id_data_[app_id] = std::make_pair(instance_id, extra_data);
537 gcm_store_->AddInstanceIDData( 596 gcm_store_->AddInstanceIDData(
538 app_id, 597 app_id,
539 instance_id_data, 598 SerializeInstanceIDData(instance_id, extra_data),
540 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, 599 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback,
541 weak_ptr_factory_.GetWeakPtr())); 600 weak_ptr_factory_.GetWeakPtr()));
542 } 601 }
543 602
544 void GCMClientImpl::RemoveInstanceIDData(const std::string& app_id) { 603 void GCMClientImpl::RemoveInstanceIDData(const std::string& app_id) {
545 instance_id_data_.erase(app_id); 604 instance_id_data_.erase(app_id);
546 gcm_store_->RemoveInstanceIDData( 605 gcm_store_->RemoveInstanceIDData(
547 app_id, 606 app_id,
548 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, 607 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback,
549 weak_ptr_factory_.GetWeakPtr())); 608 weak_ptr_factory_.GetWeakPtr()));
550 } 609 }
551 610
552 std::string GCMClientImpl::GetInstanceIDData(const std::string& app_id) { 611 void GCMClientImpl::GetInstanceIDData(const std::string& app_id,
612 std::string* instance_id,
613 std::string* extra_data) {
614 DCHECK(instance_id && extra_data);
615
553 auto iter = instance_id_data_.find(app_id); 616 auto iter = instance_id_data_.find(app_id);
554 if (iter == instance_id_data_.end()) 617 if (iter == instance_id_data_.end())
555 return std::string(); 618 return;
556 return iter->second; 619 *instance_id = iter->second.first;
620 *extra_data = iter->second.second;
557 } 621 }
558 622
559 void GCMClientImpl::AddHeartbeatInterval(const std::string& scope, 623 void GCMClientImpl::AddHeartbeatInterval(const std::string& scope,
560 int interval_ms) { 624 int interval_ms) {
561 DCHECK(mcs_client_); 625 DCHECK(mcs_client_);
562 mcs_client_->AddHeartbeatInterval(scope, interval_ms); 626 mcs_client_->AddHeartbeatInterval(scope, interval_ms);
563 } 627 }
564 628
565 void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) { 629 void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) {
566 DCHECK(mcs_client_); 630 DCHECK(mcs_client_);
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 delegate_->OnDisconnected(); 778 delegate_->OnDisconnected();
715 mcs_client_.reset(); 779 mcs_client_.reset();
716 checkin_request_.reset(); 780 checkin_request_.reset();
717 // Delete all of the pending registration and unregistration requests. 781 // Delete all of the pending registration and unregistration requests.
718 STLDeleteValues(&pending_registration_requests_); 782 STLDeleteValues(&pending_registration_requests_);
719 STLDeleteValues(&pending_unregistration_requests_); 783 STLDeleteValues(&pending_unregistration_requests_);
720 state_ = INITIALIZED; 784 state_ = INITIALIZED;
721 gcm_store_->Close(); 785 gcm_store_->Close();
722 } 786 }
723 787
724 void GCMClientImpl::Register(const std::string& app_id, 788 void GCMClientImpl::Register(
725 const std::vector<std::string>& sender_ids) { 789 const linked_ptr<RegistrationInfo>& registration_info) {
726 DCHECK_EQ(state_, READY); 790 DCHECK_EQ(state_, READY);
727 791
728 // If the same sender ids is provided, return the cached registration ID 792 // Find and use the cached registration ID.
729 // directly.
730 RegistrationInfoMap::const_iterator registrations_iter = 793 RegistrationInfoMap::const_iterator registrations_iter =
731 registrations_.find(app_id); 794 registrations_.find(registration_info);
732 if (registrations_iter != registrations_.end() && 795 if (registrations_iter != registrations_.end()) {
733 registrations_iter->second->sender_ids == sender_ids) { 796 bool matched = true;
734 delegate_->OnRegisterFinished( 797
735 app_id, registrations_iter->second->registration_id, SUCCESS); 798 // For GCM registration, we also match the sender IDs since multiple
736 return; 799 // registrations are not supported.
800 const GCMRegistrationInfo* gcm_registration_info =
801 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
802 if (gcm_registration_info) {
803 const GCMRegistrationInfo* cached_gcm_registration_info =
804 GCMRegistrationInfo::FromRegistrationInfo(
805 registrations_iter->first.get());
806 DCHECK(cached_gcm_registration_info);
807 if (cached_gcm_registration_info &&
808 gcm_registration_info->sender_ids !=
809 cached_gcm_registration_info->sender_ids) {
810 matched = false;
811 }
812 }
813
814 if (matched) {
815 delegate_->OnRegisterFinished(
816 registration_info, registrations_iter->second, SUCCESS);
817 return;
818 }
737 } 819 }
738 820
739 RegistrationRequest::RequestInfo request_info( 821 RegistrationRequest::RequestInfo request_info(
740 device_checkin_info_.android_id, 822 device_checkin_info_.android_id,
741 device_checkin_info_.secret, 823 device_checkin_info_.secret,
742 app_id, 824 registration_info->app_id);
743 sender_ids);
744 DCHECK_EQ(0u, pending_registration_requests_.count(app_id));
745 825
746 RegistrationRequest* registration_request = 826 RegistrationRequest* registration_request = NULL;
747 new RegistrationRequest(gservices_settings_.GetRegistrationURL(), 827
748 request_info, 828 const GCMRegistrationInfo* gcm_registration_info =
749 GetGCMBackoffPolicy(), 829 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
750 base::Bind(&GCMClientImpl::OnRegisterCompleted, 830 if (gcm_registration_info) {
751 weak_ptr_factory_.GetWeakPtr(), 831 GCMRegistrationRequest::ExtraRequestInfo extra_request_info(
752 app_id, 832 gcm_registration_info->sender_ids);
753 sender_ids), 833
754 kMaxRegistrationRetries, 834 registration_request = new GCMRegistrationRequest(
755 url_request_context_getter_, 835 gservices_settings_.GetRegistrationURL(),
756 &recorder_); 836 request_info,
757 pending_registration_requests_[app_id] = registration_request; 837 extra_request_info,
838 GetGCMBackoffPolicy(),
839 base::Bind(&GCMClientImpl::OnRegisterCompleted,
840 weak_ptr_factory_.GetWeakPtr(),
841 registration_info),
842 kMaxRegistrationRetries,
843 url_request_context_getter_,
844 &recorder_);
845 }
846
847 const InstanceIDTokenInfo* instance_id_token_info =
848 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get());
849 if (instance_id_token_info) {
850 auto instance_id_iter = instance_id_data_.find(registration_info->app_id);
851 DCHECK(instance_id_iter != instance_id_data_.end());
852
853 InstanceIDGetTokenRequest::ExtraRequestInfo extra_request_info(
854 instance_id_iter->second.first,
855 instance_id_token_info->authorized_entity,
856 instance_id_token_info->scope,
857 ConstructGCMVersion(chrome_build_info_.version),
858 instance_id_token_info->options);
859 registration_request = new InstanceIDGetTokenRequest(
860 gservices_settings_.GetRegistrationURL(),
861 request_info,
862 extra_request_info,
863 GetGCMBackoffPolicy(),
864 base::Bind(&GCMClientImpl::OnRegisterCompleted,
865 weak_ptr_factory_.GetWeakPtr(),
866 registration_info),
867 kMaxRegistrationRetries,
868 url_request_context_getter_,
869 &recorder_);
870 }
871
872 DCHECK(registration_request);
873 pending_registration_requests_[registration_info] = registration_request;
758 registration_request->Start(); 874 registration_request->Start();
759 } 875 }
760 876
761 void GCMClientImpl::OnRegisterCompleted( 877 void GCMClientImpl::OnRegisterCompleted(
762 const std::string& app_id, 878 const linked_ptr<RegistrationInfo>& registration_info,
763 const std::vector<std::string>& sender_ids,
764 RegistrationRequest::Status status, 879 RegistrationRequest::Status status,
765 const std::string& registration_id) { 880 const std::string& registration_id) {
766 DCHECK(delegate_); 881 DCHECK(delegate_);
767 882
768 Result result; 883 Result result;
769 PendingRegistrationRequests::iterator iter = 884 PendingRegistrationRequests::iterator iter =
770 pending_registration_requests_.find(app_id); 885 pending_registration_requests_.find(registration_info);
771 if (iter == pending_registration_requests_.end()) 886 if (iter == pending_registration_requests_.end())
772 result = UNKNOWN_ERROR; 887 result = UNKNOWN_ERROR;
773 else if (status == RegistrationRequest::INVALID_SENDER) 888 else if (status == RegistrationRequest::INVALID_SENDER)
774 result = INVALID_PARAMETER; 889 result = INVALID_PARAMETER;
775 else if (registration_id.empty()) 890 else if (registration_id.empty())
776 result = SERVER_ERROR; 891 result = SERVER_ERROR;
777 else 892 else
778 result = SUCCESS; 893 result = SUCCESS;
779 894
780 if (result == SUCCESS) { 895 if (result == SUCCESS) {
781 // Cache it. 896 // Cache it.
782 linked_ptr<RegistrationInfo> registration(new RegistrationInfo); 897 registrations_[registration_info] = registration_id;
783 registration->sender_ids = sender_ids;
784 registration->registration_id = registration_id;
785 registrations_[app_id] = registration;
786 898
787 // Save it in the persistent store. 899 // Save it in the persistent store.
788 gcm_store_->AddRegistration( 900 gcm_store_->AddRegistration(
789 app_id, 901 registration_info->GetSerializedKey(),
790 registration, 902 registration_info->GetSerializedValue(registration_id),
791 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, 903 base::Bind(&GCMClientImpl::UpdateRegistrationCallback,
792 weak_ptr_factory_.GetWeakPtr())); 904 weak_ptr_factory_.GetWeakPtr()));
793 } 905 }
794 906
795 delegate_->OnRegisterFinished( 907 delegate_->OnRegisterFinished(
796 app_id, result == SUCCESS ? registration_id : std::string(), result); 908 registration_info,
909 result == SUCCESS ? registration_id : std::string(),
910 result);
797 911
798 if (iter != pending_registration_requests_.end()) { 912 if (iter != pending_registration_requests_.end()) {
799 delete iter->second; 913 delete iter->second;
800 pending_registration_requests_.erase(iter); 914 pending_registration_requests_.erase(iter);
801 } 915 }
802 } 916 }
803 917
804 void GCMClientImpl::Unregister(const std::string& app_id) { 918 void GCMClientImpl::Unregister(
919 const linked_ptr<RegistrationInfo>& registration_info) {
805 DCHECK_EQ(state_, READY); 920 DCHECK_EQ(state_, READY);
806 if (pending_unregistration_requests_.count(app_id) == 1) 921 if (pending_unregistration_requests_.count(registration_info) == 1)
807 return; 922 return;
808 923
809 // Remove from the cache and persistent store. 924 // Remove from the cache and persistent store.
810 registrations_.erase(app_id); 925 registrations_.erase(registration_info);
811 gcm_store_->RemoveRegistration( 926 gcm_store_->RemoveRegistration(
812 app_id, 927 registration_info->GetSerializedKey(),
813 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, 928 base::Bind(&GCMClientImpl::UpdateRegistrationCallback,
814 weak_ptr_factory_.GetWeakPtr())); 929 weak_ptr_factory_.GetWeakPtr()));
815 930
816 UnregistrationRequest::RequestInfo request_info( 931 UnregistrationRequest::RequestInfo request_info(
817 device_checkin_info_.android_id, 932 device_checkin_info_.android_id,
818 device_checkin_info_.secret, 933 device_checkin_info_.secret,
819 app_id); 934 registration_info->app_id);
820 935
821 UnregistrationRequest* unregistration_request = new UnregistrationRequest( 936 UnregistrationRequest* unregistration_request = NULL;
822 gservices_settings_.GetRegistrationURL(), 937
823 request_info, 938 const GCMRegistrationInfo* gcm_registration_info =
824 GetGCMBackoffPolicy(), 939 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
825 base::Bind(&GCMClientImpl::OnUnregisterCompleted, 940 if (gcm_registration_info) {
826 weak_ptr_factory_.GetWeakPtr(), 941 unregistration_request = new GCMUnregistrationRequest(
827 app_id), 942 gservices_settings_.GetRegistrationURL(),
828 url_request_context_getter_, 943 request_info,
829 &recorder_); 944 GetGCMBackoffPolicy(),
830 pending_unregistration_requests_[app_id] = unregistration_request; 945 base::Bind(&GCMClientImpl::OnUnregisterCompleted,
946 weak_ptr_factory_.GetWeakPtr(),
947 registration_info),
948 url_request_context_getter_,
949 &recorder_);
950 }
951
952 const InstanceIDTokenInfo* instance_id_token_info =
953 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get());
954 if (instance_id_token_info) {
955 auto instance_id_iter = instance_id_data_.find(registration_info->app_id);
956 DCHECK(instance_id_iter != instance_id_data_.end());
957
958 InstanceIDDeleteTokenRequest::ExtraRequestInfo extra_request_info(
959 instance_id_iter->second.first,
960 instance_id_token_info->authorized_entity,
961 instance_id_token_info->scope,
962 ConstructGCMVersion(chrome_build_info_.version));
963 unregistration_request = new InstanceIDDeleteTokenRequest(
964 gservices_settings_.GetRegistrationURL(),
965 request_info,
966 extra_request_info,
967 GetGCMBackoffPolicy(),
968 base::Bind(&GCMClientImpl::OnUnregisterCompleted,
969 weak_ptr_factory_.GetWeakPtr(),
970 registration_info),
971 url_request_context_getter_,
972 &recorder_);
973 }
974
975 DCHECK(unregistration_request);
976 pending_unregistration_requests_[registration_info] = unregistration_request;
831 unregistration_request->Start(); 977 unregistration_request->Start();
832 } 978 }
833 979
834 void GCMClientImpl::OnUnregisterCompleted( 980 void GCMClientImpl::OnUnregisterCompleted(
835 const std::string& app_id, 981 const linked_ptr<RegistrationInfo>& registration_info,
836 UnregistrationRequest::Status status) { 982 UnregistrationRequest::Status status) {
837 DVLOG(1) << "Unregister completed for app: " << app_id 983 DVLOG(1) << "Unregister completed for app: " << registration_info->app_id
838 << " with " << (status ? "success." : "failure."); 984 << " with " << (status ? "success." : "failure.");
839 delegate_->OnUnregisterFinished( 985 delegate_->OnUnregisterFinished(
840 app_id, 986 registration_info,
841 status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR); 987 status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR);
842 988
843 PendingUnregistrationRequests::iterator iter = 989 PendingUnregistrationRequests::iterator iter =
844 pending_unregistration_requests_.find(app_id); 990 pending_unregistration_requests_.find(registration_info);
845 if (iter == pending_unregistration_requests_.end()) 991 if (iter == pending_unregistration_requests_.end())
846 return; 992 return;
847 993
848 delete iter->second; 994 delete iter->second;
849 pending_unregistration_requests_.erase(iter); 995 pending_unregistration_requests_.erase(iter);
850 } 996 }
851 997
852 void GCMClientImpl::OnGCMStoreDestroyed(bool success) { 998 void GCMClientImpl::OnGCMStoreDestroyed(bool success) {
853 DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!"; 999 DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!";
854 UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success); 1000 UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 if (mcs_client_.get()) { 1068 if (mcs_client_.get()) {
923 stats.send_queue_size = mcs_client_->GetSendQueueSize(); 1069 stats.send_queue_size = mcs_client_->GetSendQueueSize();
924 stats.resend_queue_size = mcs_client_->GetResendQueueSize(); 1070 stats.resend_queue_size = mcs_client_->GetResendQueueSize();
925 } 1071 }
926 if (device_checkin_info_.android_id > 0) 1072 if (device_checkin_info_.android_id > 0)
927 stats.android_id = device_checkin_info_.android_id; 1073 stats.android_id = device_checkin_info_.android_id;
928 recorder_.CollectActivities(&stats.recorded_activities); 1074 recorder_.CollectActivities(&stats.recorded_activities);
929 1075
930 for (RegistrationInfoMap::const_iterator it = registrations_.begin(); 1076 for (RegistrationInfoMap::const_iterator it = registrations_.begin();
931 it != registrations_.end(); ++it) { 1077 it != registrations_.end(); ++it) {
932 stats.registered_app_ids.push_back(it->first); 1078 stats.registered_app_ids.push_back(it->first->app_id);
933 } 1079 }
934 return stats; 1080 return stats;
935 } 1081 }
936 1082
937 void GCMClientImpl::OnActivityRecorded() { 1083 void GCMClientImpl::OnActivityRecorded() {
938 delegate_->OnActivityRecorded(); 1084 delegate_->OnActivityRecorded();
939 } 1085 }
940 1086
941 void GCMClientImpl::OnConnected(const GURL& current_server, 1087 void GCMClientImpl::OnConnected(const GURL& current_server,
942 const net::IPEndPoint& ip_endpoint) { 1088 const net::IPEndPoint& ip_endpoint) {
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1040 DVLOG(1) << "Unknown message_type received. Message ignored. " 1186 DVLOG(1) << "Unknown message_type received. Message ignored. "
1041 << "App ID: " << data_message_stanza.category() << "."; 1187 << "App ID: " << data_message_stanza.category() << ".";
1042 break; 1188 break;
1043 } 1189 }
1044 } 1190 }
1045 1191
1046 void GCMClientImpl::HandleIncomingDataMessage( 1192 void GCMClientImpl::HandleIncomingDataMessage(
1047 const mcs_proto::DataMessageStanza& data_message_stanza, 1193 const mcs_proto::DataMessageStanza& data_message_stanza,
1048 MessageData& message_data) { 1194 MessageData& message_data) {
1049 std::string app_id = data_message_stanza.category(); 1195 std::string app_id = data_message_stanza.category();
1196 std::string sender = data_message_stanza.from();
1050 1197
1051 // Drop the message when the app is not registered for the sender of the 1198 // Drop the message when the app is not registered for the sender of the
1052 // message. 1199 // message.
1053 RegistrationInfoMap::iterator iter = registrations_.find(app_id); 1200 bool registered = false;
1054 bool not_registered = 1201
1055 iter == registrations_.end() || 1202 // First, find among all GCM registrations.
1056 std::find(iter->second->sender_ids.begin(), 1203 scoped_ptr<GCMRegistrationInfo> gcm_registration(new GCMRegistrationInfo);
1057 iter->second->sender_ids.end(), 1204 gcm_registration->app_id = app_id;
1058 data_message_stanza.from()) == iter->second->sender_ids.end(); 1205 auto gcm_registration_iter = registrations_.find(
1059 recorder_.RecordDataMessageReceived(app_id, data_message_stanza.from(), 1206 make_linked_ptr<RegistrationInfo>(gcm_registration.release()));
1060 data_message_stanza.ByteSize(), !not_registered, 1207 if (gcm_registration_iter != registrations_.end()) {
1208 GCMRegistrationInfo* cached_gcm_registration =
1209 GCMRegistrationInfo::FromRegistrationInfo(
1210 gcm_registration_iter->first.get());
1211 if (cached_gcm_registration &&
1212 std::find(cached_gcm_registration->sender_ids.begin(),
1213 cached_gcm_registration->sender_ids.end(),
1214 sender) != cached_gcm_registration->sender_ids.end()) {
1215 registered = true;
1216 }
1217 }
1218
1219 // Then, find among all InstanceID registrations.
1220 if (!registered) {
1221 scoped_ptr<InstanceIDTokenInfo> instance_id_token(new InstanceIDTokenInfo);
1222 instance_id_token->app_id = app_id;
1223 instance_id_token->authorized_entity = sender;
1224 instance_id_token->scope = kGCMScope;
1225 auto instance_id_token_iter = registrations_.find(
1226 make_linked_ptr<RegistrationInfo>(instance_id_token.release()));
1227 if (instance_id_token_iter != registrations_.end())
1228 registered = true;
1229 }
1230
1231 recorder_.RecordDataMessageReceived(app_id, sender,
1232 data_message_stanza.ByteSize(), registered,
1061 GCMStatsRecorder::DATA_MESSAGE); 1233 GCMStatsRecorder::DATA_MESSAGE);
1062 if (not_registered) { 1234 if (!registered)
1063 return; 1235 return;
1064 }
1065 1236
1066 IncomingMessage incoming_message; 1237 IncomingMessage incoming_message;
1067 incoming_message.sender_id = data_message_stanza.from(); 1238 incoming_message.sender_id = data_message_stanza.from();
1068 if (data_message_stanza.has_token()) 1239 if (data_message_stanza.has_token())
1069 incoming_message.collapse_key = data_message_stanza.token(); 1240 incoming_message.collapse_key = data_message_stanza.token();
1070 incoming_message.data = message_data; 1241 incoming_message.data = message_data;
1071 delegate_->OnMessageReceived(app_id, incoming_message); 1242 delegate_->OnMessageReceived(app_id, incoming_message);
1072 } 1243 }
1073 1244
1074 void GCMClientImpl::HandleIncomingSendError( 1245 void GCMClientImpl::HandleIncomingSendError(
(...skipping 17 matching lines...) Expand all
1092 delegate_->OnMessageSendError(data_message_stanza.category(), 1263 delegate_->OnMessageSendError(data_message_stanza.category(),
1093 send_error_details); 1264 send_error_details);
1094 } 1265 }
1095 1266
1096 bool GCMClientImpl::HasStandaloneRegisteredApp() const { 1267 bool GCMClientImpl::HasStandaloneRegisteredApp() const {
1097 if (registrations_.empty()) 1268 if (registrations_.empty())
1098 return false; 1269 return false;
1099 // Note that account mapper is not counted as a standalone app since it is 1270 // Note that account mapper is not counted as a standalone app since it is
1100 // automatically started when other app uses GCM. 1271 // automatically started when other app uses GCM.
1101 return registrations_.size() > 1 || 1272 return registrations_.size() > 1 ||
1102 !registrations_.count(kGCMAccountMapperAppId); 1273 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId);
1103 } 1274 }
1104 1275
1105 } // namespace gcm 1276 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698