blob: 5f005f809d13b329e167faf2f89359f912509967 [file] [log] [blame]
annekao38685502015-07-14 17:46:391// Copyright 2015 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
avia2f4804a2015-12-24 23:11:135#include <stdint.h>
6
kalman6f984ae2015-09-18 17:21:587#include "base/bind_helpers.h"
avia2f4804a2015-12-24 23:11:138#include "base/macros.h"
kalman6f984ae2015-09-18 17:21:589#include "base/strings/stringprintf.h"
horo1eeddde2015-11-19 05:59:2510#include "base/strings/utf_string_conversions.h"
jam3f2d3932017-04-26 20:28:5111#include "base/threading/thread_restrictions.h"
annekao38685502015-07-14 17:46:3912#include "chrome/browser/extensions/extension_apitest.h"
rdevlin.croninf5863da2015-09-10 19:21:4513#include "chrome/browser/extensions/extension_service.h"
peter9f4490a2017-01-27 00:58:3614#include "chrome/browser/gcm/fake_gcm_profile_service.h"
15#include "chrome/browser/gcm/gcm_profile_service_factory.h"
lazyboy561b7de2015-11-19 19:27:3016#include "chrome/browser/notifications/desktop_notification_profile_util.h"
miguelg9b502862017-04-24 18:13:5317#include "chrome/browser/notifications/notification_display_service_factory.h"
18#include "chrome/browser/notifications/stub_notification_display_service.h"
lshang106c1772016-06-06 01:43:2319#include "chrome/browser/permissions/permission_manager.h"
timlohc6911802017-03-01 05:37:0320#include "chrome/browser/permissions/permission_result.h"
lazyboy561b7de2015-11-19 19:27:3021#include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
22#include "chrome/browser/push_messaging/push_messaging_service_factory.h"
23#include "chrome/browser/push_messaging/push_messaging_service_impl.h"
annekao1db36fd2015-07-29 17:09:1624#include "chrome/browser/ui/tabs/tab_strip_model.h"
rdevlin.croninf5863da2015-09-10 19:21:4525#include "chrome/test/base/ui_test_utils.h"
timloh9a180ad2017-02-20 07:15:2326#include "components/content_settings/core/common/content_settings_types.h"
johnmea5045732016-09-08 17:23:2927#include "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h"
sdefresne9fb67692015-08-03 18:48:2228#include "components/version_info/version_info.h"
kalman6f984ae2015-09-18 17:21:5829#include "content/public/browser/navigation_controller.h"
rdevlin.croninf5863da2015-09-10 19:21:4530#include "content/public/browser/navigation_entry.h"
lazyboy4c82177a2016-10-18 00:04:0931#include "content/public/browser/service_worker_context.h"
32#include "content/public/browser/storage_partition.h"
kalman6f984ae2015-09-18 17:21:5833#include "content/public/browser/web_contents.h"
lazyboybd325ae2015-11-18 21:35:2634#include "content/public/common/content_switches.h"
falkenad185092016-06-16 06:10:0235#include "content/public/common/origin_util.h"
kalman6f984ae2015-09-18 17:21:5836#include "content/public/common/page_type.h"
lazyboybd325ae2015-11-18 21:35:2637#include "content/public/test/background_sync_test_util.h"
annekao1db36fd2015-07-29 17:09:1638#include "content/public/test/browser_test_utils.h"
lazyboy63b994a2017-06-30 21:20:2339#include "content/public/test/service_worker_test_helpers.h"
kalman6f984ae2015-09-18 17:21:5840#include "extensions/browser/extension_host.h"
lazyboyc3e763a2015-12-09 23:09:5841#include "extensions/browser/extension_registry.h"
kalman6f984ae2015-09-18 17:21:5842#include "extensions/browser/process_manager.h"
43#include "extensions/test/background_page_watcher.h"
annekao38685502015-07-14 17:46:3944#include "extensions/test/extension_test_message_listener.h"
falkenad185092016-06-16 06:10:0245#include "net/dns/mock_host_resolver.h"
horo1eeddde2015-11-19 05:59:2546#include "net/test/embedded_test_server/embedded_test_server.h"
lazyboy63b994a2017-06-30 21:20:2347#include "url/url_constants.h"
annekao38685502015-07-14 17:46:3948
49namespace extensions {
50
kalman6f984ae2015-09-18 17:21:5851namespace {
52
53// Pass into ServiceWorkerTest::StartTestFromBackgroundPage to indicate that
54// registration is expected to succeed.
55std::string* const kExpectSuccess = nullptr;
56
57void DoNothingWithBool(bool b) {}
58
lazyboy22eddc712015-12-10 21:16:2659// Returns the newly added WebContents.
60content::WebContents* AddTab(Browser* browser, const GURL& url) {
61 int starting_tab_count = browser->tab_strip_model()->count();
62 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:1963 browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
lazyboy22eddc712015-12-10 21:16:2664 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
65 int tab_count = browser->tab_strip_model()->count();
66 EXPECT_EQ(starting_tab_count + 1, tab_count);
67 return browser->tab_strip_model()->GetActiveWebContents();
68}
69
70class WebContentsLoadStopObserver : content::WebContentsObserver {
71 public:
72 explicit WebContentsLoadStopObserver(content::WebContents* web_contents)
73 : content::WebContentsObserver(web_contents),
74 load_stop_observed_(false) {}
75
76 void WaitForLoadStop() {
77 if (load_stop_observed_)
78 return;
79 message_loop_runner_ = new content::MessageLoopRunner;
80 message_loop_runner_->Run();
81 }
82
83 private:
84 void DidStopLoading() override {
85 load_stop_observed_ = true;
86 if (message_loop_runner_)
87 message_loop_runner_->Quit();
88 }
89
90 bool load_stop_observed_;
91 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
92
93 DISALLOW_COPY_AND_ASSIGN(WebContentsLoadStopObserver);
94};
95
kalman6f984ae2015-09-18 17:21:5896} // namespace
97
annekao38685502015-07-14 17:46:3998class ServiceWorkerTest : public ExtensionApiTest {
99 public:
lazyboy20167c22016-05-18 00:59:30100 ServiceWorkerTest() : current_channel_(version_info::Channel::STABLE) {}
annekao38685502015-07-14 17:46:39101
102 ~ServiceWorkerTest() override {}
103
jam1a5b5582017-05-01 16:50:10104 void SetUpOnMainThread() override {
105 ExtensionApiTest::SetUpOnMainThread();
106 host_resolver()->AddRule("a.com", "127.0.0.1");
107 }
108
kalman6f984ae2015-09-18 17:21:58109 protected:
110 // Returns the ProcessManager for the test's profile.
111 ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
112
113 // Starts running a test from the background page test extension.
114 //
115 // This registers a service worker with |script_name|, and fetches the
116 // registration result.
117 //
118 // If |error_or_null| is null (kExpectSuccess), success is expected and this
119 // will fail if there is an error.
120 // If |error_or_null| is not null, nothing is assumed, and the error (which
121 // may be empty) is written to it.
122 const Extension* StartTestFromBackgroundPage(const char* script_name,
123 std::string* error_or_null) {
124 const Extension* extension =
125 LoadExtension(test_data_dir_.AppendASCII("service_worker/background"));
126 CHECK(extension);
127 ExtensionHost* background_host =
128 process_manager()->GetBackgroundHostForExtension(extension->id());
129 CHECK(background_host);
130 std::string error;
131 CHECK(content::ExecuteScriptAndExtractString(
132 background_host->host_contents(),
133 base::StringPrintf("test.registerServiceWorker('%s')", script_name),
134 &error));
135 if (error_or_null)
136 *error_or_null = error;
137 else if (!error.empty())
138 ADD_FAILURE() << "Got unexpected error " << error;
139 return extension;
140 }
141
142 // Navigates the browser to a new tab at |url|, waits for it to load, then
143 // returns it.
144 content::WebContents* Navigate(const GURL& url) {
145 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19146 browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
kalman6f984ae2015-09-18 17:21:58147 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
148 content::WebContents* web_contents =
149 browser()->tab_strip_model()->GetActiveWebContents();
150 content::WaitForLoadStop(web_contents);
151 return web_contents;
152 }
153
154 // Navigates the browser to |url| and returns the new tab's page type.
155 content::PageType NavigateAndGetPageType(const GURL& url) {
156 return Navigate(url)->GetController().GetActiveEntry()->GetPageType();
157 }
158
159 // Extracts the innerText from |contents|.
160 std::string ExtractInnerText(content::WebContents* contents) {
161 std::string inner_text;
162 if (!content::ExecuteScriptAndExtractString(
163 contents,
164 "window.domAutomationController.send(document.body.innerText)",
165 &inner_text)) {
166 ADD_FAILURE() << "Failed to get inner text for "
167 << contents->GetVisibleURL();
168 }
169 return inner_text;
170 }
171
172 // Navigates the browser to |url|, then returns the innerText of the new
173 // tab's WebContents' main frame.
174 std::string NavigateAndExtractInnerText(const GURL& url) {
175 return ExtractInnerText(Navigate(url));
176 }
177
lazyboy4c82177a2016-10-18 00:04:09178 size_t GetWorkerRefCount(const GURL& origin) {
179 content::ServiceWorkerContext* sw_context =
180 content::BrowserContext::GetDefaultStoragePartition(
181 browser()->profile())
182 ->GetServiceWorkerContext();
183 base::RunLoop run_loop;
184 size_t ref_count = 0;
185 auto set_ref_count = [](size_t* ref_count, base::RunLoop* run_loop,
186 size_t external_request_count) {
187 *ref_count = external_request_count;
188 run_loop->Quit();
189 };
190 sw_context->CountExternalRequestsForTest(
191 origin, base::Bind(set_ref_count, &ref_count, &run_loop));
192 run_loop.Run();
193 return ref_count;
194 }
195
annekao38685502015-07-14 17:46:39196 private:
lazyboy20167c22016-05-18 00:59:30197 // Sets the channel to "stable".
198 // Not useful after we've opened extension Service Workers to stable
199 // channel.
200 // TODO(lazyboy): Remove this when ExtensionServiceWorkersEnabled() is
201 // removed.
annekao38685502015-07-14 17:46:39202 ScopedCurrentChannel current_channel_;
kalman6f984ae2015-09-18 17:21:58203
annekao38685502015-07-14 17:46:39204 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTest);
205};
206
lazyboybd325ae2015-11-18 21:35:26207class ServiceWorkerBackgroundSyncTest : public ServiceWorkerTest {
208 public:
209 ServiceWorkerBackgroundSyncTest() {}
210 ~ServiceWorkerBackgroundSyncTest() override {}
211
212 void SetUpCommandLine(base::CommandLine* command_line) override {
213 // ServiceWorkerRegistration.sync requires experimental flag.
214 command_line->AppendSwitch(
215 switches::kEnableExperimentalWebPlatformFeatures);
216 ServiceWorkerTest::SetUpCommandLine(command_line);
217 }
218
219 void SetUp() override {
220 content::background_sync_test_util::SetIgnoreNetworkChangeNotifier(true);
221 ServiceWorkerTest::SetUp();
222 }
223
224 private:
225 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBackgroundSyncTest);
226};
227
lazyboy561b7de2015-11-19 19:27:30228class ServiceWorkerPushMessagingTest : public ServiceWorkerTest {
229 public:
230 ServiceWorkerPushMessagingTest()
johnmea5045732016-09-08 17:23:29231 : gcm_driver_(nullptr), push_service_(nullptr) {}
lazyboy561b7de2015-11-19 19:27:30232 ~ServiceWorkerPushMessagingTest() override {}
233
234 void GrantNotificationPermissionForTest(const GURL& url) {
235 GURL origin = url.GetOrigin();
236 DesktopNotificationProfileUtil::GrantPermission(profile(), origin);
timlohc6911802017-03-01 05:37:03237 ASSERT_EQ(CONTENT_SETTING_ALLOW,
238 PermissionManager::Get(profile())
239 ->GetPermissionStatus(CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
240 origin, origin)
241 .content_setting);
lazyboy561b7de2015-11-19 19:27:30242 }
243
244 PushMessagingAppIdentifier GetAppIdentifierForServiceWorkerRegistration(
avia2f4804a2015-12-24 23:11:13245 int64_t service_worker_registration_id,
lazyboy561b7de2015-11-19 19:27:30246 const GURL& origin) {
247 PushMessagingAppIdentifier app_identifier =
248 PushMessagingAppIdentifier::FindByServiceWorker(
249 profile(), origin, service_worker_registration_id);
250
251 EXPECT_FALSE(app_identifier.is_null());
252 return app_identifier;
253 }
254
255 // ExtensionApiTest overrides.
256 void SetUpCommandLine(base::CommandLine* command_line) override {
peter9de96272015-12-04 15:23:27257 command_line->AppendSwitch(
258 switches::kEnableExperimentalWebPlatformFeatures);
lazyboy561b7de2015-11-19 19:27:30259 ServiceWorkerTest::SetUpCommandLine(command_line);
260 }
261 void SetUpOnMainThread() override {
miguelg9b502862017-04-24 18:13:53262 NotificationDisplayServiceFactory::GetInstance()->SetTestingFactory(
263 profile(), &StubNotificationDisplayService::FactoryForTests);
264
johnmea5045732016-09-08 17:23:29265 gcm::FakeGCMProfileService* gcm_service =
266 static_cast<gcm::FakeGCMProfileService*>(
267 gcm::GCMProfileServiceFactory::GetInstance()
268 ->SetTestingFactoryAndUse(profile(),
269 &gcm::FakeGCMProfileService::Build));
270 gcm_driver_ = static_cast<instance_id::FakeGCMDriverForInstanceID*>(
271 gcm_service->driver());
lazyboy561b7de2015-11-19 19:27:30272 push_service_ = PushMessagingServiceFactory::GetForProfile(profile());
273
274 ServiceWorkerTest::SetUpOnMainThread();
275 }
276
johnmea5045732016-09-08 17:23:29277 instance_id::FakeGCMDriverForInstanceID* gcm_driver() const {
278 return gcm_driver_;
279 }
lazyboy561b7de2015-11-19 19:27:30280 PushMessagingServiceImpl* push_service() const { return push_service_; }
281
282 private:
johnmea5045732016-09-08 17:23:29283 instance_id::FakeGCMDriverForInstanceID* gcm_driver_;
lazyboy561b7de2015-11-19 19:27:30284 PushMessagingServiceImpl* push_service_;
285
286 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPushMessagingTest);
287};
288
lazyboy20167c22016-05-18 00:59:30289IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, RegisterSucceeds) {
kalman6f984ae2015-09-18 17:21:58290 StartTestFromBackgroundPage("register.js", kExpectSuccess);
annekao38685502015-07-14 17:46:39291}
292
lazyboyc3e763a2015-12-09 23:09:58293IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, UpdateRefreshesServiceWorker) {
jam3f2d3932017-04-26 20:28:51294 base::ThreadRestrictions::ScopedAllowIO allow_io;
lazyboyc3e763a2015-12-09 23:09:58295 base::ScopedTempDir scoped_temp_dir;
296 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
297 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
298 .AppendASCII("update")
299 .AppendASCII("service_worker.pem");
vabr9142fe22016-09-08 13:19:22300 base::FilePath path_v1 =
301 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
302 .AppendASCII("update")
303 .AppendASCII("v1"),
304 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
305 pem_path, base::FilePath());
306 base::FilePath path_v2 =
307 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
308 .AppendASCII("update")
309 .AppendASCII("v2"),
310 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
311 pem_path, base::FilePath());
lazyboyc3e763a2015-12-09 23:09:58312 const char* kId = "hfaanndiiilofhfokeanhddpkfffchdi";
313
314 ExtensionTestMessageListener listener_v1("Pong from version 1", false);
315 listener_v1.set_failure_message("FAILURE_V1");
316 // Install version 1.0 of the extension.
317 ASSERT_TRUE(InstallExtension(path_v1, 1));
318 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
319 ->enabled_extensions()
320 .GetByID(kId));
321 EXPECT_TRUE(listener_v1.WaitUntilSatisfied());
322
323 ExtensionTestMessageListener listener_v2("Pong from version 2", false);
324 listener_v2.set_failure_message("FAILURE_V2");
325
326 // Update to version 2.0.
327 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
328 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
329 ->enabled_extensions()
330 .GetByID(kId));
331 EXPECT_TRUE(listener_v2.WaitUntilSatisfied());
332}
333
lazyboy22eddc712015-12-10 21:16:26334IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, UpdateWithoutSkipWaiting) {
jam3f2d3932017-04-26 20:28:51335 base::ThreadRestrictions::ScopedAllowIO allow_io;
lazyboy22eddc712015-12-10 21:16:26336 base::ScopedTempDir scoped_temp_dir;
337 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
338 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
339 .AppendASCII("update_without_skip_waiting")
340 .AppendASCII("update_without_skip_waiting.pem");
vabr9142fe22016-09-08 13:19:22341 base::FilePath path_v1 =
342 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
343 .AppendASCII("update_without_skip_waiting")
344 .AppendASCII("v1"),
345 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
346 pem_path, base::FilePath());
347 base::FilePath path_v2 =
348 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
349 .AppendASCII("update_without_skip_waiting")
350 .AppendASCII("v2"),
351 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
352 pem_path, base::FilePath());
lazyboy22eddc712015-12-10 21:16:26353 const char* kId = "mhnnnflgagdakldgjpfcofkiocpdmogl";
354
355 // Install version 1.0 of the extension.
356 ASSERT_TRUE(InstallExtension(path_v1, 1));
357 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
358 ->enabled_extensions()
359 .GetByID(kId));
360 const Extension* extension = extensions::ExtensionRegistry::Get(profile())
361 ->enabled_extensions()
362 .GetByID(kId);
363
364 ExtensionTestMessageListener listener1("Pong from version 1", false);
365 listener1.set_failure_message("FAILURE");
366 content::WebContents* web_contents =
367 AddTab(browser(), extension->GetResourceURL("page.html"));
368 EXPECT_TRUE(listener1.WaitUntilSatisfied());
369
370 // Update to version 2.0.
371 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
372 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
373 ->enabled_extensions()
374 .GetByID(kId));
375 const Extension* extension_after_update =
376 extensions::ExtensionRegistry::Get(profile())
377 ->enabled_extensions()
378 .GetByID(kId);
379
380 // Service worker version 2 would be installed but it won't be controlling
381 // the extension page yet.
382 ExtensionTestMessageListener listener2("Pong from version 1", false);
383 listener2.set_failure_message("FAILURE");
384 web_contents =
385 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
386 EXPECT_TRUE(listener2.WaitUntilSatisfied());
387
388 // Navigate the tab away from the extension page so that no clients are
389 // using the service worker.
390 // Note that just closing the tab with WebContentsDestroyedWatcher doesn't
391 // seem to be enough because it returns too early.
392 WebContentsLoadStopObserver navigate_away_observer(web_contents);
393 web_contents->GetController().LoadURL(
394 GURL(url::kAboutBlankURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED,
395 std::string());
396 navigate_away_observer.WaitForLoadStop();
397
398 // Now expect service worker version 2 to control the extension page.
399 ExtensionTestMessageListener listener3("Pong from version 2", false);
400 listener3.set_failure_message("FAILURE");
401 web_contents =
402 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
403 EXPECT_TRUE(listener3.WaitUntilSatisfied());
404}
405
kalman6f984ae2015-09-18 17:21:58406IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, FetchArbitraryPaths) {
407 const Extension* extension =
408 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
annekao1db36fd2015-07-29 17:09:16409
kalman6f984ae2015-09-18 17:21:58410 // Open some arbirary paths. Their contents should be what the service worker
411 // responds with, which in this case is the path of the fetch.
412 EXPECT_EQ(
413 "Caught a fetch for /index.html",
414 NavigateAndExtractInnerText(extension->GetResourceURL("index.html")));
415 EXPECT_EQ("Caught a fetch for /path/to/other.html",
416 NavigateAndExtractInnerText(
417 extension->GetResourceURL("path/to/other.html")));
418 EXPECT_EQ("Caught a fetch for /some/text/file.txt",
419 NavigateAndExtractInnerText(
420 extension->GetResourceURL("some/text/file.txt")));
421 EXPECT_EQ("Caught a fetch for /no/file/extension",
422 NavigateAndExtractInnerText(
423 extension->GetResourceURL("no/file/extension")));
424 EXPECT_EQ("Caught a fetch for /",
425 NavigateAndExtractInnerText(extension->GetResourceURL("")));
annekao1db36fd2015-07-29 17:09:16426}
427
lazyboy52c3bcf2016-01-08 00:11:29428IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, SWServedBackgroundPageReceivesEvent) {
429 const Extension* extension =
430 StartTestFromBackgroundPage("replace_background.js", kExpectSuccess);
431 ExtensionHost* background_page =
432 process_manager()->GetBackgroundHostForExtension(extension->id());
433 ASSERT_TRUE(background_page);
434
435 // Close the background page and start it again so that the service worker
436 // will start controlling pages.
437 background_page->Close();
438 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
439 background_page = nullptr;
440 process_manager()->WakeEventPage(extension->id(),
441 base::Bind(&DoNothingWithBool));
442 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
443
444 // Since the SW is now controlling the extension, the SW serves the background
445 // script. page.html sends a message to the background script and we verify
446 // that the SW served background script correctly receives the message/event.
447 ExtensionTestMessageListener listener("onMessage/SW BG.", false);
448 listener.set_failure_message("onMessage/original BG.");
449 content::WebContents* web_contents =
450 AddTab(browser(), extension->GetResourceURL("page.html"));
451 ASSERT_TRUE(web_contents);
452 EXPECT_TRUE(listener.WaitUntilSatisfied());
453}
454
kalman6f984ae2015-09-18 17:21:58455IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
456 LoadingBackgroundPageBypassesServiceWorker) {
457 const Extension* extension =
458 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
annekao49241182015-08-18 17:14:01459
kalman6f984ae2015-09-18 17:21:58460 std::string kExpectedInnerText = "background.html contents for testing.";
annekao49241182015-08-18 17:14:01461
kalman6f984ae2015-09-18 17:21:58462 // Sanity check that the background page has the expected content.
463 ExtensionHost* background_page =
464 process_manager()->GetBackgroundHostForExtension(extension->id());
465 ASSERT_TRUE(background_page);
466 EXPECT_EQ(kExpectedInnerText,
467 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01468
kalman6f984ae2015-09-18 17:21:58469 // Close the background page.
470 background_page->Close();
471 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
472 background_page = nullptr;
473
474 // Start it again.
475 process_manager()->WakeEventPage(extension->id(),
476 base::Bind(&DoNothingWithBool));
477 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
478
479 // Content should not have been affected by the fetch, which would otherwise
480 // be "Caught fetch for...".
481 background_page =
482 process_manager()->GetBackgroundHostForExtension(extension->id());
483 ASSERT_TRUE(background_page);
484 content::WaitForLoadStop(background_page->host_contents());
485
486 // TODO(kalman): Everything you've read has been a LIE! It should be:
487 //
488 // EXPECT_EQ(kExpectedInnerText,
489 // ExtractInnerText(background_page->host_contents()));
490 //
491 // but there is a bug, and we're actually *not* bypassing the service worker
492 // for background page loads! For now, let it pass (assert wrong behavior)
493 // because it's not a regression, but this must be fixed eventually.
494 //
495 // Tracked in crbug.com/532720.
496 EXPECT_EQ("Caught a fetch for /background.html",
497 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01498}
499
kalman6f984ae2015-09-18 17:21:58500IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
501 ServiceWorkerPostsMessageToBackgroundClient) {
502 const Extension* extension = StartTestFromBackgroundPage(
503 "post_message_to_background_client.js", kExpectSuccess);
annekao533482222015-08-21 23:23:53504
kalman6f984ae2015-09-18 17:21:58505 // The service worker in this test simply posts a message to the background
506 // client it receives from getBackgroundClient().
507 const char* kScript =
508 "var messagePromise = null;\n"
509 "if (test.lastMessageFromServiceWorker) {\n"
510 " messagePromise = Promise.resolve(test.lastMessageFromServiceWorker);\n"
511 "} else {\n"
512 " messagePromise = test.waitForMessage(navigator.serviceWorker);\n"
513 "}\n"
514 "messagePromise.then(function(message) {\n"
515 " window.domAutomationController.send(String(message == 'success'));\n"
516 "})\n";
517 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53518}
519
kalman6f984ae2015-09-18 17:21:58520IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
521 BackgroundPagePostsMessageToServiceWorker) {
522 const Extension* extension =
523 StartTestFromBackgroundPage("post_message_to_sw.js", kExpectSuccess);
annekao533482222015-08-21 23:23:53524
kalman6f984ae2015-09-18 17:21:58525 // The service worker in this test waits for a message, then echoes it back
526 // by posting a message to the background page via getBackgroundClient().
527 const char* kScript =
528 "var mc = new MessageChannel();\n"
529 "test.waitForMessage(mc.port1).then(function(message) {\n"
530 " window.domAutomationController.send(String(message == 'hello'));\n"
531 "});\n"
532 "test.registeredServiceWorker.postMessage(\n"
533 " {message: 'hello', port: mc.port2}, [mc.port2])\n";
534 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53535}
536
rdevlin.croninf5863da2015-09-10 19:21:45537IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
538 ServiceWorkerSuspensionOnExtensionUnload) {
kalman6f984ae2015-09-18 17:21:58539 // For this test, only hold onto the extension's ID and URL + a function to
540 // get a resource URL, because we're going to be disabling and uninstalling
541 // it, which will invalidate the pointer.
542 std::string extension_id;
543 GURL extension_url;
544 {
545 const Extension* extension =
546 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
547 extension_id = extension->id();
548 extension_url = extension->url();
549 }
550 auto get_resource_url = [&extension_url](const std::string& path) {
551 return Extension::GetResourceURL(extension_url, path);
552 };
rdevlin.croninf5863da2015-09-10 19:21:45553
kalman6f984ae2015-09-18 17:21:58554 // Fetch should route to the service worker.
555 EXPECT_EQ("Caught a fetch for /index.html",
556 NavigateAndExtractInnerText(get_resource_url("index.html")));
rdevlin.croninf5863da2015-09-10 19:21:45557
kalman6f984ae2015-09-18 17:21:58558 // Disable the extension. Opening the page should fail.
559 extension_service()->DisableExtension(extension_id,
rdevlin.croninf5863da2015-09-10 19:21:45560 Extension::DISABLE_USER_ACTION);
561 base::RunLoop().RunUntilIdle();
rdevlin.croninf5863da2015-09-10 19:21:45562
kalman6f984ae2015-09-18 17:21:58563 EXPECT_EQ(content::PAGE_TYPE_ERROR,
564 NavigateAndGetPageType(get_resource_url("index.html")));
565 EXPECT_EQ(content::PAGE_TYPE_ERROR,
566 NavigateAndGetPageType(get_resource_url("other.html")));
567
568 // Re-enable the extension. Opening pages should immediately start to succeed
569 // again.
rdevlin.croninf5863da2015-09-10 19:21:45570 extension_service()->EnableExtension(extension_id);
571 base::RunLoop().RunUntilIdle();
572
kalman6f984ae2015-09-18 17:21:58573 EXPECT_EQ("Caught a fetch for /index.html",
574 NavigateAndExtractInnerText(get_resource_url("index.html")));
575 EXPECT_EQ("Caught a fetch for /other.html",
576 NavigateAndExtractInnerText(get_resource_url("other.html")));
577 EXPECT_EQ("Caught a fetch for /another.html",
578 NavigateAndExtractInnerText(get_resource_url("another.html")));
rdevlin.croninf5863da2015-09-10 19:21:45579
kalman6f984ae2015-09-18 17:21:58580 // Uninstall the extension. Opening pages should fail again.
581 base::string16 error;
582 extension_service()->UninstallExtension(
583 extension_id, UninstallReason::UNINSTALL_REASON_FOR_TESTING,
584 base::Bind(&base::DoNothing), &error);
585 base::RunLoop().RunUntilIdle();
586
587 EXPECT_EQ(content::PAGE_TYPE_ERROR,
588 NavigateAndGetPageType(get_resource_url("index.html")));
589 EXPECT_EQ(content::PAGE_TYPE_ERROR,
590 NavigateAndGetPageType(get_resource_url("other.html")));
591 EXPECT_EQ(content::PAGE_TYPE_ERROR,
592 NavigateAndGetPageType(get_resource_url("anotherother.html")));
593 EXPECT_EQ(content::PAGE_TYPE_ERROR,
594 NavigateAndGetPageType(get_resource_url("final.html")));
595}
596
597IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, BackgroundPageIsWokenIfAsleep) {
598 const Extension* extension =
599 StartTestFromBackgroundPage("wake_on_fetch.js", kExpectSuccess);
600
601 // Navigate to special URLs that this test's service worker recognises, each
602 // making a check then populating the response with either "true" or "false".
603 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
604 "background-client-is-awake")));
605 EXPECT_EQ("true", NavigateAndExtractInnerText(
606 extension->GetResourceURL("ping-background-client")));
607 // Ping more than once for good measure.
608 EXPECT_EQ("true", NavigateAndExtractInnerText(
609 extension->GetResourceURL("ping-background-client")));
610
611 // Shut down the event page. The SW should detect that it's closed, but still
612 // be able to ping it.
613 ExtensionHost* background_page =
614 process_manager()->GetBackgroundHostForExtension(extension->id());
615 ASSERT_TRUE(background_page);
616 background_page->Close();
617 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
618
619 EXPECT_EQ("false", NavigateAndExtractInnerText(extension->GetResourceURL(
620 "background-client-is-awake")));
621 EXPECT_EQ("true", NavigateAndExtractInnerText(
622 extension->GetResourceURL("ping-background-client")));
623 EXPECT_EQ("true", NavigateAndExtractInnerText(
624 extension->GetResourceURL("ping-background-client")));
625 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
626 "background-client-is-awake")));
627}
628
629IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
630 GetBackgroundClientFailsWithNoBackgroundPage) {
631 // This extension doesn't have a background page, only a tab at page.html.
632 // The service worker it registers tries to call getBackgroundClient() and
633 // should fail.
634 // Note that this also tests that service workers can be registered from tabs.
635 EXPECT_TRUE(RunExtensionSubtest("service_worker/no_background", "page.html"));
rdevlin.croninf5863da2015-09-10 19:21:45636}
637
lazyboy6ddb7d62015-11-10 23:15:27638IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, NotificationAPI) {
639 EXPECT_TRUE(RunExtensionSubtest("service_worker/notifications/has_permission",
640 "page.html"));
641}
642
lazyboyaea32c22016-01-04 21:37:07643IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WebAccessibleResourcesFetch) {
644 EXPECT_TRUE(RunExtensionSubtest(
645 "service_worker/web_accessible_resources/fetch/", "page.html"));
646}
647
lazyboyee4adef2016-05-24 00:55:16648IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, TabsCreate) {
649 // Extensions APIs from SW are only enabled on trunk.
650 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
651 const Extension* extension = LoadExtensionWithFlags(
652 test_data_dir_.AppendASCII("service_worker/tabs_create"), kFlagNone);
653 ASSERT_TRUE(extension);
654 ui_test_utils::NavigateToURL(browser(),
655 extension->GetResourceURL("page.html"));
656 content::WebContents* web_contents =
657 browser()->tab_strip_model()->GetActiveWebContents();
658
659 int starting_tab_count = browser()->tab_strip_model()->count();
660 std::string result;
661 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
662 web_contents, "window.runServiceWorker()", &result));
663 ASSERT_EQ("chrome.tabs.create callback", result);
664 EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count());
665
666 // Check extension shutdown path.
667 UnloadExtension(extension->id());
668 EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count());
669}
670
lazyboye7847242017-06-07 23:29:18671IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, Events) {
672 // Extensions APIs from SW are only enabled on trunk.
673 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
674 const Extension* extension = LoadExtensionWithFlags(
675 test_data_dir_.AppendASCII("service_worker/events"), kFlagNone);
676 ASSERT_TRUE(extension);
677 ui_test_utils::NavigateToURL(browser(),
678 extension->GetResourceURL("page.html"));
679 content::WebContents* web_contents =
680 browser()->tab_strip_model()->GetActiveWebContents();
681 std::string result;
682 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
683 web_contents, "window.runEventTest()", &result));
684 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
685}
686
lazyboy63b994a2017-06-30 21:20:23687IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, EventsToStoppedWorker) {
688 // Extensions APIs from SW are only enabled on trunk.
689 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
690 const Extension* extension = LoadExtensionWithFlags(
691 test_data_dir_.AppendASCII("service_worker/events_to_stopped_worker"),
692 kFlagNone);
693 ASSERT_TRUE(extension);
694 ui_test_utils::NavigateToURL(browser(),
695 extension->GetResourceURL("page.html"));
696 content::WebContents* web_contents =
697 browser()->tab_strip_model()->GetActiveWebContents();
698 {
699 std::string result;
700 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
701 web_contents, "window.runServiceWorker()", &result));
702 ASSERT_EQ("ready", result);
703
704 base::RunLoop run_loop;
705 content::StoragePartition* storage_partition =
706 content::BrowserContext::GetDefaultStoragePartition(
707 browser()->profile());
708 content::StopServiceWorkerForPattern(
709 storage_partition->GetServiceWorkerContext(),
710 // The service worker is registered at the top level scope.
711 extension->url(), run_loop.QuitClosure());
712 run_loop.Run();
713 }
714
715 std::string result;
716 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
717 web_contents, "window.createTabThenUpdate()", &result));
718 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
719}
720
lazyboy4c82177a2016-10-18 00:04:09721// Tests that worker ref count increments while extension API function is
722// active.
timloh721dc7202017-04-04 09:00:47723
724// Flaky on Linux and ChromeOS, https://crbug.com/702126
725#if defined(OS_LINUX)
726#define MAYBE_WorkerRefCount DISABLED_WorkerRefCount
727#else
728#define MAYBE_WorkerRefCount WorkerRefCount
729#endif
730IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, MAYBE_WorkerRefCount) {
lazyboy4c82177a2016-10-18 00:04:09731 // Extensions APIs from SW are only enabled on trunk.
732 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
733 const Extension* extension = LoadExtensionWithFlags(
734 test_data_dir_.AppendASCII("service_worker/api_worker_ref_count"),
735 kFlagNone);
736 ASSERT_TRUE(extension);
737 ui_test_utils::NavigateToURL(browser(),
738 extension->GetResourceURL("page.html"));
739 content::WebContents* web_contents =
740 browser()->tab_strip_model()->GetActiveWebContents();
741
742 ExtensionTestMessageListener worker_start_listener("WORKER STARTED", false);
743 worker_start_listener.set_failure_message("FAILURE");
744 ASSERT_TRUE(
745 content::ExecuteScript(web_contents, "window.runServiceWorker()"));
746 ASSERT_TRUE(worker_start_listener.WaitUntilSatisfied());
747
748 // Service worker should have no pending requests because it hasn't peformed
749 // any extension API request yet.
750 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
751
752 ExtensionTestMessageListener worker_listener("CHECK_REF_COUNT", true);
753 worker_listener.set_failure_message("FAILURE");
754 ASSERT_TRUE(content::ExecuteScript(web_contents, "window.testSendMessage()"));
755 ASSERT_TRUE(worker_listener.WaitUntilSatisfied());
756
757 // Service worker should have exactly one pending request because
758 // chrome.test.sendMessage() API call is in-flight.
759 EXPECT_EQ(1u, GetWorkerRefCount(extension->url()));
760
761 // Peform another extension API request while one is ongoing.
762 {
763 ExtensionTestMessageListener listener("CHECK_REF_COUNT", true);
764 listener.set_failure_message("FAILURE");
765 ASSERT_TRUE(
766 content::ExecuteScript(web_contents, "window.testSendMessage()"));
767 ASSERT_TRUE(listener.WaitUntilSatisfied());
768
769 // Service worker currently has two extension API requests in-flight.
770 EXPECT_EQ(2u, GetWorkerRefCount(extension->url()));
771 // Finish executing the nested chrome.test.sendMessage() first.
772 listener.Reply("Hello world");
773 }
774
775 ExtensionTestMessageListener extension_listener("SUCCESS", false);
776 extension_listener.set_failure_message("FAILURE");
777 // Finish executing chrome.test.sendMessage().
778 worker_listener.Reply("Hello world");
779 ASSERT_TRUE(extension_listener.WaitUntilSatisfied());
780
781 // The ref count should drop to 0.
782 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
783}
784
lazyboyaea32c22016-01-04 21:37:07785// This test loads a web page that has an iframe pointing to a
786// chrome-extension:// URL. The URL is listed in the extension's
787// web_accessible_resources. Initially the iframe is served from the extension's
788// resource file. After verifying that, we register a Service Worker that
789// controls the extension. Further requests to the same resource as before
790// should now be served by the Service Worker.
791// This test also verifies that if the requested resource exists in the manifest
792// but is not present in the extension directory, the Service Worker can still
793// serve the resource file.
794IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WebAccessibleResourcesIframeSrc) {
795 const Extension* extension = LoadExtensionWithFlags(
796 test_data_dir_.AppendASCII(
797 "service_worker/web_accessible_resources/iframe_src"),
798 kFlagNone);
799 ASSERT_TRUE(extension);
800 ASSERT_TRUE(StartEmbeddedTestServer());
falkenad185092016-06-16 06:10:02801
802 // Service workers can only control secure contexts
803 // (https://w3c.github.io/webappsec-secure-contexts/). For documents, this
804 // typically means the document must have a secure origin AND all its ancestor
805 // frames must have documents with secure origins. However, extension pages
806 // are considered secure, even if they have an ancestor document that is an
807 // insecure context (see GetSchemesBypassingSecureContextCheckWhitelist). So
808 // extension service workers must be able to control an extension page
809 // embedded in an insecure context. To test this, set up an insecure
810 // (non-localhost, non-https) URL for the web page. This page will create
811 // iframes that load extension pages that must be controllable by service
812 // worker.
falkenad185092016-06-16 06:10:02813 GURL page_url =
814 embedded_test_server()->GetURL("a.com",
815 "/extensions/api_test/service_worker/"
816 "web_accessible_resources/webpage.html");
817 EXPECT_FALSE(content::IsOriginSecure(page_url));
lazyboyaea32c22016-01-04 21:37:07818
819 content::WebContents* web_contents = AddTab(browser(), page_url);
820 std::string result;
821 // webpage.html will create an iframe pointing to a resource from |extension|.
822 // Expect the resource to be served by the extension.
823 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
824 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
825 extension->id().c_str()),
826 &result));
827 EXPECT_EQ("FROM_EXTENSION_RESOURCE", result);
828
829 ExtensionTestMessageListener service_worker_ready_listener("SW_READY", false);
830 EXPECT_TRUE(ExecuteScriptInBackgroundPageNoWait(
831 extension->id(), "window.registerServiceWorker()"));
832 EXPECT_TRUE(service_worker_ready_listener.WaitUntilSatisfied());
833
834 result.clear();
835 // webpage.html will create another iframe pointing to a resource from
836 // |extension| as before. But this time, the resource should be be served
837 // from the Service Worker.
838 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
839 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
840 extension->id().c_str()),
841 &result));
842 EXPECT_EQ("FROM_SW_RESOURCE", result);
843
844 result.clear();
845 // webpage.html will create yet another iframe pointing to a resource that
846 // exists in the extension manifest's web_accessible_resources, but is not
847 // present in the extension directory. Expect the resources of the iframe to
848 // be served by the Service Worker.
849 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
850 web_contents,
851 base::StringPrintf("window.testIframe('%s', 'iframe_non_existent.html')",
852 extension->id().c_str()),
853 &result));
854 EXPECT_EQ("FROM_SW_RESOURCE", result);
855}
856
benwells0af03f92017-06-28 08:35:33857// Test is flaky. See https://crbug.com/737260
858IN_PROC_BROWSER_TEST_F(ServiceWorkerBackgroundSyncTest, DISABLED_Sync) {
lazyboybd325ae2015-11-18 21:35:26859 const Extension* extension = LoadExtensionWithFlags(
860 test_data_dir_.AppendASCII("service_worker/sync"), kFlagNone);
861 ASSERT_TRUE(extension);
862 ui_test_utils::NavigateToURL(browser(),
863 extension->GetResourceURL("page.html"));
864 content::WebContents* web_contents =
865 browser()->tab_strip_model()->GetActiveWebContents();
866
867 // Prevent firing by going offline.
868 content::background_sync_test_util::SetOnline(web_contents, false);
869
870 ExtensionTestMessageListener sync_listener("SYNC: send-chats", false);
871 sync_listener.set_failure_message("FAIL");
872
873 std::string result;
874 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
875 web_contents, "window.runServiceWorker()", &result));
876 ASSERT_EQ("SERVICE_WORKER_READY", result);
877
878 EXPECT_FALSE(sync_listener.was_satisfied());
879 // Resume firing by going online.
880 content::background_sync_test_util::SetOnline(web_contents, true);
881 EXPECT_TRUE(sync_listener.WaitUntilSatisfied());
882}
883
horo1eeddde2015-11-19 05:59:25884IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
885 FetchFromContentScriptShouldNotGoToServiceWorkerOfPage) {
886 ASSERT_TRUE(StartEmbeddedTestServer());
887 GURL page_url = embedded_test_server()->GetURL(
888 "/extensions/api_test/service_worker/content_script_fetch/"
889 "controlled_page/index.html");
890 content::WebContents* tab =
891 browser()->tab_strip_model()->GetActiveWebContents();
892 ui_test_utils::NavigateToURL(browser(), page_url);
893 content::WaitForLoadStop(tab);
894
895 std::string value;
896 ASSERT_TRUE(
897 content::ExecuteScriptAndExtractString(tab, "register();", &value));
898 EXPECT_EQ("SW controlled", value);
899
900 ASSERT_TRUE(RunExtensionTest("service_worker/content_script_fetch"))
901 << message_;
902}
903
lazyboyd429e2582016-05-20 20:18:52904IN_PROC_BROWSER_TEST_F(ServiceWorkerPushMessagingTest, OnPush) {
lazyboy561b7de2015-11-19 19:27:30905 const Extension* extension = LoadExtensionWithFlags(
906 test_data_dir_.AppendASCII("service_worker/push_messaging"), kFlagNone);
907 ASSERT_TRUE(extension);
908 GURL extension_url = extension->url();
909
910 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest(extension_url));
911
912 GURL url = extension->GetResourceURL("page.html");
913 ui_test_utils::NavigateToURL(browser(), url);
914
915 content::WebContents* web_contents =
916 browser()->tab_strip_model()->GetActiveWebContents();
917
918 // Start the ServiceWorker.
919 ExtensionTestMessageListener ready_listener("SERVICE_WORKER_READY", false);
920 ready_listener.set_failure_message("SERVICE_WORKER_FAILURE");
921 const char* kScript = "window.runServiceWorker()";
922 EXPECT_TRUE(content::ExecuteScript(web_contents->GetMainFrame(), kScript));
923 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
924
925 PushMessagingAppIdentifier app_identifier =
926 GetAppIdentifierForServiceWorkerRegistration(0LL, extension_url);
johnmea5045732016-09-08 17:23:29927 ASSERT_EQ(app_identifier.app_id(), gcm_driver()->last_gettoken_app_id());
928 EXPECT_EQ("1234567890", gcm_driver()->last_gettoken_authorized_entity());
lazyboy561b7de2015-11-19 19:27:30929
lazyboyd429e2582016-05-20 20:18:52930 base::RunLoop run_loop;
lazyboy561b7de2015-11-19 19:27:30931 // Send a push message via gcm and expect the ServiceWorker to receive it.
932 ExtensionTestMessageListener push_message_listener("OK", false);
933 push_message_listener.set_failure_message("FAIL");
934 gcm::IncomingMessage message;
935 message.sender_id = "1234567890";
936 message.raw_data = "testdata";
937 message.decrypted = true;
lazyboyd429e2582016-05-20 20:18:52938 push_service()->SetMessageCallbackForTesting(run_loop.QuitClosure());
lazyboy561b7de2015-11-19 19:27:30939 push_service()->OnMessage(app_identifier.app_id(), message);
940 EXPECT_TRUE(push_message_listener.WaitUntilSatisfied());
lazyboyd429e2582016-05-20 20:18:52941 run_loop.Run(); // Wait until the message is handled by push service.
lazyboy561b7de2015-11-19 19:27:30942}
943
annekao38685502015-07-14 17:46:39944} // namespace extensions