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

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

Issue 2111973002: Add support for GCM subtypes to desktop Instance ID implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@iid9push
Patch Set: address most of peter's concerns Created 4 years, 5 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 <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <utility> 10 #include <utility>
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 }; 79 };
80 80
81 const char kGCMScope[] = "GCM"; 81 const char kGCMScope[] = "GCM";
82 const int kMaxRegistrationRetries = 5; 82 const int kMaxRegistrationRetries = 5;
83 const int kMaxUnregistrationRetries = 5; 83 const int kMaxUnregistrationRetries = 5;
84 const char kMessageTypeDataMessage[] = "gcm"; 84 const char kMessageTypeDataMessage[] = "gcm";
85 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; 85 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages";
86 const char kMessageTypeKey[] = "message_type"; 86 const char kMessageTypeKey[] = "message_type";
87 const char kMessageTypeSendErrorKey[] = "send_error"; 87 const char kMessageTypeSendErrorKey[] = "send_error";
88 const char kSendErrorMessageIdKey[] = "google.message_id"; 88 const char kSendErrorMessageIdKey[] = "google.message_id";
89 const char kSubtypeKey[] = "subtype";
89 const char kSendMessageFromValue[] = "gcm@chrome.com"; 90 const char kSendMessageFromValue[] = "gcm@chrome.com";
90 const int64_t kDefaultUserSerialNumber = 0LL; 91 const int64_t kDefaultUserSerialNumber = 0LL;
91 const int kDestroyGCMStoreDelayMS = 5 * 60 * 1000; // 5 minutes. 92 const int kDestroyGCMStoreDelayMS = 5 * 60 * 1000; // 5 minutes.
92 93
93 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { 94 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) {
94 switch (status) { 95 switch (status) {
95 case MCSClient::QUEUED: 96 case MCSClient::QUEUED:
96 return GCMClient::SUCCESS; 97 return GCMClient::SUCCESS;
97 case MCSClient::QUEUE_SIZE_LIMIT_REACHED: 98 case MCSClient::QUEUE_SIZE_LIMIT_REACHED:
98 return GCMClient::NETWORK_ERROR; 99 return GCMClient::NETWORK_ERROR;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 232
232 UMA_HISTOGRAM_ENUMERATION("GCM.OutgoingMessageTTL", 233 UMA_HISTOGRAM_ENUMERATION("GCM.OutgoingMessageTTL",
233 ttl_category, 234 ttl_category,
234 TTL_CATEGORY_COUNT); 235 TTL_CATEGORY_COUNT);
235 } 236 }
236 237
237 void RecordResetStoreErrorToUMA(ResetStoreError error) { 238 void RecordResetStoreErrorToUMA(ResetStoreError error) {
238 UMA_HISTOGRAM_ENUMERATION("GCM.ResetStore", error, RESET_STORE_ERROR_COUNT); 239 UMA_HISTOGRAM_ENUMERATION("GCM.ResetStore", error, RESET_STORE_ERROR_COUNT);
239 } 240 }
240 241
242 // Helper method for DCHECKs that prevent requesting the same token both with
243 // and without subtypes.
244 bool InstanceIDsDifferOnlyInUseSubtype(
245 const RegistrationInfo* registration_info_a,
246 const RegistrationInfo* registration_info_b) {
247 const InstanceIDTokenInfo* token_a =
248 InstanceIDTokenInfo::FromRegistrationInfo(registration_info_a);
249 const InstanceIDTokenInfo* token_b =
250 InstanceIDTokenInfo::FromRegistrationInfo(registration_info_b);
251 return token_a && token_b && token_a->use_subtype != token_b->use_subtype &&
252 token_a->app_id == token_b->app_id &&
253 token_a->authorized_entity == token_b->authorized_entity &&
254 token_a->scope == token_b->scope;
255 }
256
241 } // namespace 257 } // namespace
242 258
243 GCMInternalsBuilder::GCMInternalsBuilder() {} 259 GCMInternalsBuilder::GCMInternalsBuilder() {}
244 GCMInternalsBuilder::~GCMInternalsBuilder() {} 260 GCMInternalsBuilder::~GCMInternalsBuilder() {}
245 261
246 std::unique_ptr<base::Clock> GCMInternalsBuilder::BuildClock() { 262 std::unique_ptr<base::Clock> GCMInternalsBuilder::BuildClock() {
247 return base::WrapUnique<base::Clock>(new base::DefaultClock()); 263 return base::WrapUnique<base::Clock>(new base::DefaultClock());
248 } 264 }
249 265
250 std::unique_ptr<MCSClient> GCMInternalsBuilder::BuildMCSClient( 266 std::unique_ptr<MCSClient> GCMInternalsBuilder::BuildMCSClient(
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 std::string* extra_data) { 674 std::string* extra_data) {
659 DCHECK(instance_id && extra_data); 675 DCHECK(instance_id && extra_data);
660 676
661 auto iter = instance_id_data_.find(app_id); 677 auto iter = instance_id_data_.find(app_id);
662 if (iter == instance_id_data_.end()) 678 if (iter == instance_id_data_.end())
663 return; 679 return;
664 *instance_id = iter->second.first; 680 *instance_id = iter->second.first;
665 *extra_data = iter->second.second; 681 *extra_data = iter->second.second;
666 } 682 }
667 683
684 bool GCMClientImpl::CategoryHasSubtype(const std::string& category) {
685 // SECURITY NOTE: Subtypes that we receive from GCM *cannot* be trusted for
686 // registrations without a subtype (as the sender can pass any subtype they
687 // want). They can however be trusted for registrations that are known to have
688 // a subtype (as GCM overwrites anything passed by the sender).
689 //
690 // So a given Chrome profile always passes the same string (e.g.
691 // "com.chrome.stable.macosx") as the category when registering with a
692 // subtypes, and incoming subtypes are only trusted for that category.
693 //
694 // (On Android, all registrations made by Chrome on behalf of third-party
695 // apps/extensions/websites have always had a subtype, so we don't need such a
696 // check, indeed we cannot, since category is fixed to the true package name).
697
698 return category == chrome_build_info_.category_for_subtypes;
699 }
700
668 void GCMClientImpl::AddHeartbeatInterval(const std::string& scope, 701 void GCMClientImpl::AddHeartbeatInterval(const std::string& scope,
669 int interval_ms) { 702 int interval_ms) {
670 DCHECK(mcs_client_); 703 DCHECK(mcs_client_);
671 mcs_client_->AddHeartbeatInterval(scope, interval_ms); 704 mcs_client_->AddHeartbeatInterval(scope, interval_ms);
672 } 705 }
673 706
674 void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) { 707 void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) {
675 DCHECK(mcs_client_); 708 DCHECK(mcs_client_);
676 mcs_client_->RemoveHeartbeatInterval(scope); 709 mcs_client_->RemoveHeartbeatInterval(scope);
677 } 710 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 checkin_request_.reset(); 876 checkin_request_.reset();
844 // Delete all of the pending registration and unregistration requests. 877 // Delete all of the pending registration and unregistration requests.
845 pending_registration_requests_.clear(); 878 pending_registration_requests_.clear();
846 pending_unregistration_requests_.clear(); 879 pending_unregistration_requests_.clear();
847 } 880 }
848 881
849 void GCMClientImpl::Register( 882 void GCMClientImpl::Register(
850 const linked_ptr<RegistrationInfo>& registration_info) { 883 const linked_ptr<RegistrationInfo>& registration_info) {
851 DCHECK_EQ(state_, READY); 884 DCHECK_EQ(state_, READY);
852 885
886 // Registrations should never pass as an app_id the special category used
887 // internally when registering with a subtype. See security note in
888 // GCMClient::CategoryHasSubtype.
889 CHECK(!CategoryHasSubtype(registration_info->app_id));
890
853 // Find and use the cached registration ID. 891 // Find and use the cached registration ID.
854 RegistrationInfoMap::const_iterator registrations_iter = 892 RegistrationInfoMap::const_iterator registrations_iter =
855 registrations_.find(registration_info); 893 registrations_.find(registration_info);
856 if (registrations_iter != registrations_.end()) { 894 if (registrations_iter != registrations_.end()) {
857 bool matched = true; 895 bool matched = true;
858 896
859 // For GCM registration, we also match the sender IDs since multiple 897 // For GCM registration, we also match the sender IDs since multiple
860 // registrations are not supported. 898 // registrations are not supported.
861 const GCMRegistrationInfo* gcm_registration_info = 899 const GCMRegistrationInfo* gcm_registration_info =
862 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get()); 900 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
863 if (gcm_registration_info) { 901 if (gcm_registration_info) {
864 const GCMRegistrationInfo* cached_gcm_registration_info = 902 const GCMRegistrationInfo* cached_gcm_registration_info =
865 GCMRegistrationInfo::FromRegistrationInfo( 903 GCMRegistrationInfo::FromRegistrationInfo(
866 registrations_iter->first.get()); 904 registrations_iter->first.get());
867 DCHECK(cached_gcm_registration_info); 905 DCHECK(cached_gcm_registration_info);
868 if (cached_gcm_registration_info && 906 if (cached_gcm_registration_info &&
869 gcm_registration_info->sender_ids != 907 gcm_registration_info->sender_ids !=
870 cached_gcm_registration_info->sender_ids) { 908 cached_gcm_registration_info->sender_ids) {
871 matched = false; 909 matched = false;
872 } 910 }
911 } else {
912 DCHECK(!InstanceIDsDifferOnlyInUseSubtype(
913 registration_info.get(), registrations_iter->first.get()))
914 << "Registering the same Instance ID token both with and without "
915 "subtypes is not supported";
873 } 916 }
874 917
875 if (matched) { 918 if (matched) {
876 delegate_->OnRegisterFinished( 919 delegate_->OnRegisterFinished(
877 registration_info, registrations_iter->second, SUCCESS); 920 registration_info, registrations_iter->second, SUCCESS);
878 return; 921 return;
879 } 922 }
880 } 923 }
881 924
882 std::unique_ptr<RegistrationRequest::CustomRequestHandler> request_handler; 925 std::unique_ptr<RegistrationRequest::CustomRequestHandler> request_handler;
(...skipping 27 matching lines...) Expand all
910 instance_id_iter->second.first, 953 instance_id_iter->second.first,
911 instance_id_token_info->authorized_entity, 954 instance_id_token_info->authorized_entity,
912 instance_id_token_info->scope, 955 instance_id_token_info->scope,
913 ConstructGCMVersion(chrome_build_info_.version), 956 ConstructGCMVersion(chrome_build_info_.version),
914 instance_id_token_info->options)); 957 instance_id_token_info->options));
915 source_to_record = instance_id_token_info->authorized_entity + "/" + 958 source_to_record = instance_id_token_info->authorized_entity + "/" +
916 instance_id_token_info->scope; 959 instance_id_token_info->scope;
917 } 960 }
918 961
919 RegistrationRequest::RequestInfo request_info( 962 RegistrationRequest::RequestInfo request_info(
920 device_checkin_info_.android_id, 963 device_checkin_info_.android_id, device_checkin_info_.secret,
921 device_checkin_info_.secret, 964 registration_info->app_id,
922 registration_info->app_id); 965 instance_id_token_info && instance_id_token_info->use_subtype,
Peter Beverloo 2016/07/22 12:17:03 nit: extract to a local bool w/ an appropriate nam
johnme 2016/07/26 17:11:55 Done.
966 chrome_build_info_.category_for_subtypes);
923 967
924 std::unique_ptr<RegistrationRequest> registration_request( 968 std::unique_ptr<RegistrationRequest> registration_request(
925 new RegistrationRequest( 969 new RegistrationRequest(
926 gservices_settings_.GetRegistrationURL(), request_info, 970 gservices_settings_.GetRegistrationURL(), request_info,
927 std::move(request_handler), GetGCMBackoffPolicy(), 971 std::move(request_handler), GetGCMBackoffPolicy(),
928 base::Bind(&GCMClientImpl::OnRegisterCompleted, 972 base::Bind(&GCMClientImpl::OnRegisterCompleted,
929 weak_ptr_factory_.GetWeakPtr(), registration_info), 973 weak_ptr_factory_.GetWeakPtr(), registration_info),
930 kMaxRegistrationRetries, url_request_context_getter_, &recorder_, 974 kMaxRegistrationRetries, url_request_context_getter_, &recorder_,
931 source_to_record)); 975 source_to_record));
932 registration_request->Start(); 976 registration_request->Start();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 const InstanceIDTokenInfo* instance_id_token_info = 1039 const InstanceIDTokenInfo* instance_id_token_info =
996 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get()); 1040 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get());
997 if (instance_id_token_info) { 1041 if (instance_id_token_info) {
998 auto instance_id_iter = instance_id_data_.find(registration_info->app_id); 1042 auto instance_id_iter = instance_id_data_.find(registration_info->app_id);
999 if (instance_id_iter == instance_id_data_.end()) { 1043 if (instance_id_iter == instance_id_data_.end()) {
1000 // This should not be reached since we should not delete tokens when 1044 // This should not be reached since we should not delete tokens when
1001 // an InstanceID has not been created yet. 1045 // an InstanceID has not been created yet.
1002 NOTREACHED(); 1046 NOTREACHED();
1003 return; 1047 return;
1004 } 1048 }
1049
1005 request_handler.reset(new InstanceIDDeleteTokenRequestHandler( 1050 request_handler.reset(new InstanceIDDeleteTokenRequestHandler(
1006 instance_id_iter->second.first, 1051 instance_id_iter->second.first,
1007 instance_id_token_info->authorized_entity, 1052 instance_id_token_info->authorized_entity,
1008 instance_id_token_info->scope, 1053 instance_id_token_info->scope,
1009 ConstructGCMVersion(chrome_build_info_.version))); 1054 ConstructGCMVersion(chrome_build_info_.version)));
1010 source_to_record = instance_id_token_info->authorized_entity + "/" + 1055 source_to_record = instance_id_token_info->authorized_entity + "/" +
1011 instance_id_token_info->scope; 1056 instance_id_token_info->scope;
1012 } 1057 }
1013 1058
1014 // Remove the registration/token(s) from the cache and the store. 1059 // Remove the registration/token(s) from the cache and the store.
(...skipping 27 matching lines...) Expand all
1042 OnUnregisterCompleted(registration_info, 1087 OnUnregisterCompleted(registration_info,
1043 UnregistrationRequest::SUCCESS); 1088 UnregistrationRequest::SUCCESS);
1044 return; 1089 return;
1045 } 1090 }
1046 } else { 1091 } else {
1047 auto iter = registrations_.find(registration_info); 1092 auto iter = registrations_.find(registration_info);
1048 if (iter == registrations_.end()) { 1093 if (iter == registrations_.end()) {
1049 delegate_->OnUnregisterFinished(registration_info, INVALID_PARAMETER); 1094 delegate_->OnUnregisterFinished(registration_info, INVALID_PARAMETER);
1050 return; 1095 return;
1051 } 1096 }
1097 DCHECK(!InstanceIDsDifferOnlyInUseSubtype(registration_info.get(),
1098 iter->first.get()));
1052 registrations_.erase(iter); 1099 registrations_.erase(iter);
1053 1100
1054 gcm_store_->RemoveRegistration( 1101 gcm_store_->RemoveRegistration(
1055 registration_info->GetSerializedKey(), 1102 registration_info->GetSerializedKey(),
1056 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, 1103 base::Bind(&GCMClientImpl::UpdateRegistrationCallback,
1057 weak_ptr_factory_.GetWeakPtr())); 1104 weak_ptr_factory_.GetWeakPtr()));
1058 } 1105 }
1059 1106
1060 UnregistrationRequest::RequestInfo request_info( 1107 UnregistrationRequest::RequestInfo request_info(
1061 device_checkin_info_.android_id, 1108 device_checkin_info_.android_id, device_checkin_info_.secret,
1062 device_checkin_info_.secret, 1109 registration_info->app_id,
1063 registration_info->app_id); 1110 instance_id_token_info && instance_id_token_info->use_subtype,
Peter Beverloo 2016/07/22 12:17:03 nit: extract to a local bool w/ an appropriate nam
johnme 2016/07/26 17:11:55 Done.
1111 chrome_build_info_.category_for_subtypes);
1064 1112
1065 std::unique_ptr<UnregistrationRequest> unregistration_request( 1113 std::unique_ptr<UnregistrationRequest> unregistration_request(
1066 new UnregistrationRequest( 1114 new UnregistrationRequest(
1067 gservices_settings_.GetRegistrationURL(), request_info, 1115 gservices_settings_.GetRegistrationURL(), request_info,
1068 std::move(request_handler), GetGCMBackoffPolicy(), 1116 std::move(request_handler), GetGCMBackoffPolicy(),
1069 base::Bind(&GCMClientImpl::OnUnregisterCompleted, 1117 base::Bind(&GCMClientImpl::OnUnregisterCompleted,
1070 weak_ptr_factory_.GetWeakPtr(), registration_info), 1118 weak_ptr_factory_.GetWeakPtr(), registration_info),
1071 kMaxUnregistrationRetries, url_request_context_getter_, &recorder_, 1119 kMaxUnregistrationRetries, url_request_context_getter_, &recorder_,
1072 source_to_record)); 1120 source_to_record));
1073 unregistration_request->Start(); 1121 unregistration_request->Start();
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 } 1301 }
1254 1302
1255 void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) { 1303 void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) {
1256 DCHECK(delegate_); 1304 DCHECK(delegate_);
1257 1305
1258 const mcs_proto::DataMessageStanza& data_message_stanza = 1306 const mcs_proto::DataMessageStanza& data_message_stanza =
1259 reinterpret_cast<const mcs_proto::DataMessageStanza&>( 1307 reinterpret_cast<const mcs_proto::DataMessageStanza&>(
1260 message.GetProtobuf()); 1308 message.GetProtobuf());
1261 DCHECK_EQ(data_message_stanza.device_user_id(), kDefaultUserSerialNumber); 1309 DCHECK_EQ(data_message_stanza.device_user_id(), kDefaultUserSerialNumber);
1262 1310
1263 // Copying all the data from the stanza to a MessageData object. When present, 1311 // Copy all the data from the stanza to a MessageData object. When present,
1264 // keys like kMessageTypeKey or kSendErrorMessageIdKey will be filtered out 1312 // keys like kSubtypeKey, kMessageTypeKey or kSendErrorMessageIdKey will be
1265 // later. 1313 // filtered out later.
1266 MessageData message_data; 1314 MessageData message_data;
1267 for (int i = 0; i < data_message_stanza.app_data_size(); ++i) { 1315 for (int i = 0; i < data_message_stanza.app_data_size(); ++i) {
1268 std::string key = data_message_stanza.app_data(i).key(); 1316 std::string key = data_message_stanza.app_data(i).key();
1269 message_data[key] = data_message_stanza.app_data(i).value(); 1317 message_data[key] = data_message_stanza.app_data(i).value();
1270 } 1318 }
1271 1319
1320 std::string subtype = "";
Peter Beverloo 2016/07/22 12:17:03 nit: no init
johnme 2016/07/26 17:11:55 Done.
1321 auto subtype_iter = message_data.find(kSubtypeKey);
Peter Beverloo 2016/07/22 12:17:03 This is using "subtype", which is potentially untr
johnme 2016/07/26 17:11:55 Added TODO.
1322 if (subtype_iter != message_data.end()) {
1323 subtype = subtype_iter->second;
1324 message_data.erase(subtype_iter);
1325 }
1326
1327 // If CategoryHasSubtype returns false, the subtype is untrusted input set by
1328 // the sender, and we should ignore it.
1329 bool use_subtype =
1330 !subtype.empty() && CategoryHasSubtype(data_message_stanza.category());
1331 std::string app_id = use_subtype ? subtype : data_message_stanza.category();
1332
1272 MessageType message_type = DATA_MESSAGE; 1333 MessageType message_type = DATA_MESSAGE;
1273 MessageData::iterator iter = message_data.find(kMessageTypeKey); 1334 MessageData::iterator type_iter = message_data.find(kMessageTypeKey);
1274 if (iter != message_data.end()) { 1335 if (type_iter != message_data.end()) {
1275 message_type = DecodeMessageType(iter->second); 1336 message_type = DecodeMessageType(type_iter->second);
1276 message_data.erase(iter); 1337 message_data.erase(type_iter);
1277 } 1338 }
1278 1339
1279 switch (message_type) { 1340 switch (message_type) {
1280 case DATA_MESSAGE: 1341 case DATA_MESSAGE:
1281 HandleIncomingDataMessage(data_message_stanza, message_data); 1342 HandleIncomingDataMessage(app_id, use_subtype, data_message_stanza,
1343 message_data);
1282 break; 1344 break;
1283 case DELETED_MESSAGES: 1345 case DELETED_MESSAGES:
1284 recorder_.RecordDataMessageReceived(data_message_stanza.category(), 1346 recorder_.RecordDataMessageReceived(app_id, data_message_stanza.from(),
1285 data_message_stanza.from(), 1347 data_message_stanza.ByteSize(), true,
1286 data_message_stanza.ByteSize(),
1287 true,
1288 GCMStatsRecorder::DELETED_MESSAGES); 1348 GCMStatsRecorder::DELETED_MESSAGES);
1289 delegate_->OnMessagesDeleted(data_message_stanza.category()); 1349 delegate_->OnMessagesDeleted(app_id);
1290 break; 1350 break;
1291 case SEND_ERROR: 1351 case SEND_ERROR:
1292 HandleIncomingSendError(data_message_stanza, message_data); 1352 HandleIncomingSendError(app_id, data_message_stanza, message_data);
1293 break; 1353 break;
1294 case UNKNOWN: 1354 case UNKNOWN:
1295 default: // Treat default the same as UNKNOWN. 1355 default: // Treat default the same as UNKNOWN.
1296 DVLOG(1) << "Unknown message_type received. Message ignored. " 1356 DVLOG(1) << "Unknown message_type received. Message ignored. "
1297 << "App ID: " << data_message_stanza.category() << "."; 1357 << "App ID: " << app_id << ".";
1298 break; 1358 break;
1299 } 1359 }
1300 } 1360 }
1301 1361
1302 void GCMClientImpl::HandleIncomingDataMessage( 1362 void GCMClientImpl::HandleIncomingDataMessage(
1363 const std::string& app_id,
1364 bool use_subtype,
1303 const mcs_proto::DataMessageStanza& data_message_stanza, 1365 const mcs_proto::DataMessageStanza& data_message_stanza,
1304 MessageData& message_data) { 1366 MessageData& message_data) {
1305 std::string app_id = data_message_stanza.category();
1306 std::string sender = data_message_stanza.from(); 1367 std::string sender = data_message_stanza.from();
1307 1368
1308 // Drop the message when the app is not registered for the sender of the 1369 // Drop the message when the app is not registered for the sender of the
1309 // message. 1370 // message.
1310 bool registered = false; 1371 bool registered = false;
1311 1372
1312 // First, find among all GCM registrations. 1373 // First, find among all GCM registrations.
1313 std::unique_ptr<GCMRegistrationInfo> gcm_registration( 1374 std::unique_ptr<GCMRegistrationInfo> gcm_registration(
1314 new GCMRegistrationInfo); 1375 new GCMRegistrationInfo);
1315 gcm_registration->app_id = app_id; 1376 gcm_registration->app_id = app_id;
1316 auto gcm_registration_iter = registrations_.find( 1377 auto gcm_registration_iter = registrations_.find(
1317 make_linked_ptr<RegistrationInfo>(gcm_registration.release())); 1378 make_linked_ptr<RegistrationInfo>(gcm_registration.release()));
1318 if (gcm_registration_iter != registrations_.end()) { 1379 if (gcm_registration_iter != registrations_.end()) {
1319 GCMRegistrationInfo* cached_gcm_registration = 1380 GCMRegistrationInfo* cached_gcm_registration =
1320 GCMRegistrationInfo::FromRegistrationInfo( 1381 GCMRegistrationInfo::FromRegistrationInfo(
1321 gcm_registration_iter->first.get()); 1382 gcm_registration_iter->first.get());
1322 if (cached_gcm_registration && 1383 if (cached_gcm_registration &&
1323 std::find(cached_gcm_registration->sender_ids.begin(), 1384 std::find(cached_gcm_registration->sender_ids.begin(),
1324 cached_gcm_registration->sender_ids.end(), 1385 cached_gcm_registration->sender_ids.end(),
1325 sender) != cached_gcm_registration->sender_ids.end()) { 1386 sender) != cached_gcm_registration->sender_ids.end()) {
1326 registered = true; 1387 registered = true;
1327 } 1388 }
1328 } 1389 }
1329 1390
1330 // Then, find among all InstanceID registrations. 1391 // Then, find among all InstanceID registrations.
1331 if (!registered) { 1392 if (!registered) {
1332 std::unique_ptr<InstanceIDTokenInfo> instance_id_token( 1393 linked_ptr<InstanceIDTokenInfo> instance_id_token(new InstanceIDTokenInfo);
1333 new InstanceIDTokenInfo);
1334 instance_id_token->app_id = app_id; 1394 instance_id_token->app_id = app_id;
1395 instance_id_token->use_subtype = use_subtype;
1335 instance_id_token->authorized_entity = sender; 1396 instance_id_token->authorized_entity = sender;
1336 instance_id_token->scope = kGCMScope; 1397 instance_id_token->scope = kGCMScope;
1337 auto instance_id_token_iter = registrations_.find( 1398
1338 make_linked_ptr<RegistrationInfo>(instance_id_token.release())); 1399 auto instance_id_token_iter = registrations_.find(instance_id_token);
1339 if (instance_id_token_iter != registrations_.end()) 1400 if (instance_id_token_iter != registrations_.end()) {
1340 registered = true; 1401 if (InstanceIDsDifferOnlyInUseSubtype(
1402 instance_id_token.get(), instance_id_token_iter->first.get())) {
1403 DLOG(ERROR) << "Incoming GCM message for " << app_id
Peter Beverloo 2016/07/22 12:17:03 Is this DLOG necessary? It would only happen when
johnme 2016/07/26 17:11:55 a) it's most likely to happen if the value of use_
1404 << " had use_subtype = " << use_subtype
1405 << " which conflicts with stored registration";
1406 } else {
1407 registered = true;
1408 }
1409 }
1341 } 1410 }
1342 1411
1343 recorder_.RecordDataMessageReceived(app_id, sender, 1412 recorder_.RecordDataMessageReceived(app_id, sender,
1344 data_message_stanza.ByteSize(), registered, 1413 data_message_stanza.ByteSize(), registered,
1345 GCMStatsRecorder::DATA_MESSAGE); 1414 GCMStatsRecorder::DATA_MESSAGE);
1346 if (!registered) 1415 if (!registered)
1347 return; 1416 return;
1348 1417
1349 IncomingMessage incoming_message; 1418 IncomingMessage incoming_message;
1350 incoming_message.sender_id = data_message_stanza.from(); 1419 incoming_message.sender_id = data_message_stanza.from();
1351 if (data_message_stanza.has_token()) 1420 if (data_message_stanza.has_token())
1352 incoming_message.collapse_key = data_message_stanza.token(); 1421 incoming_message.collapse_key = data_message_stanza.token();
1353 incoming_message.data = message_data; 1422 incoming_message.data = message_data;
1354 incoming_message.raw_data = data_message_stanza.raw_data(); 1423 incoming_message.raw_data = data_message_stanza.raw_data();
1355 1424
1356 delegate_->OnMessageReceived(app_id, incoming_message); 1425 delegate_->OnMessageReceived(app_id, incoming_message);
1357 } 1426 }
1358 1427
1359 void GCMClientImpl::HandleIncomingSendError( 1428 void GCMClientImpl::HandleIncomingSendError(
1429 const std::string& app_id,
1360 const mcs_proto::DataMessageStanza& data_message_stanza, 1430 const mcs_proto::DataMessageStanza& data_message_stanza,
1361 MessageData& message_data) { 1431 MessageData& message_data) {
1362 SendErrorDetails send_error_details; 1432 SendErrorDetails send_error_details;
1363 send_error_details.additional_data = message_data; 1433 send_error_details.additional_data = message_data;
1364 send_error_details.result = SERVER_ERROR; 1434 send_error_details.result = SERVER_ERROR;
1365 1435
1366 MessageData::iterator iter = 1436 MessageData::iterator iter =
1367 send_error_details.additional_data.find(kSendErrorMessageIdKey); 1437 send_error_details.additional_data.find(kSendErrorMessageIdKey);
1368 if (iter != send_error_details.additional_data.end()) { 1438 if (iter != send_error_details.additional_data.end()) {
1369 send_error_details.message_id = iter->second; 1439 send_error_details.message_id = iter->second;
1370 send_error_details.additional_data.erase(iter); 1440 send_error_details.additional_data.erase(iter);
1371 } 1441 }
1372 1442
1373 recorder_.RecordIncomingSendError( 1443 recorder_.RecordIncomingSendError(app_id, data_message_stanza.to(),
1374 data_message_stanza.category(), 1444 data_message_stanza.id());
1375 data_message_stanza.to(), 1445 delegate_->OnMessageSendError(app_id, send_error_details);
1376 data_message_stanza.id());
1377 delegate_->OnMessageSendError(data_message_stanza.category(),
1378 send_error_details);
1379 } 1446 }
1380 1447
1381 bool GCMClientImpl::HasStandaloneRegisteredApp() const { 1448 bool GCMClientImpl::HasStandaloneRegisteredApp() const {
1382 if (registrations_.empty()) 1449 if (registrations_.empty())
1383 return false; 1450 return false;
1384 // Note that account mapper is not counted as a standalone app since it is 1451 // Note that account mapper is not counted as a standalone app since it is
1385 // automatically started when other app uses GCM. 1452 // automatically started when other app uses GCM.
1386 return registrations_.size() > 1 || 1453 return registrations_.size() > 1 ||
1387 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId); 1454 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId);
1388 } 1455 }
1389 1456
1390 } // namespace gcm 1457 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698