OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/gcm_driver/gcm_client_impl.h" | 5 #include "components/gcm_driver/gcm_client_impl.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
14 #include "base/location.h" | 14 #include "base/location.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
17 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" |
18 #include "base/sequenced_task_runner.h" | 18 #include "base/sequenced_task_runner.h" |
19 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
20 #include "base/stl_util.h" | 20 #include "base/stl_util.h" |
21 #include "base/strings/string_number_conversions.h" | 21 #include "base/strings/string_number_conversions.h" |
22 #include "base/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
23 #include "base/threading/thread_task_runner_handle.h" | 23 #include "base/threading/thread_task_runner_handle.h" |
24 #include "base/time/default_clock.h" | 24 #include "base/time/default_clock.h" |
25 #include "base/timer/timer.h" | 25 #include "base/timer/timer.h" |
| 26 #include "components/crx_file/id_util.h" |
26 #include "components/gcm_driver/gcm_account_mapper.h" | 27 #include "components/gcm_driver/gcm_account_mapper.h" |
27 #include "components/gcm_driver/gcm_backoff_policy.h" | 28 #include "components/gcm_driver/gcm_backoff_policy.h" |
28 #include "google_apis/gcm/base/encryptor.h" | 29 #include "google_apis/gcm/base/encryptor.h" |
29 #include "google_apis/gcm/base/mcs_message.h" | 30 #include "google_apis/gcm/base/mcs_message.h" |
30 #include "google_apis/gcm/base/mcs_util.h" | 31 #include "google_apis/gcm/base/mcs_util.h" |
31 #include "google_apis/gcm/engine/checkin_request.h" | 32 #include "google_apis/gcm/engine/checkin_request.h" |
32 #include "google_apis/gcm/engine/connection_factory_impl.h" | 33 #include "google_apis/gcm/engine/connection_factory_impl.h" |
33 #include "google_apis/gcm/engine/gcm_registration_request_handler.h" | 34 #include "google_apis/gcm/engine/gcm_registration_request_handler.h" |
34 #include "google_apis/gcm/engine/gcm_store_impl.h" | 35 #include "google_apis/gcm/engine/gcm_store_impl.h" |
35 #include "google_apis/gcm/engine/gcm_unregistration_request_handler.h" | 36 #include "google_apis/gcm/engine/gcm_unregistration_request_handler.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 }; | 80 }; |
80 | 81 |
81 const char kGCMScope[] = "GCM"; | 82 const char kGCMScope[] = "GCM"; |
82 const int kMaxRegistrationRetries = 5; | 83 const int kMaxRegistrationRetries = 5; |
83 const int kMaxUnregistrationRetries = 5; | 84 const int kMaxUnregistrationRetries = 5; |
84 const char kMessageTypeDataMessage[] = "gcm"; | 85 const char kMessageTypeDataMessage[] = "gcm"; |
85 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; | 86 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; |
86 const char kMessageTypeKey[] = "message_type"; | 87 const char kMessageTypeKey[] = "message_type"; |
87 const char kMessageTypeSendErrorKey[] = "send_error"; | 88 const char kMessageTypeSendErrorKey[] = "send_error"; |
88 const char kSendErrorMessageIdKey[] = "google.message_id"; | 89 const char kSendErrorMessageIdKey[] = "google.message_id"; |
| 90 const char kSubtypeKey[] = "subtype"; |
89 const char kSendMessageFromValue[] = "gcm@chrome.com"; | 91 const char kSendMessageFromValue[] = "gcm@chrome.com"; |
90 const int64_t kDefaultUserSerialNumber = 0LL; | 92 const int64_t kDefaultUserSerialNumber = 0LL; |
91 const int kDestroyGCMStoreDelayMS = 5 * 60 * 1000; // 5 minutes. | 93 const int kDestroyGCMStoreDelayMS = 5 * 60 * 1000; // 5 minutes. |
92 | 94 |
93 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { | 95 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { |
94 switch (status) { | 96 switch (status) { |
95 case MCSClient::QUEUED: | 97 case MCSClient::QUEUED: |
96 return GCMClient::SUCCESS; | 98 return GCMClient::SUCCESS; |
97 case MCSClient::QUEUE_SIZE_LIMIT_REACHED: | 99 case MCSClient::QUEUE_SIZE_LIMIT_REACHED: |
98 return GCMClient::NETWORK_ERROR; | 100 return GCMClient::NETWORK_ERROR; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 std::string* extra_data) { | 211 std::string* extra_data) { |
210 DCHECK(instance_id && extra_data); | 212 DCHECK(instance_id && extra_data); |
211 std::size_t pos = serialized_data.find(','); | 213 std::size_t pos = serialized_data.find(','); |
212 if (pos == std::string::npos) | 214 if (pos == std::string::npos) |
213 return false; | 215 return false; |
214 *instance_id = serialized_data.substr(0, pos); | 216 *instance_id = serialized_data.substr(0, pos); |
215 *extra_data = serialized_data.substr(pos + 1); | 217 *extra_data = serialized_data.substr(pos + 1); |
216 return !instance_id->empty() && !extra_data->empty(); | 218 return !instance_id->empty() && !extra_data->empty(); |
217 } | 219 } |
218 | 220 |
| 221 bool InstanceIDUsesSubtypeForAppId(const std::string& app_id) { |
| 222 // Always use subtypes with Instance ID, except for Chrome Apps/Extensions. |
| 223 return !crx_file::id_util::IdIsValid(app_id); |
| 224 } |
| 225 |
219 void RecordOutgoingMessageToUMA(const gcm::OutgoingMessage& message) { | 226 void RecordOutgoingMessageToUMA(const gcm::OutgoingMessage& message) { |
220 OutgoingMessageTTLCategory ttl_category; | 227 OutgoingMessageTTLCategory ttl_category; |
221 if (message.time_to_live == 0) | 228 if (message.time_to_live == 0) |
222 ttl_category = TTL_ZERO; | 229 ttl_category = TTL_ZERO; |
223 else if (message.time_to_live <= 60 ) | 230 else if (message.time_to_live <= 60 ) |
224 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE; | 231 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE; |
225 else if (message.time_to_live <= 60 * 60) | 232 else if (message.time_to_live <= 60 * 60) |
226 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR; | 233 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR; |
227 else if (message.time_to_live <= 24 * 60 * 60) | 234 else if (message.time_to_live <= 24 * 60 * 60) |
228 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_DAY; | 235 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_DAY; |
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 checkin_request_.reset(); | 850 checkin_request_.reset(); |
844 // Delete all of the pending registration and unregistration requests. | 851 // Delete all of the pending registration and unregistration requests. |
845 pending_registration_requests_.clear(); | 852 pending_registration_requests_.clear(); |
846 pending_unregistration_requests_.clear(); | 853 pending_unregistration_requests_.clear(); |
847 } | 854 } |
848 | 855 |
849 void GCMClientImpl::Register( | 856 void GCMClientImpl::Register( |
850 const linked_ptr<RegistrationInfo>& registration_info) { | 857 const linked_ptr<RegistrationInfo>& registration_info) { |
851 DCHECK_EQ(state_, READY); | 858 DCHECK_EQ(state_, READY); |
852 | 859 |
| 860 // Registrations should never pass as an app_id the special category used |
| 861 // internally when registering with a subtype. See security note in |
| 862 // GCMClientImpl::HandleIncomingMessage. |
| 863 CHECK_NE(registration_info->app_id, |
| 864 chrome_build_info_.product_category_for_subtypes); |
| 865 |
853 // Find and use the cached registration ID. | 866 // Find and use the cached registration ID. |
854 RegistrationInfoMap::const_iterator registrations_iter = | 867 RegistrationInfoMap::const_iterator registrations_iter = |
855 registrations_.find(registration_info); | 868 registrations_.find(registration_info); |
856 if (registrations_iter != registrations_.end()) { | 869 if (registrations_iter != registrations_.end()) { |
857 bool matched = true; | 870 bool matched = true; |
858 | 871 |
859 // For GCM registration, we also match the sender IDs since multiple | 872 // For GCM registration, we also match the sender IDs since multiple |
860 // registrations are not supported. | 873 // registrations are not supported. |
861 const GCMRegistrationInfo* gcm_registration_info = | 874 const GCMRegistrationInfo* gcm_registration_info = |
862 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get()); | 875 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get()); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
909 request_handler.reset(new InstanceIDGetTokenRequestHandler( | 922 request_handler.reset(new InstanceIDGetTokenRequestHandler( |
910 instance_id_iter->second.first, | 923 instance_id_iter->second.first, |
911 instance_id_token_info->authorized_entity, | 924 instance_id_token_info->authorized_entity, |
912 instance_id_token_info->scope, | 925 instance_id_token_info->scope, |
913 ConstructGCMVersion(chrome_build_info_.version), | 926 ConstructGCMVersion(chrome_build_info_.version), |
914 instance_id_token_info->options)); | 927 instance_id_token_info->options)); |
915 source_to_record = instance_id_token_info->authorized_entity + "/" + | 928 source_to_record = instance_id_token_info->authorized_entity + "/" + |
916 instance_id_token_info->scope; | 929 instance_id_token_info->scope; |
917 } | 930 } |
918 | 931 |
919 RegistrationRequest::RequestInfo request_info( | 932 bool use_subtype = instance_id_token_info && |
920 device_checkin_info_.android_id, | 933 InstanceIDUsesSubtypeForAppId(registration_info->app_id); |
921 device_checkin_info_.secret, | 934 std::string category = use_subtype |
922 registration_info->app_id); | 935 ? chrome_build_info_.product_category_for_subtypes |
| 936 : registration_info->app_id; |
| 937 std::string subtype = use_subtype ? registration_info->app_id : std::string(); |
| 938 RegistrationRequest::RequestInfo request_info(device_checkin_info_.android_id, |
| 939 device_checkin_info_.secret, |
| 940 category, subtype); |
923 | 941 |
924 std::unique_ptr<RegistrationRequest> registration_request( | 942 std::unique_ptr<RegistrationRequest> registration_request( |
925 new RegistrationRequest( | 943 new RegistrationRequest( |
926 gservices_settings_.GetRegistrationURL(), request_info, | 944 gservices_settings_.GetRegistrationURL(), request_info, |
927 std::move(request_handler), GetGCMBackoffPolicy(), | 945 std::move(request_handler), GetGCMBackoffPolicy(), |
928 base::Bind(&GCMClientImpl::OnRegisterCompleted, | 946 base::Bind(&GCMClientImpl::OnRegisterCompleted, |
929 weak_ptr_factory_.GetWeakPtr(), registration_info), | 947 weak_ptr_factory_.GetWeakPtr(), registration_info), |
930 kMaxRegistrationRetries, url_request_context_getter_, &recorder_, | 948 kMaxRegistrationRetries, url_request_context_getter_, &recorder_, |
931 source_to_record)); | 949 source_to_record)); |
932 registration_request->Start(); | 950 registration_request->Start(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 const InstanceIDTokenInfo* instance_id_token_info = | 1013 const InstanceIDTokenInfo* instance_id_token_info = |
996 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get()); | 1014 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get()); |
997 if (instance_id_token_info) { | 1015 if (instance_id_token_info) { |
998 auto instance_id_iter = instance_id_data_.find(registration_info->app_id); | 1016 auto instance_id_iter = instance_id_data_.find(registration_info->app_id); |
999 if (instance_id_iter == instance_id_data_.end()) { | 1017 if (instance_id_iter == instance_id_data_.end()) { |
1000 // This should not be reached since we should not delete tokens when | 1018 // This should not be reached since we should not delete tokens when |
1001 // an InstanceID has not been created yet. | 1019 // an InstanceID has not been created yet. |
1002 NOTREACHED(); | 1020 NOTREACHED(); |
1003 return; | 1021 return; |
1004 } | 1022 } |
| 1023 |
1005 request_handler.reset(new InstanceIDDeleteTokenRequestHandler( | 1024 request_handler.reset(new InstanceIDDeleteTokenRequestHandler( |
1006 instance_id_iter->second.first, | 1025 instance_id_iter->second.first, |
1007 instance_id_token_info->authorized_entity, | 1026 instance_id_token_info->authorized_entity, |
1008 instance_id_token_info->scope, | 1027 instance_id_token_info->scope, |
1009 ConstructGCMVersion(chrome_build_info_.version))); | 1028 ConstructGCMVersion(chrome_build_info_.version))); |
1010 source_to_record = instance_id_token_info->authorized_entity + "/" + | 1029 source_to_record = instance_id_token_info->authorized_entity + "/" + |
1011 instance_id_token_info->scope; | 1030 instance_id_token_info->scope; |
1012 } | 1031 } |
1013 | 1032 |
1014 // Remove the registration/token(s) from the cache and the store. | 1033 // Remove the registration/token(s) from the cache and the store. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 return; | 1069 return; |
1051 } | 1070 } |
1052 registrations_.erase(iter); | 1071 registrations_.erase(iter); |
1053 | 1072 |
1054 gcm_store_->RemoveRegistration( | 1073 gcm_store_->RemoveRegistration( |
1055 registration_info->GetSerializedKey(), | 1074 registration_info->GetSerializedKey(), |
1056 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, | 1075 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
1057 weak_ptr_factory_.GetWeakPtr())); | 1076 weak_ptr_factory_.GetWeakPtr())); |
1058 } | 1077 } |
1059 | 1078 |
| 1079 bool use_subtype = instance_id_token_info && |
| 1080 InstanceIDUsesSubtypeForAppId(registration_info->app_id); |
| 1081 std::string category = use_subtype |
| 1082 ? chrome_build_info_.product_category_for_subtypes |
| 1083 : registration_info->app_id; |
| 1084 std::string subtype = use_subtype ? registration_info->app_id : std::string(); |
1060 UnregistrationRequest::RequestInfo request_info( | 1085 UnregistrationRequest::RequestInfo request_info( |
1061 device_checkin_info_.android_id, | 1086 device_checkin_info_.android_id, device_checkin_info_.secret, category, |
1062 device_checkin_info_.secret, | 1087 subtype); |
1063 registration_info->app_id); | |
1064 | 1088 |
1065 std::unique_ptr<UnregistrationRequest> unregistration_request( | 1089 std::unique_ptr<UnregistrationRequest> unregistration_request( |
1066 new UnregistrationRequest( | 1090 new UnregistrationRequest( |
1067 gservices_settings_.GetRegistrationURL(), request_info, | 1091 gservices_settings_.GetRegistrationURL(), request_info, |
1068 std::move(request_handler), GetGCMBackoffPolicy(), | 1092 std::move(request_handler), GetGCMBackoffPolicy(), |
1069 base::Bind(&GCMClientImpl::OnUnregisterCompleted, | 1093 base::Bind(&GCMClientImpl::OnUnregisterCompleted, |
1070 weak_ptr_factory_.GetWeakPtr(), registration_info), | 1094 weak_ptr_factory_.GetWeakPtr(), registration_info), |
1071 kMaxUnregistrationRetries, url_request_context_getter_, &recorder_, | 1095 kMaxUnregistrationRetries, url_request_context_getter_, &recorder_, |
1072 source_to_record)); | 1096 source_to_record)); |
1073 unregistration_request->Start(); | 1097 unregistration_request->Start(); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1253 } | 1277 } |
1254 | 1278 |
1255 void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) { | 1279 void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) { |
1256 DCHECK(delegate_); | 1280 DCHECK(delegate_); |
1257 | 1281 |
1258 const mcs_proto::DataMessageStanza& data_message_stanza = | 1282 const mcs_proto::DataMessageStanza& data_message_stanza = |
1259 reinterpret_cast<const mcs_proto::DataMessageStanza&>( | 1283 reinterpret_cast<const mcs_proto::DataMessageStanza&>( |
1260 message.GetProtobuf()); | 1284 message.GetProtobuf()); |
1261 DCHECK_EQ(data_message_stanza.device_user_id(), kDefaultUserSerialNumber); | 1285 DCHECK_EQ(data_message_stanza.device_user_id(), kDefaultUserSerialNumber); |
1262 | 1286 |
1263 // Copying all the data from the stanza to a MessageData object. When present, | 1287 // Copy all the data from the stanza to a MessageData object. When present, |
1264 // keys like kMessageTypeKey or kSendErrorMessageIdKey will be filtered out | 1288 // keys like kSubtypeKey, kMessageTypeKey or kSendErrorMessageIdKey will be |
1265 // later. | 1289 // filtered out later. |
1266 MessageData message_data; | 1290 MessageData message_data; |
1267 for (int i = 0; i < data_message_stanza.app_data_size(); ++i) { | 1291 for (int i = 0; i < data_message_stanza.app_data_size(); ++i) { |
1268 std::string key = data_message_stanza.app_data(i).key(); | 1292 std::string key = data_message_stanza.app_data(i).key(); |
1269 message_data[key] = data_message_stanza.app_data(i).value(); | 1293 message_data[key] = data_message_stanza.app_data(i).value(); |
1270 } | 1294 } |
1271 | 1295 |
| 1296 std::string subtype; |
| 1297 auto subtype_iter = message_data.find(kSubtypeKey); |
| 1298 if (subtype_iter != message_data.end()) { |
| 1299 subtype = subtype_iter->second; |
| 1300 message_data.erase(subtype_iter); |
| 1301 } |
| 1302 |
| 1303 // SECURITY NOTE: Subtypes received from GCM *cannot* be trusted for |
| 1304 // registrations without a subtype (as the sender can pass any subtype they |
| 1305 // want). They can however be trusted for registrations that are known to have |
| 1306 // a subtype (as GCM overwrites anything passed by the sender). |
| 1307 // |
| 1308 // So a given Chrome profile always passes a fixed string called |
| 1309 // |product_category_for_subtypes| (of the form "com.chrome.macosx") as the |
| 1310 // category when registering with a subtype, and incoming subtypes are only |
| 1311 // trusted for that category. |
| 1312 // |
| 1313 // TODO(johnme): Remove this check if GCM starts sending the subtype in a |
| 1314 // field that's guaranteed to be trusted (b/18198485). |
| 1315 // |
| 1316 // (On Android, all registrations made by Chrome on behalf of third-party |
| 1317 // apps/extensions/websites have always had a subtype, so such a check is not |
| 1318 // necessary - or possible, since category is fixed to the true package name). |
| 1319 bool subtype_is_trusted = data_message_stanza.category() == |
| 1320 chrome_build_info_.product_category_for_subtypes; |
| 1321 bool use_subtype = subtype_is_trusted && !subtype.empty(); |
| 1322 std::string app_id = use_subtype ? subtype : data_message_stanza.category(); |
| 1323 |
1272 MessageType message_type = DATA_MESSAGE; | 1324 MessageType message_type = DATA_MESSAGE; |
1273 MessageData::iterator iter = message_data.find(kMessageTypeKey); | 1325 MessageData::iterator type_iter = message_data.find(kMessageTypeKey); |
1274 if (iter != message_data.end()) { | 1326 if (type_iter != message_data.end()) { |
1275 message_type = DecodeMessageType(iter->second); | 1327 message_type = DecodeMessageType(type_iter->second); |
1276 message_data.erase(iter); | 1328 message_data.erase(type_iter); |
1277 } | 1329 } |
1278 | 1330 |
1279 switch (message_type) { | 1331 switch (message_type) { |
1280 case DATA_MESSAGE: | 1332 case DATA_MESSAGE: |
1281 HandleIncomingDataMessage(data_message_stanza, message_data); | 1333 HandleIncomingDataMessage(app_id, use_subtype, data_message_stanza, |
| 1334 message_data); |
1282 break; | 1335 break; |
1283 case DELETED_MESSAGES: | 1336 case DELETED_MESSAGES: |
1284 recorder_.RecordDataMessageReceived(data_message_stanza.category(), | 1337 recorder_.RecordDataMessageReceived(app_id, data_message_stanza.from(), |
1285 data_message_stanza.from(), | 1338 data_message_stanza.ByteSize(), true, |
1286 data_message_stanza.ByteSize(), | |
1287 true, | |
1288 GCMStatsRecorder::DELETED_MESSAGES); | 1339 GCMStatsRecorder::DELETED_MESSAGES); |
1289 delegate_->OnMessagesDeleted(data_message_stanza.category()); | 1340 delegate_->OnMessagesDeleted(app_id); |
1290 break; | 1341 break; |
1291 case SEND_ERROR: | 1342 case SEND_ERROR: |
1292 HandleIncomingSendError(data_message_stanza, message_data); | 1343 HandleIncomingSendError(app_id, data_message_stanza, message_data); |
1293 break; | 1344 break; |
1294 case UNKNOWN: | 1345 case UNKNOWN: |
1295 default: // Treat default the same as UNKNOWN. | 1346 default: // Treat default the same as UNKNOWN. |
1296 DVLOG(1) << "Unknown message_type received. Message ignored. " | 1347 DVLOG(1) << "Unknown message_type received. Message ignored. " |
1297 << "App ID: " << data_message_stanza.category() << "."; | 1348 << "App ID: " << app_id << "."; |
1298 break; | 1349 break; |
1299 } | 1350 } |
1300 } | 1351 } |
1301 | 1352 |
1302 void GCMClientImpl::HandleIncomingDataMessage( | 1353 void GCMClientImpl::HandleIncomingDataMessage( |
| 1354 const std::string& app_id, |
| 1355 bool was_subtype, |
1303 const mcs_proto::DataMessageStanza& data_message_stanza, | 1356 const mcs_proto::DataMessageStanza& data_message_stanza, |
1304 MessageData& message_data) { | 1357 MessageData& message_data) { |
1305 std::string app_id = data_message_stanza.category(); | |
1306 std::string sender = data_message_stanza.from(); | 1358 std::string sender = data_message_stanza.from(); |
1307 | 1359 |
1308 // Drop the message when the app is not registered for the sender of the | 1360 // Drop the message when the app is not registered for the sender of the |
1309 // message. | 1361 // message. |
1310 bool registered = false; | 1362 bool registered = false; |
1311 | 1363 |
1312 // First, find among all GCM registrations. | 1364 // First, find among all GCM registrations. |
1313 std::unique_ptr<GCMRegistrationInfo> gcm_registration( | 1365 std::unique_ptr<GCMRegistrationInfo> gcm_registration( |
1314 new GCMRegistrationInfo); | 1366 new GCMRegistrationInfo); |
1315 gcm_registration->app_id = app_id; | 1367 gcm_registration->app_id = app_id; |
1316 auto gcm_registration_iter = registrations_.find( | 1368 auto gcm_registration_iter = registrations_.find( |
1317 make_linked_ptr<RegistrationInfo>(gcm_registration.release())); | 1369 make_linked_ptr<RegistrationInfo>(gcm_registration.release())); |
1318 if (gcm_registration_iter != registrations_.end()) { | 1370 if (gcm_registration_iter != registrations_.end()) { |
1319 GCMRegistrationInfo* cached_gcm_registration = | 1371 GCMRegistrationInfo* cached_gcm_registration = |
1320 GCMRegistrationInfo::FromRegistrationInfo( | 1372 GCMRegistrationInfo::FromRegistrationInfo( |
1321 gcm_registration_iter->first.get()); | 1373 gcm_registration_iter->first.get()); |
1322 if (cached_gcm_registration && | 1374 if (cached_gcm_registration && |
1323 std::find(cached_gcm_registration->sender_ids.begin(), | 1375 std::find(cached_gcm_registration->sender_ids.begin(), |
1324 cached_gcm_registration->sender_ids.end(), | 1376 cached_gcm_registration->sender_ids.end(), |
1325 sender) != cached_gcm_registration->sender_ids.end()) { | 1377 sender) != cached_gcm_registration->sender_ids.end()) { |
1326 registered = true; | 1378 if (was_subtype) |
| 1379 DLOG(ERROR) << "GCM message for non-IID " << app_id << " used subtype"; |
| 1380 else |
| 1381 registered = true; |
1327 } | 1382 } |
1328 } | 1383 } |
1329 | 1384 |
1330 // Then, find among all InstanceID registrations. | 1385 // Then, find among all InstanceID registrations. |
1331 if (!registered) { | 1386 if (!registered) { |
1332 std::unique_ptr<InstanceIDTokenInfo> instance_id_token( | 1387 std::unique_ptr<InstanceIDTokenInfo> instance_id_token( |
1333 new InstanceIDTokenInfo); | 1388 new InstanceIDTokenInfo); |
1334 instance_id_token->app_id = app_id; | 1389 instance_id_token->app_id = app_id; |
1335 instance_id_token->authorized_entity = sender; | 1390 instance_id_token->authorized_entity = sender; |
1336 instance_id_token->scope = kGCMScope; | 1391 instance_id_token->scope = kGCMScope; |
1337 auto instance_id_token_iter = registrations_.find( | 1392 auto instance_id_token_iter = registrations_.find( |
1338 make_linked_ptr<RegistrationInfo>(instance_id_token.release())); | 1393 make_linked_ptr<RegistrationInfo>(instance_id_token.release())); |
1339 if (instance_id_token_iter != registrations_.end()) | 1394 if (instance_id_token_iter != registrations_.end()) { |
1340 registered = true; | 1395 if (was_subtype != InstanceIDUsesSubtypeForAppId(app_id)) { |
| 1396 DLOG(ERROR) << "GCM message for " << app_id |
| 1397 << " incorrectly had was_subtype = " << was_subtype; |
| 1398 } else { |
| 1399 registered = true; |
| 1400 } |
| 1401 } |
1341 } | 1402 } |
1342 | 1403 |
1343 recorder_.RecordDataMessageReceived(app_id, sender, | 1404 recorder_.RecordDataMessageReceived(app_id, sender, |
1344 data_message_stanza.ByteSize(), registered, | 1405 data_message_stanza.ByteSize(), registered, |
1345 GCMStatsRecorder::DATA_MESSAGE); | 1406 GCMStatsRecorder::DATA_MESSAGE); |
1346 if (!registered) | 1407 if (!registered) |
1347 return; | 1408 return; |
1348 | 1409 |
1349 IncomingMessage incoming_message; | 1410 IncomingMessage incoming_message; |
1350 incoming_message.sender_id = data_message_stanza.from(); | 1411 incoming_message.sender_id = data_message_stanza.from(); |
1351 if (data_message_stanza.has_token()) | 1412 if (data_message_stanza.has_token()) |
1352 incoming_message.collapse_key = data_message_stanza.token(); | 1413 incoming_message.collapse_key = data_message_stanza.token(); |
1353 incoming_message.data = message_data; | 1414 incoming_message.data = message_data; |
1354 incoming_message.raw_data = data_message_stanza.raw_data(); | 1415 incoming_message.raw_data = data_message_stanza.raw_data(); |
1355 | 1416 |
1356 delegate_->OnMessageReceived(app_id, incoming_message); | 1417 delegate_->OnMessageReceived(app_id, incoming_message); |
1357 } | 1418 } |
1358 | 1419 |
1359 void GCMClientImpl::HandleIncomingSendError( | 1420 void GCMClientImpl::HandleIncomingSendError( |
| 1421 const std::string& app_id, |
1360 const mcs_proto::DataMessageStanza& data_message_stanza, | 1422 const mcs_proto::DataMessageStanza& data_message_stanza, |
1361 MessageData& message_data) { | 1423 MessageData& message_data) { |
1362 SendErrorDetails send_error_details; | 1424 SendErrorDetails send_error_details; |
1363 send_error_details.additional_data = message_data; | 1425 send_error_details.additional_data = message_data; |
1364 send_error_details.result = SERVER_ERROR; | 1426 send_error_details.result = SERVER_ERROR; |
1365 | 1427 |
1366 MessageData::iterator iter = | 1428 MessageData::iterator iter = |
1367 send_error_details.additional_data.find(kSendErrorMessageIdKey); | 1429 send_error_details.additional_data.find(kSendErrorMessageIdKey); |
1368 if (iter != send_error_details.additional_data.end()) { | 1430 if (iter != send_error_details.additional_data.end()) { |
1369 send_error_details.message_id = iter->second; | 1431 send_error_details.message_id = iter->second; |
1370 send_error_details.additional_data.erase(iter); | 1432 send_error_details.additional_data.erase(iter); |
1371 } | 1433 } |
1372 | 1434 |
1373 recorder_.RecordIncomingSendError( | 1435 recorder_.RecordIncomingSendError(app_id, data_message_stanza.to(), |
1374 data_message_stanza.category(), | 1436 data_message_stanza.id()); |
1375 data_message_stanza.to(), | 1437 delegate_->OnMessageSendError(app_id, send_error_details); |
1376 data_message_stanza.id()); | |
1377 delegate_->OnMessageSendError(data_message_stanza.category(), | |
1378 send_error_details); | |
1379 } | 1438 } |
1380 | 1439 |
1381 bool GCMClientImpl::HasStandaloneRegisteredApp() const { | 1440 bool GCMClientImpl::HasStandaloneRegisteredApp() const { |
1382 if (registrations_.empty()) | 1441 if (registrations_.empty()) |
1383 return false; | 1442 return false; |
1384 // Note that account mapper is not counted as a standalone app since it is | 1443 // Note that account mapper is not counted as a standalone app since it is |
1385 // automatically started when other app uses GCM. | 1444 // automatically started when other app uses GCM. |
1386 return registrations_.size() > 1 || | 1445 return registrations_.size() > 1 || |
1387 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId); | 1446 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId); |
1388 } | 1447 } |
1389 | 1448 |
1390 } // namespace gcm | 1449 } // namespace gcm |
OLD | NEW |