Home | History | Annotate | Download | only in gcm
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/prefs/pref_service.h"
      6 #include "base/run_loop.h"
      7 #include "chrome/browser/extensions/api/gcm/gcm_api.h"
      8 #include "chrome/browser/extensions/extension_apitest.h"
      9 #include "chrome/browser/extensions/extension_gcm_app_handler.h"
     10 #include "chrome/browser/profiles/profile.h"
     11 #include "chrome/browser/services/gcm/fake_gcm_profile_service.h"
     12 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
     13 #include "chrome/common/chrome_switches.h"
     14 #include "chrome/common/pref_names.h"
     15 #include "chrome/test/base/ui_test_utils.h"
     16 #include "extensions/test/result_catcher.h"
     17 
     18 using extensions::ResultCatcher;
     19 
     20 namespace {
     21 
     22 const char kEventsExtension[] = "gcm/events";
     23 
     24 gcm::GCMClient::SendErrorDetails CreateErrorDetails(
     25     const std::string& message_id,
     26     const gcm::GCMClient::Result result,
     27     const std::string& total_messages) {
     28   gcm::GCMClient::SendErrorDetails error;
     29   error.message_id = message_id;
     30   error.result = result;
     31   error.additional_data["expectedMessageId"] = message_id;
     32   switch (result) {
     33     case gcm::GCMClient::ASYNC_OPERATION_PENDING:
     34       error.additional_data["expectedErrorMessage"] =
     35           "Asynchronous operation is pending.";
     36       break;
     37     case gcm::GCMClient::SERVER_ERROR:
     38       error.additional_data["expectedErrorMessage"] = "Server error occurred.";
     39       break;
     40     case gcm::GCMClient::NETWORK_ERROR:
     41       error.additional_data["expectedErrorMessage"] = "Network error occurred.";
     42       break;
     43     case gcm::GCMClient::TTL_EXCEEDED:
     44       error.additional_data["expectedErrorMessage"] = "Time-to-live exceeded.";
     45       break;
     46     case gcm::GCMClient::UNKNOWN_ERROR:
     47     default:  // Default case is the same as UNKNOWN_ERROR
     48       error.additional_data["expectedErrorMessage"] = "Unknown error occurred.";
     49       break;
     50   }
     51   error.additional_data["totalMessages"] = total_messages;
     52   return error;
     53 }
     54 
     55 }  // namespace
     56 
     57 namespace extensions {
     58 
     59 class GcmApiTest : public ExtensionApiTest {
     60  public:
     61   GcmApiTest() : fake_gcm_profile_service_(NULL) {}
     62 
     63  protected:
     64   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
     65   virtual void SetUpOnMainThread() OVERRIDE;
     66 
     67   void StartCollecting();
     68 
     69   const Extension* LoadTestExtension(const std::string& extension_path,
     70                                      const std::string& page_name);
     71   gcm::FakeGCMProfileService* service() const;
     72 
     73  private:
     74   gcm::FakeGCMProfileService* fake_gcm_profile_service_;
     75 };
     76 
     77 void GcmApiTest::SetUpCommandLine(CommandLine* command_line) {
     78   // We now always create the GCMProfileService instance in
     79   // ProfileSyncServiceFactory that is called when a profile is being
     80   // initialized. In order to prevent it from being created, we add the switch
     81   // to disable the sync logic.
     82   command_line->AppendSwitch(switches::kDisableSync);
     83 
     84   ExtensionApiTest::SetUpCommandLine(command_line);
     85 }
     86 
     87 void GcmApiTest::SetUpOnMainThread() {
     88   // Enable GCM such that tests could be run on all channels.
     89   browser()->profile()->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true);
     90 
     91   gcm::GCMProfileServiceFactory::GetInstance()->SetTestingFactory(
     92       browser()->profile(), &gcm::FakeGCMProfileService::Build);
     93   fake_gcm_profile_service_ = static_cast<gcm::FakeGCMProfileService*>(
     94       gcm::GCMProfileServiceFactory::GetInstance()->GetForProfile(
     95           browser()->profile()));
     96 
     97   ExtensionApiTest::SetUpOnMainThread();
     98 }
     99 
    100 void GcmApiTest::StartCollecting() {
    101   service()->set_collect(true);
    102 }
    103 
    104 gcm::FakeGCMProfileService* GcmApiTest::service() const {
    105   return fake_gcm_profile_service_;
    106 }
    107 
    108 const Extension* GcmApiTest::LoadTestExtension(
    109     const std::string& extension_path,
    110     const std::string& page_name) {
    111   const Extension* extension =
    112       LoadExtension(test_data_dir_.AppendASCII(extension_path));
    113   if (extension) {
    114     ui_test_utils::NavigateToURL(
    115         browser(), extension->GetResourceURL(page_name));
    116   }
    117   return extension;
    118 }
    119 
    120 IN_PROC_BROWSER_TEST_F(GcmApiTest, RegisterValidation) {
    121   ASSERT_TRUE(RunExtensionTest("gcm/functions/register_validation"));
    122 }
    123 
    124 IN_PROC_BROWSER_TEST_F(GcmApiTest, Register) {
    125   StartCollecting();
    126   ASSERT_TRUE(RunExtensionTest("gcm/functions/register"));
    127 
    128   const std::vector<std::string>& sender_ids =
    129       service()->last_registered_sender_ids();
    130   EXPECT_TRUE(std::find(sender_ids.begin(), sender_ids.end(), "Sender1") !=
    131                   sender_ids.end());
    132   EXPECT_TRUE(std::find(sender_ids.begin(), sender_ids.end(), "Sender2") !=
    133                   sender_ids.end());
    134 }
    135 
    136 IN_PROC_BROWSER_TEST_F(GcmApiTest, Unregister) {
    137   service()->AddExpectedUnregisterResponse(gcm::GCMClient::SUCCESS);
    138   service()->AddExpectedUnregisterResponse(gcm::GCMClient::SERVER_ERROR);
    139 
    140   ASSERT_TRUE(RunExtensionTest("gcm/functions/unregister"));
    141 }
    142 
    143 IN_PROC_BROWSER_TEST_F(GcmApiTest, SendValidation) {
    144   ASSERT_TRUE(RunExtensionTest("gcm/functions/send"));
    145 }
    146 
    147 IN_PROC_BROWSER_TEST_F(GcmApiTest, SendMessageData) {
    148   StartCollecting();
    149   ASSERT_TRUE(RunExtensionTest("gcm/functions/send_message_data"));
    150 
    151   EXPECT_EQ("destination-id", service()->last_receiver_id());
    152   const gcm::GCMClient::OutgoingMessage& message =
    153       service()->last_sent_message();
    154   gcm::GCMClient::MessageData::const_iterator iter;
    155 
    156   EXPECT_EQ(100, message.time_to_live);
    157 
    158   EXPECT_TRUE((iter = message.data.find("key1")) != message.data.end());
    159   EXPECT_EQ("value1", iter->second);
    160 
    161   EXPECT_TRUE((iter = message.data.find("key2")) != message.data.end());
    162   EXPECT_EQ("value2", iter->second);
    163 }
    164 
    165 IN_PROC_BROWSER_TEST_F(GcmApiTest, SendMessageDefaultTTL) {
    166   StartCollecting();
    167   ASSERT_TRUE(RunExtensionTest("gcm/functions/send_message_default_ttl"));
    168 
    169   EXPECT_EQ("destination-id", service()->last_receiver_id());
    170   const gcm::GCMClient::OutgoingMessage& message =
    171       service()->last_sent_message();
    172   gcm::GCMClient::MessageData::const_iterator iter;
    173 
    174   EXPECT_EQ(gcm::GCMClient::OutgoingMessage::kMaximumTTL, message.time_to_live);
    175 }
    176 
    177 IN_PROC_BROWSER_TEST_F(GcmApiTest, OnMessagesDeleted) {
    178   ResultCatcher catcher;
    179   catcher.RestrictToBrowserContext(profile());
    180 
    181   const extensions::Extension* extension =
    182       LoadTestExtension(kEventsExtension, "on_messages_deleted.html");
    183   ASSERT_TRUE(extension);
    184 
    185   extensions::ExtensionGCMAppHandler app_handler(profile());
    186   app_handler.OnMessagesDeleted(extension->id());
    187   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    188 }
    189 
    190 IN_PROC_BROWSER_TEST_F(GcmApiTest, OnMessage) {
    191   ResultCatcher catcher;
    192   catcher.RestrictToBrowserContext(profile());
    193 
    194   const extensions::Extension* extension =
    195       LoadTestExtension(kEventsExtension, "on_message.html");
    196   ASSERT_TRUE(extension);
    197 
    198   extensions::ExtensionGCMAppHandler app_handler(profile());
    199 
    200   gcm::GCMClient::IncomingMessage message;
    201   message.data["property1"] = "value1";
    202   message.data["property2"] = "value2";
    203   // First message is sent without a collapse key.
    204   app_handler.OnMessage(extension->id(), message);
    205 
    206   // Second message carries the same data and a collapse key.
    207   message.collapse_key = "collapseKeyValue";
    208   app_handler.OnMessage(extension->id(), message);
    209 
    210   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    211 }
    212 
    213 IN_PROC_BROWSER_TEST_F(GcmApiTest, OnSendError) {
    214   ResultCatcher catcher;
    215   catcher.RestrictToBrowserContext(profile());
    216 
    217   const extensions::Extension* extension =
    218       LoadTestExtension(kEventsExtension, "on_send_error.html");
    219   ASSERT_TRUE(extension);
    220 
    221   std::string total_expected_messages = "5";
    222   extensions::ExtensionGCMAppHandler app_handler(profile());
    223   app_handler.OnSendError(
    224       extension->id(),
    225       CreateErrorDetails("error_message_1",
    226                          gcm::GCMClient::ASYNC_OPERATION_PENDING,
    227                          total_expected_messages));
    228   app_handler.OnSendError(
    229       extension->id(),
    230       CreateErrorDetails("error_message_2",
    231                          gcm::GCMClient::SERVER_ERROR,
    232                          total_expected_messages));
    233   app_handler.OnSendError(
    234       extension->id(),
    235       CreateErrorDetails("error_message_3",
    236                          gcm::GCMClient::NETWORK_ERROR,
    237                          total_expected_messages));
    238   app_handler.OnSendError(
    239       extension->id(),
    240       CreateErrorDetails("error_message_4",
    241                          gcm::GCMClient::UNKNOWN_ERROR,
    242                          total_expected_messages));
    243   app_handler.OnSendError(
    244       extension->id(),
    245       CreateErrorDetails("error_message_5",
    246                          gcm::GCMClient::TTL_EXCEEDED,
    247                          total_expected_messages));
    248 
    249   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    250 }
    251 
    252 IN_PROC_BROWSER_TEST_F(GcmApiTest, Incognito) {
    253   ResultCatcher catcher;
    254   catcher.RestrictToBrowserContext(profile());
    255   ResultCatcher incognito_catcher;
    256   incognito_catcher.RestrictToBrowserContext(
    257       profile()->GetOffTheRecordProfile());
    258 
    259   ASSERT_TRUE(RunExtensionTestIncognito("gcm/functions/incognito"));
    260 
    261   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    262   EXPECT_TRUE(incognito_catcher.GetNextResult()) << incognito_catcher.message();
    263 }
    264 
    265 }  // namespace extensions
    266