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