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

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 review comments Created 4 years, 4 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;
Peter Beverloo 2016/07/28 12:34:10 nit: Could we logically separate these checks for
johnme 2016/08/04 17:47:14 Done.
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 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 checkin_request_.reset(); 859 checkin_request_.reset();
844 // Delete all of the pending registration and unregistration requests. 860 // Delete all of the pending registration and unregistration requests.
845 pending_registration_requests_.clear(); 861 pending_registration_requests_.clear();
846 pending_unregistration_requests_.clear(); 862 pending_unregistration_requests_.clear();
847 } 863 }
848 864
849 void GCMClientImpl::Register( 865 void GCMClientImpl::Register(
850 const linked_ptr<RegistrationInfo>& registration_info) { 866 const linked_ptr<RegistrationInfo>& registration_info) {
851 DCHECK_EQ(state_, READY); 867 DCHECK_EQ(state_, READY);
852 868
869 // Registrations should never pass as an app_id the special category used
870 // internally when registering with a subtype. See security note in
871 // GCMClientImpl::HandleIncomingMessage.
872 CHECK_NE(registration_info->app_id, chrome_build_info_.category_for_subtypes);
873
853 // Find and use the cached registration ID. 874 // Find and use the cached registration ID.
854 RegistrationInfoMap::const_iterator registrations_iter = 875 RegistrationInfoMap::const_iterator registrations_iter =
855 registrations_.find(registration_info); 876 registrations_.find(registration_info);
856 if (registrations_iter != registrations_.end()) { 877 if (registrations_iter != registrations_.end()) {
857 bool matched = true; 878 bool matched = true;
858 879
859 // For GCM registration, we also match the sender IDs since multiple 880 // For GCM registration, we also match the sender IDs since multiple
860 // registrations are not supported. 881 // registrations are not supported.
861 const GCMRegistrationInfo* gcm_registration_info = 882 const GCMRegistrationInfo* gcm_registration_info =
862 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get()); 883 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
863 if (gcm_registration_info) { 884 if (gcm_registration_info) {
864 const GCMRegistrationInfo* cached_gcm_registration_info = 885 const GCMRegistrationInfo* cached_gcm_registration_info =
865 GCMRegistrationInfo::FromRegistrationInfo( 886 GCMRegistrationInfo::FromRegistrationInfo(
866 registrations_iter->first.get()); 887 registrations_iter->first.get());
867 DCHECK(cached_gcm_registration_info); 888 DCHECK(cached_gcm_registration_info);
868 if (cached_gcm_registration_info && 889 if (cached_gcm_registration_info &&
869 gcm_registration_info->sender_ids != 890 gcm_registration_info->sender_ids !=
870 cached_gcm_registration_info->sender_ids) { 891 cached_gcm_registration_info->sender_ids) {
871 matched = false; 892 matched = false;
872 } 893 }
894 } else {
895 DCHECK(!InstanceIDsDifferOnlyInUseSubtype(
896 registration_info.get(), registrations_iter->first.get()))
897 << "Registering the same Instance ID token both with and without "
898 "subtypes is not supported";
873 } 899 }
874 900
875 if (matched) { 901 if (matched) {
876 delegate_->OnRegisterFinished( 902 delegate_->OnRegisterFinished(
877 registration_info, registrations_iter->second, SUCCESS); 903 registration_info, registrations_iter->second, SUCCESS);
878 return; 904 return;
879 } 905 }
880 } 906 }
881 907
882 std::unique_ptr<RegistrationRequest::CustomRequestHandler> request_handler; 908 std::unique_ptr<RegistrationRequest::CustomRequestHandler> request_handler;
(...skipping 26 matching lines...) Expand all
909 request_handler.reset(new InstanceIDGetTokenRequestHandler( 935 request_handler.reset(new InstanceIDGetTokenRequestHandler(
910 instance_id_iter->second.first, 936 instance_id_iter->second.first,
911 instance_id_token_info->authorized_entity, 937 instance_id_token_info->authorized_entity,
912 instance_id_token_info->scope, 938 instance_id_token_info->scope,
913 ConstructGCMVersion(chrome_build_info_.version), 939 ConstructGCMVersion(chrome_build_info_.version),
914 instance_id_token_info->options)); 940 instance_id_token_info->options));
915 source_to_record = instance_id_token_info->authorized_entity + "/" + 941 source_to_record = instance_id_token_info->authorized_entity + "/" +
916 instance_id_token_info->scope; 942 instance_id_token_info->scope;
917 } 943 }
918 944
945 bool use_subtype =
946 instance_id_token_info && instance_id_token_info->use_subtype;
947
919 RegistrationRequest::RequestInfo request_info( 948 RegistrationRequest::RequestInfo request_info(
920 device_checkin_info_.android_id, 949 device_checkin_info_.android_id, device_checkin_info_.secret,
921 device_checkin_info_.secret, 950 registration_info->app_id, use_subtype,
922 registration_info->app_id); 951 chrome_build_info_.category_for_subtypes);
923 952
924 std::unique_ptr<RegistrationRequest> registration_request( 953 std::unique_ptr<RegistrationRequest> registration_request(
925 new RegistrationRequest( 954 new RegistrationRequest(
926 gservices_settings_.GetRegistrationURL(), request_info, 955 gservices_settings_.GetRegistrationURL(), request_info,
927 std::move(request_handler), GetGCMBackoffPolicy(), 956 std::move(request_handler), GetGCMBackoffPolicy(),
928 base::Bind(&GCMClientImpl::OnRegisterCompleted, 957 base::Bind(&GCMClientImpl::OnRegisterCompleted,
929 weak_ptr_factory_.GetWeakPtr(), registration_info), 958 weak_ptr_factory_.GetWeakPtr(), registration_info),
930 kMaxRegistrationRetries, url_request_context_getter_, &recorder_, 959 kMaxRegistrationRetries, url_request_context_getter_, &recorder_,
931 source_to_record)); 960 source_to_record));
932 registration_request->Start(); 961 registration_request->Start();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 const InstanceIDTokenInfo* instance_id_token_info = 1024 const InstanceIDTokenInfo* instance_id_token_info =
996 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get()); 1025 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get());
997 if (instance_id_token_info) { 1026 if (instance_id_token_info) {
998 auto instance_id_iter = instance_id_data_.find(registration_info->app_id); 1027 auto instance_id_iter = instance_id_data_.find(registration_info->app_id);
999 if (instance_id_iter == instance_id_data_.end()) { 1028 if (instance_id_iter == instance_id_data_.end()) {
1000 // This should not be reached since we should not delete tokens when 1029 // This should not be reached since we should not delete tokens when
1001 // an InstanceID has not been created yet. 1030 // an InstanceID has not been created yet.
1002 NOTREACHED(); 1031 NOTREACHED();
1003 return; 1032 return;
1004 } 1033 }
1034
1005 request_handler.reset(new InstanceIDDeleteTokenRequestHandler( 1035 request_handler.reset(new InstanceIDDeleteTokenRequestHandler(
1006 instance_id_iter->second.first, 1036 instance_id_iter->second.first,
1007 instance_id_token_info->authorized_entity, 1037 instance_id_token_info->authorized_entity,
1008 instance_id_token_info->scope, 1038 instance_id_token_info->scope,
1009 ConstructGCMVersion(chrome_build_info_.version))); 1039 ConstructGCMVersion(chrome_build_info_.version)));
1010 source_to_record = instance_id_token_info->authorized_entity + "/" + 1040 source_to_record = instance_id_token_info->authorized_entity + "/" +
1011 instance_id_token_info->scope; 1041 instance_id_token_info->scope;
1012 } 1042 }
1013 1043
1014 // Remove the registration/token(s) from the cache and the store. 1044 // Remove the registration/token(s) from the cache and the store.
(...skipping 27 matching lines...) Expand all
1042 OnUnregisterCompleted(registration_info, 1072 OnUnregisterCompleted(registration_info,
1043 UnregistrationRequest::SUCCESS); 1073 UnregistrationRequest::SUCCESS);
1044 return; 1074 return;
1045 } 1075 }
1046 } else { 1076 } else {
1047 auto iter = registrations_.find(registration_info); 1077 auto iter = registrations_.find(registration_info);
1048 if (iter == registrations_.end()) { 1078 if (iter == registrations_.end()) {
1049 delegate_->OnUnregisterFinished(registration_info, INVALID_PARAMETER); 1079 delegate_->OnUnregisterFinished(registration_info, INVALID_PARAMETER);
1050 return; 1080 return;
1051 } 1081 }
1082 DCHECK(!InstanceIDsDifferOnlyInUseSubtype(registration_info.get(),
1083 iter->first.get()));
1052 registrations_.erase(iter); 1084 registrations_.erase(iter);
1053 1085
1054 gcm_store_->RemoveRegistration( 1086 gcm_store_->RemoveRegistration(
1055 registration_info->GetSerializedKey(), 1087 registration_info->GetSerializedKey(),
1056 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, 1088 base::Bind(&GCMClientImpl::UpdateRegistrationCallback,
1057 weak_ptr_factory_.GetWeakPtr())); 1089 weak_ptr_factory_.GetWeakPtr()));
1058 } 1090 }
1059 1091
1092 bool use_subtype =
1093 instance_id_token_info && instance_id_token_info->use_subtype;
1094
1060 UnregistrationRequest::RequestInfo request_info( 1095 UnregistrationRequest::RequestInfo request_info(
1061 device_checkin_info_.android_id, 1096 device_checkin_info_.android_id, device_checkin_info_.secret,
1062 device_checkin_info_.secret, 1097 registration_info->app_id, use_subtype,
1063 registration_info->app_id); 1098 chrome_build_info_.category_for_subtypes);
1064 1099
1065 std::unique_ptr<UnregistrationRequest> unregistration_request( 1100 std::unique_ptr<UnregistrationRequest> unregistration_request(
1066 new UnregistrationRequest( 1101 new UnregistrationRequest(
1067 gservices_settings_.GetRegistrationURL(), request_info, 1102 gservices_settings_.GetRegistrationURL(), request_info,
1068 std::move(request_handler), GetGCMBackoffPolicy(), 1103 std::move(request_handler), GetGCMBackoffPolicy(),
1069 base::Bind(&GCMClientImpl::OnUnregisterCompleted, 1104 base::Bind(&GCMClientImpl::OnUnregisterCompleted,
1070 weak_ptr_factory_.GetWeakPtr(), registration_info), 1105 weak_ptr_factory_.GetWeakPtr(), registration_info),
1071 kMaxUnregistrationRetries, url_request_context_getter_, &recorder_, 1106 kMaxUnregistrationRetries, url_request_context_getter_, &recorder_,
1072 source_to_record)); 1107 source_to_record));
1073 unregistration_request->Start(); 1108 unregistration_request->Start();
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 } 1288 }
1254 1289
1255 void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) { 1290 void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) {
1256 DCHECK(delegate_); 1291 DCHECK(delegate_);
1257 1292
1258 const mcs_proto::DataMessageStanza& data_message_stanza = 1293 const mcs_proto::DataMessageStanza& data_message_stanza =
1259 reinterpret_cast<const mcs_proto::DataMessageStanza&>( 1294 reinterpret_cast<const mcs_proto::DataMessageStanza&>(
1260 message.GetProtobuf()); 1295 message.GetProtobuf());
1261 DCHECK_EQ(data_message_stanza.device_user_id(), kDefaultUserSerialNumber); 1296 DCHECK_EQ(data_message_stanza.device_user_id(), kDefaultUserSerialNumber);
1262 1297
1263 // Copying all the data from the stanza to a MessageData object. When present, 1298 // Copy all the data from the stanza to a MessageData object. When present,
1264 // keys like kMessageTypeKey or kSendErrorMessageIdKey will be filtered out 1299 // keys like kSubtypeKey, kMessageTypeKey or kSendErrorMessageIdKey will be
1265 // later. 1300 // filtered out later.
1266 MessageData message_data; 1301 MessageData message_data;
1267 for (int i = 0; i < data_message_stanza.app_data_size(); ++i) { 1302 for (int i = 0; i < data_message_stanza.app_data_size(); ++i) {
1268 std::string key = data_message_stanza.app_data(i).key(); 1303 std::string key = data_message_stanza.app_data(i).key();
1269 message_data[key] = data_message_stanza.app_data(i).value(); 1304 message_data[key] = data_message_stanza.app_data(i).value();
1270 } 1305 }
1271 1306
1307 std::string subtype;
1308 auto subtype_iter = message_data.find(kSubtypeKey);
1309 if (subtype_iter != message_data.end()) {
1310 subtype = subtype_iter->second;
1311 message_data.erase(subtype_iter);
1312 }
1313
1314 // SECURITY NOTE: Subtypes that we receive from GCM *cannot* be trusted for
1315 // registrations without a subtype (as the sender can pass any subtype they
1316 // want). They can however be trusted for registrations that are known to have
1317 // a subtype (as GCM overwrites anything passed by the sender).
1318 //
1319 // TODO(johnme): Get FCM to send the subtype as a trusted google.subtype key.
Peter Beverloo 2016/07/28 12:34:10 This is rather passive-aggressive :-) What about:
johnme 2016/08/04 17:47:14 I clicked on that crbug link! Done.
1320 //
1321 // So a given Chrome profile always passes a fixed string called
1322 // |category_for_subtypes| (of the form "com.chrome.stable.macosx") as the
1323 // category when registering with a subtype, and incoming subtypes are only
1324 // trusted for that category.
1325 //
1326 // (On Android, all registrations made by Chrome on behalf of third-party
1327 // apps/extensions/websites have always had a subtype, so we don't need such a
1328 // check, indeed we cannot, since category is fixed to the true package name).
Peter Beverloo 2016/07/28 12:34:10 nit: avoid use of "we" (3x) in comments... All of
johnme 2016/08/04 17:47:14 Removed we's. I can't find ways to shorten these c
1329 bool subtype_is_trusted = data_message_stanza.category() ==
1330 chrome_build_info_.category_for_subtypes;
1331 bool use_subtype = subtype_is_trusted && !subtype.empty();
1332 std::string app_id = use_subtype ? subtype : data_message_stanza.category();
1333
1272 MessageType message_type = DATA_MESSAGE; 1334 MessageType message_type = DATA_MESSAGE;
1273 MessageData::iterator iter = message_data.find(kMessageTypeKey); 1335 MessageData::iterator type_iter = message_data.find(kMessageTypeKey);
1274 if (iter != message_data.end()) { 1336 if (type_iter != message_data.end()) {
1275 message_type = DecodeMessageType(iter->second); 1337 message_type = DecodeMessageType(type_iter->second);
1276 message_data.erase(iter); 1338 message_data.erase(type_iter);
1277 } 1339 }
1278 1340
1279 switch (message_type) { 1341 switch (message_type) {
1280 case DATA_MESSAGE: 1342 case DATA_MESSAGE:
1281 HandleIncomingDataMessage(data_message_stanza, message_data); 1343 HandleIncomingDataMessage(app_id, use_subtype, data_message_stanza,
1344 message_data);
1282 break; 1345 break;
1283 case DELETED_MESSAGES: 1346 case DELETED_MESSAGES:
1284 recorder_.RecordDataMessageReceived(data_message_stanza.category(), 1347 recorder_.RecordDataMessageReceived(app_id, data_message_stanza.from(),
1285 data_message_stanza.from(), 1348 data_message_stanza.ByteSize(), true,
1286 data_message_stanza.ByteSize(),
1287 true,
1288 GCMStatsRecorder::DELETED_MESSAGES); 1349 GCMStatsRecorder::DELETED_MESSAGES);
1289 delegate_->OnMessagesDeleted(data_message_stanza.category()); 1350 delegate_->OnMessagesDeleted(app_id);
1290 break; 1351 break;
1291 case SEND_ERROR: 1352 case SEND_ERROR:
1292 HandleIncomingSendError(data_message_stanza, message_data); 1353 HandleIncomingSendError(app_id, data_message_stanza, message_data);
1293 break; 1354 break;
1294 case UNKNOWN: 1355 case UNKNOWN:
1295 default: // Treat default the same as UNKNOWN. 1356 default: // Treat default the same as UNKNOWN.
1296 DVLOG(1) << "Unknown message_type received. Message ignored. " 1357 DVLOG(1) << "Unknown message_type received. Message ignored. "
1297 << "App ID: " << data_message_stanza.category() << "."; 1358 << "App ID: " << app_id << ".";
1298 break; 1359 break;
1299 } 1360 }
1300 } 1361 }
1301 1362
1302 void GCMClientImpl::HandleIncomingDataMessage( 1363 void GCMClientImpl::HandleIncomingDataMessage(
1364 const std::string& app_id,
1365 bool use_subtype,
1303 const mcs_proto::DataMessageStanza& data_message_stanza, 1366 const mcs_proto::DataMessageStanza& data_message_stanza,
1304 MessageData& message_data) { 1367 MessageData& message_data) {
1305 std::string app_id = data_message_stanza.category();
1306 std::string sender = data_message_stanza.from(); 1368 std::string sender = data_message_stanza.from();
1307 1369
1308 // Drop the message when the app is not registered for the sender of the 1370 // Drop the message when the app is not registered for the sender of the
1309 // message. 1371 // message.
1310 bool registered = false; 1372 bool registered = false;
1311 1373
1312 // First, find among all GCM registrations. 1374 // First, find among all GCM registrations.
1313 std::unique_ptr<GCMRegistrationInfo> gcm_registration( 1375 std::unique_ptr<GCMRegistrationInfo> gcm_registration(
1314 new GCMRegistrationInfo); 1376 new GCMRegistrationInfo);
1315 gcm_registration->app_id = app_id; 1377 gcm_registration->app_id = app_id;
1316 auto gcm_registration_iter = registrations_.find( 1378 auto gcm_registration_iter = registrations_.find(
1317 make_linked_ptr<RegistrationInfo>(gcm_registration.release())); 1379 make_linked_ptr<RegistrationInfo>(gcm_registration.release()));
1318 if (gcm_registration_iter != registrations_.end()) { 1380 if (gcm_registration_iter != registrations_.end()) {
1319 GCMRegistrationInfo* cached_gcm_registration = 1381 GCMRegistrationInfo* cached_gcm_registration =
1320 GCMRegistrationInfo::FromRegistrationInfo( 1382 GCMRegistrationInfo::FromRegistrationInfo(
1321 gcm_registration_iter->first.get()); 1383 gcm_registration_iter->first.get());
1322 if (cached_gcm_registration && 1384 if (cached_gcm_registration &&
1323 std::find(cached_gcm_registration->sender_ids.begin(), 1385 std::find(cached_gcm_registration->sender_ids.begin(),
1324 cached_gcm_registration->sender_ids.end(), 1386 cached_gcm_registration->sender_ids.end(),
1325 sender) != cached_gcm_registration->sender_ids.end()) { 1387 sender) != cached_gcm_registration->sender_ids.end()) {
1326 registered = true; 1388 registered = true;
1327 } 1389 }
1328 } 1390 }
1329 1391
1330 // Then, find among all InstanceID registrations. 1392 // Then, find among all InstanceID registrations.
1331 if (!registered) { 1393 if (!registered) {
1332 std::unique_ptr<InstanceIDTokenInfo> instance_id_token( 1394 linked_ptr<InstanceIDTokenInfo> instance_id_token(new InstanceIDTokenInfo);
1333 new InstanceIDTokenInfo);
1334 instance_id_token->app_id = app_id; 1395 instance_id_token->app_id = app_id;
1396 instance_id_token->use_subtype = use_subtype;
1335 instance_id_token->authorized_entity = sender; 1397 instance_id_token->authorized_entity = sender;
1336 instance_id_token->scope = kGCMScope; 1398 instance_id_token->scope = kGCMScope;
1337 auto instance_id_token_iter = registrations_.find( 1399
1338 make_linked_ptr<RegistrationInfo>(instance_id_token.release())); 1400 auto instance_id_token_iter = registrations_.find(instance_id_token);
1339 if (instance_id_token_iter != registrations_.end()) 1401 if (instance_id_token_iter != registrations_.end()) {
1340 registered = true; 1402 if (InstanceIDsDifferOnlyInUseSubtype(
1403 instance_id_token.get(), instance_id_token_iter->first.get())) {
1404 DLOG(ERROR) << "Incoming GCM message for " << app_id
1405 << " had use_subtype = " << use_subtype
1406 << " which conflicts with stored registration";
1407 } else {
1408 registered = true;
1409 }
1410 }
1341 } 1411 }
1342 1412
1343 recorder_.RecordDataMessageReceived(app_id, sender, 1413 recorder_.RecordDataMessageReceived(app_id, sender,
1344 data_message_stanza.ByteSize(), registered, 1414 data_message_stanza.ByteSize(), registered,
1345 GCMStatsRecorder::DATA_MESSAGE); 1415 GCMStatsRecorder::DATA_MESSAGE);
1346 if (!registered) 1416 if (!registered)
1347 return; 1417 return;
1348 1418
1349 IncomingMessage incoming_message; 1419 IncomingMessage incoming_message;
1350 incoming_message.sender_id = data_message_stanza.from(); 1420 incoming_message.sender_id = data_message_stanza.from();
1351 if (data_message_stanza.has_token()) 1421 if (data_message_stanza.has_token())
1352 incoming_message.collapse_key = data_message_stanza.token(); 1422 incoming_message.collapse_key = data_message_stanza.token();
1353 incoming_message.data = message_data; 1423 incoming_message.data = message_data;
1354 incoming_message.raw_data = data_message_stanza.raw_data(); 1424 incoming_message.raw_data = data_message_stanza.raw_data();
1355 1425
1356 delegate_->OnMessageReceived(app_id, incoming_message); 1426 delegate_->OnMessageReceived(app_id, incoming_message);
1357 } 1427 }
1358 1428
1359 void GCMClientImpl::HandleIncomingSendError( 1429 void GCMClientImpl::HandleIncomingSendError(
1430 const std::string& app_id,
1360 const mcs_proto::DataMessageStanza& data_message_stanza, 1431 const mcs_proto::DataMessageStanza& data_message_stanza,
1361 MessageData& message_data) { 1432 MessageData& message_data) {
1362 SendErrorDetails send_error_details; 1433 SendErrorDetails send_error_details;
1363 send_error_details.additional_data = message_data; 1434 send_error_details.additional_data = message_data;
1364 send_error_details.result = SERVER_ERROR; 1435 send_error_details.result = SERVER_ERROR;
1365 1436
1366 MessageData::iterator iter = 1437 MessageData::iterator iter =
1367 send_error_details.additional_data.find(kSendErrorMessageIdKey); 1438 send_error_details.additional_data.find(kSendErrorMessageIdKey);
1368 if (iter != send_error_details.additional_data.end()) { 1439 if (iter != send_error_details.additional_data.end()) {
1369 send_error_details.message_id = iter->second; 1440 send_error_details.message_id = iter->second;
1370 send_error_details.additional_data.erase(iter); 1441 send_error_details.additional_data.erase(iter);
1371 } 1442 }
1372 1443
1373 recorder_.RecordIncomingSendError( 1444 recorder_.RecordIncomingSendError(app_id, data_message_stanza.to(),
1374 data_message_stanza.category(), 1445 data_message_stanza.id());
1375 data_message_stanza.to(), 1446 delegate_->OnMessageSendError(app_id, send_error_details);
1376 data_message_stanza.id());
1377 delegate_->OnMessageSendError(data_message_stanza.category(),
1378 send_error_details);
1379 } 1447 }
1380 1448
1381 bool GCMClientImpl::HasStandaloneRegisteredApp() const { 1449 bool GCMClientImpl::HasStandaloneRegisteredApp() const {
1382 if (registrations_.empty()) 1450 if (registrations_.empty())
1383 return false; 1451 return false;
1384 // Note that account mapper is not counted as a standalone app since it is 1452 // Note that account mapper is not counted as a standalone app since it is
1385 // automatically started when other app uses GCM. 1453 // automatically started when other app uses GCM.
1386 return registrations_.size() > 1 || 1454 return registrations_.size() > 1 ||
1387 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId); 1455 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId);
1388 } 1456 }
1389 1457
1390 } // namespace gcm 1458 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698