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

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: Fix issue with rebase 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
« no previous file with comments | « components/gcm_driver/gcm_client_impl.h ('k') | components/gcm_driver/gcm_client_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 5420646009c631e2568e754586fe0e6360884ad9..6f4913e9e9daa74efd4dada2d982e8c507c55af8 100644
--- a/components/gcm_driver/gcm_client_impl.cc
+++ b/components/gcm_driver/gcm_client_impl.cc
@@ -10,10 +10,12 @@
#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"
#include "base/memory/ptr_util.h"
+#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
@@ -22,10 +24,12 @@
#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 "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,16 @@ 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 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};
+const char kMessageReceiptsToSend[] = "message_receipts_to_send";
GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) {
switch (status) {
@@ -1346,6 +1367,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;
@@ -1358,6 +1381,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.
@@ -1373,14 +1397,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 registration but the sender_id " << sender
+ << " was not valid.";
+ status = GCMMessageStatus::GCM_INVALID_SENDER_ID;
+ }
}
}
@@ -1397,6 +1430,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;
}
@@ -1414,8 +1448,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();
@@ -1424,7 +1460,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(
@@ -1475,4 +1516,36 @@ bool GCMClientImpl::HasStandaloneRegisteredApp() const {
!ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId);
}
+void GCMClientImpl::SendMessageReceipt(const std::string& message_id,
+ const std::string& app_id,
+ GCMMessageStatus status) {
+ DCHECK(status != GCMMessageStatus::GCM_UNRESOLVED);
+
+ // Only send message receipts to GCM if the trial is enabled.
+ int message_types_to_send = base::GetFieldTrialParamByFeatureAsInt(
+ 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;
+ }
+
+ // 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[kMessageTypeKey] = kMessageReceiptType;
+ message.data[kReceiptMessageIdKey] = message_id;
+ message.data[kReceiptStatusKey] = base::IntToString(static_cast<int>(status));
+
+ Send(app_id, kReceiptGCMDestinationID, message);
+}
+
} // namespace gcm
« no previous file with comments | « components/gcm_driver/gcm_client_impl.h ('k') | components/gcm_driver/gcm_client_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698