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 |