blob: e3d7ca47f2b892d56ddbed5fd9179a702b9b9024 [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
Sylvain Defresne4fdc727fd2018-10-04 11:09:467#include "base/bind.h"
kalman6f984ae2015-09-18 17:21:588#include "base/bind_helpers.h"
Istiaque Ahmeda14ec482018-08-25 01:02:189#include "base/json/json_reader.h"
avia2f4804a2015-12-24 23:11:1310#include "base/macros.h"
Istiaque Ahmedd4b67ee2019-03-02 10:53:2011#include "base/optional.h"
Gabriel Charette078e3662017-08-28 22:59:0412#include "base/run_loop.h"
kalman6f984ae2015-09-18 17:21:5813#include "base/strings/stringprintf.h"
horo1eeddde2015-11-19 05:59:2514#include "base/strings/utf_string_conversions.h"
David Bertoni1d646a152019-04-25 02:09:2215#include "base/test/bind_test_util.h"
jam3f2d3932017-04-26 20:28:5116#include "base/threading/thread_restrictions.h"
Olga Sharonova3e13cd92018-02-08 16:43:5617#include "build/build_config.h"
annekao38685502015-07-14 17:46:3918#include "chrome/browser/extensions/extension_apitest.h"
rdevlin.croninf5863da2015-09-10 19:21:4519#include "chrome/browser/extensions/extension_service.h"
Istiaque Ahmed805f6a83b2017-10-05 01:23:2620#include "chrome/browser/extensions/lazy_background_page_test_util.h"
David Bertoni1d646a152019-04-25 02:09:2221#include "chrome/browser/extensions/unpacked_installer.h"
peter9f4490a2017-01-27 00:58:3622#include "chrome/browser/gcm/gcm_profile_service_factory.h"
miguelg9b502862017-04-24 18:13:5323#include "chrome/browser/notifications/notification_display_service_factory.h"
Peter Beverloodd4ef1e2018-06-21 15:41:0424#include "chrome/browser/notifications/notification_permission_context.h"
miguelg9b502862017-04-24 18:13:5325#include "chrome/browser/notifications/stub_notification_display_service.h"
lshang106c1772016-06-06 01:43:2326#include "chrome/browser/permissions/permission_manager.h"
timlohc6911802017-03-01 05:37:0327#include "chrome/browser/permissions/permission_result.h"
lazyboy561b7de2015-11-19 19:27:3028#include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
29#include "chrome/browser/push_messaging/push_messaging_service_factory.h"
30#include "chrome/browser/push_messaging/push_messaging_service_impl.h"
annekao1db36fd2015-07-29 17:09:1631#include "chrome/browser/ui/tabs/tab_strip_model.h"
Trent Apted4267b942017-10-27 03:25:3632#include "chrome/common/chrome_switches.h"
Istiaque Ahmeda14ec482018-08-25 01:02:1833#include "chrome/common/extensions/api/web_navigation.h"
rdevlin.croninf5863da2015-09-10 19:21:4534#include "chrome/test/base/ui_test_utils.h"
timloh9a180ad2017-02-20 07:15:2335#include "components/content_settings/core/common/content_settings_types.h"
Peter Beverloo34139462018-04-10 14:18:0636#include "components/gcm_driver/fake_gcm_profile_service.h"
johnmea5045732016-09-08 17:23:2937#include "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h"
sdefresne9fb67692015-08-03 18:48:2238#include "components/version_info/version_info.h"
Devlin Cronin59551d82019-03-05 01:28:5939#include "content/public/browser/console_message.h"
kalman6f984ae2015-09-18 17:21:5840#include "content/public/browser/navigation_controller.h"
rdevlin.croninf5863da2015-09-10 19:21:4541#include "content/public/browser/navigation_entry.h"
Istiaque Ahmedd4b67ee2019-03-02 10:53:2042#include "content/public/browser/render_process_host.h"
lazyboy4c82177a2016-10-18 00:04:0943#include "content/public/browser/service_worker_context.h"
Devlin Cronin59551d82019-03-05 01:28:5944#include "content/public/browser/service_worker_context_observer.h"
lazyboy4c82177a2016-10-18 00:04:0945#include "content/public/browser/storage_partition.h"
kalman6f984ae2015-09-18 17:21:5846#include "content/public/browser/web_contents.h"
lazyboybd325ae2015-11-18 21:35:2647#include "content/public/common/content_switches.h"
falkenad185092016-06-16 06:10:0248#include "content/public/common/origin_util.h"
kalman6f984ae2015-09-18 17:21:5849#include "content/public/common/page_type.h"
Istiaque Ahmedd4b67ee2019-03-02 10:53:2050#include "content/public/common/result_codes.h"
lazyboybd325ae2015-11-18 21:35:2651#include "content/public/test/background_sync_test_util.h"
annekao1db36fd2015-07-29 17:09:1652#include "content/public/test/browser_test_utils.h"
lazyboy63b994a2017-06-30 21:20:2353#include "content/public/test/service_worker_test_helpers.h"
Istiaque Ahmed771aa8a22018-06-20 23:40:5354#include "extensions/browser/event_router.h"
kalman6f984ae2015-09-18 17:21:5855#include "extensions/browser/extension_host.h"
lazyboyc3e763a2015-12-09 23:09:5856#include "extensions/browser/extension_registry.h"
kalman6f984ae2015-09-18 17:21:5857#include "extensions/browser/process_manager.h"
Istiaque Ahmed70f76ac2018-11-02 02:59:5558#include "extensions/browser/service_worker_task_queue.h"
Istiaque Ahmeda14ec482018-08-25 01:02:1859#include "extensions/common/api/test.h"
Istiaque Ahmed771aa8a22018-06-20 23:40:5360#include "extensions/common/value_builder.h"
kalman6f984ae2015-09-18 17:21:5861#include "extensions/test/background_page_watcher.h"
annekao38685502015-07-14 17:46:3962#include "extensions/test/extension_test_message_listener.h"
Istiaque Ahmed805f6a83b2017-10-05 01:23:2663#include "extensions/test/result_catcher.h"
Devlin Cronin59551d82019-03-05 01:28:5964#include "extensions/test/test_extension_dir.h"
falkenad185092016-06-16 06:10:0265#include "net/dns/mock_host_resolver.h"
horo1eeddde2015-11-19 05:59:2566#include "net/test/embedded_test_server/embedded_test_server.h"
lazyboy63b994a2017-06-30 21:20:2367#include "url/url_constants.h"
annekao38685502015-07-14 17:46:3968
69namespace extensions {
70
kalman6f984ae2015-09-18 17:21:5871namespace {
72
lazyboy22eddc712015-12-10 21:16:2673// Returns the newly added WebContents.
74content::WebContents* AddTab(Browser* browser, const GURL& url) {
75 int starting_tab_count = browser->tab_strip_model()->count();
76 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:1977 browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
lazyboy22eddc712015-12-10 21:16:2678 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
79 int tab_count = browser->tab_strip_model()->count();
80 EXPECT_EQ(starting_tab_count + 1, tab_count);
81 return browser->tab_strip_model()->GetActiveWebContents();
82}
83
lazyboy22eddc712015-12-10 21:16:2684class WebContentsLoadStopObserver : content::WebContentsObserver {
85 public:
86 explicit WebContentsLoadStopObserver(content::WebContents* web_contents)
87 : content::WebContentsObserver(web_contents),
88 load_stop_observed_(false) {}
89
90 void WaitForLoadStop() {
91 if (load_stop_observed_)
92 return;
93 message_loop_runner_ = new content::MessageLoopRunner;
94 message_loop_runner_->Run();
95 }
96
97 private:
98 void DidStopLoading() override {
99 load_stop_observed_ = true;
100 if (message_loop_runner_)
101 message_loop_runner_->Quit();
102 }
103
104 bool load_stop_observed_;
105 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
106
107 DISALLOW_COPY_AND_ASSIGN(WebContentsLoadStopObserver);
108};
109
kalman6f984ae2015-09-18 17:21:58110} // namespace
111
Devlin Cronin242d19d22019-03-12 18:08:48112class ServiceWorkerTest : public ExtensionApiTest {
annekao38685502015-07-14 17:46:39113 public:
lazyboy20167c22016-05-18 00:59:30114 ServiceWorkerTest() : current_channel_(version_info::Channel::STABLE) {}
Istiaque Ahmed7105f2a2017-10-07 01:11:59115 explicit ServiceWorkerTest(version_info::Channel channel)
116 : current_channel_(channel) {}
annekao38685502015-07-14 17:46:39117
118 ~ServiceWorkerTest() override {}
119
jam1a5b5582017-05-01 16:50:10120 void SetUpOnMainThread() override {
121 ExtensionApiTest::SetUpOnMainThread();
David Bertoni3929f552019-03-28 22:10:36122 host_resolver()->AddRule("*", "127.0.0.1");
jam1a5b5582017-05-01 16:50:10123 }
124
kalman6f984ae2015-09-18 17:21:58125 protected:
126 // Returns the ProcessManager for the test's profile.
127 ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
128
129 // Starts running a test from the background page test extension.
130 //
131 // This registers a service worker with |script_name|, and fetches the
132 // registration result.
Istiaque Ahmed93ff7f42018-08-31 01:42:22133 const Extension* StartTestFromBackgroundPage(const char* script_name) {
Istiaque Ahmed6475f542018-08-28 04:20:21134 ExtensionTestMessageListener ready_listener("ready", false);
kalman6f984ae2015-09-18 17:21:58135 const Extension* extension =
136 LoadExtension(test_data_dir_.AppendASCII("service_worker/background"));
137 CHECK(extension);
Istiaque Ahmed6475f542018-08-28 04:20:21138 CHECK(ready_listener.WaitUntilSatisfied());
139
kalman6f984ae2015-09-18 17:21:58140 ExtensionHost* background_host =
141 process_manager()->GetBackgroundHostForExtension(extension->id());
142 CHECK(background_host);
Istiaque Ahmed6475f542018-08-28 04:20:21143
kalman6f984ae2015-09-18 17:21:58144 std::string error;
145 CHECK(content::ExecuteScriptAndExtractString(
146 background_host->host_contents(),
147 base::StringPrintf("test.registerServiceWorker('%s')", script_name),
148 &error));
Istiaque Ahmed93ff7f42018-08-31 01:42:22149 if (!error.empty())
kalman6f984ae2015-09-18 17:21:58150 ADD_FAILURE() << "Got unexpected error " << error;
151 return extension;
152 }
153
154 // Navigates the browser to a new tab at |url|, waits for it to load, then
155 // returns it.
156 content::WebContents* Navigate(const GURL& url) {
157 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19158 browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
kalman6f984ae2015-09-18 17:21:58159 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
160 content::WebContents* web_contents =
161 browser()->tab_strip_model()->GetActiveWebContents();
162 content::WaitForLoadStop(web_contents);
163 return web_contents;
164 }
165
166 // Navigates the browser to |url| and returns the new tab's page type.
167 content::PageType NavigateAndGetPageType(const GURL& url) {
clamy1d7a4112018-06-15 15:47:16168 return Navigate(url)
169 ->GetController()
170 .GetLastCommittedEntry()
171 ->GetPageType();
kalman6f984ae2015-09-18 17:21:58172 }
173
174 // Extracts the innerText from |contents|.
175 std::string ExtractInnerText(content::WebContents* contents) {
176 std::string inner_text;
177 if (!content::ExecuteScriptAndExtractString(
178 contents,
179 "window.domAutomationController.send(document.body.innerText)",
180 &inner_text)) {
181 ADD_FAILURE() << "Failed to get inner text for "
182 << contents->GetVisibleURL();
183 }
184 return inner_text;
185 }
186
187 // Navigates the browser to |url|, then returns the innerText of the new
188 // tab's WebContents' main frame.
189 std::string NavigateAndExtractInnerText(const GURL& url) {
190 return ExtractInnerText(Navigate(url));
191 }
192
lazyboy4c82177a2016-10-18 00:04:09193 size_t GetWorkerRefCount(const GURL& origin) {
194 content::ServiceWorkerContext* sw_context =
195 content::BrowserContext::GetDefaultStoragePartition(
196 browser()->profile())
197 ->GetServiceWorkerContext();
198 base::RunLoop run_loop;
199 size_t ref_count = 0;
200 auto set_ref_count = [](size_t* ref_count, base::RunLoop* run_loop,
201 size_t external_request_count) {
202 *ref_count = external_request_count;
203 run_loop->Quit();
204 };
205 sw_context->CountExternalRequestsForTest(
Matt Falkenhagenc5cb4282017-09-07 08:43:42206 origin, base::BindOnce(set_ref_count, &ref_count, &run_loop));
lazyboy4c82177a2016-10-18 00:04:09207 run_loop.Run();
208 return ref_count;
209 }
210
annekao38685502015-07-14 17:46:39211 private:
lazyboy20167c22016-05-18 00:59:30212 // Sets the channel to "stable".
213 // Not useful after we've opened extension Service Workers to stable
214 // channel.
215 // TODO(lazyboy): Remove this when ExtensionServiceWorkersEnabled() is
216 // removed.
annekao38685502015-07-14 17:46:39217 ScopedCurrentChannel current_channel_;
kalman6f984ae2015-09-18 17:21:58218
annekao38685502015-07-14 17:46:39219 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTest);
220};
221
Istiaque Ahmedccb444022018-06-19 02:11:12222class ServiceWorkerBasedBackgroundTest : public ServiceWorkerTest {
223 public:
224 ServiceWorkerBasedBackgroundTest()
225 : ServiceWorkerTest(
226 // Extensions APIs from SW are only enabled on trunk.
227 // It is important to set the channel early so that this change is
228 // visible in renderers running with service workers (and no
229 // extension).
230 version_info::Channel::UNKNOWN) {}
231 ~ServiceWorkerBasedBackgroundTest() override {}
232
233 void SetUpOnMainThread() override {
234 host_resolver()->AddRule("*", "127.0.0.1");
235 ASSERT_TRUE(embedded_test_server()->Start());
236 ServiceWorkerTest::SetUpOnMainThread();
237 }
238
Istiaque Ahmedd4b67ee2019-03-02 10:53:20239 // Returns the only running worker id for |extension_id|.
240 // Returns base::nullopt if there isn't any worker running or more than one
241 // worker is running for |extension_id|.
242 base::Optional<WorkerId> GetUniqueRunningWorkerId(
243 const ExtensionId& extension_id) {
244 ProcessManager* process_manager = ProcessManager::Get(profile());
245 std::vector<WorkerId> all_workers =
246 process_manager->GetAllWorkersIdsForTesting();
247 base::Optional<WorkerId> running_worker_id;
248 for (const WorkerId& worker_id : all_workers) {
249 if (worker_id.extension_id == extension_id) {
250 if (running_worker_id) // More than one worker present.
251 return base::nullopt;
252 running_worker_id = worker_id;
253 }
254 }
255 return running_worker_id;
256 }
257
Istiaque Ahmedccb444022018-06-19 02:11:12258 private:
259 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBasedBackgroundTest);
260};
261
262// Tests that Service Worker based background pages can be loaded and they can
263// receive extension events.
264// The extension is installed and loaded during this step and it registers
265// an event listener for tabs.onCreated event. The step also verifies that tab
266// creation correctly fires the listener.
Devlin Cronin242d19d22019-03-12 18:08:48267IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, PRE_Basic) {
Istiaque Ahmedccb444022018-06-19 02:11:12268 ExtensionTestMessageListener newtab_listener("CREATED", false);
269 newtab_listener.set_failure_message("CREATE_FAILED");
270 ExtensionTestMessageListener worker_listener("WORKER_RUNNING", false);
271 worker_listener.set_failure_message("NON_WORKER_SCOPE");
272 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
273 "service_worker/worker_based_background/basic"));
274 ASSERT_TRUE(extension);
275 const ExtensionId extension_id = extension->id();
276 EXPECT_TRUE(worker_listener.WaitUntilSatisfied());
277
278 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
279 content::WebContents* new_web_contents = AddTab(browser(), url);
280 EXPECT_TRUE(new_web_contents);
281 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
282
283 // Service Worker extension does not have ExtensionHost.
284 EXPECT_FALSE(process_manager()->GetBackgroundHostForExtension(extension_id));
285}
286
287// After browser restarts, this test step ensures that opening a tab fires
288// tabs.onCreated event listener to the extension without explicitly loading the
289// extension. This is because the extension registered a listener before browser
290// restarted in PRE_Basic.
Devlin Cronin242d19d22019-03-12 18:08:48291IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, Basic) {
Istiaque Ahmedccb444022018-06-19 02:11:12292 ExtensionTestMessageListener newtab_listener("CREATED", false);
293 newtab_listener.set_failure_message("CREATE_FAILED");
294 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
295 content::WebContents* new_web_contents = AddTab(browser(), url);
296 EXPECT_TRUE(new_web_contents);
297 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
298}
299
Istiaque Ahmedbf08f952018-10-02 01:22:04300// Tests chrome.runtime.onInstalled fires for extension service workers.
Devlin Cronin242d19d22019-03-12 18:08:48301IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, OnInstalledEvent) {
Istiaque Ahmedbf08f952018-10-02 01:22:04302 ASSERT_TRUE(RunExtensionTest(
303 "service_worker/worker_based_background/events_on_installed"))
304 << message_;
305}
306
David Bertoni69982832019-02-13 21:24:21307// Tests chrome.storage APIs.
Devlin Cronin242d19d22019-03-12 18:08:48308IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, StorageSetAndGet) {
David Bertoni69982832019-02-13 21:24:21309 ASSERT_TRUE(
310 RunExtensionTest("service_worker/worker_based_background/storage"))
311 << message_;
312}
313
David Bertoni0665c892019-02-14 00:27:26314// Tests chrome.storage.local and chrome.storage.local APIs.
Devlin Cronin242d19d22019-03-12 18:08:48315IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, StorageNoPermissions) {
David Bertoni0665c892019-02-14 00:27:26316 ASSERT_TRUE(RunExtensionTest(
317 "service_worker/worker_based_background/storage_no_permissions"))
318 << message_;
319}
320
David Bertoni30809312019-02-28 22:56:05321// Tests chrome.tabs APIs.
Devlin Cronin242d19d22019-03-12 18:08:48322IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, TabsBasic) {
David Bertoni30809312019-02-28 22:56:05323 ASSERT_TRUE(
324 RunExtensionTest("service_worker/worker_based_background/tabs_basic"))
325 << message_;
326}
327
David Bertoni46d698892019-02-26 00:29:10328// Tests chrome.tabs events.
Devlin Cronin242d19d22019-03-12 18:08:48329IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, TabsEvents) {
David Bertoni46d698892019-02-26 00:29:10330 ASSERT_TRUE(
331 RunExtensionTest("service_worker/worker_based_background/tabs_events"))
332 << message_;
333}
334
David Bertoni4c7dfcc2019-03-27 23:49:34335// Tests chrome.tabs APIs.
336IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, TabsExecuteScript) {
337 ASSERT_TRUE(RunExtensionTest(
338 "service_worker/worker_based_background/tabs_execute_script"))
339 << message_;
340}
341
David Bertoni37ae0222019-04-04 01:30:54342// Tests chrome.webRequest APIs.
David Bertoni3929f552019-03-28 22:10:36343IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, WebRequest) {
344 ASSERT_TRUE(
345 RunExtensionTest("service_worker/worker_based_background/web_request"))
346 << message_;
347}
348
David Bertoni37ae0222019-04-04 01:30:54349// Tests chrome.webRequest APIs in blocking mode.
350IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, WebRequestBlocking) {
351 // Try to load the page before installing the extension, which should work.
352 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
353 EXPECT_EQ(content::PAGE_TYPE_NORMAL, NavigateAndGetPageType(url));
354
355 // Install the extension and navigate again to the page.
356 ExtensionTestMessageListener ready_listener("ready", false);
357 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
358 "service_worker/worker_based_background/web_request_blocking")));
359 ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
360 EXPECT_EQ(content::PAGE_TYPE_ERROR, NavigateAndGetPageType(url));
361}
362
Istiaque Ahmed70f76ac2018-11-02 02:59:55363// Listens for |message| from extension Service Worker early so that tests can
364// wait for the message on startup (and not miss it).
365class ServiceWorkerWithEarlyMessageListenerTest
366 : public ServiceWorkerBasedBackgroundTest {
Istiaque Ahmedf70ab222018-10-02 03:08:24367 public:
Istiaque Ahmed70f76ac2018-11-02 02:59:55368 explicit ServiceWorkerWithEarlyMessageListenerTest(
369 const std::string& test_message)
370 : test_message_(test_message) {}
371 ~ServiceWorkerWithEarlyMessageListenerTest() override = default;
Istiaque Ahmedf70ab222018-10-02 03:08:24372
Istiaque Ahmed70f76ac2018-11-02 02:59:55373 bool WaitForMessage() { return listener_->WaitUntilSatisfied(); }
Istiaque Ahmedf70ab222018-10-02 03:08:24374
375 void CreatedBrowserMainParts(content::BrowserMainParts* main_parts) override {
376 // At this point, the notification service is initialized but the profile
377 // and extensions have not.
Istiaque Ahmed70f76ac2018-11-02 02:59:55378 listener_ =
379 std::make_unique<ExtensionTestMessageListener>(test_message_, false);
Istiaque Ahmedf70ab222018-10-02 03:08:24380 ServiceWorkerBasedBackgroundTest::CreatedBrowserMainParts(main_parts);
381 }
382
383 private:
Istiaque Ahmed70f76ac2018-11-02 02:59:55384 const std::string test_message_;
Istiaque Ahmedf70ab222018-10-02 03:08:24385 std::unique_ptr<ExtensionTestMessageListener> listener_;
386
Istiaque Ahmed70f76ac2018-11-02 02:59:55387 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerWithEarlyMessageListenerTest);
388};
389
390class ServiceWorkerOnStartupEventTest
391 : public ServiceWorkerWithEarlyMessageListenerTest {
392 public:
393 ServiceWorkerOnStartupEventTest()
394 : ServiceWorkerWithEarlyMessageListenerTest("onStartup event") {}
395 ~ServiceWorkerOnStartupEventTest() override = default;
396
397 private:
398 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerOnStartupEventTest);
Istiaque Ahmedf70ab222018-10-02 03:08:24399};
400
401// Tests "runtime.onStartup" for extension SW.
Devlin Cronin242d19d22019-03-12 18:08:48402IN_PROC_BROWSER_TEST_F(ServiceWorkerOnStartupEventTest, PRE_Event) {
Istiaque Ahmedf70ab222018-10-02 03:08:24403 ASSERT_TRUE(RunExtensionTest(
404 "service_worker/worker_based_background/on_startup_event"))
405 << message_;
406}
407
Devlin Cronin242d19d22019-03-12 18:08:48408IN_PROC_BROWSER_TEST_F(ServiceWorkerOnStartupEventTest, Event) {
Istiaque Ahmed70f76ac2018-11-02 02:59:55409 EXPECT_TRUE(WaitForMessage());
410}
411
412class ServiceWorkerRegistrationAtStartupTest
413 : public ServiceWorkerWithEarlyMessageListenerTest,
414 public ServiceWorkerTaskQueue::TestObserver {
415 public:
416 ServiceWorkerRegistrationAtStartupTest()
417 : ServiceWorkerWithEarlyMessageListenerTest("WORKER_RUNNING") {
418 ServiceWorkerTaskQueue::SetObserverForTest(this);
419 }
420 ~ServiceWorkerRegistrationAtStartupTest() override {
421 ServiceWorkerTaskQueue::SetObserverForTest(nullptr);
422 }
423
424 // ServiceWorkerTaskQueue::TestObserver:
425 void OnActivateExtension(const ExtensionId& extension_id,
426 bool will_register_service_worker) override {
427 if (extension_id != kExtensionId)
428 return;
429
430 will_register_service_worker_ = will_register_service_worker;
431
432 extension_activated_ = true;
433 if (run_loop_)
434 run_loop_->Quit();
435 }
436
437 void WaitForOnActivateExtension() {
438 if (extension_activated_)
439 return;
440 run_loop_ = std::make_unique<base::RunLoop>();
441 run_loop_->Run();
442 }
443
444 bool WillRegisterServiceWorker() {
445 return will_register_service_worker_.value();
446 }
447
448 protected:
449 static const char kExtensionId[];
450
451 private:
452 bool extension_activated_ = false;
453 base::Optional<bool> will_register_service_worker_;
454 std::unique_ptr<base::RunLoop> run_loop_;
455
456 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistrationAtStartupTest);
457};
458
459// Test extension id at
460// api_test/service_worker/worker_based_background/registration_at_startup/.
461const char ServiceWorkerRegistrationAtStartupTest::kExtensionId[] =
462 "gnchfmandajfaiajniicagenfmhdjila";
463
464// Tests that Service Worker registration for existing extension isn't issued
465// upon browser restart.
466// Regression test for https://crbug.com/889687.
Devlin Cronin242d19d22019-03-12 18:08:48467IN_PROC_BROWSER_TEST_F(ServiceWorkerRegistrationAtStartupTest,
Istiaque Ahmed70f76ac2018-11-02 02:59:55468 PRE_ExtensionActivationDoesNotReregister) {
469 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
470 "service_worker/worker_based_background/registration_at_startup"));
471 ASSERT_TRUE(extension);
472 EXPECT_EQ(kExtensionId, extension->id());
473 // Wait for "WORKER_RUNNING" message from the Service Worker.
474 EXPECT_TRUE(WaitForMessage());
475 EXPECT_TRUE(WillRegisterServiceWorker());
476}
477
Devlin Cronin242d19d22019-03-12 18:08:48478IN_PROC_BROWSER_TEST_F(ServiceWorkerRegistrationAtStartupTest,
Istiaque Ahmed70f76ac2018-11-02 02:59:55479 ExtensionActivationDoesNotReregister) {
480 // Since the extension has onStartup listener, the Service Worker will run on
481 // browser start and we'll see "WORKER_RUNNING" message from the worker.
482 EXPECT_TRUE(WaitForMessage());
483 // As the extension activated during first run on PRE_ step, it shouldn't
484 // re-register the Service Worker upon browser restart.
485 EXPECT_FALSE(WillRegisterServiceWorker());
Istiaque Ahmedf70ab222018-10-02 03:08:24486}
487
Istiaque Ahmeda14ec482018-08-25 01:02:18488// Class that dispatches an event to |extension_id| right after a
489// non-lazy listener to the event is added from the extension's Service Worker.
Istiaque Ahmed771aa8a22018-06-20 23:40:53490class EarlyWorkerMessageSender : public EventRouter::Observer {
491 public:
492 EarlyWorkerMessageSender(content::BrowserContext* browser_context,
Istiaque Ahmeda14ec482018-08-25 01:02:18493 const ExtensionId& extension_id,
494 std::unique_ptr<Event> event)
Istiaque Ahmed771aa8a22018-06-20 23:40:53495 : browser_context_(browser_context),
496 event_router_(EventRouter::EventRouter::Get(browser_context_)),
497 extension_id_(extension_id),
Istiaque Ahmeda14ec482018-08-25 01:02:18498 event_(std::move(event)),
Istiaque Ahmed771aa8a22018-06-20 23:40:53499 listener_("PASS", false) {
500 DCHECK(browser_context_);
501 listener_.set_failure_message("FAIL");
Istiaque Ahmeda14ec482018-08-25 01:02:18502 event_router_->RegisterObserver(this, event_->event_name);
Istiaque Ahmed771aa8a22018-06-20 23:40:53503 }
504
505 ~EarlyWorkerMessageSender() override {
506 event_router_->UnregisterObserver(this);
507 }
508
509 // EventRouter::Observer:
510 void OnListenerAdded(const EventListenerInfo& details) override {
Istiaque Ahmeda14ec482018-08-25 01:02:18511 if (!event_ || extension_id_ != details.extension_id ||
512 event_->event_name != details.event_name) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53513 return;
Istiaque Ahmeda14ec482018-08-25 01:02:18514 }
515
Istiaque Ahmed771aa8a22018-06-20 23:40:53516 const bool is_lazy_listener = details.browser_context == nullptr;
517 if (is_lazy_listener) {
518 // Wait for the non-lazy listener as we want to exercise the code to
519 // dispatch the event right after the Service Worker registration is
520 // completing.
521 return;
522 }
Istiaque Ahmeda14ec482018-08-25 01:02:18523 DispatchEvent(std::move(event_));
Istiaque Ahmed771aa8a22018-06-20 23:40:53524 }
525
526 bool SendAndWait() { return listener_.WaitUntilSatisfied(); }
527
528 private:
529 static constexpr const char* const kTestOnMessageEventName = "test.onMessage";
530
Istiaque Ahmeda14ec482018-08-25 01:02:18531 void DispatchEvent(std::unique_ptr<Event> event) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53532 EventRouter::Get(browser_context_)
533 ->DispatchEventToExtension(extension_id_, std::move(event));
534 }
535
536 content::BrowserContext* const browser_context_ = nullptr;
537 EventRouter* const event_router_ = nullptr;
538 const ExtensionId extension_id_;
Istiaque Ahmeda14ec482018-08-25 01:02:18539 std::unique_ptr<Event> event_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53540 ExtensionTestMessageListener listener_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53541
542 DISALLOW_COPY_AND_ASSIGN(EarlyWorkerMessageSender);
543};
544
545// Tests that extension event dispatch works correctly right after extension
546// installation registers its Service Worker.
547// Regression test for: https://crbug.com/850792.
Devlin Cronin242d19d22019-03-12 18:08:48548IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, EarlyEventDispatch) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53549 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
Istiaque Ahmeda14ec482018-08-25 01:02:18550
551 // Build "test.onMessage" event for dispatch.
552 auto event = std::make_unique<Event>(
553 events::FOR_TEST, extensions::api::test::OnMessage::kEventName,
Lei Zhang582ecd12019-02-13 20:28:54554 base::ListValue::From(base::JSONReader::ReadDeprecated(
Istiaque Ahmeda14ec482018-08-25 01:02:18555 R"([{"data": "hello", "lastMessage": true}])")),
556 profile());
557
558 EarlyWorkerMessageSender sender(profile(), kId, std::move(event));
Istiaque Ahmed771aa8a22018-06-20 23:40:53559 // pkplfbidichfdicaijlchgnapepdginl
560 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
561 "service_worker/worker_based_background/early_event_dispatch"));
562 CHECK(extension);
563 EXPECT_EQ(kId, extension->id());
564 EXPECT_TRUE(sender.SendAndWait());
565}
566
Istiaque Ahmeda14ec482018-08-25 01:02:18567// Tests that filtered events dispatches correctly right after a non-lazy
568// listener is registered for that event (and before the corresponding lazy
569// listener is registered).
Devlin Cronin242d19d22019-03-12 18:08:48570IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest,
Istiaque Ahmeda14ec482018-08-25 01:02:18571 EarlyFilteredEventDispatch) {
572 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
573
574 // Add minimal details required to dispatch webNavigation.onCommitted event:
575 extensions::api::web_navigation::OnCommitted::Details details;
576 details.transition_type =
577 extensions::api::web_navigation::TRANSITION_TYPE_TYPED;
578
579 // Build a dummy onCommited event to dispatch.
580 auto on_committed_event = std::make_unique<Event>(
581 events::WEB_NAVIGATION_ON_COMMITTED, "webNavigation.onCommitted",
582 api::web_navigation::OnCommitted::Create(details), profile());
583 // The filter will match the listener filter registered from the extension.
584 EventFilteringInfo info;
585 info.url = GURL("http://foo.com/a.html");
586 on_committed_event->filter_info = info;
587
588 EarlyWorkerMessageSender sender(profile(), kId,
589 std::move(on_committed_event));
590
591 // pkplfbidichfdicaijlchgnapepdginl
592 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
593 "service_worker/worker_based_background/early_filtered_event_dispatch"));
594 ASSERT_TRUE(extension);
595 EXPECT_EQ(kId, extension->id());
596 EXPECT_TRUE(sender.SendAndWait());
597}
598
lazyboybd325ae2015-11-18 21:35:26599class ServiceWorkerBackgroundSyncTest : public ServiceWorkerTest {
600 public:
601 ServiceWorkerBackgroundSyncTest() {}
602 ~ServiceWorkerBackgroundSyncTest() override {}
603
604 void SetUpCommandLine(base::CommandLine* command_line) override {
605 // ServiceWorkerRegistration.sync requires experimental flag.
606 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16607 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboybd325ae2015-11-18 21:35:26608 ServiceWorkerTest::SetUpCommandLine(command_line);
609 }
610
611 void SetUp() override {
Robbie McElrathdb12d8e2018-09-18 21:20:40612 content::background_sync_test_util::SetIgnoreNetworkChanges(true);
lazyboybd325ae2015-11-18 21:35:26613 ServiceWorkerTest::SetUp();
614 }
615
616 private:
617 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBackgroundSyncTest);
618};
619
lazyboy561b7de2015-11-19 19:27:30620class ServiceWorkerPushMessagingTest : public ServiceWorkerTest {
621 public:
622 ServiceWorkerPushMessagingTest()
Sylvain Defresne212b4b02018-10-11 16:32:05623 : scoped_testing_factory_installer_(
624 base::BindRepeating(&gcm::FakeGCMProfileService::Build)),
625 gcm_driver_(nullptr),
626 push_service_(nullptr) {}
627
lazyboy561b7de2015-11-19 19:27:30628 ~ServiceWorkerPushMessagingTest() override {}
629
630 void GrantNotificationPermissionForTest(const GURL& url) {
Peter Beverloodd4ef1e2018-06-21 15:41:04631 NotificationPermissionContext::UpdatePermission(profile(), url.GetOrigin(),
632 CONTENT_SETTING_ALLOW);
lazyboy561b7de2015-11-19 19:27:30633 }
634
635 PushMessagingAppIdentifier GetAppIdentifierForServiceWorkerRegistration(
avia2f4804a2015-12-24 23:11:13636 int64_t service_worker_registration_id,
lazyboy561b7de2015-11-19 19:27:30637 const GURL& origin) {
638 PushMessagingAppIdentifier app_identifier =
639 PushMessagingAppIdentifier::FindByServiceWorker(
640 profile(), origin, service_worker_registration_id);
641
642 EXPECT_FALSE(app_identifier.is_null());
643 return app_identifier;
644 }
645
646 // ExtensionApiTest overrides.
647 void SetUpCommandLine(base::CommandLine* command_line) override {
peter9de96272015-12-04 15:23:27648 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16649 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboy561b7de2015-11-19 19:27:30650 ServiceWorkerTest::SetUpCommandLine(command_line);
651 }
Tanja Gornak89128fd2018-09-18 08:49:34652
lazyboy561b7de2015-11-19 19:27:30653 void SetUpOnMainThread() override {
miguelg9b502862017-04-24 18:13:53654 NotificationDisplayServiceFactory::GetInstance()->SetTestingFactory(
Sylvain Defresne711ff6b2018-10-04 12:33:54655 profile(),
656 base::BindRepeating(&StubNotificationDisplayService::FactoryForTests));
miguelg9b502862017-04-24 18:13:53657
johnmea5045732016-09-08 17:23:29658 gcm::FakeGCMProfileService* gcm_service =
659 static_cast<gcm::FakeGCMProfileService*>(
Tanja Gornak89128fd2018-09-18 08:49:34660 gcm::GCMProfileServiceFactory::GetForProfile(profile()));
johnmea5045732016-09-08 17:23:29661 gcm_driver_ = static_cast<instance_id::FakeGCMDriverForInstanceID*>(
662 gcm_service->driver());
lazyboy561b7de2015-11-19 19:27:30663 push_service_ = PushMessagingServiceFactory::GetForProfile(profile());
664
665 ServiceWorkerTest::SetUpOnMainThread();
666 }
667
johnmea5045732016-09-08 17:23:29668 instance_id::FakeGCMDriverForInstanceID* gcm_driver() const {
669 return gcm_driver_;
670 }
lazyboy561b7de2015-11-19 19:27:30671 PushMessagingServiceImpl* push_service() const { return push_service_; }
672
673 private:
Sylvain Defresne212b4b02018-10-11 16:32:05674 gcm::GCMProfileServiceFactory::ScopedTestingFactoryInstaller
675 scoped_testing_factory_installer_;
676
johnmea5045732016-09-08 17:23:29677 instance_id::FakeGCMDriverForInstanceID* gcm_driver_;
lazyboy561b7de2015-11-19 19:27:30678 PushMessagingServiceImpl* push_service_;
679
680 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPushMessagingTest);
681};
682
Istiaque Ahmed805f6a83b2017-10-05 01:23:26683class ServiceWorkerLazyBackgroundTest : public ServiceWorkerTest {
684 public:
Istiaque Ahmed7105f2a2017-10-07 01:11:59685 ServiceWorkerLazyBackgroundTest()
686 : ServiceWorkerTest(
687 // Extensions APIs from SW are only enabled on trunk.
688 // It is important to set the channel early so that this change is
689 // visible in renderers running with service workers (and no
690 // extension).
691 version_info::Channel::UNKNOWN) {}
Istiaque Ahmed805f6a83b2017-10-05 01:23:26692 ~ServiceWorkerLazyBackgroundTest() override {}
693
694 void SetUpCommandLine(base::CommandLine* command_line) override {
695 ServiceWorkerTest::SetUpCommandLine(command_line);
696 // Disable background network activity as it can suddenly bring the Lazy
697 // Background Page alive.
698 command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
699 command_line->AppendSwitch(::switches::kNoProxyServer);
700 }
701
702 void SetUpInProcessBrowserTestFixture() override {
703 ServiceWorkerTest::SetUpInProcessBrowserTestFixture();
704 // Set shorter delays to prevent test timeouts.
705 ProcessManager::SetEventPageIdleTimeForTesting(1);
706 ProcessManager::SetEventPageSuspendingTimeForTesting(1);
707 }
708
709 private:
710 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerLazyBackgroundTest);
711};
712
Devlin Cronin242d19d22019-03-12 18:08:48713IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, RegisterSucceeds) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22714 StartTestFromBackgroundPage("register.js");
annekao38685502015-07-14 17:46:39715}
716
Devlin Cronin242d19d22019-03-12 18:08:48717IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, UpdateRefreshesServiceWorker) {
Francois Doraye6fb2d02017-10-18 21:29:13718 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboyc3e763a2015-12-09 23:09:58719 base::ScopedTempDir scoped_temp_dir;
720 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
721 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
722 .AppendASCII("update")
723 .AppendASCII("service_worker.pem");
vabr9142fe22016-09-08 13:19:22724 base::FilePath path_v1 =
725 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
726 .AppendASCII("update")
727 .AppendASCII("v1"),
728 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
729 pem_path, base::FilePath());
730 base::FilePath path_v2 =
731 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
732 .AppendASCII("update")
733 .AppendASCII("v2"),
734 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
735 pem_path, base::FilePath());
lazyboyc3e763a2015-12-09 23:09:58736 const char* kId = "hfaanndiiilofhfokeanhddpkfffchdi";
737
738 ExtensionTestMessageListener listener_v1("Pong from version 1", false);
739 listener_v1.set_failure_message("FAILURE_V1");
740 // Install version 1.0 of the extension.
741 ASSERT_TRUE(InstallExtension(path_v1, 1));
742 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
743 ->enabled_extensions()
744 .GetByID(kId));
745 EXPECT_TRUE(listener_v1.WaitUntilSatisfied());
746
747 ExtensionTestMessageListener listener_v2("Pong from version 2", false);
748 listener_v2.set_failure_message("FAILURE_V2");
749
750 // Update to version 2.0.
751 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
752 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
753 ->enabled_extensions()
754 .GetByID(kId));
755 EXPECT_TRUE(listener_v2.WaitUntilSatisfied());
756}
757
[email protected]2ef85d562017-09-15 18:41:52758// TODO(crbug.com/765736) Fix the test.
Devlin Cronin242d19d22019-03-12 18:08:48759IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, DISABLED_UpdateWithoutSkipWaiting) {
Francois Doraye6fb2d02017-10-18 21:29:13760 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboy22eddc712015-12-10 21:16:26761 base::ScopedTempDir scoped_temp_dir;
762 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
763 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
764 .AppendASCII("update_without_skip_waiting")
765 .AppendASCII("update_without_skip_waiting.pem");
vabr9142fe22016-09-08 13:19:22766 base::FilePath path_v1 =
767 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
768 .AppendASCII("update_without_skip_waiting")
769 .AppendASCII("v1"),
770 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
771 pem_path, base::FilePath());
772 base::FilePath path_v2 =
773 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
774 .AppendASCII("update_without_skip_waiting")
775 .AppendASCII("v2"),
776 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
777 pem_path, base::FilePath());
lazyboy22eddc712015-12-10 21:16:26778 const char* kId = "mhnnnflgagdakldgjpfcofkiocpdmogl";
779
780 // Install version 1.0 of the extension.
781 ASSERT_TRUE(InstallExtension(path_v1, 1));
782 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
783 ->enabled_extensions()
784 .GetByID(kId));
785 const Extension* extension = extensions::ExtensionRegistry::Get(profile())
786 ->enabled_extensions()
787 .GetByID(kId);
788
789 ExtensionTestMessageListener listener1("Pong from version 1", false);
790 listener1.set_failure_message("FAILURE");
791 content::WebContents* web_contents =
792 AddTab(browser(), extension->GetResourceURL("page.html"));
793 EXPECT_TRUE(listener1.WaitUntilSatisfied());
794
795 // Update to version 2.0.
796 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
797 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
798 ->enabled_extensions()
799 .GetByID(kId));
800 const Extension* extension_after_update =
801 extensions::ExtensionRegistry::Get(profile())
802 ->enabled_extensions()
803 .GetByID(kId);
804
805 // Service worker version 2 would be installed but it won't be controlling
806 // the extension page yet.
807 ExtensionTestMessageListener listener2("Pong from version 1", false);
808 listener2.set_failure_message("FAILURE");
809 web_contents =
810 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
811 EXPECT_TRUE(listener2.WaitUntilSatisfied());
812
813 // Navigate the tab away from the extension page so that no clients are
814 // using the service worker.
815 // Note that just closing the tab with WebContentsDestroyedWatcher doesn't
816 // seem to be enough because it returns too early.
817 WebContentsLoadStopObserver navigate_away_observer(web_contents);
818 web_contents->GetController().LoadURL(
819 GURL(url::kAboutBlankURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED,
820 std::string());
821 navigate_away_observer.WaitForLoadStop();
822
823 // Now expect service worker version 2 to control the extension page.
824 ExtensionTestMessageListener listener3("Pong from version 2", false);
825 listener3.set_failure_message("FAILURE");
826 web_contents =
827 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
828 EXPECT_TRUE(listener3.WaitUntilSatisfied());
829}
830
Devlin Cronin242d19d22019-03-12 18:08:48831IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, FetchArbitraryPaths) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22832 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
annekao1db36fd2015-07-29 17:09:16833
kalman6f984ae2015-09-18 17:21:58834 // Open some arbirary paths. Their contents should be what the service worker
835 // responds with, which in this case is the path of the fetch.
836 EXPECT_EQ(
837 "Caught a fetch for /index.html",
838 NavigateAndExtractInnerText(extension->GetResourceURL("index.html")));
839 EXPECT_EQ("Caught a fetch for /path/to/other.html",
840 NavigateAndExtractInnerText(
841 extension->GetResourceURL("path/to/other.html")));
842 EXPECT_EQ("Caught a fetch for /some/text/file.txt",
843 NavigateAndExtractInnerText(
844 extension->GetResourceURL("some/text/file.txt")));
845 EXPECT_EQ("Caught a fetch for /no/file/extension",
846 NavigateAndExtractInnerText(
847 extension->GetResourceURL("no/file/extension")));
848 EXPECT_EQ("Caught a fetch for /",
849 NavigateAndExtractInnerText(extension->GetResourceURL("")));
annekao1db36fd2015-07-29 17:09:16850}
851
Devlin Cronin242d19d22019-03-12 18:08:48852IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
Kenichi Ishibashi773b82972018-08-30 07:02:03853 FetchExtensionResourceFromServiceWorker) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22854 const Extension* extension = StartTestFromBackgroundPage("fetch_from_sw.js");
Kenichi Ishibashi773b82972018-08-30 07:02:03855 ASSERT_TRUE(extension);
856
857 // The service worker in this test tries to load 'hello.txt' via fetch()
858 // and sends back the content of the file, which should be 'hello'.
859 const char* kScript = R"(
860 let channel = new MessageChannel();
861 test.waitForMessage(channel.port1).then(message => {
862 window.domAutomationController.send(message);
863 });
864 test.registeredServiceWorker.postMessage(
865 {port: channel.port2}, [channel.port2]);
866 )";
867 EXPECT_EQ("hello", ExecuteScriptInBackgroundPage(extension->id(), kScript));
868}
869
Kenichi Ishibashi09ee5e72018-11-27 07:12:38870// Tests that fetch() from service worker and network fallback
871// go through webRequest.onBeforeRequest API.
Devlin Cronin242d19d22019-03-12 18:08:48872IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, OnBeforeRequest) {
Kenichi Ishibashi09ee5e72018-11-27 07:12:38873 const Extension* extension = LoadExtensionWithFlags(
874 test_data_dir_.AppendASCII("service_worker/webrequest"), kFlagNone);
875 ASSERT_TRUE(extension);
876 ASSERT_TRUE(StartEmbeddedTestServer());
877
878 // Start a service worker and make it control the page.
879 GURL page_url = embedded_test_server()->GetURL(
880 "/extensions/api_test/service_worker/"
881 "webrequest/webpage.html");
882 content::WebContents* web_contents =
883 browser()->tab_strip_model()->GetActiveWebContents();
884 ui_test_utils::NavigateToURL(browser(), page_url);
885 content::WaitForLoadStop(web_contents);
886
887 std::string result;
888 ASSERT_TRUE(content::ExecuteScriptAndExtractString(web_contents,
889 "register();", &result));
890 EXPECT_EQ("ready", result);
891
892 // Initiate a fetch that the service worker doesn't intercept
893 // (network fallback).
894 result.clear();
895 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
896 web_contents, "doFetch('hello.txt?fallthrough');", &result));
897 EXPECT_EQ("hello", result);
898 EXPECT_EQ(
899 "/extensions/api_test/service_worker/webrequest/hello.txt?fallthrough",
900 ExecuteScriptInBackgroundPage(extension->id(), "getLastHookedPath()"));
901
902 // Initiate a fetch that results in calling fetch() in the service worker.
903 result.clear();
904 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
905 web_contents, "doFetch('hello.txt?respondWithFetch');", &result));
906 EXPECT_EQ("hello", result);
907 EXPECT_EQ(
908 "/extensions/api_test/service_worker/webrequest/"
909 "hello.txt?respondWithFetch",
910 ExecuteScriptInBackgroundPage(extension->id(), "getLastHookedPath()"));
911}
912
Devlin Cronin242d19d22019-03-12 18:08:48913IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, SWServedBackgroundPageReceivesEvent) {
lazyboy52c3bcf2016-01-08 00:11:29914 const Extension* extension =
Istiaque Ahmed93ff7f42018-08-31 01:42:22915 StartTestFromBackgroundPage("replace_background.js");
lazyboy52c3bcf2016-01-08 00:11:29916 ExtensionHost* background_page =
917 process_manager()->GetBackgroundHostForExtension(extension->id());
918 ASSERT_TRUE(background_page);
919
920 // Close the background page and start it again so that the service worker
921 // will start controlling pages.
922 background_page->Close();
923 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
924 background_page = nullptr;
Peter Kasting341e1fb2018-02-24 00:03:01925 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
lazyboy52c3bcf2016-01-08 00:11:29926 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
927
928 // Since the SW is now controlling the extension, the SW serves the background
929 // script. page.html sends a message to the background script and we verify
930 // that the SW served background script correctly receives the message/event.
931 ExtensionTestMessageListener listener("onMessage/SW BG.", false);
932 listener.set_failure_message("onMessage/original BG.");
933 content::WebContents* web_contents =
934 AddTab(browser(), extension->GetResourceURL("page.html"));
935 ASSERT_TRUE(web_contents);
936 EXPECT_TRUE(listener.WaitUntilSatisfied());
937}
938
Devlin Cronin242d19d22019-03-12 18:08:48939IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, SWServedBackgroundPage) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22940 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
annekao49241182015-08-18 17:14:01941
kalman6f984ae2015-09-18 17:21:58942 std::string kExpectedInnerText = "background.html contents for testing.";
annekao49241182015-08-18 17:14:01943
kalman6f984ae2015-09-18 17:21:58944 // Sanity check that the background page has the expected content.
945 ExtensionHost* background_page =
946 process_manager()->GetBackgroundHostForExtension(extension->id());
947 ASSERT_TRUE(background_page);
948 EXPECT_EQ(kExpectedInnerText,
949 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01950
kalman6f984ae2015-09-18 17:21:58951 // Close the background page.
952 background_page->Close();
953 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
954 background_page = nullptr;
955
956 // Start it again.
Peter Kasting341e1fb2018-02-24 00:03:01957 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
kalman6f984ae2015-09-18 17:21:58958 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
959
Matt Falkenhagena612fc02018-05-30 00:35:39960 // The service worker should get a fetch event for the background page.
kalman6f984ae2015-09-18 17:21:58961 background_page =
962 process_manager()->GetBackgroundHostForExtension(extension->id());
963 ASSERT_TRUE(background_page);
964 content::WaitForLoadStop(background_page->host_contents());
965
kalman6f984ae2015-09-18 17:21:58966 EXPECT_EQ("Caught a fetch for /background.html",
967 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01968}
969
Devlin Cronin242d19d22019-03-12 18:08:48970IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58971 ServiceWorkerPostsMessageToBackgroundClient) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22972 const Extension* extension =
973 StartTestFromBackgroundPage("post_message_to_background_client.js");
annekao533482222015-08-21 23:23:53974
kalman6f984ae2015-09-18 17:21:58975 // The service worker in this test simply posts a message to the background
976 // client it receives from getBackgroundClient().
977 const char* kScript =
978 "var messagePromise = null;\n"
979 "if (test.lastMessageFromServiceWorker) {\n"
980 " messagePromise = Promise.resolve(test.lastMessageFromServiceWorker);\n"
981 "} else {\n"
982 " messagePromise = test.waitForMessage(navigator.serviceWorker);\n"
983 "}\n"
984 "messagePromise.then(function(message) {\n"
985 " window.domAutomationController.send(String(message == 'success'));\n"
986 "})\n";
987 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53988}
989
Devlin Cronin242d19d22019-03-12 18:08:48990IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58991 BackgroundPagePostsMessageToServiceWorker) {
992 const Extension* extension =
Istiaque Ahmed93ff7f42018-08-31 01:42:22993 StartTestFromBackgroundPage("post_message_to_sw.js");
annekao533482222015-08-21 23:23:53994
kalman6f984ae2015-09-18 17:21:58995 // The service worker in this test waits for a message, then echoes it back
996 // by posting a message to the background page via getBackgroundClient().
997 const char* kScript =
998 "var mc = new MessageChannel();\n"
999 "test.waitForMessage(mc.port1).then(function(message) {\n"
1000 " window.domAutomationController.send(String(message == 'hello'));\n"
1001 "});\n"
1002 "test.registeredServiceWorker.postMessage(\n"
1003 " {message: 'hello', port: mc.port2}, [mc.port2])\n";
1004 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:531005}
1006
Devlin Cronin242d19d22019-03-12 18:08:481007IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
rdevlin.croninf5863da2015-09-10 19:21:451008 ServiceWorkerSuspensionOnExtensionUnload) {
kalman6f984ae2015-09-18 17:21:581009 // For this test, only hold onto the extension's ID and URL + a function to
1010 // get a resource URL, because we're going to be disabling and uninstalling
1011 // it, which will invalidate the pointer.
1012 std::string extension_id;
1013 GURL extension_url;
1014 {
Istiaque Ahmed93ff7f42018-08-31 01:42:221015 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
kalman6f984ae2015-09-18 17:21:581016 extension_id = extension->id();
1017 extension_url = extension->url();
1018 }
1019 auto get_resource_url = [&extension_url](const std::string& path) {
1020 return Extension::GetResourceURL(extension_url, path);
1021 };
rdevlin.croninf5863da2015-09-10 19:21:451022
kalman6f984ae2015-09-18 17:21:581023 // Fetch should route to the service worker.
1024 EXPECT_EQ("Caught a fetch for /index.html",
1025 NavigateAndExtractInnerText(get_resource_url("index.html")));
rdevlin.croninf5863da2015-09-10 19:21:451026
kalman6f984ae2015-09-18 17:21:581027 // Disable the extension. Opening the page should fail.
1028 extension_service()->DisableExtension(extension_id,
Minh X. Nguyen45479012017-08-18 21:35:361029 disable_reason::DISABLE_USER_ACTION);
rdevlin.croninf5863da2015-09-10 19:21:451030 base::RunLoop().RunUntilIdle();
rdevlin.croninf5863da2015-09-10 19:21:451031
kalman6f984ae2015-09-18 17:21:581032 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1033 NavigateAndGetPageType(get_resource_url("index.html")));
1034 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1035 NavigateAndGetPageType(get_resource_url("other.html")));
1036
1037 // Re-enable the extension. Opening pages should immediately start to succeed
1038 // again.
rdevlin.croninf5863da2015-09-10 19:21:451039 extension_service()->EnableExtension(extension_id);
1040 base::RunLoop().RunUntilIdle();
1041
kalman6f984ae2015-09-18 17:21:581042 EXPECT_EQ("Caught a fetch for /index.html",
1043 NavigateAndExtractInnerText(get_resource_url("index.html")));
1044 EXPECT_EQ("Caught a fetch for /other.html",
1045 NavigateAndExtractInnerText(get_resource_url("other.html")));
1046 EXPECT_EQ("Caught a fetch for /another.html",
1047 NavigateAndExtractInnerText(get_resource_url("another.html")));
rdevlin.croninf5863da2015-09-10 19:21:451048
kalman6f984ae2015-09-18 17:21:581049 // Uninstall the extension. Opening pages should fail again.
1050 base::string16 error;
1051 extension_service()->UninstallExtension(
Devlin Cronin218df7f2017-11-21 21:41:311052 extension_id, UninstallReason::UNINSTALL_REASON_FOR_TESTING, &error);
kalman6f984ae2015-09-18 17:21:581053 base::RunLoop().RunUntilIdle();
1054
1055 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1056 NavigateAndGetPageType(get_resource_url("index.html")));
1057 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1058 NavigateAndGetPageType(get_resource_url("other.html")));
1059 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1060 NavigateAndGetPageType(get_resource_url("anotherother.html")));
1061 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1062 NavigateAndGetPageType(get_resource_url("final.html")));
1063}
1064
Devlin Cronin242d19d22019-03-12 18:08:481065IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, BackgroundPageIsWokenIfAsleep) {
Istiaque Ahmed93ff7f42018-08-31 01:42:221066 const Extension* extension = StartTestFromBackgroundPage("wake_on_fetch.js");
kalman6f984ae2015-09-18 17:21:581067
1068 // Navigate to special URLs that this test's service worker recognises, each
1069 // making a check then populating the response with either "true" or "false".
1070 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
1071 "background-client-is-awake")));
1072 EXPECT_EQ("true", NavigateAndExtractInnerText(
1073 extension->GetResourceURL("ping-background-client")));
1074 // Ping more than once for good measure.
1075 EXPECT_EQ("true", NavigateAndExtractInnerText(
1076 extension->GetResourceURL("ping-background-client")));
1077
1078 // Shut down the event page. The SW should detect that it's closed, but still
1079 // be able to ping it.
1080 ExtensionHost* background_page =
1081 process_manager()->GetBackgroundHostForExtension(extension->id());
1082 ASSERT_TRUE(background_page);
1083 background_page->Close();
1084 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
1085
1086 EXPECT_EQ("false", NavigateAndExtractInnerText(extension->GetResourceURL(
1087 "background-client-is-awake")));
1088 EXPECT_EQ("true", NavigateAndExtractInnerText(
1089 extension->GetResourceURL("ping-background-client")));
1090 EXPECT_EQ("true", NavigateAndExtractInnerText(
1091 extension->GetResourceURL("ping-background-client")));
1092 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
1093 "background-client-is-awake")));
1094}
1095
Devlin Cronin242d19d22019-03-12 18:08:481096IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:581097 GetBackgroundClientFailsWithNoBackgroundPage) {
1098 // This extension doesn't have a background page, only a tab at page.html.
1099 // The service worker it registers tries to call getBackgroundClient() and
1100 // should fail.
1101 // Note that this also tests that service workers can be registered from tabs.
1102 EXPECT_TRUE(RunExtensionSubtest("service_worker/no_background", "page.html"));
rdevlin.croninf5863da2015-09-10 19:21:451103}
1104
Devlin Cronin242d19d22019-03-12 18:08:481105IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, NotificationAPI) {
lazyboy6ddb7d62015-11-10 23:15:271106 EXPECT_TRUE(RunExtensionSubtest("service_worker/notifications/has_permission",
1107 "page.html"));
1108}
1109
Devlin Cronin242d19d22019-03-12 18:08:481110IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WebAccessibleResourcesFetch) {
lazyboyaea32c22016-01-04 21:37:071111 EXPECT_TRUE(RunExtensionSubtest(
1112 "service_worker/web_accessible_resources/fetch/", "page.html"));
1113}
1114
Devlin Cronin242d19d22019-03-12 18:08:481115IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, TabsCreate) {
lazyboyee4adef2016-05-24 00:55:161116 // Extensions APIs from SW are only enabled on trunk.
1117 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1118 const Extension* extension = LoadExtensionWithFlags(
1119 test_data_dir_.AppendASCII("service_worker/tabs_create"), kFlagNone);
1120 ASSERT_TRUE(extension);
1121 ui_test_utils::NavigateToURL(browser(),
1122 extension->GetResourceURL("page.html"));
1123 content::WebContents* web_contents =
1124 browser()->tab_strip_model()->GetActiveWebContents();
1125
1126 int starting_tab_count = browser()->tab_strip_model()->count();
1127 std::string result;
1128 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1129 web_contents, "window.runServiceWorker()", &result));
1130 ASSERT_EQ("chrome.tabs.create callback", result);
1131 EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count());
1132
1133 // Check extension shutdown path.
1134 UnloadExtension(extension->id());
1135 EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count());
1136}
1137
David Bertoni1d646a152019-04-25 02:09:221138// Tests that updating an unpacked extension with modified scripts works
1139// properly -- we expect that the new script will execute, rather than the
1140// previous one.
1141IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, UpdateUnpackedExtension) {
1142 // Extensions APIs from SW are only enabled on trunk.
1143 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1144 constexpr char kManifest1[] =
1145 R"({
1146 "name": "Test Extension",
1147 "manifest_version": 2,
1148 "version": "0.1",
1149 "background": {"service_worker": "script.js"}
1150 })";
1151 constexpr char kManifest2[] =
1152 R"({
1153 "name": "Test Extension",
1154 "manifest_version": 2,
1155 "version": "0.2",
1156 "background": {"service_worker": "script.js"}
1157 })";
1158
1159 std::string id;
1160
1161 ExtensionService* const extension_service =
1162 ExtensionSystem::Get(profile())->extension_service();
1163 scoped_refptr<UnpackedInstaller> installer =
1164 UnpackedInstaller::Create(extension_service);
1165
1166 // Set a completion callback so we can get the ID of the extension.
1167 installer->set_completion_callback(base::BindLambdaForTesting(
1168 [&id](const Extension* extension, const base::FilePath& path,
1169 const std::string& error) {
1170 ASSERT_TRUE(extension);
1171 ASSERT_TRUE(error.empty());
1172 id = extension->id();
1173 }));
1174
1175 TestExtensionDir test_dir;
1176
1177 // Write the manifest and script files and load the extension.
1178 test_dir.WriteManifest(kManifest1);
1179 test_dir.WriteFile(FILE_PATH_LITERAL("script.js"),
1180 "chrome.test.sendMessage('ready1');");
1181 {
1182 ExtensionTestMessageListener ready_listener("ready1", false);
1183
1184 installer->Load(test_dir.UnpackedPath());
1185 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1186 ASSERT_FALSE(id.empty());
1187 }
1188
1189 // Rewrite the script file without a version change in the manifest and reload
1190 // the extension. The new script should execute.
1191 test_dir.WriteFile(FILE_PATH_LITERAL("script.js"),
1192 "chrome.test.sendMessage('ready2');");
1193 {
1194 ExtensionTestMessageListener ready_listener("ready2", false);
1195
1196 extension_service->ReloadExtension(id);
1197 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1198 }
1199
1200 // Rewrite the manifest and script files with a version change in the manifest
1201 // file. After reloading the extension, the new script should execute.
1202 test_dir.WriteManifest(kManifest2);
1203 test_dir.WriteFile(FILE_PATH_LITERAL("script.js"),
1204 "chrome.test.sendMessage('ready3');");
1205 {
1206 ExtensionTestMessageListener ready_listener("ready3", false);
1207
1208 extension_service->ReloadExtension(id);
1209 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1210 }
1211}
1212
Devlin Cronin242d19d22019-03-12 18:08:481213IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, Events) {
lazyboye7847242017-06-07 23:29:181214 // Extensions APIs from SW are only enabled on trunk.
1215 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1216 const Extension* extension = LoadExtensionWithFlags(
1217 test_data_dir_.AppendASCII("service_worker/events"), kFlagNone);
1218 ASSERT_TRUE(extension);
1219 ui_test_utils::NavigateToURL(browser(),
1220 extension->GetResourceURL("page.html"));
1221 content::WebContents* web_contents =
1222 browser()->tab_strip_model()->GetActiveWebContents();
1223 std::string result;
1224 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1225 web_contents, "window.runEventTest()", &result));
1226 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
1227}
1228
Devlin Cronin242d19d22019-03-12 18:08:481229IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, EventsToStoppedWorker) {
lazyboy63b994a2017-06-30 21:20:231230 // Extensions APIs from SW are only enabled on trunk.
1231 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1232 const Extension* extension = LoadExtensionWithFlags(
1233 test_data_dir_.AppendASCII("service_worker/events_to_stopped_worker"),
1234 kFlagNone);
1235 ASSERT_TRUE(extension);
1236 ui_test_utils::NavigateToURL(browser(),
1237 extension->GetResourceURL("page.html"));
1238 content::WebContents* web_contents =
1239 browser()->tab_strip_model()->GetActiveWebContents();
1240 {
1241 std::string result;
1242 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1243 web_contents, "window.runServiceWorker()", &result));
1244 ASSERT_EQ("ready", result);
1245
1246 base::RunLoop run_loop;
1247 content::StoragePartition* storage_partition =
1248 content::BrowserContext::GetDefaultStoragePartition(
1249 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001250 content::StopServiceWorkerForScope(
lazyboy63b994a2017-06-30 21:20:231251 storage_partition->GetServiceWorkerContext(),
1252 // The service worker is registered at the top level scope.
1253 extension->url(), run_loop.QuitClosure());
1254 run_loop.Run();
1255 }
1256
1257 std::string result;
1258 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1259 web_contents, "window.createTabThenUpdate()", &result));
1260 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
1261}
1262
Istiaque Ahmed805f6a83b2017-10-05 01:23:261263// Tests that events to service worker arrives correctly event if the owner
1264// extension of the worker is not running.
Devlin Cronin242d19d22019-03-12 18:08:481265IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmedb8e24bdb2018-09-13 15:17:251266 EventsToStoppedExtension) {
Istiaque Ahmed805f6a83b2017-10-05 01:23:261267 LazyBackgroundObserver lazy_observer;
1268 ResultCatcher catcher;
1269 const Extension* extension = LoadExtensionWithFlags(
1270 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
1271 kFlagNone);
1272 ASSERT_TRUE(extension);
1273 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1274
1275 ProcessManager* pm = ProcessManager::Get(browser()->profile());
1276 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:301277 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed805f6a83b2017-10-05 01:23:261278
1279 // |extension|'s background page opens a tab to its resource.
1280 content::WebContents* extension_web_contents =
1281 browser()->tab_strip_model()->GetActiveWebContents();
1282 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1283 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1284 extension_web_contents->GetURL().spec());
1285 {
1286 // Let the service worker start and register a listener to
1287 // chrome.tabs.onCreated event.
1288 ExtensionTestMessageListener add_listener_done("listener-added", false);
1289 content::ExecuteScriptAsync(extension_web_contents,
1290 "window.runServiceWorkerAsync()");
1291 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1292
1293 base::RunLoop run_loop;
1294 content::StoragePartition* storage_partition =
1295 content::BrowserContext::GetDefaultStoragePartition(
1296 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001297 content::StopServiceWorkerForScope(
Istiaque Ahmed805f6a83b2017-10-05 01:23:261298 storage_partition->GetServiceWorkerContext(),
1299 // The service worker is registered at the top level scope.
1300 extension->url(), run_loop.QuitClosure());
1301 run_loop.Run();
1302 }
1303
1304 // Close the tab to |extension|'s resource. This will also close the
1305 // extension's event page.
1306 browser()->tab_strip_model()->CloseWebContentsAt(
1307 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1308 lazy_observer.Wait();
1309
1310 // At this point both the extension worker and extension event page is not
1311 // running. Since the worker registered a listener for tabs.onCreated, it
1312 // will be started to dispatch the event once we create a tab.
1313 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1314 newtab_listener.set_failure_message("WRONG_NEWTAB");
1315 content::WebContents* new_web_contents =
Istiaque Ahmed7105f2a2017-10-07 01:11:591316 AddTab(browser(), GURL(url::kAboutBlankURL));
1317 EXPECT_TRUE(new_web_contents);
1318 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1319}
1320
1321// Tests that events to service worker correctly after browser restart.
1322// This test is similar to EventsToStoppedExtension, except that the event
1323// delivery is verified after a browser restart.
Devlin Cronin242d19d22019-03-12 18:08:481324IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmed7105f2a2017-10-07 01:11:591325 PRE_EventsAfterRestart) {
1326 LazyBackgroundObserver lazy_observer;
1327 ResultCatcher catcher;
1328 const Extension* extension = LoadExtensionWithFlags(
1329 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
1330 kFlagNone);
1331 ASSERT_TRUE(extension);
1332 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1333
1334 ProcessManager* pm = ProcessManager::Get(browser()->profile());
1335 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:301336 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed7105f2a2017-10-07 01:11:591337
1338 // |extension|'s background page opens a tab to its resource.
1339 content::WebContents* extension_web_contents =
1340 browser()->tab_strip_model()->GetActiveWebContents();
1341 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1342 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1343 extension_web_contents->GetURL().spec());
1344 {
1345 // Let the service worker start and register a listener to
1346 // chrome.tabs.onCreated event.
1347 ExtensionTestMessageListener add_listener_done("listener-added", false);
1348 content::ExecuteScriptAsync(extension_web_contents,
1349 "window.runServiceWorkerAsync()");
1350 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1351
1352 base::RunLoop run_loop;
1353 content::StoragePartition* storage_partition =
1354 content::BrowserContext::GetDefaultStoragePartition(
1355 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001356 content::StopServiceWorkerForScope(
Istiaque Ahmed7105f2a2017-10-07 01:11:591357 storage_partition->GetServiceWorkerContext(),
1358 // The service worker is registered at the top level scope.
1359 extension->url(), run_loop.QuitClosure());
1360 run_loop.Run();
1361 }
1362
1363 // Close the tab to |extension|'s resource. This will also close the
1364 // extension's event page.
1365 browser()->tab_strip_model()->CloseWebContentsAt(
1366 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1367 lazy_observer.Wait();
1368}
1369
Devlin Cronin242d19d22019-03-12 18:08:481370IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest, EventsAfterRestart) {
Istiaque Ahmed7105f2a2017-10-07 01:11:591371 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1372 content::WebContents* new_web_contents =
1373 AddTab(browser(), GURL(url::kAboutBlankURL));
Istiaque Ahmed805f6a83b2017-10-05 01:23:261374 EXPECT_TRUE(new_web_contents);
1375 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1376}
1377
lazyboy4c82177a2016-10-18 00:04:091378// Tests that worker ref count increments while extension API function is
1379// active.
Devlin Cronin242d19d22019-03-12 18:08:481380IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WorkerRefCount) {
lazyboy4c82177a2016-10-18 00:04:091381 // Extensions APIs from SW are only enabled on trunk.
1382 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1383 const Extension* extension = LoadExtensionWithFlags(
1384 test_data_dir_.AppendASCII("service_worker/api_worker_ref_count"),
1385 kFlagNone);
1386 ASSERT_TRUE(extension);
1387 ui_test_utils::NavigateToURL(browser(),
1388 extension->GetResourceURL("page.html"));
1389 content::WebContents* web_contents =
1390 browser()->tab_strip_model()->GetActiveWebContents();
1391
1392 ExtensionTestMessageListener worker_start_listener("WORKER STARTED", false);
1393 worker_start_listener.set_failure_message("FAILURE");
1394 ASSERT_TRUE(
1395 content::ExecuteScript(web_contents, "window.runServiceWorker()"));
1396 ASSERT_TRUE(worker_start_listener.WaitUntilSatisfied());
1397
1398 // Service worker should have no pending requests because it hasn't peformed
1399 // any extension API request yet.
1400 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1401
1402 ExtensionTestMessageListener worker_listener("CHECK_REF_COUNT", true);
1403 worker_listener.set_failure_message("FAILURE");
1404 ASSERT_TRUE(content::ExecuteScript(web_contents, "window.testSendMessage()"));
1405 ASSERT_TRUE(worker_listener.WaitUntilSatisfied());
1406
1407 // Service worker should have exactly one pending request because
1408 // chrome.test.sendMessage() API call is in-flight.
1409 EXPECT_EQ(1u, GetWorkerRefCount(extension->url()));
1410
1411 // Peform another extension API request while one is ongoing.
1412 {
1413 ExtensionTestMessageListener listener("CHECK_REF_COUNT", true);
1414 listener.set_failure_message("FAILURE");
1415 ASSERT_TRUE(
1416 content::ExecuteScript(web_contents, "window.testSendMessage()"));
1417 ASSERT_TRUE(listener.WaitUntilSatisfied());
1418
1419 // Service worker currently has two extension API requests in-flight.
1420 EXPECT_EQ(2u, GetWorkerRefCount(extension->url()));
1421 // Finish executing the nested chrome.test.sendMessage() first.
1422 listener.Reply("Hello world");
1423 }
1424
Istiaque Ahmedb57c9752017-08-20 19:08:571425 ExtensionTestMessageListener worker_completion_listener("SUCCESS_FROM_WORKER",
1426 false);
lazyboy4c82177a2016-10-18 00:04:091427 // Finish executing chrome.test.sendMessage().
1428 worker_listener.Reply("Hello world");
Istiaque Ahmedb57c9752017-08-20 19:08:571429 EXPECT_TRUE(worker_completion_listener.WaitUntilSatisfied());
1430
1431 // The following block makes sure we have received all the IPCs related to
1432 // ref-count from the worker.
1433 {
1434 // The following roundtrip:
1435 // browser->extension->worker->extension->browser
1436 // will ensure that the worker sent the relevant ref count IPCs.
1437 std::string result;
1438 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1439 web_contents, "window.roundtripToWorker();", &result));
1440 EXPECT_EQ("roundtrip-succeeded", result);
1441
1442 // Ensure IO thread IPCs run.
Gabriel Charette01507a22017-09-27 21:30:081443 content::RunAllTasksUntilIdle();
Istiaque Ahmedb57c9752017-08-20 19:08:571444 }
lazyboy4c82177a2016-10-18 00:04:091445
1446 // The ref count should drop to 0.
1447 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1448}
1449
lazyboyaea32c22016-01-04 21:37:071450// This test loads a web page that has an iframe pointing to a
1451// chrome-extension:// URL. The URL is listed in the extension's
1452// web_accessible_resources. Initially the iframe is served from the extension's
1453// resource file. After verifying that, we register a Service Worker that
1454// controls the extension. Further requests to the same resource as before
1455// should now be served by the Service Worker.
1456// This test also verifies that if the requested resource exists in the manifest
1457// but is not present in the extension directory, the Service Worker can still
1458// serve the resource file.
Devlin Cronin242d19d22019-03-12 18:08:481459IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WebAccessibleResourcesIframeSrc) {
lazyboyaea32c22016-01-04 21:37:071460 const Extension* extension = LoadExtensionWithFlags(
1461 test_data_dir_.AppendASCII(
1462 "service_worker/web_accessible_resources/iframe_src"),
1463 kFlagNone);
1464 ASSERT_TRUE(extension);
1465 ASSERT_TRUE(StartEmbeddedTestServer());
falkenad185092016-06-16 06:10:021466
1467 // Service workers can only control secure contexts
1468 // (https://w3c.github.io/webappsec-secure-contexts/). For documents, this
1469 // typically means the document must have a secure origin AND all its ancestor
1470 // frames must have documents with secure origins. However, extension pages
1471 // are considered secure, even if they have an ancestor document that is an
1472 // insecure context (see GetSchemesBypassingSecureContextCheckWhitelist). So
1473 // extension service workers must be able to control an extension page
1474 // embedded in an insecure context. To test this, set up an insecure
1475 // (non-localhost, non-https) URL for the web page. This page will create
1476 // iframes that load extension pages that must be controllable by service
1477 // worker.
falkenad185092016-06-16 06:10:021478 GURL page_url =
1479 embedded_test_server()->GetURL("a.com",
1480 "/extensions/api_test/service_worker/"
1481 "web_accessible_resources/webpage.html");
1482 EXPECT_FALSE(content::IsOriginSecure(page_url));
lazyboyaea32c22016-01-04 21:37:071483
1484 content::WebContents* web_contents = AddTab(browser(), page_url);
1485 std::string result;
1486 // webpage.html will create an iframe pointing to a resource from |extension|.
1487 // Expect the resource to be served by the extension.
1488 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1489 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1490 extension->id().c_str()),
1491 &result));
1492 EXPECT_EQ("FROM_EXTENSION_RESOURCE", result);
1493
1494 ExtensionTestMessageListener service_worker_ready_listener("SW_READY", false);
1495 EXPECT_TRUE(ExecuteScriptInBackgroundPageNoWait(
1496 extension->id(), "window.registerServiceWorker()"));
1497 EXPECT_TRUE(service_worker_ready_listener.WaitUntilSatisfied());
1498
1499 result.clear();
1500 // webpage.html will create another iframe pointing to a resource from
1501 // |extension| as before. But this time, the resource should be be served
1502 // from the Service Worker.
1503 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1504 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1505 extension->id().c_str()),
1506 &result));
1507 EXPECT_EQ("FROM_SW_RESOURCE", result);
1508
1509 result.clear();
1510 // webpage.html will create yet another iframe pointing to a resource that
1511 // exists in the extension manifest's web_accessible_resources, but is not
1512 // present in the extension directory. Expect the resources of the iframe to
1513 // be served by the Service Worker.
1514 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1515 web_contents,
1516 base::StringPrintf("window.testIframe('%s', 'iframe_non_existent.html')",
1517 extension->id().c_str()),
1518 &result));
1519 EXPECT_EQ("FROM_SW_RESOURCE", result);
1520}
1521
Devlin Cronin242d19d22019-03-12 18:08:481522IN_PROC_BROWSER_TEST_F(ServiceWorkerBackgroundSyncTest, Sync) {
lazyboybd325ae2015-11-18 21:35:261523 const Extension* extension = LoadExtensionWithFlags(
1524 test_data_dir_.AppendASCII("service_worker/sync"), kFlagNone);
1525 ASSERT_TRUE(extension);
1526 ui_test_utils::NavigateToURL(browser(),
1527 extension->GetResourceURL("page.html"));
1528 content::WebContents* web_contents =
1529 browser()->tab_strip_model()->GetActiveWebContents();
1530
1531 // Prevent firing by going offline.
1532 content::background_sync_test_util::SetOnline(web_contents, false);
1533
1534 ExtensionTestMessageListener sync_listener("SYNC: send-chats", false);
1535 sync_listener.set_failure_message("FAIL");
1536
1537 std::string result;
1538 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1539 web_contents, "window.runServiceWorker()", &result));
1540 ASSERT_EQ("SERVICE_WORKER_READY", result);
1541
1542 EXPECT_FALSE(sync_listener.was_satisfied());
1543 // Resume firing by going online.
1544 content::background_sync_test_util::SetOnline(web_contents, true);
1545 EXPECT_TRUE(sync_listener.WaitUntilSatisfied());
1546}
1547
Devlin Cronin242d19d22019-03-12 18:08:481548IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
horo1eeddde2015-11-19 05:59:251549 FetchFromContentScriptShouldNotGoToServiceWorkerOfPage) {
1550 ASSERT_TRUE(StartEmbeddedTestServer());
1551 GURL page_url = embedded_test_server()->GetURL(
1552 "/extensions/api_test/service_worker/content_script_fetch/"
1553 "controlled_page/index.html");
1554 content::WebContents* tab =
1555 browser()->tab_strip_model()->GetActiveWebContents();
1556 ui_test_utils::NavigateToURL(browser(), page_url);
1557 content::WaitForLoadStop(tab);
1558
1559 std::string value;
1560 ASSERT_TRUE(
1561 content::ExecuteScriptAndExtractString(tab, "register();", &value));
1562 EXPECT_EQ("SW controlled", value);
1563
1564 ASSERT_TRUE(RunExtensionTest("service_worker/content_script_fetch"))
1565 << message_;
1566}
1567
Devlin Cronin242d19d22019-03-12 18:08:481568IN_PROC_BROWSER_TEST_F(ServiceWorkerPushMessagingTest, OnPush) {
lazyboy561b7de2015-11-19 19:27:301569 const Extension* extension = LoadExtensionWithFlags(
1570 test_data_dir_.AppendASCII("service_worker/push_messaging"), kFlagNone);
1571 ASSERT_TRUE(extension);
1572 GURL extension_url = extension->url();
1573
Peter Beverloodd4ef1e2018-06-21 15:41:041574 GrantNotificationPermissionForTest(extension_url);
lazyboy561b7de2015-11-19 19:27:301575
1576 GURL url = extension->GetResourceURL("page.html");
1577 ui_test_utils::NavigateToURL(browser(), url);
1578
1579 content::WebContents* web_contents =
1580 browser()->tab_strip_model()->GetActiveWebContents();
1581
1582 // Start the ServiceWorker.
1583 ExtensionTestMessageListener ready_listener("SERVICE_WORKER_READY", false);
1584 ready_listener.set_failure_message("SERVICE_WORKER_FAILURE");
1585 const char* kScript = "window.runServiceWorker()";
1586 EXPECT_TRUE(content::ExecuteScript(web_contents->GetMainFrame(), kScript));
1587 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1588
1589 PushMessagingAppIdentifier app_identifier =
1590 GetAppIdentifierForServiceWorkerRegistration(0LL, extension_url);
johnmea5045732016-09-08 17:23:291591 ASSERT_EQ(app_identifier.app_id(), gcm_driver()->last_gettoken_app_id());
1592 EXPECT_EQ("1234567890", gcm_driver()->last_gettoken_authorized_entity());
lazyboy561b7de2015-11-19 19:27:301593
lazyboyd429e2582016-05-20 20:18:521594 base::RunLoop run_loop;
lazyboy561b7de2015-11-19 19:27:301595 // Send a push message via gcm and expect the ServiceWorker to receive it.
1596 ExtensionTestMessageListener push_message_listener("OK", false);
1597 push_message_listener.set_failure_message("FAIL");
1598 gcm::IncomingMessage message;
1599 message.sender_id = "1234567890";
1600 message.raw_data = "testdata";
1601 message.decrypted = true;
lazyboyd429e2582016-05-20 20:18:521602 push_service()->SetMessageCallbackForTesting(run_loop.QuitClosure());
lazyboy561b7de2015-11-19 19:27:301603 push_service()->OnMessage(app_identifier.app_id(), message);
1604 EXPECT_TRUE(push_message_listener.WaitUntilSatisfied());
lazyboyd429e2582016-05-20 20:18:521605 run_loop.Run(); // Wait until the message is handled by push service.
lazyboy561b7de2015-11-19 19:27:301606}
1607
Devlin Cronin242d19d22019-03-12 18:08:481608IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, FilteredEvents) {
Istiaque Ahmed9d1666182017-09-21 23:58:181609 // Extensions APIs from SW are only enabled on trunk.
1610 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1611 ASSERT_TRUE(RunExtensionTest("service_worker/filtered_events"));
1612}
1613
Devlin Cronin242d19d22019-03-12 18:08:481614IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, MimeHandlerView) {
Rob Wue89b90032018-02-16 19:46:081615 ASSERT_TRUE(RunExtensionTest("service_worker/mime_handler_view"));
1616}
1617
Devlin Cronin242d19d22019-03-12 18:08:481618IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmed9ce21b32017-10-10 20:43:181619 PRE_FilteredEventsAfterRestart) {
1620 LazyBackgroundObserver lazy_observer;
1621 ResultCatcher catcher;
1622 const Extension* extension = LoadExtensionWithFlags(
1623 test_data_dir_.AppendASCII(
1624 "service_worker/filtered_events_after_restart"),
1625 kFlagNone);
1626 ASSERT_TRUE(extension);
1627 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1628
1629 // |extension|'s background page opens a tab to its resource.
1630 content::WebContents* extension_web_contents =
1631 browser()->tab_strip_model()->GetActiveWebContents();
1632 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1633 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1634 extension_web_contents->GetURL().spec());
1635 {
1636 // Let the service worker start and register a filtered listener to
1637 // chrome.webNavigation.onCommitted event.
1638 ExtensionTestMessageListener add_listener_done("listener-added", false);
1639 add_listener_done.set_failure_message("FAILURE");
1640 content::ExecuteScriptAsync(extension_web_contents,
1641 "window.runServiceWorkerAsync()");
1642 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1643
1644 base::RunLoop run_loop;
1645 content::StoragePartition* storage_partition =
1646 content::BrowserContext::GetDefaultStoragePartition(
1647 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001648 content::StopServiceWorkerForScope(
Istiaque Ahmed9ce21b32017-10-10 20:43:181649 storage_partition->GetServiceWorkerContext(),
1650 // The service worker is registered at the top level scope.
1651 extension->url(), run_loop.QuitClosure());
1652 run_loop.Run();
1653 }
1654
1655 // Close the tab to |extension|'s resource. This will also close the
1656 // extension's event page.
1657 browser()->tab_strip_model()->CloseWebContentsAt(
1658 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1659 lazy_observer.Wait();
1660}
1661
Devlin Cronin242d19d22019-03-12 18:08:481662IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmedf5712522018-09-20 03:35:471663 FilteredEventsAfterRestart) {
Istiaque Ahmed9ce21b32017-10-10 20:43:181664 // Create a tab to a.html, expect it to navigate to b.html. The service worker
1665 // will see two webNavigation.onCommitted events.
1666 ASSERT_TRUE(StartEmbeddedTestServer());
1667 GURL page_url = embedded_test_server()->GetURL(
1668 "/extensions/api_test/service_worker/filtered_events_after_restart/"
1669 "a.html");
1670 ExtensionTestMessageListener worker_filtered_event_listener(
1671 "PASS_FROM_WORKER", false);
1672 worker_filtered_event_listener.set_failure_message("FAIL_FROM_WORKER");
1673 content::WebContents* web_contents = AddTab(browser(), page_url);
1674 EXPECT_TRUE(web_contents);
1675 EXPECT_TRUE(worker_filtered_event_listener.WaitUntilSatisfied());
1676}
1677
Devlin Cronin242d19d22019-03-12 18:08:481678IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest,
Istiaque Ahmedd4b67ee2019-03-02 10:53:201679 ProcessManagerRegistrationOnShutdown) {
1680 // Note that StopServiceWorkerForScope call below expects the worker to be
1681 // completely installed, so wait for the |extension| worker to see "activate"
1682 // event.
1683 ExtensionTestMessageListener activated_listener("WORKER_ACTIVATED", false);
1684 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
1685 "service_worker/worker_based_background/process_manager"));
1686 ASSERT_TRUE(extension);
1687 EXPECT_TRUE(activated_listener.WaitUntilSatisfied());
1688
1689 base::Optional<WorkerId> worker_id =
1690 GetUniqueRunningWorkerId(extension->id());
1691 ASSERT_TRUE(worker_id);
1692 {
1693 // Shutdown the worker.
1694 // TODO(lazyboy): Ideally we'd want to test worker shutdown on idle, do that
1695 // once //content API allows to override test timeouts for Service Workers.
1696 base::RunLoop run_loop;
1697 content::StoragePartition* storage_partition =
1698 content::BrowserContext::GetDefaultStoragePartition(
1699 browser()->profile());
1700 GURL scope = extension->url();
1701 content::StopServiceWorkerForScope(
1702 storage_partition->GetServiceWorkerContext(),
1703 // The service worker is registered at the top level scope.
1704 extension->url(), run_loop.QuitClosure());
1705 run_loop.Run();
1706 }
1707
1708 EXPECT_FALSE(ProcessManager::Get(profile())->HasServiceWorker(*worker_id));
1709}
1710
Devlin Cronin242d19d22019-03-12 18:08:481711IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest,
Istiaque Ahmedd4b67ee2019-03-02 10:53:201712 ProcessManagerRegistrationOnTerminate) {
1713 // NOTE: It is not necessary to wait for "activate" event from the worker
1714 // for this test, but we're lazily reusing the extension from
1715 // ProcessManagerRegistrationOnShutdown test.
1716 ExtensionTestMessageListener activated_listener("WORKER_ACTIVATED", false);
1717 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
1718 "service_worker/worker_based_background/process_manager"));
1719 ASSERT_TRUE(extension);
1720 EXPECT_TRUE(activated_listener.WaitUntilSatisfied());
1721
1722 base::Optional<WorkerId> worker_id =
1723 GetUniqueRunningWorkerId(extension->id());
1724 ASSERT_TRUE(worker_id);
1725 {
1726 // Terminate worker's RenderProcessHost.
1727 content::RenderProcessHost* worker_render_process_host =
1728 content::RenderProcessHost::FromID(worker_id->render_process_id);
1729 ASSERT_TRUE(worker_render_process_host);
1730 content::RenderProcessHostWatcher process_exit_observer(
1731 worker_render_process_host,
1732 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
1733 worker_render_process_host->Shutdown(content::RESULT_CODE_KILLED);
1734 process_exit_observer.Wait();
1735 }
1736
1737 EXPECT_FALSE(ProcessManager::Get(profile())->HasServiceWorker(*worker_id));
1738}
1739
Devlin Cronin59551d82019-03-05 01:28:591740// Tests that console messages logged by extension service workers, both via
1741// the typical console.* methods and via our custom bindings console, are
1742// passed through the normal ServiceWorker console messaging and are
1743// observable.
Devlin Cronin242d19d22019-03-12 18:08:481744IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest, ConsoleLogging) {
Devlin Cronin59551d82019-03-05 01:28:591745 // A helper class to wait for a particular message to be logged from a
1746 // ServiceWorker.
1747 class ConsoleMessageObserver : public content::ServiceWorkerContextObserver {
1748 public:
1749 ConsoleMessageObserver(content::BrowserContext* browser_context,
1750 const std::string& expected_message)
1751 : expected_message_(base::UTF8ToUTF16(expected_message)),
1752 scoped_observer_(this) {
1753 content::StoragePartition* partition =
1754 content::BrowserContext::GetDefaultStoragePartition(browser_context);
1755 scoped_observer_.Add(partition->GetServiceWorkerContext());
1756 }
1757 ~ConsoleMessageObserver() override = default;
1758
1759 void Wait() { run_loop_.Run(); }
1760
1761 private:
1762 // ServiceWorkerContextObserver:
1763 void OnReportConsoleMessage(
1764 int64_t version_id,
1765 const content::ConsoleMessage& message) override {
1766 // NOTE: We could check the version_id, but it shouldn't be necessary with
1767 // the expected messages we're verifying (they're uncommon enough).
1768 if (message.message != expected_message_)
1769 return;
1770 scoped_observer_.RemoveAll();
1771 run_loop_.QuitWhenIdle();
1772 }
1773
1774 base::string16 expected_message_;
1775 base::RunLoop run_loop_;
1776 ScopedObserver<content::ServiceWorkerContext,
1777 content::ServiceWorkerContextObserver>
1778 scoped_observer_;
1779
1780 DISALLOW_COPY_AND_ASSIGN(ConsoleMessageObserver);
1781 };
1782
1783 TestExtensionDir test_dir;
1784 test_dir.WriteManifest(
1785 R"({
1786 "name": "Test Extension",
1787 "manifest_version": 2,
1788 "version": "0.1",
David Bertoni630837d2019-04-02 21:22:101789 "background": {"service_worker": "script.js"}
Devlin Cronin59551d82019-03-05 01:28:591790 })");
1791 constexpr char kScript[] =
1792 R"(// First, log a message using the normal, built-in blink console.
1793 console.log('test message');
1794 chrome.test.runTests([
1795 function justATest() {
1796 // Next, we use the "Console" object from
1797 // extensions/renderer/console.cc, which is used by custom bindings
1798 // so that it isn't tampered with by untrusted script. The test
1799 // custom bindings log a message whenever a test is passed, so we
1800 // force a log by just passing this test.
1801 chrome.test.succeed();
1802 }
1803 ]);)";
1804 test_dir.WriteFile(FILE_PATH_LITERAL("script.js"), kScript);
1805
1806 // The observer for the built-in blink console.
1807 ConsoleMessageObserver default_console_observer(profile(), "test message");
1808 // The observer for our custom extensions bindings console.
1809 ConsoleMessageObserver custom_console_observer(profile(),
1810 "[SUCCESS] justATest");
1811
1812 const Extension* extension = LoadExtension(test_dir.UnpackedPath());
1813 ASSERT_TRUE(extension);
1814
1815 default_console_observer.Wait();
1816 custom_console_observer.Wait();
1817 // If we receive both messages, we passed!
1818}
1819
annekao38685502015-07-14 17:46:391820} // namespace extensions