blob: b578697b693f3d6257f8a12994e684ef31fccbc2 [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"
Istiaque Ahmedea5ed5042017-09-25 19:00:1644#include "extensions/common/switches.h"
kalman6f984ae2015-09-18 17:21:5845#include "extensions/test/background_page_watcher.h"
annekao38685502015-07-14 17:46:3946#include "extensions/test/extension_test_message_listener.h"
falkenad185092016-06-16 06:10:0247#include "net/dns/mock_host_resolver.h"
horo1eeddde2015-11-19 05:59:2548#include "net/test/embedded_test_server/embedded_test_server.h"
lazyboy63b994a2017-06-30 21:20:2349#include "url/url_constants.h"
annekao38685502015-07-14 17:46:3950
51namespace extensions {
52
kalman6f984ae2015-09-18 17:21:5853namespace {
54
55// Pass into ServiceWorkerTest::StartTestFromBackgroundPage to indicate that
56// registration is expected to succeed.
57std::string* const kExpectSuccess = nullptr;
58
59void DoNothingWithBool(bool b) {}
60
lazyboy22eddc712015-12-10 21:16:2661// Returns the newly added WebContents.
62content::WebContents* AddTab(Browser* browser, const GURL& url) {
63 int starting_tab_count = browser->tab_strip_model()->count();
64 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:1965 browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
lazyboy22eddc712015-12-10 21:16:2666 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
67 int tab_count = browser->tab_strip_model()->count();
68 EXPECT_EQ(starting_tab_count + 1, tab_count);
69 return browser->tab_strip_model()->GetActiveWebContents();
70}
71
Istiaque Ahmedea5ed5042017-09-25 19:00:1672enum BindingsType { NATIVE_BINDINGS, JAVASCRIPT_BINDINGS };
73
lazyboy22eddc712015-12-10 21:16:2674class WebContentsLoadStopObserver : content::WebContentsObserver {
75 public:
76 explicit WebContentsLoadStopObserver(content::WebContents* web_contents)
77 : content::WebContentsObserver(web_contents),
78 load_stop_observed_(false) {}
79
80 void WaitForLoadStop() {
81 if (load_stop_observed_)
82 return;
83 message_loop_runner_ = new content::MessageLoopRunner;
84 message_loop_runner_->Run();
85 }
86
87 private:
88 void DidStopLoading() override {
89 load_stop_observed_ = true;
90 if (message_loop_runner_)
91 message_loop_runner_->Quit();
92 }
93
94 bool load_stop_observed_;
95 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
96
97 DISALLOW_COPY_AND_ASSIGN(WebContentsLoadStopObserver);
98};
99
kalman6f984ae2015-09-18 17:21:58100} // namespace
101
Istiaque Ahmedea5ed5042017-09-25 19:00:16102class ServiceWorkerTest : public ExtensionApiTest,
103 public ::testing::WithParamInterface<BindingsType> {
annekao38685502015-07-14 17:46:39104 public:
lazyboy20167c22016-05-18 00:59:30105 ServiceWorkerTest() : current_channel_(version_info::Channel::STABLE) {}
annekao38685502015-07-14 17:46:39106
107 ~ServiceWorkerTest() override {}
108
jam1a5b5582017-05-01 16:50:10109 void SetUpOnMainThread() override {
110 ExtensionApiTest::SetUpOnMainThread();
111 host_resolver()->AddRule("a.com", "127.0.0.1");
112 }
113
Istiaque Ahmedea5ed5042017-09-25 19:00:16114 void SetUpCommandLine(base::CommandLine* command_line) override {
115 ExtensionApiTest::SetUpCommandLine(command_line);
116 command_line->AppendSwitchASCII(switches::kNativeCrxBindings,
117 GetParam() == NATIVE_BINDINGS ? "1" : "0");
118 }
119
kalman6f984ae2015-09-18 17:21:58120 protected:
121 // Returns the ProcessManager for the test's profile.
122 ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
123
124 // Starts running a test from the background page test extension.
125 //
126 // This registers a service worker with |script_name|, and fetches the
127 // registration result.
128 //
129 // If |error_or_null| is null (kExpectSuccess), success is expected and this
130 // will fail if there is an error.
131 // If |error_or_null| is not null, nothing is assumed, and the error (which
132 // may be empty) is written to it.
133 const Extension* StartTestFromBackgroundPage(const char* script_name,
134 std::string* error_or_null) {
135 const Extension* extension =
136 LoadExtension(test_data_dir_.AppendASCII("service_worker/background"));
137 CHECK(extension);
138 ExtensionHost* background_host =
139 process_manager()->GetBackgroundHostForExtension(extension->id());
140 CHECK(background_host);
141 std::string error;
142 CHECK(content::ExecuteScriptAndExtractString(
143 background_host->host_contents(),
144 base::StringPrintf("test.registerServiceWorker('%s')", script_name),
145 &error));
146 if (error_or_null)
147 *error_or_null = error;
148 else if (!error.empty())
149 ADD_FAILURE() << "Got unexpected error " << error;
150 return extension;
151 }
152
153 // Navigates the browser to a new tab at |url|, waits for it to load, then
154 // returns it.
155 content::WebContents* Navigate(const GURL& url) {
156 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19157 browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
kalman6f984ae2015-09-18 17:21:58158 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
159 content::WebContents* web_contents =
160 browser()->tab_strip_model()->GetActiveWebContents();
161 content::WaitForLoadStop(web_contents);
162 return web_contents;
163 }
164
165 // Navigates the browser to |url| and returns the new tab's page type.
166 content::PageType NavigateAndGetPageType(const GURL& url) {
167 return Navigate(url)->GetController().GetActiveEntry()->GetPageType();
168 }
169
170 // Extracts the innerText from |contents|.
171 std::string ExtractInnerText(content::WebContents* contents) {
172 std::string inner_text;
173 if (!content::ExecuteScriptAndExtractString(
174 contents,
175 "window.domAutomationController.send(document.body.innerText)",
176 &inner_text)) {
177 ADD_FAILURE() << "Failed to get inner text for "
178 << contents->GetVisibleURL();
179 }
180 return inner_text;
181 }
182
183 // Navigates the browser to |url|, then returns the innerText of the new
184 // tab's WebContents' main frame.
185 std::string NavigateAndExtractInnerText(const GURL& url) {
186 return ExtractInnerText(Navigate(url));
187 }
188
lazyboy4c82177a2016-10-18 00:04:09189 size_t GetWorkerRefCount(const GURL& origin) {
190 content::ServiceWorkerContext* sw_context =
191 content::BrowserContext::GetDefaultStoragePartition(
192 browser()->profile())
193 ->GetServiceWorkerContext();
194 base::RunLoop run_loop;
195 size_t ref_count = 0;
196 auto set_ref_count = [](size_t* ref_count, base::RunLoop* run_loop,
197 size_t external_request_count) {
198 *ref_count = external_request_count;
199 run_loop->Quit();
200 };
201 sw_context->CountExternalRequestsForTest(
Matt Falkenhagenc5cb4282017-09-07 08:43:42202 origin, base::BindOnce(set_ref_count, &ref_count, &run_loop));
lazyboy4c82177a2016-10-18 00:04:09203 run_loop.Run();
204 return ref_count;
205 }
206
annekao38685502015-07-14 17:46:39207 private:
lazyboy20167c22016-05-18 00:59:30208 // Sets the channel to "stable".
209 // Not useful after we've opened extension Service Workers to stable
210 // channel.
211 // TODO(lazyboy): Remove this when ExtensionServiceWorkersEnabled() is
212 // removed.
annekao38685502015-07-14 17:46:39213 ScopedCurrentChannel current_channel_;
kalman6f984ae2015-09-18 17:21:58214
annekao38685502015-07-14 17:46:39215 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTest);
216};
217
lazyboybd325ae2015-11-18 21:35:26218class ServiceWorkerBackgroundSyncTest : public ServiceWorkerTest {
219 public:
220 ServiceWorkerBackgroundSyncTest() {}
221 ~ServiceWorkerBackgroundSyncTest() override {}
222
223 void SetUpCommandLine(base::CommandLine* command_line) override {
224 // ServiceWorkerRegistration.sync requires experimental flag.
225 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16226 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboybd325ae2015-11-18 21:35:26227 ServiceWorkerTest::SetUpCommandLine(command_line);
228 }
229
230 void SetUp() override {
231 content::background_sync_test_util::SetIgnoreNetworkChangeNotifier(true);
232 ServiceWorkerTest::SetUp();
233 }
234
235 private:
236 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBackgroundSyncTest);
237};
238
lazyboy561b7de2015-11-19 19:27:30239class ServiceWorkerPushMessagingTest : public ServiceWorkerTest {
240 public:
241 ServiceWorkerPushMessagingTest()
johnmea5045732016-09-08 17:23:29242 : gcm_driver_(nullptr), push_service_(nullptr) {}
lazyboy561b7de2015-11-19 19:27:30243 ~ServiceWorkerPushMessagingTest() override {}
244
245 void GrantNotificationPermissionForTest(const GURL& url) {
246 GURL origin = url.GetOrigin();
247 DesktopNotificationProfileUtil::GrantPermission(profile(), origin);
timlohc6911802017-03-01 05:37:03248 ASSERT_EQ(CONTENT_SETTING_ALLOW,
249 PermissionManager::Get(profile())
250 ->GetPermissionStatus(CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
251 origin, origin)
252 .content_setting);
lazyboy561b7de2015-11-19 19:27:30253 }
254
255 PushMessagingAppIdentifier GetAppIdentifierForServiceWorkerRegistration(
avia2f4804a2015-12-24 23:11:13256 int64_t service_worker_registration_id,
lazyboy561b7de2015-11-19 19:27:30257 const GURL& origin) {
258 PushMessagingAppIdentifier app_identifier =
259 PushMessagingAppIdentifier::FindByServiceWorker(
260 profile(), origin, service_worker_registration_id);
261
262 EXPECT_FALSE(app_identifier.is_null());
263 return app_identifier;
264 }
265
266 // ExtensionApiTest overrides.
267 void SetUpCommandLine(base::CommandLine* command_line) override {
peter9de96272015-12-04 15:23:27268 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16269 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboy561b7de2015-11-19 19:27:30270 ServiceWorkerTest::SetUpCommandLine(command_line);
271 }
272 void SetUpOnMainThread() override {
miguelg9b502862017-04-24 18:13:53273 NotificationDisplayServiceFactory::GetInstance()->SetTestingFactory(
274 profile(), &StubNotificationDisplayService::FactoryForTests);
275
johnmea5045732016-09-08 17:23:29276 gcm::FakeGCMProfileService* gcm_service =
277 static_cast<gcm::FakeGCMProfileService*>(
278 gcm::GCMProfileServiceFactory::GetInstance()
279 ->SetTestingFactoryAndUse(profile(),
280 &gcm::FakeGCMProfileService::Build));
281 gcm_driver_ = static_cast<instance_id::FakeGCMDriverForInstanceID*>(
282 gcm_service->driver());
lazyboy561b7de2015-11-19 19:27:30283 push_service_ = PushMessagingServiceFactory::GetForProfile(profile());
284
285 ServiceWorkerTest::SetUpOnMainThread();
286 }
287
johnmea5045732016-09-08 17:23:29288 instance_id::FakeGCMDriverForInstanceID* gcm_driver() const {
289 return gcm_driver_;
290 }
lazyboy561b7de2015-11-19 19:27:30291 PushMessagingServiceImpl* push_service() const { return push_service_; }
292
293 private:
johnmea5045732016-09-08 17:23:29294 instance_id::FakeGCMDriverForInstanceID* gcm_driver_;
lazyboy561b7de2015-11-19 19:27:30295 PushMessagingServiceImpl* push_service_;
296
297 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPushMessagingTest);
298};
299
Istiaque Ahmedea5ed5042017-09-25 19:00:16300IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, RegisterSucceeds) {
kalman6f984ae2015-09-18 17:21:58301 StartTestFromBackgroundPage("register.js", kExpectSuccess);
annekao38685502015-07-14 17:46:39302}
303
Istiaque Ahmedea5ed5042017-09-25 19:00:16304IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, UpdateRefreshesServiceWorker) {
jam3f2d3932017-04-26 20:28:51305 base::ThreadRestrictions::ScopedAllowIO allow_io;
lazyboyc3e763a2015-12-09 23:09:58306 base::ScopedTempDir scoped_temp_dir;
307 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
308 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
309 .AppendASCII("update")
310 .AppendASCII("service_worker.pem");
vabr9142fe22016-09-08 13:19:22311 base::FilePath path_v1 =
312 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
313 .AppendASCII("update")
314 .AppendASCII("v1"),
315 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
316 pem_path, base::FilePath());
317 base::FilePath path_v2 =
318 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
319 .AppendASCII("update")
320 .AppendASCII("v2"),
321 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
322 pem_path, base::FilePath());
lazyboyc3e763a2015-12-09 23:09:58323 const char* kId = "hfaanndiiilofhfokeanhddpkfffchdi";
324
325 ExtensionTestMessageListener listener_v1("Pong from version 1", false);
326 listener_v1.set_failure_message("FAILURE_V1");
327 // Install version 1.0 of the extension.
328 ASSERT_TRUE(InstallExtension(path_v1, 1));
329 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
330 ->enabled_extensions()
331 .GetByID(kId));
332 EXPECT_TRUE(listener_v1.WaitUntilSatisfied());
333
334 ExtensionTestMessageListener listener_v2("Pong from version 2", false);
335 listener_v2.set_failure_message("FAILURE_V2");
336
337 // Update to version 2.0.
338 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
339 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
340 ->enabled_extensions()
341 .GetByID(kId));
342 EXPECT_TRUE(listener_v2.WaitUntilSatisfied());
343}
344
[email protected]2ef85d562017-09-15 18:41:52345// TODO(crbug.com/765736) Fix the test.
Istiaque Ahmedea5ed5042017-09-25 19:00:16346IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, DISABLED_UpdateWithoutSkipWaiting) {
jam3f2d3932017-04-26 20:28:51347 base::ThreadRestrictions::ScopedAllowIO allow_io;
lazyboy22eddc712015-12-10 21:16:26348 base::ScopedTempDir scoped_temp_dir;
349 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
350 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
351 .AppendASCII("update_without_skip_waiting")
352 .AppendASCII("update_without_skip_waiting.pem");
vabr9142fe22016-09-08 13:19:22353 base::FilePath path_v1 =
354 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
355 .AppendASCII("update_without_skip_waiting")
356 .AppendASCII("v1"),
357 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
358 pem_path, base::FilePath());
359 base::FilePath path_v2 =
360 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
361 .AppendASCII("update_without_skip_waiting")
362 .AppendASCII("v2"),
363 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
364 pem_path, base::FilePath());
lazyboy22eddc712015-12-10 21:16:26365 const char* kId = "mhnnnflgagdakldgjpfcofkiocpdmogl";
366
367 // Install version 1.0 of the extension.
368 ASSERT_TRUE(InstallExtension(path_v1, 1));
369 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
370 ->enabled_extensions()
371 .GetByID(kId));
372 const Extension* extension = extensions::ExtensionRegistry::Get(profile())
373 ->enabled_extensions()
374 .GetByID(kId);
375
376 ExtensionTestMessageListener listener1("Pong from version 1", false);
377 listener1.set_failure_message("FAILURE");
378 content::WebContents* web_contents =
379 AddTab(browser(), extension->GetResourceURL("page.html"));
380 EXPECT_TRUE(listener1.WaitUntilSatisfied());
381
382 // Update to version 2.0.
383 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
384 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
385 ->enabled_extensions()
386 .GetByID(kId));
387 const Extension* extension_after_update =
388 extensions::ExtensionRegistry::Get(profile())
389 ->enabled_extensions()
390 .GetByID(kId);
391
392 // Service worker version 2 would be installed but it won't be controlling
393 // the extension page yet.
394 ExtensionTestMessageListener listener2("Pong from version 1", false);
395 listener2.set_failure_message("FAILURE");
396 web_contents =
397 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
398 EXPECT_TRUE(listener2.WaitUntilSatisfied());
399
400 // Navigate the tab away from the extension page so that no clients are
401 // using the service worker.
402 // Note that just closing the tab with WebContentsDestroyedWatcher doesn't
403 // seem to be enough because it returns too early.
404 WebContentsLoadStopObserver navigate_away_observer(web_contents);
405 web_contents->GetController().LoadURL(
406 GURL(url::kAboutBlankURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED,
407 std::string());
408 navigate_away_observer.WaitForLoadStop();
409
410 // Now expect service worker version 2 to control the extension page.
411 ExtensionTestMessageListener listener3("Pong from version 2", false);
412 listener3.set_failure_message("FAILURE");
413 web_contents =
414 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
415 EXPECT_TRUE(listener3.WaitUntilSatisfied());
416}
417
Istiaque Ahmedea5ed5042017-09-25 19:00:16418IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, FetchArbitraryPaths) {
kalman6f984ae2015-09-18 17:21:58419 const Extension* extension =
420 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
annekao1db36fd2015-07-29 17:09:16421
kalman6f984ae2015-09-18 17:21:58422 // Open some arbirary paths. Their contents should be what the service worker
423 // responds with, which in this case is the path of the fetch.
424 EXPECT_EQ(
425 "Caught a fetch for /index.html",
426 NavigateAndExtractInnerText(extension->GetResourceURL("index.html")));
427 EXPECT_EQ("Caught a fetch for /path/to/other.html",
428 NavigateAndExtractInnerText(
429 extension->GetResourceURL("path/to/other.html")));
430 EXPECT_EQ("Caught a fetch for /some/text/file.txt",
431 NavigateAndExtractInnerText(
432 extension->GetResourceURL("some/text/file.txt")));
433 EXPECT_EQ("Caught a fetch for /no/file/extension",
434 NavigateAndExtractInnerText(
435 extension->GetResourceURL("no/file/extension")));
436 EXPECT_EQ("Caught a fetch for /",
437 NavigateAndExtractInnerText(extension->GetResourceURL("")));
annekao1db36fd2015-07-29 17:09:16438}
439
Istiaque Ahmedea5ed5042017-09-25 19:00:16440IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, SWServedBackgroundPageReceivesEvent) {
lazyboy52c3bcf2016-01-08 00:11:29441 const Extension* extension =
442 StartTestFromBackgroundPage("replace_background.js", kExpectSuccess);
443 ExtensionHost* background_page =
444 process_manager()->GetBackgroundHostForExtension(extension->id());
445 ASSERT_TRUE(background_page);
446
447 // Close the background page and start it again so that the service worker
448 // will start controlling pages.
449 background_page->Close();
450 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
451 background_page = nullptr;
452 process_manager()->WakeEventPage(extension->id(),
453 base::Bind(&DoNothingWithBool));
454 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
455
456 // Since the SW is now controlling the extension, the SW serves the background
457 // script. page.html sends a message to the background script and we verify
458 // that the SW served background script correctly receives the message/event.
459 ExtensionTestMessageListener listener("onMessage/SW BG.", false);
460 listener.set_failure_message("onMessage/original BG.");
461 content::WebContents* web_contents =
462 AddTab(browser(), extension->GetResourceURL("page.html"));
463 ASSERT_TRUE(web_contents);
464 EXPECT_TRUE(listener.WaitUntilSatisfied());
465}
466
Istiaque Ahmedea5ed5042017-09-25 19:00:16467IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58468 LoadingBackgroundPageBypassesServiceWorker) {
469 const Extension* extension =
470 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
annekao49241182015-08-18 17:14:01471
kalman6f984ae2015-09-18 17:21:58472 std::string kExpectedInnerText = "background.html contents for testing.";
annekao49241182015-08-18 17:14:01473
kalman6f984ae2015-09-18 17:21:58474 // Sanity check that the background page has the expected content.
475 ExtensionHost* background_page =
476 process_manager()->GetBackgroundHostForExtension(extension->id());
477 ASSERT_TRUE(background_page);
478 EXPECT_EQ(kExpectedInnerText,
479 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01480
kalman6f984ae2015-09-18 17:21:58481 // Close the background page.
482 background_page->Close();
483 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
484 background_page = nullptr;
485
486 // Start it again.
487 process_manager()->WakeEventPage(extension->id(),
488 base::Bind(&DoNothingWithBool));
489 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
490
491 // Content should not have been affected by the fetch, which would otherwise
492 // be "Caught fetch for...".
493 background_page =
494 process_manager()->GetBackgroundHostForExtension(extension->id());
495 ASSERT_TRUE(background_page);
496 content::WaitForLoadStop(background_page->host_contents());
497
498 // TODO(kalman): Everything you've read has been a LIE! It should be:
499 //
500 // EXPECT_EQ(kExpectedInnerText,
501 // ExtractInnerText(background_page->host_contents()));
502 //
503 // but there is a bug, and we're actually *not* bypassing the service worker
504 // for background page loads! For now, let it pass (assert wrong behavior)
505 // because it's not a regression, but this must be fixed eventually.
506 //
507 // Tracked in crbug.com/532720.
508 EXPECT_EQ("Caught a fetch for /background.html",
509 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01510}
511
Istiaque Ahmedea5ed5042017-09-25 19:00:16512IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58513 ServiceWorkerPostsMessageToBackgroundClient) {
514 const Extension* extension = StartTestFromBackgroundPage(
515 "post_message_to_background_client.js", kExpectSuccess);
annekao533482222015-08-21 23:23:53516
kalman6f984ae2015-09-18 17:21:58517 // The service worker in this test simply posts a message to the background
518 // client it receives from getBackgroundClient().
519 const char* kScript =
520 "var messagePromise = null;\n"
521 "if (test.lastMessageFromServiceWorker) {\n"
522 " messagePromise = Promise.resolve(test.lastMessageFromServiceWorker);\n"
523 "} else {\n"
524 " messagePromise = test.waitForMessage(navigator.serviceWorker);\n"
525 "}\n"
526 "messagePromise.then(function(message) {\n"
527 " window.domAutomationController.send(String(message == 'success'));\n"
528 "})\n";
529 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53530}
531
Istiaque Ahmedea5ed5042017-09-25 19:00:16532IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58533 BackgroundPagePostsMessageToServiceWorker) {
534 const Extension* extension =
535 StartTestFromBackgroundPage("post_message_to_sw.js", kExpectSuccess);
annekao533482222015-08-21 23:23:53536
kalman6f984ae2015-09-18 17:21:58537 // The service worker in this test waits for a message, then echoes it back
538 // by posting a message to the background page via getBackgroundClient().
539 const char* kScript =
540 "var mc = new MessageChannel();\n"
541 "test.waitForMessage(mc.port1).then(function(message) {\n"
542 " window.domAutomationController.send(String(message == 'hello'));\n"
543 "});\n"
544 "test.registeredServiceWorker.postMessage(\n"
545 " {message: 'hello', port: mc.port2}, [mc.port2])\n";
546 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53547}
548
Istiaque Ahmedea5ed5042017-09-25 19:00:16549IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
rdevlin.croninf5863da2015-09-10 19:21:45550 ServiceWorkerSuspensionOnExtensionUnload) {
kalman6f984ae2015-09-18 17:21:58551 // For this test, only hold onto the extension's ID and URL + a function to
552 // get a resource URL, because we're going to be disabling and uninstalling
553 // it, which will invalidate the pointer.
554 std::string extension_id;
555 GURL extension_url;
556 {
557 const Extension* extension =
558 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
559 extension_id = extension->id();
560 extension_url = extension->url();
561 }
562 auto get_resource_url = [&extension_url](const std::string& path) {
563 return Extension::GetResourceURL(extension_url, path);
564 };
rdevlin.croninf5863da2015-09-10 19:21:45565
kalman6f984ae2015-09-18 17:21:58566 // Fetch should route to the service worker.
567 EXPECT_EQ("Caught a fetch for /index.html",
568 NavigateAndExtractInnerText(get_resource_url("index.html")));
rdevlin.croninf5863da2015-09-10 19:21:45569
kalman6f984ae2015-09-18 17:21:58570 // Disable the extension. Opening the page should fail.
571 extension_service()->DisableExtension(extension_id,
Minh X. Nguyen45479012017-08-18 21:35:36572 disable_reason::DISABLE_USER_ACTION);
rdevlin.croninf5863da2015-09-10 19:21:45573 base::RunLoop().RunUntilIdle();
rdevlin.croninf5863da2015-09-10 19:21:45574
kalman6f984ae2015-09-18 17:21:58575 EXPECT_EQ(content::PAGE_TYPE_ERROR,
576 NavigateAndGetPageType(get_resource_url("index.html")));
577 EXPECT_EQ(content::PAGE_TYPE_ERROR,
578 NavigateAndGetPageType(get_resource_url("other.html")));
579
580 // Re-enable the extension. Opening pages should immediately start to succeed
581 // again.
rdevlin.croninf5863da2015-09-10 19:21:45582 extension_service()->EnableExtension(extension_id);
583 base::RunLoop().RunUntilIdle();
584
kalman6f984ae2015-09-18 17:21:58585 EXPECT_EQ("Caught a fetch for /index.html",
586 NavigateAndExtractInnerText(get_resource_url("index.html")));
587 EXPECT_EQ("Caught a fetch for /other.html",
588 NavigateAndExtractInnerText(get_resource_url("other.html")));
589 EXPECT_EQ("Caught a fetch for /another.html",
590 NavigateAndExtractInnerText(get_resource_url("another.html")));
rdevlin.croninf5863da2015-09-10 19:21:45591
kalman6f984ae2015-09-18 17:21:58592 // Uninstall the extension. Opening pages should fail again.
593 base::string16 error;
594 extension_service()->UninstallExtension(
595 extension_id, UninstallReason::UNINSTALL_REASON_FOR_TESTING,
596 base::Bind(&base::DoNothing), &error);
597 base::RunLoop().RunUntilIdle();
598
599 EXPECT_EQ(content::PAGE_TYPE_ERROR,
600 NavigateAndGetPageType(get_resource_url("index.html")));
601 EXPECT_EQ(content::PAGE_TYPE_ERROR,
602 NavigateAndGetPageType(get_resource_url("other.html")));
603 EXPECT_EQ(content::PAGE_TYPE_ERROR,
604 NavigateAndGetPageType(get_resource_url("anotherother.html")));
605 EXPECT_EQ(content::PAGE_TYPE_ERROR,
606 NavigateAndGetPageType(get_resource_url("final.html")));
607}
608
Istiaque Ahmedea5ed5042017-09-25 19:00:16609IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, BackgroundPageIsWokenIfAsleep) {
kalman6f984ae2015-09-18 17:21:58610 const Extension* extension =
611 StartTestFromBackgroundPage("wake_on_fetch.js", kExpectSuccess);
612
613 // Navigate to special URLs that this test's service worker recognises, each
614 // making a check then populating the response with either "true" or "false".
615 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
616 "background-client-is-awake")));
617 EXPECT_EQ("true", NavigateAndExtractInnerText(
618 extension->GetResourceURL("ping-background-client")));
619 // Ping more than once for good measure.
620 EXPECT_EQ("true", NavigateAndExtractInnerText(
621 extension->GetResourceURL("ping-background-client")));
622
623 // Shut down the event page. The SW should detect that it's closed, but still
624 // be able to ping it.
625 ExtensionHost* background_page =
626 process_manager()->GetBackgroundHostForExtension(extension->id());
627 ASSERT_TRUE(background_page);
628 background_page->Close();
629 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
630
631 EXPECT_EQ("false", NavigateAndExtractInnerText(extension->GetResourceURL(
632 "background-client-is-awake")));
633 EXPECT_EQ("true", NavigateAndExtractInnerText(
634 extension->GetResourceURL("ping-background-client")));
635 EXPECT_EQ("true", NavigateAndExtractInnerText(
636 extension->GetResourceURL("ping-background-client")));
637 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
638 "background-client-is-awake")));
639}
640
Istiaque Ahmedea5ed5042017-09-25 19:00:16641IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58642 GetBackgroundClientFailsWithNoBackgroundPage) {
643 // This extension doesn't have a background page, only a tab at page.html.
644 // The service worker it registers tries to call getBackgroundClient() and
645 // should fail.
646 // Note that this also tests that service workers can be registered from tabs.
647 EXPECT_TRUE(RunExtensionSubtest("service_worker/no_background", "page.html"));
rdevlin.croninf5863da2015-09-10 19:21:45648}
649
Istiaque Ahmedea5ed5042017-09-25 19:00:16650IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, NotificationAPI) {
lazyboy6ddb7d62015-11-10 23:15:27651 EXPECT_TRUE(RunExtensionSubtest("service_worker/notifications/has_permission",
652 "page.html"));
653}
654
Istiaque Ahmedea5ed5042017-09-25 19:00:16655IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WebAccessibleResourcesFetch) {
lazyboyaea32c22016-01-04 21:37:07656 EXPECT_TRUE(RunExtensionSubtest(
657 "service_worker/web_accessible_resources/fetch/", "page.html"));
658}
659
Istiaque Ahmedea5ed5042017-09-25 19:00:16660IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, TabsCreate) {
lazyboyee4adef2016-05-24 00:55:16661 // Extensions APIs from SW are only enabled on trunk.
662 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
663 const Extension* extension = LoadExtensionWithFlags(
664 test_data_dir_.AppendASCII("service_worker/tabs_create"), kFlagNone);
665 ASSERT_TRUE(extension);
666 ui_test_utils::NavigateToURL(browser(),
667 extension->GetResourceURL("page.html"));
668 content::WebContents* web_contents =
669 browser()->tab_strip_model()->GetActiveWebContents();
670
671 int starting_tab_count = browser()->tab_strip_model()->count();
672 std::string result;
673 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
674 web_contents, "window.runServiceWorker()", &result));
675 ASSERT_EQ("chrome.tabs.create callback", result);
676 EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count());
677
678 // Check extension shutdown path.
679 UnloadExtension(extension->id());
680 EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count());
681}
682
Istiaque Ahmedea5ed5042017-09-25 19:00:16683IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, Events) {
lazyboye7847242017-06-07 23:29:18684 // Extensions APIs from SW are only enabled on trunk.
685 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
686 const Extension* extension = LoadExtensionWithFlags(
687 test_data_dir_.AppendASCII("service_worker/events"), kFlagNone);
688 ASSERT_TRUE(extension);
689 ui_test_utils::NavigateToURL(browser(),
690 extension->GetResourceURL("page.html"));
691 content::WebContents* web_contents =
692 browser()->tab_strip_model()->GetActiveWebContents();
693 std::string result;
694 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
695 web_contents, "window.runEventTest()", &result));
696 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
697}
698
Istiaque Ahmedea5ed5042017-09-25 19:00:16699IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, EventsToStoppedWorker) {
lazyboy63b994a2017-06-30 21:20:23700 // Extensions APIs from SW are only enabled on trunk.
701 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
702 const Extension* extension = LoadExtensionWithFlags(
703 test_data_dir_.AppendASCII("service_worker/events_to_stopped_worker"),
704 kFlagNone);
705 ASSERT_TRUE(extension);
706 ui_test_utils::NavigateToURL(browser(),
707 extension->GetResourceURL("page.html"));
708 content::WebContents* web_contents =
709 browser()->tab_strip_model()->GetActiveWebContents();
710 {
711 std::string result;
712 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
713 web_contents, "window.runServiceWorker()", &result));
714 ASSERT_EQ("ready", result);
715
716 base::RunLoop run_loop;
717 content::StoragePartition* storage_partition =
718 content::BrowserContext::GetDefaultStoragePartition(
719 browser()->profile());
720 content::StopServiceWorkerForPattern(
721 storage_partition->GetServiceWorkerContext(),
722 // The service worker is registered at the top level scope.
723 extension->url(), run_loop.QuitClosure());
724 run_loop.Run();
725 }
726
727 std::string result;
728 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
729 web_contents, "window.createTabThenUpdate()", &result));
730 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
731}
732
lazyboy4c82177a2016-10-18 00:04:09733// Tests that worker ref count increments while extension API function is
734// active.
Istiaque Ahmedea5ed5042017-09-25 19:00:16735IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WorkerRefCount) {
lazyboy4c82177a2016-10-18 00:04:09736 // Extensions APIs from SW are only enabled on trunk.
737 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
738 const Extension* extension = LoadExtensionWithFlags(
739 test_data_dir_.AppendASCII("service_worker/api_worker_ref_count"),
740 kFlagNone);
741 ASSERT_TRUE(extension);
742 ui_test_utils::NavigateToURL(browser(),
743 extension->GetResourceURL("page.html"));
744 content::WebContents* web_contents =
745 browser()->tab_strip_model()->GetActiveWebContents();
746
747 ExtensionTestMessageListener worker_start_listener("WORKER STARTED", false);
748 worker_start_listener.set_failure_message("FAILURE");
749 ASSERT_TRUE(
750 content::ExecuteScript(web_contents, "window.runServiceWorker()"));
751 ASSERT_TRUE(worker_start_listener.WaitUntilSatisfied());
752
753 // Service worker should have no pending requests because it hasn't peformed
754 // any extension API request yet.
755 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
756
757 ExtensionTestMessageListener worker_listener("CHECK_REF_COUNT", true);
758 worker_listener.set_failure_message("FAILURE");
759 ASSERT_TRUE(content::ExecuteScript(web_contents, "window.testSendMessage()"));
760 ASSERT_TRUE(worker_listener.WaitUntilSatisfied());
761
762 // Service worker should have exactly one pending request because
763 // chrome.test.sendMessage() API call is in-flight.
764 EXPECT_EQ(1u, GetWorkerRefCount(extension->url()));
765
766 // Peform another extension API request while one is ongoing.
767 {
768 ExtensionTestMessageListener listener("CHECK_REF_COUNT", true);
769 listener.set_failure_message("FAILURE");
770 ASSERT_TRUE(
771 content::ExecuteScript(web_contents, "window.testSendMessage()"));
772 ASSERT_TRUE(listener.WaitUntilSatisfied());
773
774 // Service worker currently has two extension API requests in-flight.
775 EXPECT_EQ(2u, GetWorkerRefCount(extension->url()));
776 // Finish executing the nested chrome.test.sendMessage() first.
777 listener.Reply("Hello world");
778 }
779
Istiaque Ahmedb57c9752017-08-20 19:08:57780 ExtensionTestMessageListener worker_completion_listener("SUCCESS_FROM_WORKER",
781 false);
lazyboy4c82177a2016-10-18 00:04:09782 // Finish executing chrome.test.sendMessage().
783 worker_listener.Reply("Hello world");
Istiaque Ahmedb57c9752017-08-20 19:08:57784 EXPECT_TRUE(worker_completion_listener.WaitUntilSatisfied());
785
786 // The following block makes sure we have received all the IPCs related to
787 // ref-count from the worker.
788 {
789 // The following roundtrip:
790 // browser->extension->worker->extension->browser
791 // will ensure that the worker sent the relevant ref count IPCs.
792 std::string result;
793 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
794 web_contents, "window.roundtripToWorker();", &result));
795 EXPECT_EQ("roundtrip-succeeded", result);
796
797 // Ensure IO thread IPCs run.
Gabriel Charette01507a22017-09-27 21:30:08798 content::RunAllTasksUntilIdle();
Istiaque Ahmedb57c9752017-08-20 19:08:57799 }
lazyboy4c82177a2016-10-18 00:04:09800
801 // The ref count should drop to 0.
802 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
803}
804
lazyboyaea32c22016-01-04 21:37:07805// This test loads a web page that has an iframe pointing to a
806// chrome-extension:// URL. The URL is listed in the extension's
807// web_accessible_resources. Initially the iframe is served from the extension's
808// resource file. After verifying that, we register a Service Worker that
809// controls the extension. Further requests to the same resource as before
810// should now be served by the Service Worker.
811// This test also verifies that if the requested resource exists in the manifest
812// but is not present in the extension directory, the Service Worker can still
813// serve the resource file.
Istiaque Ahmedea5ed5042017-09-25 19:00:16814IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WebAccessibleResourcesIframeSrc) {
lazyboyaea32c22016-01-04 21:37:07815 const Extension* extension = LoadExtensionWithFlags(
816 test_data_dir_.AppendASCII(
817 "service_worker/web_accessible_resources/iframe_src"),
818 kFlagNone);
819 ASSERT_TRUE(extension);
820 ASSERT_TRUE(StartEmbeddedTestServer());
falkenad185092016-06-16 06:10:02821
822 // Service workers can only control secure contexts
823 // (https://w3c.github.io/webappsec-secure-contexts/). For documents, this
824 // typically means the document must have a secure origin AND all its ancestor
825 // frames must have documents with secure origins. However, extension pages
826 // are considered secure, even if they have an ancestor document that is an
827 // insecure context (see GetSchemesBypassingSecureContextCheckWhitelist). So
828 // extension service workers must be able to control an extension page
829 // embedded in an insecure context. To test this, set up an insecure
830 // (non-localhost, non-https) URL for the web page. This page will create
831 // iframes that load extension pages that must be controllable by service
832 // worker.
falkenad185092016-06-16 06:10:02833 GURL page_url =
834 embedded_test_server()->GetURL("a.com",
835 "/extensions/api_test/service_worker/"
836 "web_accessible_resources/webpage.html");
837 EXPECT_FALSE(content::IsOriginSecure(page_url));
lazyboyaea32c22016-01-04 21:37:07838
839 content::WebContents* web_contents = AddTab(browser(), page_url);
840 std::string result;
841 // webpage.html will create an iframe pointing to a resource from |extension|.
842 // Expect the resource to be served by the extension.
843 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
844 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
845 extension->id().c_str()),
846 &result));
847 EXPECT_EQ("FROM_EXTENSION_RESOURCE", result);
848
849 ExtensionTestMessageListener service_worker_ready_listener("SW_READY", false);
850 EXPECT_TRUE(ExecuteScriptInBackgroundPageNoWait(
851 extension->id(), "window.registerServiceWorker()"));
852 EXPECT_TRUE(service_worker_ready_listener.WaitUntilSatisfied());
853
854 result.clear();
855 // webpage.html will create another iframe pointing to a resource from
856 // |extension| as before. But this time, the resource should be be served
857 // from the Service Worker.
858 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
859 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
860 extension->id().c_str()),
861 &result));
862 EXPECT_EQ("FROM_SW_RESOURCE", result);
863
864 result.clear();
865 // webpage.html will create yet another iframe pointing to a resource that
866 // exists in the extension manifest's web_accessible_resources, but is not
867 // present in the extension directory. Expect the resources of the iframe to
868 // be served by the Service Worker.
869 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
870 web_contents,
871 base::StringPrintf("window.testIframe('%s', 'iframe_non_existent.html')",
872 extension->id().c_str()),
873 &result));
874 EXPECT_EQ("FROM_SW_RESOURCE", result);
875}
876
Istiaque Ahmedea5ed5042017-09-25 19:00:16877IN_PROC_BROWSER_TEST_P(ServiceWorkerBackgroundSyncTest, Sync) {
lazyboybd325ae2015-11-18 21:35:26878 const Extension* extension = LoadExtensionWithFlags(
879 test_data_dir_.AppendASCII("service_worker/sync"), kFlagNone);
880 ASSERT_TRUE(extension);
881 ui_test_utils::NavigateToURL(browser(),
882 extension->GetResourceURL("page.html"));
883 content::WebContents* web_contents =
884 browser()->tab_strip_model()->GetActiveWebContents();
885
886 // Prevent firing by going offline.
887 content::background_sync_test_util::SetOnline(web_contents, false);
888
889 ExtensionTestMessageListener sync_listener("SYNC: send-chats", false);
890 sync_listener.set_failure_message("FAIL");
891
892 std::string result;
893 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
894 web_contents, "window.runServiceWorker()", &result));
895 ASSERT_EQ("SERVICE_WORKER_READY", result);
896
897 EXPECT_FALSE(sync_listener.was_satisfied());
898 // Resume firing by going online.
899 content::background_sync_test_util::SetOnline(web_contents, true);
900 EXPECT_TRUE(sync_listener.WaitUntilSatisfied());
901}
902
Istiaque Ahmedea5ed5042017-09-25 19:00:16903IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
horo1eeddde2015-11-19 05:59:25904 FetchFromContentScriptShouldNotGoToServiceWorkerOfPage) {
905 ASSERT_TRUE(StartEmbeddedTestServer());
906 GURL page_url = embedded_test_server()->GetURL(
907 "/extensions/api_test/service_worker/content_script_fetch/"
908 "controlled_page/index.html");
909 content::WebContents* tab =
910 browser()->tab_strip_model()->GetActiveWebContents();
911 ui_test_utils::NavigateToURL(browser(), page_url);
912 content::WaitForLoadStop(tab);
913
914 std::string value;
915 ASSERT_TRUE(
916 content::ExecuteScriptAndExtractString(tab, "register();", &value));
917 EXPECT_EQ("SW controlled", value);
918
919 ASSERT_TRUE(RunExtensionTest("service_worker/content_script_fetch"))
920 << message_;
921}
922
Istiaque Ahmedea5ed5042017-09-25 19:00:16923IN_PROC_BROWSER_TEST_P(ServiceWorkerPushMessagingTest, OnPush) {
lazyboy561b7de2015-11-19 19:27:30924 const Extension* extension = LoadExtensionWithFlags(
925 test_data_dir_.AppendASCII("service_worker/push_messaging"), kFlagNone);
926 ASSERT_TRUE(extension);
927 GURL extension_url = extension->url();
928
929 ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest(extension_url));
930
931 GURL url = extension->GetResourceURL("page.html");
932 ui_test_utils::NavigateToURL(browser(), url);
933
934 content::WebContents* web_contents =
935 browser()->tab_strip_model()->GetActiveWebContents();
936
937 // Start the ServiceWorker.
938 ExtensionTestMessageListener ready_listener("SERVICE_WORKER_READY", false);
939 ready_listener.set_failure_message("SERVICE_WORKER_FAILURE");
940 const char* kScript = "window.runServiceWorker()";
941 EXPECT_TRUE(content::ExecuteScript(web_contents->GetMainFrame(), kScript));
942 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
943
944 PushMessagingAppIdentifier app_identifier =
945 GetAppIdentifierForServiceWorkerRegistration(0LL, extension_url);
johnmea5045732016-09-08 17:23:29946 ASSERT_EQ(app_identifier.app_id(), gcm_driver()->last_gettoken_app_id());
947 EXPECT_EQ("1234567890", gcm_driver()->last_gettoken_authorized_entity());
lazyboy561b7de2015-11-19 19:27:30948
lazyboyd429e2582016-05-20 20:18:52949 base::RunLoop run_loop;
lazyboy561b7de2015-11-19 19:27:30950 // Send a push message via gcm and expect the ServiceWorker to receive it.
951 ExtensionTestMessageListener push_message_listener("OK", false);
952 push_message_listener.set_failure_message("FAIL");
953 gcm::IncomingMessage message;
954 message.sender_id = "1234567890";
955 message.raw_data = "testdata";
956 message.decrypted = true;
lazyboyd429e2582016-05-20 20:18:52957 push_service()->SetMessageCallbackForTesting(run_loop.QuitClosure());
lazyboy561b7de2015-11-19 19:27:30958 push_service()->OnMessage(app_identifier.app_id(), message);
959 EXPECT_TRUE(push_message_listener.WaitUntilSatisfied());
lazyboyd429e2582016-05-20 20:18:52960 run_loop.Run(); // Wait until the message is handled by push service.
lazyboy561b7de2015-11-19 19:27:30961}
962
Istiaque Ahmedea5ed5042017-09-25 19:00:16963IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, FilteredEvents) {
Istiaque Ahmed9d1666182017-09-21 23:58:18964 // Extensions APIs from SW are only enabled on trunk.
965 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
966 ASSERT_TRUE(RunExtensionTest("service_worker/filtered_events"));
967}
968
Istiaque Ahmedea5ed5042017-09-25 19:00:16969// Run with both native and JS-based bindings. This ensures that both stable
970// (JS) and experimental (native) phases work correctly with worker scripts
971// while we launch native bindings to stable.
972INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
973 ServiceWorkerTest,
974 ::testing::Values(NATIVE_BINDINGS));
975INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
976 ServiceWorkerTest,
977 ::testing::Values(JAVASCRIPT_BINDINGS));
978INSTANTIATE_TEST_CASE_P(ServiceWorkerBackgroundSyncTestWithNativeBindings,
979 ServiceWorkerBackgroundSyncTest,
980 ::testing::Values(NATIVE_BINDINGS));
981INSTANTIATE_TEST_CASE_P(ServiceWorkerBackgroundSyncTestWithJSBindings,
982 ServiceWorkerBackgroundSyncTest,
983 ::testing::Values(JAVASCRIPT_BINDINGS));
984INSTANTIATE_TEST_CASE_P(ServiceWorkerPushMessagingTestWithNativeBindings,
985 ServiceWorkerPushMessagingTest,
986 ::testing::Values(NATIVE_BINDINGS));
987INSTANTIATE_TEST_CASE_P(ServiceWorkerPushMessagingTestWithJSBindings,
988 ServiceWorkerPushMessagingTest,
989 ::testing::Values(JAVASCRIPT_BINDINGS));
990
annekao38685502015-07-14 17:46:39991} // namespace extensions