blob: bbb364da2c3a821f009d1f3ec0a869ffbf2a4175 [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"
Gabriel Charette078e3662017-08-28 22:59:049#include "base/run_loop.h"
kalman6f984ae2015-09-18 17:21:5810#include "base/strings/stringprintf.h"
horo1eeddde2015-11-19 05:59:2511#include "base/strings/utf_string_conversions.h"
jam3f2d3932017-04-26 20:28:5112#include "base/threading/thread_restrictions.h"
annekao38685502015-07-14 17:46:3913#include "chrome/browser/extensions/extension_apitest.h"
rdevlin.croninf5863da2015-09-10 19:21:4514#include "chrome/browser/extensions/extension_service.h"
peter9f4490a2017-01-27 00:58:3615#include "chrome/browser/gcm/fake_gcm_profile_service.h"
16#include "chrome/browser/gcm/gcm_profile_service_factory.h"
lazyboy561b7de2015-11-19 19:27:3017#include "chrome/browser/notifications/desktop_notification_profile_util.h"
miguelg9b502862017-04-24 18:13:5318#include "chrome/browser/notifications/notification_display_service_factory.h"
19#include "chrome/browser/notifications/stub_notification_display_service.h"
lshang106c1772016-06-06 01:43:2320#include "chrome/browser/permissions/permission_manager.h"
timlohc6911802017-03-01 05:37:0321#include "chrome/browser/permissions/permission_result.h"
lazyboy561b7de2015-11-19 19:27:3022#include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
23#include "chrome/browser/push_messaging/push_messaging_service_factory.h"
24#include "chrome/browser/push_messaging/push_messaging_service_impl.h"
annekao1db36fd2015-07-29 17:09:1625#include "chrome/browser/ui/tabs/tab_strip_model.h"
rdevlin.croninf5863da2015-09-10 19:21:4526#include "chrome/test/base/ui_test_utils.h"
timloh9a180ad2017-02-20 07:15:2327#include "components/content_settings/core/common/content_settings_types.h"
johnmea5045732016-09-08 17:23:2928#include "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h"
sdefresne9fb67692015-08-03 18:48:2229#include "components/version_info/version_info.h"
kalman6f984ae2015-09-18 17:21:5830#include "content/public/browser/navigation_controller.h"
rdevlin.croninf5863da2015-09-10 19:21:4531#include "content/public/browser/navigation_entry.h"
lazyboy4c82177a2016-10-18 00:04:0932#include "content/public/browser/service_worker_context.h"
33#include "content/public/browser/storage_partition.h"
kalman6f984ae2015-09-18 17:21:5834#include "content/public/browser/web_contents.h"
lazyboybd325ae2015-11-18 21:35:2635#include "content/public/common/content_switches.h"
falkenad185092016-06-16 06:10:0236#include "content/public/common/origin_util.h"
kalman6f984ae2015-09-18 17:21:5837#include "content/public/common/page_type.h"
lazyboybd325ae2015-11-18 21:35:2638#include "content/public/test/background_sync_test_util.h"
annekao1db36fd2015-07-29 17:09:1639#include "content/public/test/browser_test_utils.h"
lazyboy63b994a2017-06-30 21:20:2340#include "content/public/test/service_worker_test_helpers.h"
kalman6f984ae2015-09-18 17:21:5841#include "extensions/browser/extension_host.h"
lazyboyc3e763a2015-12-09 23:09:5842#include "extensions/browser/extension_registry.h"
kalman6f984ae2015-09-18 17:21:5843#include "extensions/browser/process_manager.h"
44#include "extensions/test/background_page_watcher.h"
annekao38685502015-07-14 17:46:3945#include "extensions/test/extension_test_message_listener.h"
falkenad185092016-06-16 06:10:0246#include "net/dns/mock_host_resolver.h"
horo1eeddde2015-11-19 05:59:2547#include "net/test/embedded_test_server/embedded_test_server.h"
lazyboy63b994a2017-06-30 21:20:2348#include "url/url_constants.h"
annekao38685502015-07-14 17:46:3949
50namespace extensions {
51
kalman6f984ae2015-09-18 17:21:5852namespace {
53
54// Pass into ServiceWorkerTest::StartTestFromBackgroundPage to indicate that
55// registration is expected to succeed.
56std::string* const kExpectSuccess = nullptr;
57
58void DoNothingWithBool(bool b) {}
59
lazyboy22eddc712015-12-10 21:16:2660// Returns the newly added WebContents.
61content::WebContents* AddTab(Browser* browser, const GURL& url) {
62 int starting_tab_count = browser->tab_strip_model()->count();
63 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:1964 browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
lazyboy22eddc712015-12-10 21:16:2665 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
66 int tab_count = browser->tab_strip_model()->count();
67 EXPECT_EQ(starting_tab_count + 1, tab_count);
68 return browser->tab_strip_model()->GetActiveWebContents();
69}
70
71class WebContentsLoadStopObserver : content::WebContentsObserver {
72 public:
73 explicit WebContentsLoadStopObserver(content::WebContents* web_contents)
74 : content::WebContentsObserver(web_contents),
75 load_stop_observed_(false) {}
76
77 void WaitForLoadStop() {
78 if (load_stop_observed_)
79 return;
80 message_loop_runner_ = new content::MessageLoopRunner;
81 message_loop_runner_->Run();
82 }
83
84 private:
85 void DidStopLoading() override {
86 load_stop_observed_ = true;
87 if (message_loop_runner_)
88 message_loop_runner_->Quit();
89 }
90
91 bool load_stop_observed_;
92 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
93
94 DISALLOW_COPY_AND_ASSIGN(WebContentsLoadStopObserver);
95};
96
kalman6f984ae2015-09-18 17:21:5897} // namespace
98
annekao38685502015-07-14 17:46:3999class ServiceWorkerTest : public ExtensionApiTest {
100 public:
lazyboy20167c22016-05-18 00:59:30101 ServiceWorkerTest() : current_channel_(version_info::Channel::STABLE) {}
annekao38685502015-07-14 17:46:39102
103 ~ServiceWorkerTest() override {}
104
jam1a5b5582017-05-01 16:50:10105 void SetUpOnMainThread() override {
106 ExtensionApiTest::SetUpOnMainThread();
107 host_resolver()->AddRule("a.com", "127.0.0.1");
108 }
109
kalman6f984ae2015-09-18 17:21:58110 protected:
111 // Returns the ProcessManager for the test's profile.
112 ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
113
114 // Starts running a test from the background page test extension.
115 //
116 // This registers a service worker with |script_name|, and fetches the
117 // registration result.
118 //
119 // If |error_or_null| is null (kExpectSuccess), success is expected and this
120 // will fail if there is an error.
121 // If |error_or_null| is not null, nothing is assumed, and the error (which
122 // may be empty) is written to it.
123 const Extension* StartTestFromBackgroundPage(const char* script_name,
124 std::string* error_or_null) {
125 const Extension* extension =
126 LoadExtension(test_data_dir_.AppendASCII("service_worker/background"));
127 CHECK(extension);
128 ExtensionHost* background_host =
129 process_manager()->GetBackgroundHostForExtension(extension->id());
130 CHECK(background_host);
131 std::string error;
132 CHECK(content::ExecuteScriptAndExtractString(
133 background_host->host_contents(),
134 base::StringPrintf("test.registerServiceWorker('%s')", script_name),
135 &error));
136 if (error_or_null)
137 *error_or_null = error;
138 else if (!error.empty())
139 ADD_FAILURE() << "Got unexpected error " << error;
140 return extension;
141 }
142
143 // Navigates the browser to a new tab at |url|, waits for it to load, then
144 // returns it.
145 content::WebContents* Navigate(const GURL& url) {
146 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19147 browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
kalman6f984ae2015-09-18 17:21:58148 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
149 content::WebContents* web_contents =
150 browser()->tab_strip_model()->GetActiveWebContents();
151 content::WaitForLoadStop(web_contents);
152 return web_contents;
153 }
154
155 // Navigates the browser to |url| and returns the new tab's page type.
156 content::PageType NavigateAndGetPageType(const GURL& url) {
157 return Navigate(url)->GetController().GetActiveEntry()->GetPageType();
158 }
159
160 // Extracts the innerText from |contents|.
161 std::string ExtractInnerText(content::WebContents* contents) {
162 std::string inner_text;
163 if (!content::ExecuteScriptAndExtractString(
164 contents,
165 "window.domAutomationController.send(document.body.innerText)",
166 &inner_text)) {
167 ADD_FAILURE() << "Failed to get inner text for "
168 << contents->GetVisibleURL();
169 }
170 return inner_text;
171 }
172
173 // Navigates the browser to |url|, then returns the innerText of the new
174 // tab's WebContents' main frame.
175 std::string NavigateAndExtractInnerText(const GURL& url) {
176 return ExtractInnerText(Navigate(url));
177 }
178
lazyboy4c82177a2016-10-18 00:04:09179 size_t GetWorkerRefCount(const GURL& origin) {
180 content::ServiceWorkerContext* sw_context =
181 content::BrowserContext::GetDefaultStoragePartition(
182 browser()->profile())
183 ->GetServiceWorkerContext();
184 base::RunLoop run_loop;
185 size_t ref_count = 0;
186 auto set_ref_count = [](size_t* ref_count, base::RunLoop* run_loop,
187 size_t external_request_count) {
188 *ref_count = external_request_count;
189 run_loop->Quit();
190 };
191 sw_context->CountExternalRequestsForTest(
Matt Falkenhagenc5cb4282017-09-07 08:43:42192 origin, base::BindOnce(set_ref_count, &ref_count, &run_loop));
lazyboy4c82177a2016-10-18 00:04:09193 run_loop.Run();
194 return ref_count;
195 }
196
annekao38685502015-07-14 17:46:39197 private:
lazyboy20167c22016-05-18 00:59:30198 // Sets the channel to "stable".
199 // Not useful after we've opened extension Service Workers to stable
200 // channel.
201 // TODO(lazyboy): Remove this when ExtensionServiceWorkersEnabled() is
202 // removed.
annekao38685502015-07-14 17:46:39203 ScopedCurrentChannel current_channel_;
kalman6f984ae2015-09-18 17:21:58204
annekao38685502015-07-14 17:46:39205 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTest);
206};
207
lazyboybd325ae2015-11-18 21:35:26208class ServiceWorkerBackgroundSyncTest : public ServiceWorkerTest {
209 public:
210 ServiceWorkerBackgroundSyncTest() {}
211 ~ServiceWorkerBackgroundSyncTest() override {}
212
213 void SetUpCommandLine(base::CommandLine* command_line) override {
214 // ServiceWorkerRegistration.sync requires experimental flag.
215 command_line->AppendSwitch(
216 switches::kEnableExperimentalWebPlatformFeatures);
217 ServiceWorkerTest::SetUpCommandLine(command_line);
218 }
219
220 void SetUp() override {
221 content::background_sync_test_util::SetIgnoreNetworkChangeNotifier(true);
222 ServiceWorkerTest::SetUp();
223 }
224
225 private:
226 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBackgroundSyncTest);
227};
228
lazyboy561b7de2015-11-19 19:27:30229class ServiceWorkerPushMessagingTest : public ServiceWorkerTest {
230 public:
231 ServiceWorkerPushMessagingTest()
johnmea5045732016-09-08 17:23:29232 : gcm_driver_(nullptr), push_service_(nullptr) {}
lazyboy561b7de2015-11-19 19:27:30233 ~ServiceWorkerPushMessagingTest() override {}
234
235 void GrantNotificationPermissionForTest(const GURL& url) {
236 GURL origin = url.GetOrigin();
237 DesktopNotificationProfileUtil::GrantPermission(profile(), origin);
timlohc6911802017-03-01 05:37:03238 ASSERT_EQ(CONTENT_SETTING_ALLOW,
239 PermissionManager::Get(profile())
240 ->GetPermissionStatus(CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
241 origin, origin)
242 .content_setting);
lazyboy561b7de2015-11-19 19:27:30243 }
244
245 PushMessagingAppIdentifier GetAppIdentifierForServiceWorkerRegistration(
avia2f4804a2015-12-24 23:11:13246 int64_t service_worker_registration_id,
lazyboy561b7de2015-11-19 19:27:30247 const GURL& origin) {
248 PushMessagingAppIdentifier app_identifier =
249 PushMessagingAppIdentifier::FindByServiceWorker(
250 profile(), origin, service_worker_registration_id);
251
252 EXPECT_FALSE(app_identifier.is_null());
253 return app_identifier;
254 }
255
256 // ExtensionApiTest overrides.
257 void SetUpCommandLine(base::CommandLine* command_line) override {
peter9de96272015-12-04 15:23:27258 command_line->AppendSwitch(
259 switches::kEnableExperimentalWebPlatformFeatures);
lazyboy561b7de2015-11-19 19:27:30260 ServiceWorkerTest::SetUpCommandLine(command_line);
261 }
262 void SetUpOnMainThread() override {
miguelg9b502862017-04-24 18:13:53263 NotificationDisplayServiceFactory::GetInstance()->SetTestingFactory(
264 profile(), &StubNotificationDisplayService::FactoryForTests);
265
johnmea5045732016-09-08 17:23:29266 gcm::FakeGCMProfileService* gcm_service =
267 static_cast<gcm::FakeGCMProfileService*>(
268 gcm::GCMProfileServiceFactory::GetInstance()
269 ->SetTestingFactoryAndUse(profile(),
270 &gcm::FakeGCMProfileService::Build));
271 gcm_driver_ = static_cast<instance_id::FakeGCMDriverForInstanceID*>(
272 gcm_service->driver());
lazyboy561b7de2015-11-19 19:27:30273 push_service_ = PushMessagingServiceFactory::GetForProfile(profile());
274
275 ServiceWorkerTest::SetUpOnMainThread();
276 }
277
johnmea5045732016-09-08 17:23:29278 instance_id::FakeGCMDriverForInstanceID* gcm_driver() const {
279 return gcm_driver_;
280 }
lazyboy561b7de2015-11-19 19:27:30281 PushMessagingServiceImpl* push_service() const { return push_service_; }
282
283 private:
johnmea5045732016-09-08 17:23:29284 instance_id::FakeGCMDriverForInstanceID* gcm_driver_;
lazyboy561b7de2015-11-19 19:27:30285 PushMessagingServiceImpl* push_service_;
286
287 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPushMessagingTest);
288};
289
lazyboy20167c22016-05-18 00:59:30290IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, RegisterSucceeds) {
kalman6f984ae2015-09-18 17:21:58291 StartTestFromBackgroundPage("register.js", kExpectSuccess);
annekao38685502015-07-14 17:46:39292}
293
lazyboyc3e763a2015-12-09 23:09:58294IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, UpdateRefreshesServiceWorker) {
jam3f2d3932017-04-26 20:28:51295 base::ThreadRestrictions::ScopedAllowIO allow_io;
lazyboyc3e763a2015-12-09 23:09:58296 base::ScopedTempDir scoped_temp_dir;
297 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
298 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
299 .AppendASCII("update")
300 .AppendASCII("service_worker.pem");
vabr9142fe22016-09-08 13:19:22301 base::FilePath path_v1 =
302 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
303 .AppendASCII("update")
304 .AppendASCII("v1"),
305 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
306 pem_path, base::FilePath());
307 base::FilePath path_v2 =
308 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
309 .AppendASCII("update")
310 .AppendASCII("v2"),
311 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
312 pem_path, base::FilePath());
lazyboyc3e763a2015-12-09 23:09:58313 const char* kId = "hfaanndiiilofhfokeanhddpkfffchdi";
314
315 ExtensionTestMessageListener listener_v1("Pong from version 1", false);
316 listener_v1.set_failure_message("FAILURE_V1");
317 // Install version 1.0 of the extension.
318 ASSERT_TRUE(InstallExtension(path_v1, 1));
319 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
320 ->enabled_extensions()
321 .GetByID(kId));
322 EXPECT_TRUE(listener_v1.WaitUntilSatisfied());
323
324 ExtensionTestMessageListener listener_v2("Pong from version 2", false);
325 listener_v2.set_failure_message("FAILURE_V2");
326
327 // Update to version 2.0.
328 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
329 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
330 ->enabled_extensions()
331 .GetByID(kId));
332 EXPECT_TRUE(listener_v2.WaitUntilSatisfied());
333}
334
lazyboy22eddc712015-12-10 21:16:26335IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, UpdateWithoutSkipWaiting) {
jam3f2d3932017-04-26 20:28:51336 base::ThreadRestrictions::ScopedAllowIO allow_io;
lazyboy22eddc712015-12-10 21:16:26337 base::ScopedTempDir scoped_temp_dir;
338 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
339 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
340 .AppendASCII("update_without_skip_waiting")
341 .AppendASCII("update_without_skip_waiting.pem");
vabr9142fe22016-09-08 13:19:22342 base::FilePath path_v1 =
343 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
344 .AppendASCII("update_without_skip_waiting")
345 .AppendASCII("v1"),
346 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
347 pem_path, base::FilePath());
348 base::FilePath path_v2 =
349 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
350 .AppendASCII("update_without_skip_waiting")
351 .AppendASCII("v2"),
352 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
353 pem_path, base::FilePath());
lazyboy22eddc712015-12-10 21:16:26354 const char* kId = "mhnnnflgagdakldgjpfcofkiocpdmogl";
355
356 // Install version 1.0 of the extension.
357 ASSERT_TRUE(InstallExtension(path_v1, 1));
358 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
359 ->enabled_extensions()
360 .GetByID(kId));
361 const Extension* extension = extensions::ExtensionRegistry::Get(profile())
362 ->enabled_extensions()
363 .GetByID(kId);
364
365 ExtensionTestMessageListener listener1("Pong from version 1", false);
366 listener1.set_failure_message("FAILURE");
367 content::WebContents* web_contents =
368 AddTab(browser(), extension->GetResourceURL("page.html"));
369 EXPECT_TRUE(listener1.WaitUntilSatisfied());
370
371 // Update to version 2.0.
372 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
373 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
374 ->enabled_extensions()
375 .GetByID(kId));
376 const Extension* extension_after_update =
377 extensions::ExtensionRegistry::Get(profile())
378 ->enabled_extensions()
379 .GetByID(kId);
380
381 // Service worker version 2 would be installed but it won't be controlling
382 // the extension page yet.
383 ExtensionTestMessageListener listener2("Pong from version 1", false);
384 listener2.set_failure_message("FAILURE");
385 web_contents =
386 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
387 EXPECT_TRUE(listener2.WaitUntilSatisfied());
388
389 // Navigate the tab away from the extension page so that no clients are
390 // using the service worker.
391 // Note that just closing the tab with WebContentsDestroyedWatcher doesn't
392 // seem to be enough because it returns too early.
393 WebContentsLoadStopObserver navigate_away_observer(web_contents);
394 web_contents->GetController().LoadURL(
395 GURL(url::kAboutBlankURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED,
396 std::string());
397 navigate_away_observer.WaitForLoadStop();
398
399 // Now expect service worker version 2 to control the extension page.
400 ExtensionTestMessageListener listener3("Pong from version 2", false);
401 listener3.set_failure_message("FAILURE");
402 web_contents =
403 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
404 EXPECT_TRUE(listener3.WaitUntilSatisfied());
405}
406
kalman6f984ae2015-09-18 17:21:58407IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, FetchArbitraryPaths) {
408 const Extension* extension =
409 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
annekao1db36fd2015-07-29 17:09:16410
kalman6f984ae2015-09-18 17:21:58411 // Open some arbirary paths. Their contents should be what the service worker
412 // responds with, which in this case is the path of the fetch.
413 EXPECT_EQ(
414 "Caught a fetch for /index.html",
415 NavigateAndExtractInnerText(extension->GetResourceURL("index.html")));
416 EXPECT_EQ("Caught a fetch for /path/to/other.html",
417 NavigateAndExtractInnerText(
418 extension->GetResourceURL("path/to/other.html")));
419 EXPECT_EQ("Caught a fetch for /some/text/file.txt",
420 NavigateAndExtractInnerText(
421 extension->GetResourceURL("some/text/file.txt")));
422 EXPECT_EQ("Caught a fetch for /no/file/extension",
423 NavigateAndExtractInnerText(
424 extension->GetResourceURL("no/file/extension")));
425 EXPECT_EQ("Caught a fetch for /",
426 NavigateAndExtractInnerText(extension->GetResourceURL("")));
annekao1db36fd2015-07-29 17:09:16427}
428
lazyboy52c3bcf2016-01-08 00:11:29429IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, SWServedBackgroundPageReceivesEvent) {
430 const Extension* extension =
431 StartTestFromBackgroundPage("replace_background.js", kExpectSuccess);
432 ExtensionHost* background_page =
433 process_manager()->GetBackgroundHostForExtension(extension->id());
434 ASSERT_TRUE(background_page);
435
436 // Close the background page and start it again so that the service worker
437 // will start controlling pages.
438 background_page->Close();
439 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
440 background_page = nullptr;
441 process_manager()->WakeEventPage(extension->id(),
442 base::Bind(&DoNothingWithBool));
443 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
444
445 // Since the SW is now controlling the extension, the SW serves the background
446 // script. page.html sends a message to the background script and we verify
447 // that the SW served background script correctly receives the message/event.
448 ExtensionTestMessageListener listener("onMessage/SW BG.", false);
449 listener.set_failure_message("onMessage/original BG.");
450 content::WebContents* web_contents =
451 AddTab(browser(), extension->GetResourceURL("page.html"));
452 ASSERT_TRUE(web_contents);
453 EXPECT_TRUE(listener.WaitUntilSatisfied());
454}
455
kalman6f984ae2015-09-18 17:21:58456IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
457 LoadingBackgroundPageBypassesServiceWorker) {
458 const Extension* extension =
459 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
annekao49241182015-08-18 17:14:01460
kalman6f984ae2015-09-18 17:21:58461 std::string kExpectedInnerText = "background.html contents for testing.";
annekao49241182015-08-18 17:14:01462
kalman6f984ae2015-09-18 17:21:58463 // Sanity check that the background page has the expected content.
464 ExtensionHost* background_page =
465 process_manager()->GetBackgroundHostForExtension(extension->id());
466 ASSERT_TRUE(background_page);
467 EXPECT_EQ(kExpectedInnerText,
468 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01469
kalman6f984ae2015-09-18 17:21:58470 // Close the background page.
471 background_page->Close();
472 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
473 background_page = nullptr;
474
475 // Start it again.
476 process_manager()->WakeEventPage(extension->id(),
477 base::Bind(&DoNothingWithBool));
478 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
479
480 // Content should not have been affected by the fetch, which would otherwise
481 // be "Caught fetch for...".
482 background_page =
483 process_manager()->GetBackgroundHostForExtension(extension->id());
484 ASSERT_TRUE(background_page);
485 content::WaitForLoadStop(background_page->host_contents());
486
487 // TODO(kalman): Everything you've read has been a LIE! It should be:
488 //
489 // EXPECT_EQ(kExpectedInnerText,
490 // ExtractInnerText(background_page->host_contents()));
491 //
492 // but there is a bug, and we're actually *not* bypassing the service worker
493 // for background page loads! For now, let it pass (assert wrong behavior)
494 // because it's not a regression, but this must be fixed eventually.
495 //
496 // Tracked in crbug.com/532720.
497 EXPECT_EQ("Caught a fetch for /background.html",
498 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01499}
500
kalman6f984ae2015-09-18 17:21:58501IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
502 ServiceWorkerPostsMessageToBackgroundClient) {
503 const Extension* extension = StartTestFromBackgroundPage(
504 "post_message_to_background_client.js", kExpectSuccess);
annekao533482222015-08-21 23:23:53505
kalman6f984ae2015-09-18 17:21:58506 // The service worker in this test simply posts a message to the background
507 // client it receives from getBackgroundClient().
508 const char* kScript =
509 "var messagePromise = null;\n"
510 "if (test.lastMessageFromServiceWorker) {\n"
511 " messagePromise = Promise.resolve(test.lastMessageFromServiceWorker);\n"
512 "} else {\n"
513 " messagePromise = test.waitForMessage(navigator.serviceWorker);\n"
514 "}\n"
515 "messagePromise.then(function(message) {\n"
516 " window.domAutomationController.send(String(message == 'success'));\n"
517 "})\n";
518 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53519}
520
kalman6f984ae2015-09-18 17:21:58521IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
522 BackgroundPagePostsMessageToServiceWorker) {
523 const Extension* extension =
524 StartTestFromBackgroundPage("post_message_to_sw.js", kExpectSuccess);
annekao533482222015-08-21 23:23:53525
kalman6f984ae2015-09-18 17:21:58526 // The service worker in this test waits for a message, then echoes it back
527 // by posting a message to the background page via getBackgroundClient().
528 const char* kScript =
529 "var mc = new MessageChannel();\n"
530 "test.waitForMessage(mc.port1).then(function(message) {\n"
531 " window.domAutomationController.send(String(message == 'hello'));\n"
532 "});\n"
533 "test.registeredServiceWorker.postMessage(\n"
534 " {message: 'hello', port: mc.port2}, [mc.port2])\n";
535 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53536}
537
rdevlin.croninf5863da2015-09-10 19:21:45538IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
539 ServiceWorkerSuspensionOnExtensionUnload) {
kalman6f984ae2015-09-18 17:21:58540 // For this test, only hold onto the extension's ID and URL + a function to
541 // get a resource URL, because we're going to be disabling and uninstalling
542 // it, which will invalidate the pointer.
543 std::string extension_id;
544 GURL extension_url;
545 {
546 const Extension* extension =
547 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
548 extension_id = extension->id();
549 extension_url = extension->url();
550 }
551 auto get_resource_url = [&extension_url](const std::string& path) {
552 return Extension::GetResourceURL(extension_url, path);
553 };
rdevlin.croninf5863da2015-09-10 19:21:45554
kalman6f984ae2015-09-18 17:21:58555 // Fetch should route to the service worker.
556 EXPECT_EQ("Caught a fetch for /index.html",
557 NavigateAndExtractInnerText(get_resource_url("index.html")));
rdevlin.croninf5863da2015-09-10 19:21:45558
kalman6f984ae2015-09-18 17:21:58559 // Disable the extension. Opening the page should fail.
560 extension_service()->DisableExtension(extension_id,
Minh X. Nguyen45479012017-08-18 21:35:36561 disable_reason::DISABLE_USER_ACTION);
rdevlin.croninf5863da2015-09-10 19:21:45562 base::RunLoop().RunUntilIdle();
rdevlin.croninf5863da2015-09-10 19:21:45563
kalman6f984ae2015-09-18 17:21:58564 EXPECT_EQ(content::PAGE_TYPE_ERROR,
565 NavigateAndGetPageType(get_resource_url("index.html")));
566 EXPECT_EQ(content::PAGE_TYPE_ERROR,
567 NavigateAndGetPageType(get_resource_url("other.html")));
568
569 // Re-enable the extension. Opening pages should immediately start to succeed
570 // again.
rdevlin.croninf5863da2015-09-10 19:21:45571 extension_service()->EnableExtension(extension_id);
572 base::RunLoop().RunUntilIdle();
573
kalman6f984ae2015-09-18 17:21:58574 EXPECT_EQ("Caught a fetch for /index.html",
575 NavigateAndExtractInnerText(get_resource_url("index.html")));
576 EXPECT_EQ("Caught a fetch for /other.html",
577 NavigateAndExtractInnerText(get_resource_url("other.html")));
578 EXPECT_EQ("Caught a fetch for /another.html",
579 NavigateAndExtractInnerText(get_resource_url("another.html")));
rdevlin.croninf5863da2015-09-10 19:21:45580
kalman6f984ae2015-09-18 17:21:58581 // Uninstall the extension. Opening pages should fail again.
582 base::string16 error;
583 extension_service()->UninstallExtension(
584 extension_id, UninstallReason::UNINSTALL_REASON_FOR_TESTING,
585 base::Bind(&base::DoNothing), &error);
586 base::RunLoop().RunUntilIdle();
587
588 EXPECT_EQ(content::PAGE_TYPE_ERROR,
589 NavigateAndGetPageType(get_resource_url("index.html")));
590 EXPECT_EQ(content::PAGE_TYPE_ERROR,
591 NavigateAndGetPageType(get_resource_url("other.html")));
592 EXPECT_EQ(content::PAGE_TYPE_ERROR,
593 NavigateAndGetPageType(get_resource_url("anotherother.html")));
594 EXPECT_EQ(content::PAGE_TYPE_ERROR,
595 NavigateAndGetPageType(get_resource_url("final.html")));
596}
597
598IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, BackgroundPageIsWokenIfAsleep) {
599 const Extension* extension =
600 StartTestFromBackgroundPage("wake_on_fetch.js", kExpectSuccess);
601
602 // Navigate to special URLs that this test's service worker recognises, each
603 // making a check then populating the response with either "true" or "false".
604 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
605 "background-client-is-awake")));
606 EXPECT_EQ("true", NavigateAndExtractInnerText(
607 extension->GetResourceURL("ping-background-client")));
608 // Ping more than once for good measure.
609 EXPECT_EQ("true", NavigateAndExtractInnerText(
610 extension->GetResourceURL("ping-background-client")));
611
612 // Shut down the event page. The SW should detect that it's closed, but still
613 // be able to ping it.
614 ExtensionHost* background_page =
615 process_manager()->GetBackgroundHostForExtension(extension->id());
616 ASSERT_TRUE(background_page);
617 background_page->Close();
618 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
619
620 EXPECT_EQ("false", NavigateAndExtractInnerText(extension->GetResourceURL(
621 "background-client-is-awake")));
622 EXPECT_EQ("true", NavigateAndExtractInnerText(
623 extension->GetResourceURL("ping-background-client")));
624 EXPECT_EQ("true", NavigateAndExtractInnerText(
625 extension->GetResourceURL("ping-background-client")));
626 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
627 "background-client-is-awake")));
628}
629
630IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
631 GetBackgroundClientFailsWithNoBackgroundPage) {
632 // This extension doesn't have a background page, only a tab at page.html.
633 // The service worker it registers tries to call getBackgroundClient() and
634 // should fail.
635 // Note that this also tests that service workers can be registered from tabs.
636 EXPECT_TRUE(RunExtensionSubtest("service_worker/no_background", "page.html"));
rdevlin.croninf5863da2015-09-10 19:21:45637}
638
lazyboy6ddb7d62015-11-10 23:15:27639IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, NotificationAPI) {
640 EXPECT_TRUE(RunExtensionSubtest("service_worker/notifications/has_permission",
641 "page.html"));
642}
643
lazyboyaea32c22016-01-04 21:37:07644IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WebAccessibleResourcesFetch) {
645 EXPECT_TRUE(RunExtensionSubtest(
646 "service_worker/web_accessible_resources/fetch/", "page.html"));
647}
648
lazyboyee4adef2016-05-24 00:55:16649IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, TabsCreate) {
650 // Extensions APIs from SW are only enabled on trunk.
651 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
652 const Extension* extension = LoadExtensionWithFlags(
653 test_data_dir_.AppendASCII("service_worker/tabs_create"), kFlagNone);
654 ASSERT_TRUE(extension);
655 ui_test_utils::NavigateToURL(browser(),
656 extension->GetResourceURL("page.html"));
657 content::WebContents* web_contents =
658 browser()->tab_strip_model()->GetActiveWebContents();
659
660 int starting_tab_count = browser()->tab_strip_model()->count();
661 std::string result;
662 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
663 web_contents, "window.runServiceWorker()", &result));
664 ASSERT_EQ("chrome.tabs.create callback", result);
665 EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count());
666
667 // Check extension shutdown path.
668 UnloadExtension(extension->id());
669 EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count());
670}
671
lazyboye7847242017-06-07 23:29:18672IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, Events) {
673 // Extensions APIs from SW are only enabled on trunk.
674 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
675 const Extension* extension = LoadExtensionWithFlags(
676 test_data_dir_.AppendASCII("service_worker/events"), kFlagNone);
677 ASSERT_TRUE(extension);
678 ui_test_utils::NavigateToURL(browser(),
679 extension->GetResourceURL("page.html"));
680 content::WebContents* web_contents =
681 browser()->tab_strip_model()->GetActiveWebContents();
682 std::string result;
683 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
684 web_contents, "window.runEventTest()", &result));
685 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
686}
687
lazyboy63b994a2017-06-30 21:20:23688IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, EventsToStoppedWorker) {
689 // Extensions APIs from SW are only enabled on trunk.
690 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
691 const Extension* extension = LoadExtensionWithFlags(
692 test_data_dir_.AppendASCII("service_worker/events_to_stopped_worker"),
693 kFlagNone);
694 ASSERT_TRUE(extension);
695 ui_test_utils::NavigateToURL(browser(),
696 extension->GetResourceURL("page.html"));
697 content::WebContents* web_contents =
698 browser()->tab_strip_model()->GetActiveWebContents();
699 {
700 std::string result;
701 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
702 web_contents, "window.runServiceWorker()", &result));
703 ASSERT_EQ("ready", result);
704
705 base::RunLoop run_loop;
706 content::StoragePartition* storage_partition =
707 content::BrowserContext::GetDefaultStoragePartition(
708 browser()->profile());
709 content::StopServiceWorkerForPattern(
710 storage_partition->GetServiceWorkerContext(),
711 // The service worker is registered at the top level scope.
712 extension->url(), run_loop.QuitClosure());
713 run_loop.Run();
714 }
715
716 std::string result;
717 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
718 web_contents, "window.createTabThenUpdate()", &result));
719 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
720}
721
lazyboy4c82177a2016-10-18 00:04:09722// Tests that worker ref count increments while extension API function is
723// active.
Istiaque Ahmedb57c9752017-08-20 19:08:57724IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WorkerRefCount) {
lazyboy4c82177a2016-10-18 00:04:09725 // Extensions APIs from SW are only enabled on trunk.
726 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
727 const Extension* extension = LoadExtensionWithFlags(
728 test_data_dir_.AppendASCII("service_worker/api_worker_ref_count"),
729 kFlagNone);
730 ASSERT_TRUE(extension);
731 ui_test_utils::NavigateToURL(browser(),
732 extension->GetResourceURL("page.html"));
733 content::WebContents* web_contents =
734 browser()->tab_strip_model()->GetActiveWebContents();
735
736 ExtensionTestMessageListener worker_start_listener("WORKER STARTED", false);
737 worker_start_listener.set_failure_message("FAILURE");
738 ASSERT_TRUE(
739 content::ExecuteScript(web_contents, "window.runServiceWorker()"));
740 ASSERT_TRUE(worker_start_listener.WaitUntilSatisfied());
741
742 // Service worker should have no pending requests because it hasn't peformed
743 // any extension API request yet.
744 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
745
746 ExtensionTestMessageListener worker_listener("CHECK_REF_COUNT", true);
747 worker_listener.set_failure_message("FAILURE");
748 ASSERT_TRUE(content::ExecuteScript(web_contents, "window.testSendMessage()"));
749 ASSERT_TRUE(worker_listener.WaitUntilSatisfied());
750
751 // Service worker should have exactly one pending request because
752 // chrome.test.sendMessage() API call is in-flight.
753 EXPECT_EQ(1u, GetWorkerRefCount(extension->url()));
754
755 // Peform another extension API request while one is ongoing.
756 {
757 ExtensionTestMessageListener listener("CHECK_REF_COUNT", true);
758 listener.set_failure_message("FAILURE");
759 ASSERT_TRUE(
760 content::ExecuteScript(web_contents, "window.testSendMessage()"));
761 ASSERT_TRUE(listener.WaitUntilSatisfied());
762
763 // Service worker currently has two extension API requests in-flight.
764 EXPECT_EQ(2u, GetWorkerRefCount(extension->url()));
765 // Finish executing the nested chrome.test.sendMessage() first.
766 listener.Reply("Hello world");
767 }
768
Istiaque Ahmedb57c9752017-08-20 19:08:57769 ExtensionTestMessageListener worker_completion_listener("SUCCESS_FROM_WORKER",
770 false);
lazyboy4c82177a2016-10-18 00:04:09771 // Finish executing chrome.test.sendMessage().
772 worker_listener.Reply("Hello world");
Istiaque Ahmedb57c9752017-08-20 19:08:57773 EXPECT_TRUE(worker_completion_listener.WaitUntilSatisfied());
774
775 // The following block makes sure we have received all the IPCs related to
776 // ref-count from the worker.
777 {
778 // The following roundtrip:
779 // browser->extension->worker->extension->browser
780 // will ensure that the worker sent the relevant ref count IPCs.
781 std::string result;
782 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
783 web_contents, "window.roundtripToWorker();", &result));
784 EXPECT_EQ("roundtrip-succeeded", result);
785
786 // Ensure IO thread IPCs run.
787 content::RunAllBlockingPoolTasksUntilIdle();
788 }
lazyboy4c82177a2016-10-18 00:04:09789
790 // The ref count should drop to 0.
791 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
792}
793
lazyboyaea32c22016-01-04 21:37:07794// This test loads a web page that has an iframe pointing to a
795// chrome-extension:// URL. The URL is listed in the extension's
796// web_accessible_resources. Initially the iframe is served from the extension's
797// resource file. After verifying that, we register a Service Worker that
798// controls the extension. Further requests to the same resource as before
799// should now be served by the Service Worker.
800// This test also verifies that if the requested resource exists in the manifest
801// but is not present in the extension directory, the Service Worker can still
802// serve the resource file.
803IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WebAccessibleResourcesIframeSrc) {
804 const Extension* extension = LoadExtensionWithFlags(
805 test_data_dir_.AppendASCII(
806 "service_worker/web_accessible_resources/iframe_src"),
807 kFlagNone);
808 ASSERT_TRUE(extension);
809 ASSERT_TRUE(StartEmbeddedTestServer());
falkenad185092016-06-16 06:10:02810
811 // Service workers can only control secure contexts
812 // (https://w3c.github.io/webappsec-secure-contexts/). For documents, this
813 // typically means the document must have a secure origin AND all its ancestor
814 // frames must have documents with secure origins. However, extension pages
815 // are considered secure, even if they have an ancestor document that is an
816 // insecure context (see GetSchemesBypassingSecureContextCheckWhitelist). So
817 // extension service workers must be able to control an extension page
818 // embedded in an insecure context. To test this, set up an insecure
819 // (non-localhost, non-https) URL for the web page. This page will create
820 // iframes that load extension pages that must be controllable by service
821 // worker.
falkenad185092016-06-16 06:10:02822 GURL page_url =
823 embedded_test_server()->GetURL("a.com",
824 "/extensions/api_test/service_worker/"
825 "web_accessible_resources/webpage.html");
826 EXPECT_FALSE(content::IsOriginSecure(page_url));
lazyboyaea32c22016-01-04 21:37:07827
828 content::WebContents* web_contents = AddTab(browser(), page_url);
829 std::string result;
830 // webpage.html will create an iframe pointing to a resource from |extension|.
831 // Expect the resource to be served by the extension.
832 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
833 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
834 extension->id().c_str()),
835 &result));
836 EXPECT_EQ("FROM_EXTENSION_RESOURCE", result);
837
838 ExtensionTestMessageListener service_worker_ready_listener("SW_READY", false);
839 EXPECT_TRUE(ExecuteScriptInBackgroundPageNoWait(
840 extension->id(), "window.registerServiceWorker()"));
841 EXPECT_TRUE(service_worker_ready_listener.WaitUntilSatisfied());
842
843 result.clear();
844 // webpage.html will create another iframe pointing to a resource from
845 // |extension| as before. But this time, the resource should be be served
846 // from the Service Worker.
847 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
848 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
849 extension->id().c_str()),
850 &result));
851 EXPECT_EQ("FROM_SW_RESOURCE", result);
852
853 result.clear();
854 // webpage.html will create yet another iframe pointing to a resource that
855 // exists in the extension manifest's web_accessible_resources, but is not
856 // present in the extension directory. Expect the resources of the iframe to
857 // be served by the Service Worker.
858 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
859 web_contents,
860 base::StringPrintf("window.testIframe('%s', 'iframe_non_existent.html')",
861 extension->id().c_str()),
862 &result));
863 EXPECT_EQ("FROM_SW_RESOURCE", result);
864}
865
Istiaque Ahmed311f4832017-08-17 00:13:32866IN_PROC_BROWSER_TEST_F(ServiceWorkerBackgroundSyncTest, Sync) {
lazyboybd325ae2015-11-18 21:35:26867 const Extension* extension = LoadExtensionWithFlags(
868 test_data_dir_.AppendASCII("service_worker/sync"), kFlagNone);
869 ASSERT_TRUE(extension);
870 ui_test_utils::NavigateToURL(browser(),
871 extension->GetResourceURL("page.html"));
872 content::WebContents* web_contents =
873 browser()->tab_strip_model()->GetActiveWebContents();
874
875 // Prevent firing by going offline.
876 content::background_sync_test_util::SetOnline(web_contents, false);
877
878 ExtensionTestMessageListener sync_listener("SYNC: send-chats", false);
879 sync_listener.set_failure_message("FAIL");
880
881 std::string result;
882 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
883 web_contents, "window.runServiceWorker()", &result));
884 ASSERT_EQ("SERVICE_WORKER_READY", result);
885
886 EXPECT_FALSE(sync_listener.was_satisfied());
887 // Resume firing by going online.
888 content::background_sync_test_util::SetOnline(web_contents, true);
889 EXPECT_TRUE(sync_listener.WaitUntilSatisfied());
890}
891
horo1eeddde2015-11-19 05:59:25892IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
893 FetchFromContentScriptShouldNotGoToServiceWorkerOfPage) {
894 ASSERT_TRUE(StartEmbeddedTestServer());
895 GURL page_url = embedded_test_server()->GetURL(
896 "/extensions/api_test/service_worker/content_script_fetch/"
897 "controlled_page/index.html");
898 content::WebContents* tab =
899 browser()->tab_strip_model()->GetActiveWebContents();
900 ui_test_utils::NavigateToURL(browser(), page_url);
901 content::WaitForLoadStop(tab);
902
903 std::string value;
904 ASSERT_TRUE(
905 content::ExecuteScriptAndExtractString(tab, "register();", &value));
906 EXPECT_EQ("SW controlled", value);
907
908 ASSERT_TRUE(RunExtensionTest("service_worker/content_script_fetch"))
909 << message_;
910}
911
lazyboyd429e2582016-05-20 20:18:52912IN_PROC_BROWSER_TEST_F(ServiceWorkerPushMessagingTest, OnPush) {
lazyboy561b7de2015-11-19 19:27:30913 const Extension* extension = LoadExtensionWithFlags(
914 test_data_dir_.AppendASCII("service_worker/push_messaging"), kFlagNone);
915 ASSERT_TRUE(extension);
916 GURL extension_url = extension->url();
917
918 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest(extension_url));
919
920 GURL url = extension->GetResourceURL("page.html");
921 ui_test_utils::NavigateToURL(browser(), url);
922
923 content::WebContents* web_contents =
924 browser()->tab_strip_model()->GetActiveWebContents();
925
926 // Start the ServiceWorker.
927 ExtensionTestMessageListener ready_listener("SERVICE_WORKER_READY", false);
928 ready_listener.set_failure_message("SERVICE_WORKER_FAILURE");
929 const char* kScript = "window.runServiceWorker()";
930 EXPECT_TRUE(content::ExecuteScript(web_contents->GetMainFrame(), kScript));
931 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
932
933 PushMessagingAppIdentifier app_identifier =
934 GetAppIdentifierForServiceWorkerRegistration(0LL, extension_url);
johnmea5045732016-09-08 17:23:29935 ASSERT_EQ(app_identifier.app_id(), gcm_driver()->last_gettoken_app_id());
936 EXPECT_EQ("1234567890", gcm_driver()->last_gettoken_authorized_entity());
lazyboy561b7de2015-11-19 19:27:30937
lazyboyd429e2582016-05-20 20:18:52938 base::RunLoop run_loop;
lazyboy561b7de2015-11-19 19:27:30939 // Send a push message via gcm and expect the ServiceWorker to receive it.
940 ExtensionTestMessageListener push_message_listener("OK", false);
941 push_message_listener.set_failure_message("FAIL");
942 gcm::IncomingMessage message;
943 message.sender_id = "1234567890";
944 message.raw_data = "testdata";
945 message.decrypted = true;
lazyboyd429e2582016-05-20 20:18:52946 push_service()->SetMessageCallbackForTesting(run_loop.QuitClosure());
lazyboy561b7de2015-11-19 19:27:30947 push_service()->OnMessage(app_identifier.app_id(), message);
948 EXPECT_TRUE(push_message_listener.WaitUntilSatisfied());
lazyboyd429e2582016-05-20 20:18:52949 run_loop.Run(); // Wait until the message is handled by push service.
lazyboy561b7de2015-11-19 19:27:30950}
951
annekao38685502015-07-14 17:46:39952} // namespace extensions