Chromium Code Reviews| 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..86599e2392de7158acf25229cef5c4f8bb044800 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 kCategoryForSubtypes[] = "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.category_for_subtypes = kCategoryForSubtypes; |
| 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) { |
| + EXPECT_EQ(GCMClientImpl::READY, gcm_client_state()); |
|
Peter Beverloo
2016/07/22 12:17:03
Sounds like an ASSERT_EQ?
johnme
2016/07/26 17:11:55
Done.
|
| + |
| + 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, kCategoryForSubtypes, 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, kCategoryForSubtypes, 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, kCategoryForSubtypes, 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, kCategoryForSubtypes, 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 |