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

Unified Diff: components/gcm_driver/gcm_client_impl.cc

Issue 2578583002: Provide a mechanism for the GCM driver to send message receipts to GCM.
Patch Set: Registration, not reservation Created 3 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: components/gcm_driver/gcm_client_impl.cc
diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gcm_client_impl.cc
index a18b5850b5d8bb4e78dca77ee4628e696dc3f20d..7c0494fe3d45b9e4c12504fa44e1e6ce51af6e8a 100644
--- a/components/gcm_driver/gcm_client_impl.cc
+++ b/components/gcm_driver/gcm_client_impl.cc
@@ -10,6 +10,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/logging.h"
@@ -22,10 +23,13 @@
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
+#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/crx_file/id_util.h"
#include "components/gcm_driver/gcm_account_mapper.h"
#include "components/gcm_driver/gcm_backoff_policy.h"
+#include "components/gcm_driver/gcm_message_status.h"
+#include "components/variations/variations_associated_data.h"
#include "google_apis/gcm/base/encryptor.h"
#include "google_apis/gcm/base/mcs_message.h"
#include "google_apis/gcm/base/mcs_util.h"
@@ -79,6 +83,13 @@ enum ResetStoreError {
RESET_STORE_ERROR_COUNT
};
+// Indicates what type of message receipts should be sent to the GCM.
+enum MessageReceiptsToSend {
+ SEND_NONE = 0,
+ SEND_FAILURES = 1,
+ SEND_ALL = 2,
+};
+
const char kGCMScope[] = "GCM";
const int kMaxRegistrationRetries = 5;
const int kMaxUnregistrationRetries = 5;
@@ -92,6 +103,17 @@ const char kSubtypeKey[] = "subtype";
const char kSendMessageFromValue[] = "gcm@chrome.com";
const int64_t kDefaultUserSerialNumber = 0LL;
const int kDestroyGCMStoreDelayMS = 5 * 60 * 1000; // 5 minutes.
+const char kGcmMessageTypeKey[] = "type";
Peter Beverloo 2017/02/13 13:47:07 Q: Why id this different from kMessageTypeKey?
harkness 2017/02/14 19:22:29 Actually, I don't remember where I got this key fr
+const char kMessageReceiptType[] = "message_receipt";
+const char kReceiptMessageIdKey[] = "message_id";
+const char kReceiptStatusKey[] = "status";
+// kReceiptGCMDestinationID is the destination ID which GCM listens to for
+// upstream receipt messages.
+const char kReceiptGCMDestinationID[] = "1029510549786@google.com";
+const int kReceiptTTLInSeconds = 10;
+const base::Feature kGCMMessageReceiptsFeature{
+ "GCMMessageReceiptsFeature", base::FEATURE_ENABLED_BY_DEFAULT};
Peter Beverloo 2017/02/13 13:47:06 Rather than having a trial that's always enabled a
harkness 2017/02/14 19:22:28 I did consider that, and functionally they're iden
Ilya Sherman 2017/02/22 23:17:02 Either approach is okay from a functionality persp
+const char kMessageReceiptsToSend[] = "message_receipts_to_send";
GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) {
switch (status) {
@@ -1342,6 +1364,8 @@ void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) {
HandleIncomingSendError(app_id, data_message_stanza, message_data);
break;
case UNKNOWN:
+ SendMessageReceipt(data_message_stanza.id(), app_id,
+ GCMMessageStatus::GCM_UNKNOWN_MESSAGE_TYPE);
DVLOG(1) << "Unknown message_type received. Message ignored. "
<< "App ID: " << app_id << ".";
break;
@@ -1354,6 +1378,7 @@ void GCMClientImpl::HandleIncomingDataMessage(
const mcs_proto::DataMessageStanza& data_message_stanza,
MessageData& message_data) {
std::string sender = data_message_stanza.from();
+ GCMMessageStatus status = GCMMessageStatus::GCM_NO_REGISTRATION;
// Drop the message when the app is not registered for the sender of the
// message.
@@ -1369,14 +1394,23 @@ void GCMClientImpl::HandleIncomingDataMessage(
GCMRegistrationInfo* cached_gcm_registration =
GCMRegistrationInfo::FromRegistrationInfo(
gcm_registration_iter->first.get());
- if (cached_gcm_registration &&
- std::find(cached_gcm_registration->sender_ids.begin(),
- cached_gcm_registration->sender_ids.end(),
- sender) != cached_gcm_registration->sender_ids.end()) {
- if (was_subtype)
- DLOG(ERROR) << "GCM message for non-IID " << app_id << " used subtype";
- else
- registered = true;
+ if (cached_gcm_registration) {
+ if (std::find(cached_gcm_registration->sender_ids.begin(),
+ cached_gcm_registration->sender_ids.end(),
+ sender) != cached_gcm_registration->sender_ids.end()) {
+ if (was_subtype) {
+ DLOG(ERROR) << "GCM message for non-IID " << app_id
+ << " used subtype";
+ status = GCMMessageStatus::GCM_INVALID_SUBTYPE;
+ } else {
+ registered = true;
+ }
+ } else {
+ DLOG(ERROR) << "GCM message for non-IID " << app_id
+ << " had a reservation but the sender_id " << sender
Peter Beverloo 2017/02/13 13:47:07 s/reservation/registration/
harkness 2017/02/14 19:22:28 Done.
+ << " was not valid.";
+ status = GCMMessageStatus::GCM_INVALID_SENDER_ID;
+ }
}
}
@@ -1393,6 +1427,7 @@ void GCMClientImpl::HandleIncomingDataMessage(
if (was_subtype != InstanceIDUsesSubtypeForAppId(app_id)) {
DLOG(ERROR) << "GCM message for " << app_id
<< " incorrectly had was_subtype = " << was_subtype;
+ status = GCMMessageStatus::GCM_INVALID_SUBTYPE;
} else {
registered = true;
}
@@ -1410,8 +1445,10 @@ void GCMClientImpl::HandleIncomingDataMessage(
recorder_.RecordDataMessageReceived(app_id, sender,
data_message_stanza.ByteSize(), registered,
GCMStatsRecorder::DATA_MESSAGE);
- if (!registered)
+ if (!registered) {
+ SendMessageReceipt(data_message_stanza.id(), app_id, status);
return;
+ }
IncomingMessage incoming_message;
incoming_message.sender_id = data_message_stanza.from();
@@ -1420,7 +1457,12 @@ void GCMClientImpl::HandleIncomingDataMessage(
incoming_message.data = message_data;
incoming_message.raw_data = data_message_stanza.raw_data();
- delegate_->OnMessageReceived(app_id, incoming_message);
+ // Pass the message up to the GCMDriver. Also pass a callback which will send
+ // a receipt for this message if invoked with a message status.
+ delegate_->OnMessageReceived(app_id, incoming_message,
+ base::Bind(&GCMClientImpl::SendMessageReceipt,
+ weak_ptr_factory_.GetWeakPtr(),
+ data_message_stanza.id(), app_id));
}
void GCMClientImpl::HandleIncomingDeletedMessages(
@@ -1471,4 +1513,33 @@ bool GCMClientImpl::HasStandaloneRegisteredApp() const {
!ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId);
}
+void GCMClientImpl::SendMessageReceipt(const std::string& message_id,
+ const std::string& app_id,
+ GCMMessageStatus status) {
+ // Only send message receipts to GCM if the trial is enabled.
+ int message_types_to_send = variations::GetVariationParamByFeatureAsInt(
Peter Beverloo 2017/02/13 13:47:06 Use base::GetFieldTrialParamByFeatureAsInt() inste
harkness 2017/02/14 19:22:28 Ah, I wasn't aware of that one. I'll update it.
+ kGCMMessageReceiptsFeature, kMessageReceiptsToSend,
+ MessageReceiptsToSend::SEND_NONE);
+
+ if (message_types_to_send == MessageReceiptsToSend::SEND_NONE)
+ return;
+
+ if (message_types_to_send == MessageReceiptsToSend::SEND_FAILURES &&
+ (status == GCMMessageStatus::GCM_SUCCESS ||
+ status == GCMMessageStatus::GCM_UNRESOLVED))
+ return;
Peter Beverloo 2017/02/13 13:47:07 nit: we tend to prefer switch() statements so that
harkness 2017/02/14 19:22:28 I agree in 95% of cases that a switch is better, b
+
+ // Prepare a message to send to GCM which will log the status of the received
+ // message. This is aggregated by GCM to provide better error alerting.
+ OutgoingMessage message;
+ message.time_to_live = kReceiptTTLInSeconds;
+ message.id =
+ base::Int64ToString(base::Time::NowFromSystemTime().ToInternalValue());
+ message.data[kGcmMessageTypeKey] = kMessageReceiptType;
+ message.data[kReceiptMessageIdKey] = message_id;
+ message.data[kReceiptStatusKey] = base::IntToString(static_cast<int>(status));
+
+ Send(app_id, kReceiptGCMDestinationID, message);
+}
+
} // namespace gcm

Powered by Google App Engine
This is Rietveld 408576698