| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/prefs/pref_service.h" |
| #include "base/run_loop.h" |
| #include "chrome/browser/extensions/api/gcm/gcm_api.h" |
| #include "chrome/browser/extensions/extension_apitest.h" |
| #include "chrome/browser/extensions/extension_gcm_app_handler.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/services/gcm/fake_gcm_profile_service.h" |
| #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "extensions/test/result_catcher.h" |
| |
| using extensions::ResultCatcher; |
| |
| 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 { |
| |
| class GcmApiTest : public ExtensionApiTest { |
| public: |
| GcmApiTest() : fake_gcm_profile_service_(NULL) {} |
| |
| protected: |
| virtual void SetUpCommandLine(CommandLine* command_line) override; |
| virtual void SetUpOnMainThread() override; |
| |
| void StartCollecting(); |
| |
| const Extension* LoadTestExtension(const std::string& extension_path, |
| const std::string& page_name); |
| gcm::FakeGCMProfileService* service() const; |
| |
| private: |
| gcm::FakeGCMProfileService* fake_gcm_profile_service_; |
| }; |
| |
| void GcmApiTest::SetUpCommandLine(CommandLine* command_line) { |
| // We now always create the GCMProfileService instance in |
| // ProfileSyncServiceFactory that is called when a profile is being |
| // initialized. In order to prevent it from being created, we add the switch |
| // to disable the sync logic. |
| command_line->AppendSwitch(switches::kDisableSync); |
| |
| ExtensionApiTest::SetUpCommandLine(command_line); |
| } |
| |
| void GcmApiTest::SetUpOnMainThread() { |
| // Enable GCM such that tests could be run on all channels. |
| browser()->profile()->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true); |
| |
| gcm::GCMProfileServiceFactory::GetInstance()->SetTestingFactory( |
| browser()->profile(), &gcm::FakeGCMProfileService::Build); |
| fake_gcm_profile_service_ = static_cast<gcm::FakeGCMProfileService*>( |
| gcm::GCMProfileServiceFactory::GetInstance()->GetForProfile( |
| browser()->profile())); |
| |
| ExtensionApiTest::SetUpOnMainThread(); |
| } |
| |
| void GcmApiTest::StartCollecting() { |
| service()->set_collect(true); |
| } |
| |
| gcm::FakeGCMProfileService* GcmApiTest::service() const { |
| return fake_gcm_profile_service_; |
| } |
| |
| const Extension* GcmApiTest::LoadTestExtension( |
| const std::string& extension_path, |
| const std::string& page_name) { |
| const Extension* extension = |
| LoadExtension(test_data_dir_.AppendASCII(extension_path)); |
| if (extension) { |
| ui_test_utils::NavigateToURL( |
| browser(), extension->GetResourceURL(page_name)); |
| } |
| return extension; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GcmApiTest, RegisterValidation) { |
| ASSERT_TRUE(RunExtensionTest("gcm/functions/register_validation")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GcmApiTest, Register) { |
| StartCollecting(); |
| ASSERT_TRUE(RunExtensionTest("gcm/functions/register")); |
| |
| const std::vector<std::string>& sender_ids = |
| service()->last_registered_sender_ids(); |
| EXPECT_TRUE(std::find(sender_ids.begin(), sender_ids.end(), "Sender1") != |
| sender_ids.end()); |
| EXPECT_TRUE(std::find(sender_ids.begin(), sender_ids.end(), "Sender2") != |
| sender_ids.end()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GcmApiTest, Unregister) { |
| service()->AddExpectedUnregisterResponse(gcm::GCMClient::SUCCESS); |
| service()->AddExpectedUnregisterResponse(gcm::GCMClient::SERVER_ERROR); |
| |
| ASSERT_TRUE(RunExtensionTest("gcm/functions/unregister")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GcmApiTest, SendValidation) { |
| ASSERT_TRUE(RunExtensionTest("gcm/functions/send")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GcmApiTest, SendMessageData) { |
| StartCollecting(); |
| ASSERT_TRUE(RunExtensionTest("gcm/functions/send_message_data")); |
| |
| EXPECT_EQ("destination-id", service()->last_receiver_id()); |
| const gcm::GCMClient::OutgoingMessage& message = |
| service()->last_sent_message(); |
| gcm::GCMClient::MessageData::const_iterator iter; |
| |
| EXPECT_EQ(100, message.time_to_live); |
| |
| EXPECT_TRUE((iter = message.data.find("key1")) != message.data.end()); |
| EXPECT_EQ("value1", iter->second); |
| |
| EXPECT_TRUE((iter = message.data.find("key2")) != message.data.end()); |
| EXPECT_EQ("value2", iter->second); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GcmApiTest, SendMessageDefaultTTL) { |
| StartCollecting(); |
| ASSERT_TRUE(RunExtensionTest("gcm/functions/send_message_default_ttl")); |
| |
| EXPECT_EQ("destination-id", service()->last_receiver_id()); |
| const gcm::GCMClient::OutgoingMessage& message = |
| service()->last_sent_message(); |
| gcm::GCMClient::MessageData::const_iterator iter; |
| |
| EXPECT_EQ(gcm::GCMClient::OutgoingMessage::kMaximumTTL, message.time_to_live); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GcmApiTest, OnMessagesDeleted) { |
| ResultCatcher catcher; |
| catcher.RestrictToBrowserContext(profile()); |
| |
| const extensions::Extension* extension = |
| LoadTestExtension(kEventsExtension, "on_messages_deleted.html"); |
| ASSERT_TRUE(extension); |
| |
| extensions::ExtensionGCMAppHandler app_handler(profile()); |
| app_handler.OnMessagesDeleted(extension->id()); |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GcmApiTest, OnMessage) { |
| ResultCatcher catcher; |
| catcher.RestrictToBrowserContext(profile()); |
| |
| const extensions::Extension* extension = |
| LoadTestExtension(kEventsExtension, "on_message.html"); |
| ASSERT_TRUE(extension); |
| |
| extensions::ExtensionGCMAppHandler app_handler(profile()); |
| |
| gcm::GCMClient::IncomingMessage message; |
| message.data["property1"] = "value1"; |
| message.data["property2"] = "value2"; |
| // First message is sent without a collapse key. |
| app_handler.OnMessage(extension->id(), message); |
| |
| // Second message carries the same data and a collapse key. |
| message.collapse_key = "collapseKeyValue"; |
| app_handler.OnMessage(extension->id(), message); |
| |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GcmApiTest, OnSendError) { |
| ResultCatcher catcher; |
| catcher.RestrictToBrowserContext(profile()); |
| |
| const extensions::Extension* extension = |
| LoadTestExtension(kEventsExtension, "on_send_error.html"); |
| ASSERT_TRUE(extension); |
| |
| std::string total_expected_messages = "5"; |
| extensions::ExtensionGCMAppHandler app_handler(profile()); |
| app_handler.OnSendError( |
| extension->id(), |
| CreateErrorDetails("error_message_1", |
| gcm::GCMClient::ASYNC_OPERATION_PENDING, |
| total_expected_messages)); |
| app_handler.OnSendError( |
| extension->id(), |
| CreateErrorDetails("error_message_2", |
| gcm::GCMClient::SERVER_ERROR, |
| total_expected_messages)); |
| app_handler.OnSendError( |
| extension->id(), |
| CreateErrorDetails("error_message_3", |
| gcm::GCMClient::NETWORK_ERROR, |
| total_expected_messages)); |
| app_handler.OnSendError( |
| extension->id(), |
| CreateErrorDetails("error_message_4", |
| gcm::GCMClient::UNKNOWN_ERROR, |
| total_expected_messages)); |
| app_handler.OnSendError( |
| extension->id(), |
| CreateErrorDetails("error_message_5", |
| gcm::GCMClient::TTL_EXCEEDED, |
| total_expected_messages)); |
| |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(GcmApiTest, Incognito) { |
| ResultCatcher catcher; |
| catcher.RestrictToBrowserContext(profile()); |
| ResultCatcher incognito_catcher; |
| incognito_catcher.RestrictToBrowserContext( |
| profile()->GetOffTheRecordProfile()); |
| |
| ASSERT_TRUE(RunExtensionTestIncognito("gcm/functions/incognito")); |
| |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| EXPECT_TRUE(incognito_catcher.GetNextResult()) << incognito_catcher.message(); |
| } |
| |
| } // namespace extensions |