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

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

Powered by Google App Engine
This is Rietveld 408576698