diff options
-rw-r--r-- | chrome/browser/extensions/api/gcm/gcm_api.cc | 11 | ||||
-rw-r--r-- | chrome/browser/extensions/api/gcm/gcm_api.h | 6 | ||||
-rw-r--r-- | chrome/browser/extensions/api/gcm/gcm_apitest.cc | 62 | ||||
-rw-r--r-- | chrome/browser/services/gcm/gcm_client_mock.cc | 21 | ||||
-rw-r--r-- | chrome/browser/services/gcm/gcm_client_mock.h | 4 | ||||
-rw-r--r-- | chrome/browser/services/gcm/gcm_event_router.h | 6 | ||||
-rw-r--r-- | chrome/browser/services/gcm/gcm_profile_service.cc | 20 | ||||
-rw-r--r-- | chrome/browser/services/gcm/gcm_profile_service.h | 3 | ||||
-rw-r--r-- | chrome/browser/services/gcm/gcm_profile_service_unittest.cc | 47 | ||||
-rw-r--r-- | chrome/test/data/extensions/api_test/gcm/events/on_send_error.js | 32 | ||||
-rw-r--r-- | google_apis/gcm/gcm_client.cc | 4 | ||||
-rw-r--r-- | google_apis/gcm/gcm_client.h | 19 | ||||
-rw-r--r-- | google_apis/gcm/gcm_client_impl.cc | 78 | ||||
-rw-r--r-- | google_apis/gcm/gcm_client_impl.h | 20 | ||||
-rw-r--r-- | google_apis/gcm/gcm_client_impl_unittest.cc | 27 |
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) { |