summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/api/gcm/gcm_api.cc11
-rw-r--r--chrome/browser/extensions/api/gcm/gcm_api.h6
-rw-r--r--chrome/browser/extensions/api/gcm/gcm_apitest.cc62
-rw-r--r--chrome/browser/services/gcm/gcm_client_mock.cc21
-rw-r--r--chrome/browser/services/gcm/gcm_client_mock.h4
-rw-r--r--chrome/browser/services/gcm/gcm_event_router.h6
-rw-r--r--chrome/browser/services/gcm/gcm_profile_service.cc20
-rw-r--r--chrome/browser/services/gcm/gcm_profile_service.h3
-rw-r--r--chrome/browser/services/gcm/gcm_profile_service_unittest.cc47
-rw-r--r--chrome/test/data/extensions/api_test/gcm/events/on_send_error.js32
-rw-r--r--google_apis/gcm/gcm_client.cc4
-rw-r--r--google_apis/gcm/gcm_client.h19
-rw-r--r--google_apis/gcm/gcm_client_impl.cc78
-rw-r--r--google_apis/gcm/gcm_client_impl.h20
-rw-r--r--google_apis/gcm/gcm_client_impl_unittest.cc27
15 files changed, 229 insertions, 131 deletions
diff --git a/chrome/browser/extensions/api/gcm/gcm_api.cc b/chrome/browser/extensions/api/gcm/gcm_api.cc
index ed3a72e4b..1ad05d2 100644
--- a/chrome/browser/extensions/api/gcm/gcm_api.cc
+++ b/chrome/browser/extensions/api/gcm/gcm_api.cc
@@ -219,12 +219,13 @@ void GcmJsEventRouter::OnMessagesDeleted(const std::string& app_id) {
app_id, event.Pass());
}
-void GcmJsEventRouter::OnSendError(const std::string& app_id,
- const std::string& message_id,
- gcm::GCMClient::Result result) {
+void GcmJsEventRouter::OnSendError(
+ const std::string& app_id,
+ const gcm::GCMClient::SendErrorDetails& send_error_details) {
api::gcm::OnSendError::Error error;
- error.message_id.reset(new std::string(message_id));
- error.error_message = GcmResultToError(result);
+ error.message_id.reset(new std::string(send_error_details.message_id));
+ error.error_message = GcmResultToError(send_error_details.result);
+ error.details.additional_properties = send_error_details.additional_data;
scoped_ptr<Event> event(new Event(
api::gcm::OnSendError::kEventName,
diff --git a/chrome/browser/extensions/api/gcm/gcm_api.h b/chrome/browser/extensions/api/gcm/gcm_api.h
index 71c73d1..320fe72 100644
--- a/chrome/browser/extensions/api/gcm/gcm_api.h
+++ b/chrome/browser/extensions/api/gcm/gcm_api.h
@@ -88,9 +88,9 @@ class GcmJsEventRouter : public gcm::GCMEventRouter,
const std::string& app_id,
const gcm::GCMClient::IncomingMessage& message) OVERRIDE;
virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
- virtual void OnSendError(const std::string& app_id,
- const std::string& message_id,
- gcm::GCMClient::Result result) OVERRIDE;
+ virtual void OnSendError(
+ const std::string& app_id,
+ const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
// EventRouter::Observer:
virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE;
diff --git a/chrome/browser/extensions/api/gcm/gcm_apitest.cc b/chrome/browser/extensions/api/gcm/gcm_apitest.cc
index 85a70a6..002e210 100644
--- a/chrome/browser/extensions/api/gcm/gcm_apitest.cc
+++ b/chrome/browser/extensions/api/gcm/gcm_apitest.cc
@@ -17,6 +17,37 @@ namespace {
const char kEventsExtension[] = "gcm/events";
+gcm::GCMClient::SendErrorDetails CreateErrorDetails(
+ const std::string& message_id,
+ const gcm::GCMClient::Result result,
+ const std::string& total_messages) {
+ gcm::GCMClient::SendErrorDetails error;
+ error.message_id = message_id;
+ error.result = result;
+ error.additional_data["expectedMessageId"] = message_id;
+ switch (result) {
+ case gcm::GCMClient::ASYNC_OPERATION_PENDING:
+ error.additional_data["expectedErrorMessage"] =
+ "Asynchronous operation is pending.";
+ break;
+ case gcm::GCMClient::SERVER_ERROR:
+ error.additional_data["expectedErrorMessage"] = "Server error occurred.";
+ break;
+ case gcm::GCMClient::NETWORK_ERROR:
+ error.additional_data["expectedErrorMessage"] = "Network error occurred.";
+ break;
+ case gcm::GCMClient::TTL_EXCEEDED:
+ error.additional_data["expectedErrorMessage"] = "Time-to-live exceeded.";
+ break;
+ case gcm::GCMClient::UNKNOWN_ERROR:
+ default: // Default case is the same as UNKNOWN_ERROR
+ error.additional_data["expectedErrorMessage"] = "Unknown error occurred.";
+ break;
+ }
+ error.additional_data["totalMessages"] = total_messages;
+ return error;
+}
+
} // namespace
namespace extensions {
@@ -181,17 +212,28 @@ IN_PROC_BROWSER_TEST_F(GcmApiTest, OnSendError) {
LoadTestExtension(kEventsExtension, "on_send_error.html");
ASSERT_TRUE(extension);
+ std::string total_expected_messages = "5";
GcmJsEventRouter router(profile());
- router.OnSendError(extension->id(), "error_message_1",
- gcm::GCMClient::ASYNC_OPERATION_PENDING);
- router.OnSendError(extension->id(), "error_message_2",
- gcm::GCMClient::SERVER_ERROR);
- router.OnSendError(extension->id(), "error_message_3",
- gcm::GCMClient::NETWORK_ERROR);
- router.OnSendError(extension->id(), "error_message_4",
- gcm::GCMClient::UNKNOWN_ERROR);
- router.OnSendError(extension->id(), "error_message_5",
- gcm::GCMClient::TTL_EXCEEDED);
+ router.OnSendError(extension->id(),
+ CreateErrorDetails("error_message_1",
+ gcm::GCMClient::ASYNC_OPERATION_PENDING,
+ total_expected_messages));
+ router.OnSendError(extension->id(),
+ CreateErrorDetails("error_message_2",
+ gcm::GCMClient::SERVER_ERROR,
+ total_expected_messages));
+ router.OnSendError(extension->id(),
+ CreateErrorDetails("error_message_3",
+ gcm::GCMClient::NETWORK_ERROR,
+ total_expected_messages));
+ router.OnSendError(extension->id(),
+ CreateErrorDetails("error_message_4",
+ gcm::GCMClient::UNKNOWN_ERROR,
+ total_expected_messages));
+ router.OnSendError(extension->id(),
+ CreateErrorDetails("error_message_5",
+ gcm::GCMClient::TTL_EXCEEDED,
+ total_expected_messages));
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
diff --git a/chrome/browser/services/gcm/gcm_client_mock.cc b/chrome/browser/services/gcm/gcm_client_mock.cc
index 6f839aa..678d6bc 100644
--- a/chrome/browser/services/gcm/gcm_client_mock.cc
+++ b/chrome/browser/services/gcm/gcm_client_mock.cc
@@ -92,7 +92,7 @@ void GCMClientMock::Send(const std::string& app_id,
base::Bind(&GCMClientMock::SendFinished,
weak_ptr_factory_.GetWeakPtr(),
app_id,
- message.id));
+ message));
}
GCMClient::GCMStatistics GCMClientMock::GetStatistics() const {
@@ -165,17 +165,21 @@ void GCMClientMock::RegisterFinished(const std::string& app_id,
}
void GCMClientMock::SendFinished(const std::string& app_id,
- const std::string& message_id) {
- delegate_->OnSendFinished(app_id, message_id, SUCCESS);
+ const OutgoingMessage& message) {
+ delegate_->OnSendFinished(app_id, message.id, SUCCESS);
// Simulate send error if message id contains a hint.
- if (message_id.find("error") != std::string::npos) {
+ if (message.id.find("error") != std::string::npos) {
+ SendErrorDetails send_error_details;
+ send_error_details.message_id = message.id;
+ send_error_details.result = NETWORK_ERROR;
+ send_error_details.additional_data = message.data;
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&GCMClientMock::MessageSendError,
weak_ptr_factory_.GetWeakPtr(),
app_id,
- message_id),
+ send_error_details),
base::TimeDelta::FromMilliseconds(200));
}
}
@@ -191,10 +195,11 @@ void GCMClientMock::MessagesDeleted(const std::string& app_id) {
delegate_->OnMessagesDeleted(app_id);
}
-void GCMClientMock::MessageSendError(const std::string& app_id,
- const std::string& message_id) {
+void GCMClientMock::MessageSendError(
+ const std::string& app_id,
+ const GCMClient::SendErrorDetails& send_error_details) {
if (delegate_)
- delegate_->OnMessageSendError(app_id, message_id, NETWORK_ERROR);
+ delegate_->OnMessageSendError(app_id, send_error_details);
}
} // namespace gcm
diff --git a/chrome/browser/services/gcm/gcm_client_mock.h b/chrome/browser/services/gcm/gcm_client_mock.h
index 5c6cf7b..e2d217a 100644
--- a/chrome/browser/services/gcm/gcm_client_mock.h
+++ b/chrome/browser/services/gcm/gcm_client_mock.h
@@ -77,12 +77,12 @@ class GCMClientMock : public GCMClient {
void CheckinFinished();
void RegisterFinished(const std::string& app_id,
const std::string& registrion_id);
- void SendFinished(const std::string& app_id, const std::string& message_id);
+ void SendFinished(const std::string& app_id, const OutgoingMessage& message);
void MessageReceived(const std::string& app_id,
const IncomingMessage& message);
void MessagesDeleted(const std::string& app_id);
void MessageSendError(const std::string& app_id,
- const std::string& message_id);
+ const SendErrorDetails& send_error_details);
Delegate* delegate_;
Status status_;
diff --git a/chrome/browser/services/gcm/gcm_event_router.h b/chrome/browser/services/gcm/gcm_event_router.h
index 48b109e..a99e7ad 100644
--- a/chrome/browser/services/gcm/gcm_event_router.h
+++ b/chrome/browser/services/gcm/gcm_event_router.h
@@ -18,9 +18,9 @@ class GCMEventRouter {
virtual void OnMessage(const std::string& app_id,
const GCMClient::IncomingMessage& message) = 0;
virtual void OnMessagesDeleted(const std::string& app_id) = 0;
- virtual void OnSendError(const std::string& app_id,
- const std::string& message_id,
- GCMClient::Result result) = 0;
+ virtual void OnSendError(
+ const std::string& app_id,
+ const GCMClient::SendErrorDetails& send_error_details) = 0;
};
} // namespace gcm
diff --git a/chrome/browser/services/gcm/gcm_profile_service.cc b/chrome/browser/services/gcm/gcm_profile_service.cc
index 73af428..64e0418 100644
--- a/chrome/browser/services/gcm/gcm_profile_service.cc
+++ b/chrome/browser/services/gcm/gcm_profile_service.cc
@@ -253,9 +253,9 @@ class GCMProfileService::IOWorker
const std::string& app_id,
const GCMClient::IncomingMessage& message) OVERRIDE;
virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
- virtual void OnMessageSendError(const std::string& app_id,
- const std::string& message_id,
- GCMClient::Result result) OVERRIDE;
+ virtual void OnMessageSendError(
+ const std::string& app_id,
+ const GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
virtual void OnGCMReady() OVERRIDE;
// Called on IO thread.
@@ -398,8 +398,7 @@ void GCMProfileService::IOWorker::OnMessagesDeleted(const std::string& app_id) {
void GCMProfileService::IOWorker::OnMessageSendError(
const std::string& app_id,
- const std::string& message_id,
- GCMClient::Result result) {
+ const GCMClient::SendErrorDetails& send_error_details) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
content::BrowserThread::PostTask(
@@ -408,8 +407,7 @@ void GCMProfileService::IOWorker::OnMessageSendError(
base::Bind(&GCMProfileService::MessageSendError,
service_,
app_id,
- message_id,
- result));
+ send_error_details));
}
void GCMProfileService::IOWorker::OnGCMReady() {
@@ -1026,16 +1024,16 @@ void GCMProfileService::MessagesDeleted(const std::string& app_id) {
GetEventRouter(app_id)->OnMessagesDeleted(app_id);
}
-void GCMProfileService::MessageSendError(const std::string& app_id,
- const std::string& message_id,
- GCMClient::Result result) {
+void GCMProfileService::MessageSendError(
+ const std::string& app_id,
+ const GCMClient::SendErrorDetails& send_error_details) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
// Drop the event if signed out.
if (username_.empty())
return;
- GetEventRouter(app_id)->OnSendError(app_id, message_id, result);
+ GetEventRouter(app_id)->OnSendError(app_id, send_error_details);
}
void GCMProfileService::GCMClientReady() {
diff --git a/chrome/browser/services/gcm/gcm_profile_service.h b/chrome/browser/services/gcm/gcm_profile_service.h
index 7158780..741dcfc 100644
--- a/chrome/browser/services/gcm/gcm_profile_service.h
+++ b/chrome/browser/services/gcm/gcm_profile_service.h
@@ -186,8 +186,7 @@ class GCMProfileService : public BrowserContextKeyedService,
GCMClient::IncomingMessage message);
void MessagesDeleted(const std::string& app_id);
void MessageSendError(const std::string& app_id,
- const std::string& message_id,
- GCMClient::Result result);
+ const GCMClient::SendErrorDetails& send_error_details);
void GCMClientReady();
// Returns the event router to fire the event for the given app.
diff --git a/chrome/browser/services/gcm/gcm_profile_service_unittest.cc b/chrome/browser/services/gcm/gcm_profile_service_unittest.cc
index 9237851..32d35a5 100644
--- a/chrome/browser/services/gcm/gcm_profile_service_unittest.cc
+++ b/chrome/browser/services/gcm/gcm_profile_service_unittest.cc
@@ -172,10 +172,7 @@ class FakeGCMEventRouter : public GCMEventRouter {
};
explicit FakeGCMEventRouter(Waiter* waiter)
- : waiter_(waiter),
- received_event_(NO_EVENT),
- send_error_result_(GCMClient::SUCCESS) {
- }
+ : waiter_(waiter), received_event_(NO_EVENT) {}
virtual ~FakeGCMEventRouter() {
}
@@ -196,29 +193,37 @@ class FakeGCMEventRouter : public GCMEventRouter {
waiter_->SignalCompleted();
}
- virtual void OnSendError(const std::string& app_id,
- const std::string& message_id,
- GCMClient::Result result) OVERRIDE {
+ virtual void OnSendError(
+ const std::string& app_id,
+ const GCMClient::SendErrorDetails& send_error_details) OVERRIDE {
clear_results();
received_event_ = SEND_ERROR_EVENT;
app_id_ = app_id;
- send_error_message_id_ = message_id;
- send_error_result_ = result;
+ send_error_details_ = send_error_details;
waiter_->SignalCompleted();
}
Event received_event() const { return received_event_; }
const std::string& app_id() const { return app_id_; }
const GCMClient::IncomingMessage& message() const { return message_; }
- const std::string& send_message_id() const { return send_error_message_id_; }
- GCMClient::Result send_result() const { return send_error_result_; }
+ const GCMClient::SendErrorDetails& send_error_details() const {
+ return send_error_details_;
+ }
+ const std::string& send_error_message_id() const {
+ return send_error_details_.message_id;
+ }
+ GCMClient::Result send_error_result() const {
+ return send_error_details_.result;
+ }
+ const GCMClient::MessageData& send_error_data() const {
+ return send_error_details_.additional_data;
+ }
void clear_results() {
received_event_ = NO_EVENT;
app_id_.clear();
message_.data.clear();
- send_error_message_id_.clear();
- send_error_result_ = GCMClient::UNKNOWN_ERROR;
+ send_error_details_ = GCMClient::SendErrorDetails();
}
private:
@@ -226,8 +231,7 @@ class FakeGCMEventRouter : public GCMEventRouter {
Event received_event_;
std::string app_id_;
GCMClient::IncomingMessage message_;
- std::string send_error_message_id_;
- GCMClient::Result send_error_result_;
+ GCMClient::SendErrorDetails send_error_details_;
};
class FakeGCMClientFactory : public GCMClientFactory {
@@ -1076,9 +1080,10 @@ TEST_F(GCMProfileServiceSingleProfileTest, SendError) {
consumer()->gcm_event_router()->received_event());
EXPECT_EQ(kTestingAppId, consumer()->gcm_event_router()->app_id());
EXPECT_EQ(consumer()->send_message_id(),
- consumer()->gcm_event_router()->send_message_id());
+ consumer()->gcm_event_router()->send_error_message_id());
EXPECT_NE(GCMClient::SUCCESS,
- consumer()->gcm_event_router()->send_result());
+ consumer()->gcm_event_router()->send_error_result());
+ EXPECT_EQ(message.data, consumer()->gcm_event_router()->send_error_data());
}
TEST_F(GCMProfileServiceSingleProfileTest, MessageReceived) {
@@ -1488,10 +1493,12 @@ TEST_F(GCMProfileServiceMultiProfileTest, Combined) {
EXPECT_EQ(FakeGCMEventRouter::SEND_ERROR_EVENT,
consumer2()->gcm_event_router()->received_event());
EXPECT_EQ(kTestingAppId, consumer2()->gcm_event_router()->app_id());
- EXPECT_EQ(consumer2()->send_message_id(),
- consumer2()->gcm_event_router()->send_message_id());
+ EXPECT_EQ(out_message4.id,
+ consumer2()->gcm_event_router()->send_error_message_id());
EXPECT_NE(GCMClient::SUCCESS,
- consumer2()->gcm_event_router()->send_result());
+ consumer2()->gcm_event_router()->send_error_result());
+ EXPECT_EQ(out_message4.data,
+ consumer2()->gcm_event_router()->send_error_data());
// Sign in with a different user.
consumer()->SignIn(kTestingUsername3);
diff --git a/chrome/test/data/extensions/api_test/gcm/events/on_send_error.js b/chrome/test/data/extensions/api_test/gcm/events/on_send_error.js
index 8223142..1afcb28 100644
--- a/chrome/test/data/extensions/api_test/gcm/events/on_send_error.js
+++ b/chrome/test/data/extensions/api_test/gcm/events/on_send_error.js
@@ -5,26 +5,24 @@
onload = function() {
chrome.test.runTests([
function onSendError() {
- var errorMessages = [
- 'Asynchronous operation is pending.',
- 'Server error occurred.',
- 'Network error occurred.',
- 'Unknown error occurred.',
- 'Time-to-live exceeded.'
- ];
- var messageIds = [
- 'error_message_1',
- 'error_message_2',
- 'error_message_3',
- 'error_message_4',
- 'error_message_5'
- ];
var currentError = 0;
+ var totalMessages = 0;
var eventHandler = function(error) {
- chrome.test.assertEq(errorMessages[currentError], error.errorMessage);
- chrome.test.assertEq(messageIds[currentError], error.messageId);
+ chrome.test.assertEq(3, Object.keys(error.details).length);
+ chrome.test.assertTrue(
+ error.details.hasOwnProperty("expectedMessageId"));
+ chrome.test.assertTrue(
+ error.details.hasOwnProperty("expectedErrorMessage"));
+ chrome.test.assertEq(error.details.expectedMessageId, error.messageId);
+ chrome.test.assertEq(error.details.expectedErrorMessage,
+ error.errorMessage);
currentError += 1;
- if (currentError == messageIds.length) {
+ var tempTotalMessages = +error.details.totalMessages;
+ if (totalMessages == 0)
+ totalMessages = tempTotalMessages;
+ else
+ chrome.test.assertEq(totalMessages, tempTotalMessages);
+ if (currentError == totalMessages) {
chrome.gcm.onSendError.removeListener(eventHandler);
chrome.test.succeed();
}
diff --git a/google_apis/gcm/gcm_client.cc b/google_apis/gcm/gcm_client.cc
index 78b4e08..3bdd699 100644
--- a/google_apis/gcm/gcm_client.cc
+++ b/google_apis/gcm/gcm_client.cc
@@ -19,6 +19,10 @@ GCMClient::IncomingMessage::IncomingMessage() {
GCMClient::IncomingMessage::~IncomingMessage() {
}
+GCMClient::SendErrorDetails::SendErrorDetails() : result(UNKNOWN_ERROR) {}
+
+GCMClient::SendErrorDetails::~SendErrorDetails() {}
+
GCMClient::GCMStatistics::GCMStatistics()
: gcm_client_created(false), connection_client_created(false) {
}
diff --git a/google_apis/gcm/gcm_client.h b/google_apis/gcm/gcm_client.h
index 7bffa4c..0d68712 100644
--- a/google_apis/gcm/gcm_client.h
+++ b/google_apis/gcm/gcm_client.h
@@ -78,6 +78,16 @@ class GCM_EXPORT GCMClient {
std::string sender_id;
};
+ // Detailed information of the Send Error event.
+ struct GCM_EXPORT SendErrorDetails {
+ SendErrorDetails();
+ ~SendErrorDetails();
+
+ std::string message_id;
+ MessageData additional_data;
+ Result result;
+ };
+
// Internal states and activity statistics of a GCM client.
struct GCM_EXPORT GCMStatistics {
public:
@@ -130,11 +140,10 @@ class GCM_EXPORT GCMClient {
// Called when a message failed to send to the server.
// |app_id|: application ID.
- // |message_id|: ID of the message being sent.
- // |result|: the type of the error if an error occured, success otherwise.
- virtual void OnMessageSendError(const std::string& app_id,
- const std::string& message_id,
- Result result) = 0;
+ // |send_error_detials|: Details of the send error event, like mesasge ID.
+ virtual void OnMessageSendError(
+ const std::string& app_id,
+ const SendErrorDetails& send_error_details) = 0;
// Called when the GCM becomes ready. To get to this state, GCMClient
// finished loading from the GCM store and retrieved the device check-in
diff --git a/google_apis/gcm/gcm_client_impl.cc b/google_apis/gcm/gcm_client_impl.cc
index af20a5a..0c9d0fa 100644
--- a/google_apis/gcm/gcm_client_impl.cc
+++ b/google_apis/gcm/gcm_client_impl.cc
@@ -471,17 +471,21 @@ void GCMClientImpl::OnMessageSentToMCS(int64 user_serial_number,
// TTL_EXCEEDED is singled out here, because it can happen long time after the
// message was sent. That is why it comes as |OnMessageSendError| event rather
- // than |OnSendFinished|. All other errors will be raised immediately, through
- // asynchronous callback.
+ // than |OnSendFinished|. SendErrorDetails.additional_data is left empty.
+ // All other errors will be raised immediately, through asynchronous callback.
// It is expected that TTL_EXCEEDED will be issued for a message that was
// previously issued |OnSendFinished| with status SUCCESS.
// For now, we do not report that the message has been sent and acked
// successfully.
// TODO(jianli): Consider adding UMA for this status.
- if (status == MCSClient::TTL_EXCEEDED)
- delegate_->OnMessageSendError(app_id, message_id, GCMClient::TTL_EXCEEDED);
- else if (status != MCSClient::SENT)
+ if (status == MCSClient::TTL_EXCEEDED) {
+ SendErrorDetails send_error_details;
+ send_error_details.message_id = message_id;
+ send_error_details.result = GCMClient::TTL_EXCEEDED;
+ delegate_->OnMessageSendError(app_id, send_error_details);
+ } else if (status != MCSClient::SENT) {
delegate_->OnSendFinished(app_id, message_id, ToGCMClientResult(status));
+ }
}
void GCMClientImpl::OnMCSError() {
@@ -497,31 +501,31 @@ void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) {
message.GetProtobuf());
DCHECK_EQ(data_message_stanza.device_user_id(), kDefaultUserSerialNumber);
- IncomingMessage incoming_message;
- MessageType message_type = DATA_MESSAGE;
+ // Copying all the data from the stanza to a MessageData object. When present,
+ // keys like kMessageTypeKey or kSendErrorMessageIdKey will be filtered out
+ // later.
+ MessageData message_data;
for (int i = 0; i < data_message_stanza.app_data_size(); ++i) {
std::string key = data_message_stanza.app_data(i).key();
- if (key == kMessageTypeKey)
- message_type = DecodeMessageType(data_message_stanza.app_data(i).value());
- else
- incoming_message.data[key] = data_message_stanza.app_data(i).value();
+ message_data[key] = data_message_stanza.app_data(i).value();
}
+ MessageType message_type = UNKNOWN;
+ MessageData::iterator iter = message_data.find(kMessageTypeKey);
+ if (iter != message_data.end()) {
+ message_type = DecodeMessageType(iter->second);
+ message_data.erase(iter);
+ }
switch (message_type) {
case DATA_MESSAGE:
- incoming_message.sender_id = data_message_stanza.from();
- if (data_message_stanza.has_token())
- incoming_message.collapse_key = data_message_stanza.token();
- delegate_->OnMessageReceived(data_message_stanza.category(),
- incoming_message);
+ HandleIncomingDataMessage(data_message_stanza, message_data);
break;
case DELETED_MESSAGES:
delegate_->OnMessagesDeleted(data_message_stanza.category());
break;
case SEND_ERROR:
- NotifyDelegateOnMessageSendError(
- delegate_, data_message_stanza.category(), incoming_message);
+ HandleIncomingSendError(data_message_stanza, message_data);
break;
case UNKNOWN:
default: // Treat default the same as UNKNOWN.
@@ -531,16 +535,34 @@ void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) {
}
}
-void GCMClientImpl::NotifyDelegateOnMessageSendError(
- GCMClient::Delegate* delegate,
- const std::string& app_id,
- const IncomingMessage& incoming_message) {
- MessageData::const_iterator iter =
- incoming_message.data.find(kSendErrorMessageIdKey);
- std::string message_id;
- if (iter != incoming_message.data.end())
- message_id = iter->second;
- delegate->OnMessageSendError(app_id, message_id, SERVER_ERROR);
+void GCMClientImpl::HandleIncomingDataMessage(
+ const mcs_proto::DataMessageStanza& data_message_stanza,
+ MessageData& message_data) {
+ IncomingMessage incoming_message;
+ incoming_message.sender_id = data_message_stanza.from();
+ if (data_message_stanza.has_token())
+ incoming_message.collapse_key = data_message_stanza.token();
+ incoming_message.data = message_data;
+ delegate_->OnMessageReceived(data_message_stanza.category(),
+ incoming_message);
+}
+
+void GCMClientImpl::HandleIncomingSendError(
+ const mcs_proto::DataMessageStanza& data_message_stanza,
+ MessageData& message_data) {
+ SendErrorDetails send_error_details;
+ send_error_details.additional_data = message_data;
+ send_error_details.result = SERVER_ERROR;
+
+ MessageData::iterator iter =
+ send_error_details.additional_data.find(kSendErrorMessageIdKey);
+ if (iter != send_error_details.additional_data.end()) {
+ send_error_details.message_id = iter->second;
+ send_error_details.additional_data.erase(iter);
+ }
+
+ delegate_->OnMessageSendError(data_message_stanza.category(),
+ send_error_details);
}
void GCMClientImpl::SetMCSClientForTesting(scoped_ptr<MCSClient> mcs_client) {
diff --git a/google_apis/gcm/gcm_client_impl.h b/google_apis/gcm/gcm_client_impl.h
index f7eafcb..d7f47d0 100644
--- a/google_apis/gcm/gcm_client_impl.h
+++ b/google_apis/gcm/gcm_client_impl.h
@@ -161,16 +161,20 @@ class GCM_EXPORT GCMClientImpl : public GCMClient {
// Completes the GCM store destroy request.
void OnGCMStoreDestroyed(bool success);
- // Handles incoming data message and dispatches it the a relevant user
- // delegate.
+ // Handles incoming data message and dispatches it the delegate of this class.
void HandleIncomingMessage(const gcm::MCSMessage& message);
- // Fires OnMessageSendError event on |delegate|, with specified |app_id| and
- // message ID obtained from |incoming_message| if one is available.
- void NotifyDelegateOnMessageSendError(
- GCMClient::Delegate* delegate,
- const std::string& app_id,
- const IncomingMessage& incoming_message);
+ // Fires OnMessageReceived event on the delegate of this class, based on the
+ // details in |data_message_stanza| and |message_data|.
+ void HandleIncomingDataMessage(
+ const mcs_proto::DataMessageStanza& data_message_stanza,
+ MessageData& message_data);
+
+ // Fires OnMessageSendError event on the delegate of this calss, based on the
+ // details in |data_message_stanza| and |message_data|.
+ void HandleIncomingSendError(
+ const mcs_proto::DataMessageStanza& data_message_stanza,
+ MessageData& message_data);
// For testing purpose only.
// Sets an |mcs_client_| for testing. Takes the ownership of |mcs_client|.
diff --git a/google_apis/gcm/gcm_client_impl_unittest.cc b/google_apis/gcm/gcm_client_impl_unittest.cc
index 2e1d4c9..7320c00 100644
--- a/google_apis/gcm/gcm_client_impl_unittest.cc
+++ b/google_apis/gcm/gcm_client_impl_unittest.cc
@@ -140,9 +140,9 @@ class GCMClientImplTest : public testing::Test,
const GCMClient::IncomingMessage& message)
OVERRIDE;
virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
- virtual void OnMessageSendError(const std::string& app_id,
- const std::string& message_id,
- GCMClient::Result result) OVERRIDE;
+ virtual void OnMessageSendError(
+ const std::string& app_id,
+ const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
virtual void OnGCMReady() OVERRIDE;
GCMClientImpl* gcm_client() const { return gcm_client_.get(); }
@@ -160,6 +160,9 @@ class GCMClientImplTest : public testing::Test,
const GCMClient::IncomingMessage& last_message() const {
return last_message_;
}
+ const GCMClient::SendErrorDetails& last_error_details() const {
+ return last_error_details_;
+ }
int64 CurrentTime();
@@ -180,6 +183,7 @@ class GCMClientImplTest : public testing::Test,
std::string last_message_id_;
GCMClient::Result last_result_;
GCMClient::IncomingMessage last_message_;
+ GCMClient::SendErrorDetails last_error_details_;
scoped_ptr<GCMClientImpl> gcm_client_;
scoped_ptr<FakeConnectionFactory> connection_factory_;
@@ -338,13 +342,12 @@ void GCMClientImplTest::OnMessagesDeleted(const std::string& app_id) {
last_app_id_ = app_id;
}
-void GCMClientImplTest::OnMessageSendError(const std::string& app_id,
- const std::string& message_id,
- GCMClient::Result result) {
+void GCMClientImplTest::OnMessageSendError(
+ const std::string& app_id,
+ const gcm::GCMClient::SendErrorDetails& send_error_details) {
last_event_ = MESSAGE_SEND_ERROR;
last_app_id_ = app_id;
- last_message_id_ = message_id;
- last_result_ = result;
+ last_error_details_ = send_error_details;
}
int64 GCMClientImplTest::CurrentTime() {
@@ -406,6 +409,7 @@ TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) {
std::map<std::string, std::string> expected_data;
expected_data["message_type"] = "send_error";
expected_data["google.message_id"] = "007";
+ expected_data["error_details"] = "some details";
MCSMessage message(BuildDownstreamMessage(
"project_id", "app_id", expected_data));
EXPECT_TRUE(message.IsValid());
@@ -413,7 +417,12 @@ TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) {
EXPECT_EQ(MESSAGE_SEND_ERROR, last_event());
EXPECT_EQ("app_id", last_app_id());
- EXPECT_EQ("007", last_message_id());
+ EXPECT_EQ("007", last_error_details().message_id);
+ EXPECT_EQ(1UL, last_error_details().additional_data.size());
+ GCMClient::MessageData::const_iterator iter =
+ last_error_details().additional_data.find("error_details");
+ EXPECT_TRUE(iter != last_error_details().additional_data.end());
+ EXPECT_EQ("some details", iter->second);
}
TEST_F(GCMClientImplTest, DispatchDownstreamMessgaesDeleted) {