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

Unified Diff: components/gcm_driver/gcm_client_impl_unittest.cc

Issue 2111973002: Add support for GCM subtypes to desktop Instance ID implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@iid9push
Patch Set: Fix thestig nits and Chrome OS compile Created 4 years, 4 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_unittest.cc
diff --git a/components/gcm_driver/gcm_client_impl_unittest.cc b/components/gcm_driver/gcm_client_impl_unittest.cc
index 0368e7648539f327d37c0c8566ee9d7dd66bcc75..ea99e71a37badf9abd3aee90d87003ea6befbdb8 100644
--- a/components/gcm_driver/gcm_client_impl_unittest.cc
+++ b/components/gcm_driver/gcm_client_impl_unittest.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include <initializer_list>
#include <memory>
#include "base/command_line.h"
@@ -29,9 +30,12 @@
#include "google_apis/gcm/protocol/android_checkin.pb.h"
#include "google_apis/gcm/protocol/checkin.pb.h"
#include "google_apis/gcm/protocol/mcs.pb.h"
+#include "net/test/gtest_util.h"
+#include "net/test/scoped_disable_exit_on_dfatal.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest-spi.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace gcm {
@@ -55,6 +59,7 @@ const uint64_t kDeviceSecurityToken = 12345;
const uint64_t kDeviceAndroidId2 = 11111;
const uint64_t kDeviceSecurityToken2 = 2222;
const int64_t kSettingsCheckinInterval = 16 * 60 * 60;
+const char kProductCategoryForSubtypes[] = "com.chrome.stable:macosx";
const char kAppId[] = "app_id";
const char kSender[] = "project_id";
const char kSender2[] = "project_id2";
@@ -70,12 +75,13 @@ const char kDeleteTokenResponse[] = "token=foo";
// Helper for building arbitrary data messages.
MCSMessage BuildDownstreamMessage(
const std::string& project_id,
- const std::string& app_id,
+ const std::string& category,
+ const std::string& subtype,
const std::map<std::string, std::string>& data,
const std::string& raw_data) {
mcs_proto::DataMessageStanza data_message;
data_message.set_from(project_id);
- data_message.set_category(app_id);
+ data_message.set_category(category);
for (std::map<std::string, std::string>::const_iterator iter = data.begin();
iter != data.end();
++iter) {
@@ -83,6 +89,11 @@ MCSMessage BuildDownstreamMessage(
app_data->set_key(iter->first);
app_data->set_value(iter->second);
}
+ if (!subtype.empty()) {
+ mcs_proto::AppData* app_data = data_message.add_app_data();
+ app_data->set_key("subtype");
+ app_data->set_value(subtype);
+ }
data_message.set_raw_data(raw_data);
return MCSMessage(kDataMessageStanzaTag, data_message);
}
@@ -531,6 +542,7 @@ void GCMClientImplTest::InitializeGCMClient() {
// Actual initialization.
GCMClient::ChromeBuildInfo chrome_build_info;
chrome_build_info.version = kChromeVersion;
+ chrome_build_info.product_category_for_subtypes = kProductCategoryForSubtypes;
gcm_client_->Initialize(chrome_build_info, gcm_store_path(), task_runner_,
url_request_context_getter_,
base::WrapUnique<Encryptor>(new FakeEncryptor), this);
@@ -818,8 +830,9 @@ TEST_F(GCMClientImplTest, DispatchDownstreamMessage) {
expected_data["key2"] = "value2";
// Message for kSender will be received.
- MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data,
- std::string() /* raw_data */));
+ MCSMessage message(
+ BuildDownstreamMessage(kSender, kAppId, std::string() /* subtype */,
+ expected_data, std::string() /* raw_data */));
EXPECT_TRUE(message.IsValid());
ReceiveMessageFromMCS(message);
@@ -833,8 +846,9 @@ TEST_F(GCMClientImplTest, DispatchDownstreamMessage) {
reset_last_event();
// Message for kSender2 will be received.
- MCSMessage message2(BuildDownstreamMessage(kSender2, kAppId, expected_data,
- std::string() /* raw_data */));
+ MCSMessage message2(
+ BuildDownstreamMessage(kSender2, kAppId, std::string() /* subtype */,
+ expected_data, std::string() /* raw_data */));
EXPECT_TRUE(message2.IsValid());
ReceiveMessageFromMCS(message2);
@@ -847,8 +861,9 @@ TEST_F(GCMClientImplTest, DispatchDownstreamMessage) {
reset_last_event();
// Message from kSender3 will be dropped.
- MCSMessage message3(BuildDownstreamMessage(kSender3, kAppId, expected_data,
- std::string() /* raw_data */));
+ MCSMessage message3(
+ BuildDownstreamMessage(kSender3, kAppId, std::string() /* subtype */,
+ expected_data, std::string() /* raw_data */));
EXPECT_TRUE(message3.IsValid());
ReceiveMessageFromMCS(message3);
@@ -862,8 +877,8 @@ TEST_F(GCMClientImplTest, DispatchDownstreamMessageRawData) {
std::map<std::string, std::string> expected_data;
- MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data,
- kRawData));
+ MCSMessage message(BuildDownstreamMessage(
+ kSender, kAppId, std::string() /* subtype */, expected_data, kRawData));
EXPECT_TRUE(message.IsValid());
ReceiveMessageFromMCS(message);
@@ -879,8 +894,9 @@ TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) {
expected_data["message_type"] = "send_error";
expected_data["google.message_id"] = "007";
expected_data["error_details"] = "some details";
- MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data,
- std::string() /* raw_data */));
+ MCSMessage message(
+ BuildDownstreamMessage(kSender, kAppId, std::string() /* subtype */,
+ expected_data, std::string() /* raw_data */));
EXPECT_TRUE(message.IsValid());
ReceiveMessageFromMCS(message);
@@ -897,8 +913,9 @@ TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) {
TEST_F(GCMClientImplTest, DispatchDownstreamMessgaesDeleted) {
std::map<std::string, std::string> expected_data;
expected_data["message_type"] = "deleted_messages";
- MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data,
- std::string() /* raw_data */));
+ MCSMessage message(
+ BuildDownstreamMessage(kSender, kAppId, std::string() /* subtype */,
+ expected_data, std::string() /* raw_data */));
EXPECT_TRUE(message.IsValid());
ReceiveMessageFromMCS(message);
@@ -1392,13 +1409,16 @@ class GCMClientInstanceIDTest : public GCMClientImplTest {
const std::string& instance_id);
void RemoveInstanceID(const std::string& app_id);
void GetToken(const std::string& app_id,
+ bool use_subtype,
const std::string& authorized_entity,
const std::string& scope);
void DeleteToken(const std::string& app_id,
+ bool use_subtype,
const std::string& authorized_entity,
const std::string& scope);
void CompleteDeleteToken();
bool ExistsToken(const std::string& app_id,
+ bool use_subtype,
const std::string& authorized_entity,
const std::string& scope) const;
};
@@ -1419,11 +1439,13 @@ void GCMClientInstanceIDTest::RemoveInstanceID(const std::string& app_id) {
}
void GCMClientInstanceIDTest::GetToken(const std::string& app_id,
+ bool use_subtype,
const std::string& authorized_entity,
const std::string& scope) {
std::unique_ptr<InstanceIDTokenInfo> instance_id_info(
new InstanceIDTokenInfo);
instance_id_info->app_id = app_id;
+ instance_id_info->use_subtype = use_subtype;
instance_id_info->authorized_entity = authorized_entity;
instance_id_info->scope = scope;
gcm_client()->Register(
@@ -1431,11 +1453,13 @@ void GCMClientInstanceIDTest::GetToken(const std::string& app_id,
}
void GCMClientInstanceIDTest::DeleteToken(const std::string& app_id,
+ bool use_subtype,
const std::string& authorized_entity,
const std::string& scope) {
std::unique_ptr<InstanceIDTokenInfo> instance_id_info(
new InstanceIDTokenInfo);
instance_id_info->app_id = app_id;
+ instance_id_info->use_subtype = use_subtype;
instance_id_info->authorized_entity = authorized_entity;
instance_id_info->scope = scope;
gcm_client()->Unregister(
@@ -1454,50 +1478,98 @@ void GCMClientInstanceIDTest::CompleteDeleteToken() {
}
bool GCMClientInstanceIDTest::ExistsToken(const std::string& app_id,
+ bool use_subtype,
const std::string& authorized_entity,
const std::string& scope) const {
std::unique_ptr<InstanceIDTokenInfo> instance_id_info(
new InstanceIDTokenInfo);
instance_id_info->app_id = app_id;
+ instance_id_info->use_subtype = use_subtype;
instance_id_info->authorized_entity = authorized_entity;
instance_id_info->scope = scope;
- return gcm_client()->registrations_.count(
- make_linked_ptr<RegistrationInfo>(instance_id_info.release())) > 0;
+ RegistrationInfoMap::const_iterator registrations_iter =
+ gcm_client()->registrations_.find(
+ make_linked_ptr<RegistrationInfo>(instance_id_info.release()));
+ if (registrations_iter == gcm_client()->registrations_.end())
+ return false;
+ const InstanceIDTokenInfo* instance_id_token_info =
+ InstanceIDTokenInfo::FromRegistrationInfo(
+ registrations_iter->first.get());
+ // Compare use_subtype since RegistrationInfoComparer::operator() does not.
+ return instance_id_token_info &&
+ instance_id_token_info->use_subtype == use_subtype;
}
TEST_F(GCMClientInstanceIDTest, GetToken) {
AddInstanceID(kAppId, kInstanceID);
// Get a token.
- EXPECT_FALSE(ExistsToken(kAppId, kSender, kScope));
- GetToken(kAppId, kSender, kScope);
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
+ GetToken(kAppId, false /* use_subtype */, kSender, kScope);
ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token1"));
EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
EXPECT_EQ(kAppId, last_app_id());
EXPECT_EQ("token1", last_registration_id());
EXPECT_EQ(GCMClient::SUCCESS, last_result());
- EXPECT_TRUE(ExistsToken(kAppId, kSender, kScope));
+ EXPECT_TRUE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
// Get another token.
- EXPECT_FALSE(ExistsToken(kAppId, kSender2, kScope));
- GetToken(kAppId, kSender2, kScope);
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender2, kScope));
+ GetToken(kAppId, false /* use_subtype */, kSender2, kScope);
ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token2"));
EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
EXPECT_EQ(kAppId, last_app_id());
EXPECT_EQ("token2", last_registration_id());
EXPECT_EQ(GCMClient::SUCCESS, last_result());
- EXPECT_TRUE(ExistsToken(kAppId, kSender2, kScope));
+ EXPECT_TRUE(ExistsToken(kAppId, false /* use_subtype */, kSender2, kScope));
// The 1st token still exists.
- EXPECT_TRUE(ExistsToken(kAppId, kSender, kScope));
+ EXPECT_TRUE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
+}
+
+TEST_F(GCMClientInstanceIDTest, GetTokenWithAndWithoutSubtype) {
+ ASSERT_EQ(GCMClientImpl::READY, gcm_client_state());
+
+ AddInstanceID(kAppId, kInstanceID);
+
+ EXPECT_FALSE(ExistsToken(kAppId, false, kSender, kScope));
+ EXPECT_FALSE(ExistsToken(kAppId, true, kSender, kScope));
+
+ DLOG(INFO) << "THIS TEST USES EXPECT_DCHECK - IGNORE STACKTRACES LOGGED DUE "
+ "TO \"Registering the same Instance ID token both with and "
+ "without subtypes is not supported\" SINCE THOSE ARE EXPECTED";
+
+ for (bool use_subtype : {false, true}) {
+ // Get a token.
+ GetToken(kAppId, use_subtype, kSender, kScope);
+ ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token1"));
+ EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
+ EXPECT_EQ(kAppId, last_app_id());
+ EXPECT_EQ("token1", last_registration_id());
+ EXPECT_EQ(GCMClient::SUCCESS, last_result());
+ EXPECT_TRUE(ExistsToken(kAppId, use_subtype, kSender, kScope));
+ EXPECT_FALSE(ExistsToken(kAppId, !use_subtype, kSender, kScope));
+
+ // Getting the same token with opposite value of use_subtype should assert.
+ EXPECT_DCHECK(
+ { GetToken(kAppId, !use_subtype, kSender, kScope); },
+ "Registering the same Instance ID token both with and without subtypes "
+ "is not supported");
+
+ // Deletion should work. Clean up for next loop iteration.
+ DeleteToken(kAppId, use_subtype, kSender, kScope);
+ ASSERT_NO_FATAL_FAILURE(CompleteDeleteToken());
+ EXPECT_FALSE(ExistsToken(kAppId, use_subtype, kSender, kScope));
+ EXPECT_FALSE(ExistsToken(kAppId, !use_subtype, kSender, kScope));
+ }
}
TEST_F(GCMClientInstanceIDTest, DeleteInvalidToken) {
AddInstanceID(kAppId, kInstanceID);
// Delete an invalid token.
- DeleteToken(kAppId, "Foo@#$", kScope);
+ DeleteToken(kAppId, false /* use_subtype */, "Foo@#$", kScope);
PumpLoopUntilIdle();
EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
@@ -1507,7 +1579,7 @@ TEST_F(GCMClientInstanceIDTest, DeleteInvalidToken) {
reset_last_event();
// Delete a non-existing token.
- DeleteToken(kAppId, kSender, kScope);
+ DeleteToken(kAppId, false /* use_subtype */, kSender, kScope);
PumpLoopUntilIdle();
EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
@@ -1519,61 +1591,61 @@ TEST_F(GCMClientInstanceIDTest, DeleteSingleToken) {
AddInstanceID(kAppId, kInstanceID);
// Get a token.
- EXPECT_FALSE(ExistsToken(kAppId, kSender, kScope));
- GetToken(kAppId, kSender, kScope);
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
+ GetToken(kAppId, false /* use_subtype */, kSender, kScope);
ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token1"));
EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
EXPECT_EQ(kAppId, last_app_id());
EXPECT_EQ("token1", last_registration_id());
EXPECT_EQ(GCMClient::SUCCESS, last_result());
- EXPECT_TRUE(ExistsToken(kAppId, kSender, kScope));
+ EXPECT_TRUE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
reset_last_event();
// Get another token.
- EXPECT_FALSE(ExistsToken(kAppId, kSender2, kScope));
- GetToken(kAppId, kSender2, kScope);
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender2, kScope));
+ GetToken(kAppId, false /* use_subtype */, kSender2, kScope);
ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token2"));
EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
EXPECT_EQ(kAppId, last_app_id());
EXPECT_EQ("token2", last_registration_id());
EXPECT_EQ(GCMClient::SUCCESS, last_result());
- EXPECT_TRUE(ExistsToken(kAppId, kSender2, kScope));
+ EXPECT_TRUE(ExistsToken(kAppId, false /* use_subtype */, kSender2, kScope));
// The 1st token still exists.
- EXPECT_TRUE(ExistsToken(kAppId, kSender, kScope));
+ EXPECT_TRUE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
reset_last_event();
// Delete the 2nd token.
- DeleteToken(kAppId, kSender2, kScope);
+ DeleteToken(kAppId, false /* use_subtype */, kSender2, kScope);
ASSERT_NO_FATAL_FAILURE(CompleteDeleteToken());
EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
EXPECT_EQ(kAppId, last_app_id());
EXPECT_EQ(GCMClient::SUCCESS, last_result());
// The 2nd token is gone while the 1st token still exists.
- EXPECT_TRUE(ExistsToken(kAppId, kSender, kScope));
- EXPECT_FALSE(ExistsToken(kAppId, kSender2, kScope));
+ EXPECT_TRUE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender2, kScope));
reset_last_event();
// Delete the 1st token.
- DeleteToken(kAppId, kSender, kScope);
+ DeleteToken(kAppId, false /* use_subtype */, kSender, kScope);
ASSERT_NO_FATAL_FAILURE(CompleteDeleteToken());
EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
EXPECT_EQ(kAppId, last_app_id());
EXPECT_EQ(GCMClient::SUCCESS, last_result());
// Both tokens are gone now.
- EXPECT_FALSE(ExistsToken(kAppId, kSender, kScope));
- EXPECT_FALSE(ExistsToken(kAppId, kSender, kScope));
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
reset_last_event();
// Trying to delete the token again will get an error.
- DeleteToken(kAppId, kSender, kScope);
+ DeleteToken(kAppId, false /* use_subtype */, kSender, kScope);
PumpLoopUntilIdle();
EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
@@ -1585,50 +1657,50 @@ TEST_F(GCMClientInstanceIDTest, DeleteAllTokens) {
AddInstanceID(kAppId, kInstanceID);
// Get a token.
- EXPECT_FALSE(ExistsToken(kAppId, kSender, kScope));
- GetToken(kAppId, kSender, kScope);
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
+ GetToken(kAppId, false /* use_subtype */, kSender, kScope);
ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token1"));
EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
EXPECT_EQ(kAppId, last_app_id());
EXPECT_EQ("token1", last_registration_id());
EXPECT_EQ(GCMClient::SUCCESS, last_result());
- EXPECT_TRUE(ExistsToken(kAppId, kSender, kScope));
+ EXPECT_TRUE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
reset_last_event();
// Get another token.
- EXPECT_FALSE(ExistsToken(kAppId, kSender2, kScope));
- GetToken(kAppId, kSender2, kScope);
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender2, kScope));
+ GetToken(kAppId, false /* use_subtype */, kSender2, kScope);
ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token2"));
EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
EXPECT_EQ(kAppId, last_app_id());
EXPECT_EQ("token2", last_registration_id());
EXPECT_EQ(GCMClient::SUCCESS, last_result());
- EXPECT_TRUE(ExistsToken(kAppId, kSender2, kScope));
+ EXPECT_TRUE(ExistsToken(kAppId, false /* use_subtype */, kSender2, kScope));
// The 1st token still exists.
- EXPECT_TRUE(ExistsToken(kAppId, kSender, kScope));
+ EXPECT_TRUE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
reset_last_event();
// Delete all tokens.
- DeleteToken(kAppId, "*", "*");
+ DeleteToken(kAppId, false /* use_subtype */, "*", "*");
ASSERT_NO_FATAL_FAILURE(CompleteDeleteToken());
EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
EXPECT_EQ(kAppId, last_app_id());
EXPECT_EQ(GCMClient::SUCCESS, last_result());
// All tokens are gone now.
- EXPECT_FALSE(ExistsToken(kAppId, kSender, kScope));
- EXPECT_FALSE(ExistsToken(kAppId, kSender, kScope));
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender, kScope));
+ EXPECT_FALSE(ExistsToken(kAppId, false /* use_subtype */, kSender2, kScope));
}
TEST_F(GCMClientInstanceIDTest, DeleteAllTokensBeforeGetAnyToken) {
AddInstanceID(kAppId, kInstanceID);
// Delete all tokens without getting a token first.
- DeleteToken(kAppId, "*", "*");
+ DeleteToken(kAppId, false /* use_subtype */, "*", "*");
// No need to call CompleteDeleteToken since unregistration request should
// not be triggered.
PumpLoopUntilIdle();
@@ -1638,4 +1710,153 @@ TEST_F(GCMClientInstanceIDTest, DeleteAllTokensBeforeGetAnyToken) {
EXPECT_EQ(GCMClient::SUCCESS, last_result());
}
+TEST_F(GCMClientInstanceIDTest, DispatchDownstreamMessageWithoutSubtype) {
+ AddInstanceID(kAppId, kInstanceID);
+ GetToken(kAppId, false /* use_subtype */, kSender, kScope);
+ ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token1"));
+ GetToken(kAppId, false /* use_subtype */, kSender2, kScope);
+ ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token2"));
+
+ std::map<std::string, std::string> expected_data;
+
+ // Message for kSender with a subtype will be dropped.
+ MCSMessage message0(BuildDownstreamMessage(
+ kSender, kProductCategoryForSubtypes, kAppId /* subtype */, expected_data,
+ std::string() /* raw_data */));
+ EXPECT_TRUE(message0.IsValid());
+ ReceiveMessageFromMCS(message0);
+
+ EXPECT_NE(MESSAGE_RECEIVED, last_event());
+
+ reset_last_event();
+
+ // Message for kSender will be received.
+ MCSMessage message1(
+ BuildDownstreamMessage(kSender, kAppId, std::string() /* subtype */,
+ expected_data, std::string() /* raw_data */));
+ EXPECT_TRUE(message1.IsValid());
+ ReceiveMessageFromMCS(message1);
+
+ EXPECT_EQ(MESSAGE_RECEIVED, last_event());
+ EXPECT_EQ(kAppId, last_app_id());
+ EXPECT_EQ(expected_data.size(), last_message().data.size());
+ EXPECT_EQ(expected_data, last_message().data);
+ EXPECT_EQ(kSender, last_message().sender_id);
+
+ reset_last_event();
+
+ // Message for kSender2 will be received.
+ MCSMessage message2(
+ BuildDownstreamMessage(kSender2, kAppId, std::string() /* subtype */,
+ expected_data, std::string() /* raw_data */));
+ EXPECT_TRUE(message2.IsValid());
+ ReceiveMessageFromMCS(message2);
+
+ EXPECT_EQ(MESSAGE_RECEIVED, last_event());
+ EXPECT_EQ(kAppId, last_app_id());
+ EXPECT_EQ(expected_data.size(), last_message().data.size());
+ EXPECT_EQ(expected_data, last_message().data);
+ EXPECT_EQ(kSender2, last_message().sender_id);
+
+ reset_last_event();
+
+ // Message from kSender3 will be dropped.
+ MCSMessage message3(
+ BuildDownstreamMessage(kSender3, kAppId, std::string() /* subtype */,
+ expected_data, std::string() /* raw_data */));
+ EXPECT_TRUE(message3.IsValid());
+ ReceiveMessageFromMCS(message3);
+
+ EXPECT_NE(MESSAGE_RECEIVED, last_event());
+ EXPECT_NE(kAppId, last_app_id());
+}
+
+TEST_F(GCMClientInstanceIDTest, DispatchDownstreamMessageWithSubtype) {
+ AddInstanceID(kAppId, kInstanceID);
+ GetToken(kAppId, true /* use_subtype */, kSender, kScope);
+ ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token1"));
+ GetToken(kAppId, true /* use_subtype */, kSender2, kScope);
+ ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token2"));
+
+ std::map<std::string, std::string> expected_data;
+
+ // Message for kSender without a subtype will be dropped.
+ MCSMessage message0(
+ BuildDownstreamMessage(kSender, kAppId, std::string() /* subtype */,
+ expected_data, std::string() /* raw_data */));
+ EXPECT_TRUE(message0.IsValid());
+ ReceiveMessageFromMCS(message0);
+
+ EXPECT_NE(MESSAGE_RECEIVED, last_event());
+
+ reset_last_event();
+
+ // Message for kSender will be received.
+ MCSMessage message1(BuildDownstreamMessage(
+ kSender, kProductCategoryForSubtypes, kAppId /* subtype */, expected_data,
+ std::string() /* raw_data */));
+ EXPECT_TRUE(message1.IsValid());
+ ReceiveMessageFromMCS(message1);
+
+ EXPECT_EQ(MESSAGE_RECEIVED, last_event());
+ EXPECT_EQ(kAppId, last_app_id());
+ EXPECT_EQ(expected_data.size(), last_message().data.size());
+ EXPECT_EQ(expected_data, last_message().data);
+ EXPECT_EQ(kSender, last_message().sender_id);
+
+ reset_last_event();
+
+ // Message for kSender2 will be received.
+ MCSMessage message2(BuildDownstreamMessage(
+ kSender2, kProductCategoryForSubtypes, kAppId /* subtype */,
+ expected_data, std::string() /* raw_data */));
+ EXPECT_TRUE(message2.IsValid());
+ ReceiveMessageFromMCS(message2);
+
+ EXPECT_EQ(MESSAGE_RECEIVED, last_event());
+ EXPECT_EQ(kAppId, last_app_id());
+ EXPECT_EQ(expected_data.size(), last_message().data.size());
+ EXPECT_EQ(expected_data, last_message().data);
+ EXPECT_EQ(kSender2, last_message().sender_id);
+
+ reset_last_event();
+
+ // Message from kSender3 will be dropped.
+ MCSMessage message3(BuildDownstreamMessage(
+ kSender3, kProductCategoryForSubtypes, kAppId /* subtype */,
+ expected_data, std::string() /* raw_data */));
+ EXPECT_TRUE(message3.IsValid());
+ ReceiveMessageFromMCS(message3);
+
+ EXPECT_NE(MESSAGE_RECEIVED, last_event());
+ EXPECT_NE(kAppId, last_app_id());
+}
+
+TEST_F(GCMClientInstanceIDTest, DispatchDownstreamMessageWithFakeSubtype) {
+ AddInstanceID("victim_app_id", "iid_1");
+ GetToken("victim_app_id", true /* use_subtype */, kSender, kScope);
+ ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token1"));
+
+ AddInstanceID("evil_app_id", "iid_2");
+ GetToken("evil_app_id", false /* use_subtype */, kSender, kScope);
+ ASSERT_NO_FATAL_FAILURE(CompleteRegistration("token2"));
+
+ std::map<std::string, std::string> expected_data;
+
+ // Message for "evil_app_id" should be delivered to evil app rather than
+ // victim app, despite the malicious subtype property attempting to
+ // impersonate victim app.
+ MCSMessage message(BuildDownstreamMessage(
+ kSender, "evil_app_id" /* category */, "victim_app_id" /* subtype */,
+ expected_data, std::string() /* raw_data */));
+ EXPECT_TRUE(message.IsValid());
+ ReceiveMessageFromMCS(message);
+
+ EXPECT_EQ(MESSAGE_RECEIVED, last_event());
+ EXPECT_EQ("evil_app_id", last_app_id());
+ EXPECT_EQ(expected_data.size(), last_message().data.size());
+ EXPECT_EQ(expected_data, last_message().data);
+ EXPECT_EQ(kSender, last_message().sender_id);
+}
+
} // namespace gcm

Powered by Google App Engine
This is Rietveld 408576698