Chromium Code Reviews| 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/time/time.h" | |
| 25 #include "base/timer/timer.h" | 26 #include "base/timer/timer.h" |
| 26 #include "components/crx_file/id_util.h" | 27 #include "components/crx_file/id_util.h" |
| 27 #include "components/gcm_driver/gcm_account_mapper.h" | 28 #include "components/gcm_driver/gcm_account_mapper.h" |
| 28 #include "components/gcm_driver/gcm_backoff_policy.h" | 29 #include "components/gcm_driver/gcm_backoff_policy.h" |
| 30 #include "components/gcm_driver/gcm_message_status.h" | |
| 29 #include "google_apis/gcm/base/encryptor.h" | 31 #include "google_apis/gcm/base/encryptor.h" |
| 30 #include "google_apis/gcm/base/mcs_message.h" | 32 #include "google_apis/gcm/base/mcs_message.h" |
| 31 #include "google_apis/gcm/base/mcs_util.h" | 33 #include "google_apis/gcm/base/mcs_util.h" |
| 32 #include "google_apis/gcm/engine/checkin_request.h" | 34 #include "google_apis/gcm/engine/checkin_request.h" |
| 33 #include "google_apis/gcm/engine/connection_factory_impl.h" | 35 #include "google_apis/gcm/engine/connection_factory_impl.h" |
| 34 #include "google_apis/gcm/engine/gcm_registration_request_handler.h" | 36 #include "google_apis/gcm/engine/gcm_registration_request_handler.h" |
| 35 #include "google_apis/gcm/engine/gcm_store_impl.h" | 37 #include "google_apis/gcm/engine/gcm_store_impl.h" |
| 36 #include "google_apis/gcm/engine/gcm_unregistration_request_handler.h" | 38 #include "google_apis/gcm/engine/gcm_unregistration_request_handler.h" |
| 37 #include "google_apis/gcm/engine/instance_id_delete_token_request_handler.h" | 39 #include "google_apis/gcm/engine/instance_id_delete_token_request_handler.h" |
| 38 #include "google_apis/gcm/engine/instance_id_get_token_request_handler.h" | 40 #include "google_apis/gcm/engine/instance_id_get_token_request_handler.h" |
| 39 #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" | 41 #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" |
| 40 #include "google_apis/gcm/protocol/checkin.pb.h" | 42 #include "google_apis/gcm/protocol/checkin.pb.h" |
| 41 #include "google_apis/gcm/protocol/mcs.pb.h" | 43 #include "google_apis/gcm/protocol/mcs.pb.h" |
| 42 #include "net/http/http_network_session.h" | 44 #include "net/http/http_network_session.h" |
| 43 #include "net/http/http_transaction_factory.h" | 45 #include "net/http/http_transaction_factory.h" |
| 44 #include "net/url_request/url_request_context.h" | 46 #include "net/url_request/url_request_context.h" |
| 45 #include "url/gurl.h" | 47 #include "url/gurl.h" |
| 46 | 48 |
| 47 namespace gcm { | 49 namespace gcm { |
| 48 | 50 |
| 49 namespace { | 51 namespace { |
| 50 | 52 |
| 53 const char kGcmMessageTypeKey[] = "type"; | |
| 54 const char kMessageReceiptType[] = "message_receipt"; | |
| 55 const char kReceiptMessageIdKey[] = "message_id"; | |
| 56 const char kReceiptStatusKey[] = "status"; | |
| 57 // kReceiptGCMDestinationID is the destination ID which GCM listens to for | |
| 58 // upstream receipt messages. | |
| 59 const char kReceiptGCMDestinationID[] = "1029510549786@google.com"; | |
| 60 const int kReceiptTTLInSeconds = 10; | |
|
Peter Beverloo
2017/02/08 17:09:09
micro nit: unify with the constant block around li
harkness
2017/02/09 16:27:29
Done.
| |
| 61 | |
| 51 // Indicates a message type of the received message. | 62 // Indicates a message type of the received message. |
| 52 enum MessageType { | 63 enum MessageType { |
| 53 UNKNOWN, // Undetermined type. | 64 UNKNOWN, // Undetermined type. |
| 54 DATA_MESSAGE, // Regular data message. | 65 DATA_MESSAGE, // Regular data message. |
| 55 DELETED_MESSAGES, // Messages were deleted on the server. | 66 DELETED_MESSAGES, // Messages were deleted on the server. |
| 56 SEND_ERROR, // Error sending a message. | 67 SEND_ERROR, // Error sending a message. |
| 57 }; | 68 }; |
| 58 | 69 |
| 59 enum OutgoingMessageTTLCategory { | 70 enum OutgoingMessageTTLCategory { |
| 60 TTL_ZERO, | 71 TTL_ZERO, |
| (...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1335 HandleIncomingDataMessage(app_id, use_subtype, data_message_stanza, | 1346 HandleIncomingDataMessage(app_id, use_subtype, data_message_stanza, |
| 1336 message_data); | 1347 message_data); |
| 1337 break; | 1348 break; |
| 1338 case DELETED_MESSAGES: | 1349 case DELETED_MESSAGES: |
| 1339 HandleIncomingDeletedMessages(app_id, data_message_stanza, message_data); | 1350 HandleIncomingDeletedMessages(app_id, data_message_stanza, message_data); |
| 1340 break; | 1351 break; |
| 1341 case SEND_ERROR: | 1352 case SEND_ERROR: |
| 1342 HandleIncomingSendError(app_id, data_message_stanza, message_data); | 1353 HandleIncomingSendError(app_id, data_message_stanza, message_data); |
| 1343 break; | 1354 break; |
| 1344 case UNKNOWN: | 1355 case UNKNOWN: |
| 1356 SendMessageReceipt(data_message_stanza.id(), app_id, | |
| 1357 GCMMessageStatus::GCM_UNKNOWN_MESSAGE_TYPE); | |
| 1345 DVLOG(1) << "Unknown message_type received. Message ignored. " | 1358 DVLOG(1) << "Unknown message_type received. Message ignored. " |
| 1346 << "App ID: " << app_id << "."; | 1359 << "App ID: " << app_id << "."; |
| 1347 break; | 1360 break; |
| 1348 } | 1361 } |
| 1349 } | 1362 } |
| 1350 | 1363 |
| 1351 void GCMClientImpl::HandleIncomingDataMessage( | 1364 void GCMClientImpl::HandleIncomingDataMessage( |
| 1352 const std::string& app_id, | 1365 const std::string& app_id, |
| 1353 bool was_subtype, | 1366 bool was_subtype, |
| 1354 const mcs_proto::DataMessageStanza& data_message_stanza, | 1367 const mcs_proto::DataMessageStanza& data_message_stanza, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1403 if (registered) { | 1416 if (registered) { |
| 1404 UMA_HISTOGRAM_BOOLEAN("GCM.DataMessageReceived", true); | 1417 UMA_HISTOGRAM_BOOLEAN("GCM.DataMessageReceived", true); |
| 1405 bool has_collapse_key = | 1418 bool has_collapse_key = |
| 1406 data_message_stanza.has_token() && !data_message_stanza.token().empty(); | 1419 data_message_stanza.has_token() && !data_message_stanza.token().empty(); |
| 1407 UMA_HISTOGRAM_BOOLEAN("GCM.DataMessageReceivedHasCollapseKey", | 1420 UMA_HISTOGRAM_BOOLEAN("GCM.DataMessageReceivedHasCollapseKey", |
| 1408 has_collapse_key); | 1421 has_collapse_key); |
| 1409 } | 1422 } |
| 1410 recorder_.RecordDataMessageReceived(app_id, sender, | 1423 recorder_.RecordDataMessageReceived(app_id, sender, |
| 1411 data_message_stanza.ByteSize(), registered, | 1424 data_message_stanza.ByteSize(), registered, |
| 1412 GCMStatsRecorder::DATA_MESSAGE); | 1425 GCMStatsRecorder::DATA_MESSAGE); |
| 1413 if (!registered) | 1426 if (!registered) { |
| 1427 SendMessageReceipt(data_message_stanza.id(), app_id, | |
| 1428 GCMMessageStatus::GCM_INVALID_SUBTYPE); | |
|
Peter Beverloo
2017/02/08 17:09:09
INVALID_SUBTYPE is not really accurate - INVALID_R
harkness
2017/02/09 16:27:30
Thanks for reminding me, I was planning to rewrite
| |
| 1414 return; | 1429 return; |
| 1430 } | |
| 1415 | 1431 |
| 1416 IncomingMessage incoming_message; | 1432 IncomingMessage incoming_message; |
| 1417 incoming_message.sender_id = data_message_stanza.from(); | 1433 incoming_message.sender_id = data_message_stanza.from(); |
| 1418 if (data_message_stanza.has_token()) | 1434 if (data_message_stanza.has_token()) |
| 1419 incoming_message.collapse_key = data_message_stanza.token(); | 1435 incoming_message.collapse_key = data_message_stanza.token(); |
| 1420 incoming_message.data = message_data; | 1436 incoming_message.data = message_data; |
| 1421 incoming_message.raw_data = data_message_stanza.raw_data(); | 1437 incoming_message.raw_data = data_message_stanza.raw_data(); |
| 1422 | 1438 |
| 1423 delegate_->OnMessageReceived(app_id, incoming_message); | 1439 // Pass the message up to the GCMDriver. Also pass a callback which will send |
| 1440 // a receipt for this message if invoked with a message status. | |
| 1441 delegate_->OnMessageReceived(app_id, incoming_message, | |
| 1442 base::Bind(&GCMClientImpl::SendMessageReceipt, | |
| 1443 weak_ptr_factory_.GetWeakPtr(), | |
| 1444 data_message_stanza.id(), app_id)); | |
| 1424 } | 1445 } |
| 1425 | 1446 |
| 1426 void GCMClientImpl::HandleIncomingDeletedMessages( | 1447 void GCMClientImpl::HandleIncomingDeletedMessages( |
| 1427 const std::string& app_id, | 1448 const std::string& app_id, |
| 1428 const mcs_proto::DataMessageStanza& data_message_stanza, | 1449 const mcs_proto::DataMessageStanza& data_message_stanza, |
| 1429 MessageData& message_data) { | 1450 MessageData& message_data) { |
| 1430 int deleted_count = 0; | 1451 int deleted_count = 0; |
| 1431 MessageData::iterator count_iter = message_data.find(kDeletedCountKey); | 1452 MessageData::iterator count_iter = message_data.find(kDeletedCountKey); |
| 1432 if (count_iter != message_data.end()) { | 1453 if (count_iter != message_data.end()) { |
| 1433 if (!base::StringToInt(count_iter->second, &deleted_count)) | 1454 if (!base::StringToInt(count_iter->second, &deleted_count)) |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1464 | 1485 |
| 1465 bool GCMClientImpl::HasStandaloneRegisteredApp() const { | 1486 bool GCMClientImpl::HasStandaloneRegisteredApp() const { |
| 1466 if (registrations_.empty()) | 1487 if (registrations_.empty()) |
| 1467 return false; | 1488 return false; |
| 1468 // Note that account mapper is not counted as a standalone app since it is | 1489 // Note that account mapper is not counted as a standalone app since it is |
| 1469 // automatically started when other app uses GCM. | 1490 // automatically started when other app uses GCM. |
| 1470 return registrations_.size() > 1 || | 1491 return registrations_.size() > 1 || |
| 1471 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId); | 1492 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId); |
| 1472 } | 1493 } |
| 1473 | 1494 |
| 1495 void GCMClientImpl::SendMessageReceipt(const std::string& message_id, | |
| 1496 const std::string& app_id, | |
| 1497 GCMMessageStatus status) { | |
| 1498 DCHECK(!app_id.empty()); | |
|
Peter Beverloo
2017/02/08 17:09:09
Could |app_id| (or |message_id|, which should get
harkness
2017/02/09 16:27:30
There are checks in some of the GCMDriver code, bu
| |
| 1499 | |
| 1500 // Prepare a message to send to GCM which will log the status of the received | |
|
Peter Beverloo
2017/02/08 17:09:09
What do you think about guarding this behind a fin
harkness
2017/02/09 16:27:29
Sounds like a good idea. I'll upload the patch set
| |
| 1501 // message. This is aggregated by GCM to provide better error alerting. | |
| 1502 OutgoingMessage message; | |
| 1503 message.time_to_live = kReceiptTTLInSeconds; | |
| 1504 message.id = | |
| 1505 base::Int64ToString(base::Time::NowFromSystemTime().ToInternalValue()); | |
|
Peter Beverloo
2017/02/08 17:09:09
How was this decided? base::Time stores millisecon
harkness
2017/02/09 16:27:30
I'm using the time because that's the way GCMClien
| |
| 1506 message.data[kGcmMessageTypeKey] = kMessageReceiptType; | |
| 1507 message.data[kReceiptMessageIdKey] = message_id; | |
| 1508 message.data[kReceiptStatusKey] = base::IntToString(static_cast<int>(status)); | |
| 1509 | |
| 1510 Send(app_id, kReceiptGCMDestinationID, message); | |
| 1511 } | |
| 1512 | |
| 1474 } // namespace gcm | 1513 } // namespace gcm |
| OLD | NEW |