blob: 9391ad5ecc54c3b88633894d73cdcd04d8248f96 [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"
David Bertoni9026eff2019-05-01 18:04:3118#include "chrome/browser/extensions/crx_installer.h"
annekao38685502015-07-14 17:46:3919#include "chrome/browser/extensions/extension_apitest.h"
rdevlin.croninf5863da2015-09-10 19:21:4520#include "chrome/browser/extensions/extension_service.h"
Istiaque Ahmed805f6a83b2017-10-05 01:23:2621#include "chrome/browser/extensions/lazy_background_page_test_util.h"
David Bertoni1d646a152019-04-25 02:09:2222#include "chrome/browser/extensions/unpacked_installer.h"
peter9f4490a2017-01-27 00:58:3623#include "chrome/browser/gcm/gcm_profile_service_factory.h"
miguelg9b502862017-04-24 18:13:5324#include "chrome/browser/notifications/notification_display_service_factory.h"
Peter Beverloodd4ef1e2018-06-21 15:41:0425#include "chrome/browser/notifications/notification_permission_context.h"
miguelg9b502862017-04-24 18:13:5326#include "chrome/browser/notifications/stub_notification_display_service.h"
lshang106c1772016-06-06 01:43:2327#include "chrome/browser/permissions/permission_manager.h"
timlohc6911802017-03-01 05:37:0328#include "chrome/browser/permissions/permission_result.h"
lazyboy561b7de2015-11-19 19:27:3029#include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
30#include "chrome/browser/push_messaging/push_messaging_service_factory.h"
31#include "chrome/browser/push_messaging/push_messaging_service_impl.h"
annekao1db36fd2015-07-29 17:09:1632#include "chrome/browser/ui/tabs/tab_strip_model.h"
Trent Apted4267b942017-10-27 03:25:3633#include "chrome/common/chrome_switches.h"
Istiaque Ahmeda14ec482018-08-25 01:02:1834#include "chrome/common/extensions/api/web_navigation.h"
rdevlin.croninf5863da2015-09-10 19:21:4535#include "chrome/test/base/ui_test_utils.h"
timloh9a180ad2017-02-20 07:15:2336#include "components/content_settings/core/common/content_settings_types.h"
Peter Beverloo34139462018-04-10 14:18:0637#include "components/gcm_driver/fake_gcm_profile_service.h"
johnmea5045732016-09-08 17:23:2938#include "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h"
sdefresne9fb67692015-08-03 18:48:2239#include "components/version_info/version_info.h"
Devlin Cronin59551d82019-03-05 01:28:5940#include "content/public/browser/console_message.h"
kalman6f984ae2015-09-18 17:21:5841#include "content/public/browser/navigation_controller.h"
rdevlin.croninf5863da2015-09-10 19:21:4542#include "content/public/browser/navigation_entry.h"
Istiaque Ahmedd4b67ee2019-03-02 10:53:2043#include "content/public/browser/render_process_host.h"
lazyboy4c82177a2016-10-18 00:04:0944#include "content/public/browser/service_worker_context.h"
Devlin Cronin59551d82019-03-05 01:28:5945#include "content/public/browser/service_worker_context_observer.h"
lazyboy4c82177a2016-10-18 00:04:0946#include "content/public/browser/storage_partition.h"
kalman6f984ae2015-09-18 17:21:5847#include "content/public/browser/web_contents.h"
lazyboybd325ae2015-11-18 21:35:2648#include "content/public/common/content_switches.h"
falkenad185092016-06-16 06:10:0249#include "content/public/common/origin_util.h"
kalman6f984ae2015-09-18 17:21:5850#include "content/public/common/page_type.h"
Istiaque Ahmedd4b67ee2019-03-02 10:53:2051#include "content/public/common/result_codes.h"
lazyboybd325ae2015-11-18 21:35:2652#include "content/public/test/background_sync_test_util.h"
annekao1db36fd2015-07-29 17:09:1653#include "content/public/test/browser_test_utils.h"
lazyboy63b994a2017-06-30 21:20:2354#include "content/public/test/service_worker_test_helpers.h"
Istiaque Ahmed771aa8a22018-06-20 23:40:5355#include "extensions/browser/event_router.h"
kalman6f984ae2015-09-18 17:21:5856#include "extensions/browser/extension_host.h"
lazyboyc3e763a2015-12-09 23:09:5857#include "extensions/browser/extension_registry.h"
kalman6f984ae2015-09-18 17:21:5858#include "extensions/browser/process_manager.h"
Istiaque Ahmed70f76ac2018-11-02 02:59:5559#include "extensions/browser/service_worker_task_queue.h"
Istiaque Ahmeda14ec482018-08-25 01:02:1860#include "extensions/common/api/test.h"
Istiaque Ahmed771aa8a22018-06-20 23:40:5361#include "extensions/common/value_builder.h"
David Bertoni9026eff2019-05-01 18:04:3162#include "extensions/common/verifier_formats.h"
kalman6f984ae2015-09-18 17:21:5863#include "extensions/test/background_page_watcher.h"
annekao38685502015-07-14 17:46:3964#include "extensions/test/extension_test_message_listener.h"
Istiaque Ahmed805f6a83b2017-10-05 01:23:2665#include "extensions/test/result_catcher.h"
Devlin Cronin59551d82019-03-05 01:28:5966#include "extensions/test/test_extension_dir.h"
falkenad185092016-06-16 06:10:0267#include "net/dns/mock_host_resolver.h"
horo1eeddde2015-11-19 05:59:2568#include "net/test/embedded_test_server/embedded_test_server.h"
lazyboy63b994a2017-06-30 21:20:2369#include "url/url_constants.h"
annekao38685502015-07-14 17:46:3970
71namespace extensions {
72
kalman6f984ae2015-09-18 17:21:5873namespace {
74
lazyboy22eddc712015-12-10 21:16:2675// Returns the newly added WebContents.
76content::WebContents* AddTab(Browser* browser, const GURL& url) {
77 int starting_tab_count = browser->tab_strip_model()->count();
78 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:1979 browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
lazyboy22eddc712015-12-10 21:16:2680 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
81 int tab_count = browser->tab_strip_model()->count();
82 EXPECT_EQ(starting_tab_count + 1, tab_count);
83 return browser->tab_strip_model()->GetActiveWebContents();
84}
85
lazyboy22eddc712015-12-10 21:16:2686class WebContentsLoadStopObserver : content::WebContentsObserver {
87 public:
88 explicit WebContentsLoadStopObserver(content::WebContents* web_contents)
89 : content::WebContentsObserver(web_contents),
90 load_stop_observed_(false) {}
91
92 void WaitForLoadStop() {
93 if (load_stop_observed_)
94 return;
95 message_loop_runner_ = new content::MessageLoopRunner;
96 message_loop_runner_->Run();
97 }
98
99 private:
100 void DidStopLoading() override {
101 load_stop_observed_ = true;
102 if (message_loop_runner_)
103 message_loop_runner_->Quit();
104 }
105
106 bool load_stop_observed_;
107 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
108
109 DISALLOW_COPY_AND_ASSIGN(WebContentsLoadStopObserver);
110};
111
kalman6f984ae2015-09-18 17:21:58112} // namespace
113
Devlin Cronin242d19d22019-03-12 18:08:48114class ServiceWorkerTest : public ExtensionApiTest {
annekao38685502015-07-14 17:46:39115 public:
lazyboy20167c22016-05-18 00:59:30116 ServiceWorkerTest() : current_channel_(version_info::Channel::STABLE) {}
Istiaque Ahmed7105f2a2017-10-07 01:11:59117 explicit ServiceWorkerTest(version_info::Channel channel)
118 : current_channel_(channel) {}
annekao38685502015-07-14 17:46:39119
120 ~ServiceWorkerTest() override {}
121
jam1a5b5582017-05-01 16:50:10122 void SetUpOnMainThread() override {
123 ExtensionApiTest::SetUpOnMainThread();
David Bertoni3929f552019-03-28 22:10:36124 host_resolver()->AddRule("*", "127.0.0.1");
jam1a5b5582017-05-01 16:50:10125 }
126
kalman6f984ae2015-09-18 17:21:58127 protected:
128 // Returns the ProcessManager for the test's profile.
129 ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
130
131 // Starts running a test from the background page test extension.
132 //
133 // This registers a service worker with |script_name|, and fetches the
134 // registration result.
Istiaque Ahmed93ff7f42018-08-31 01:42:22135 const Extension* StartTestFromBackgroundPage(const char* script_name) {
Istiaque Ahmed6475f542018-08-28 04:20:21136 ExtensionTestMessageListener ready_listener("ready", false);
kalman6f984ae2015-09-18 17:21:58137 const Extension* extension =
138 LoadExtension(test_data_dir_.AppendASCII("service_worker/background"));
139 CHECK(extension);
Istiaque Ahmed6475f542018-08-28 04:20:21140 CHECK(ready_listener.WaitUntilSatisfied());
141
kalman6f984ae2015-09-18 17:21:58142 ExtensionHost* background_host =
143 process_manager()->GetBackgroundHostForExtension(extension->id());
144 CHECK(background_host);
Istiaque Ahmed6475f542018-08-28 04:20:21145
kalman6f984ae2015-09-18 17:21:58146 std::string error;
147 CHECK(content::ExecuteScriptAndExtractString(
148 background_host->host_contents(),
149 base::StringPrintf("test.registerServiceWorker('%s')", script_name),
150 &error));
Istiaque Ahmed93ff7f42018-08-31 01:42:22151 if (!error.empty())
kalman6f984ae2015-09-18 17:21:58152 ADD_FAILURE() << "Got unexpected error " << error;
153 return extension;
154 }
155
156 // Navigates the browser to a new tab at |url|, waits for it to load, then
157 // returns it.
158 content::WebContents* Navigate(const GURL& url) {
159 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19160 browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
kalman6f984ae2015-09-18 17:21:58161 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
162 content::WebContents* web_contents =
163 browser()->tab_strip_model()->GetActiveWebContents();
164 content::WaitForLoadStop(web_contents);
165 return web_contents;
166 }
167
168 // Navigates the browser to |url| and returns the new tab's page type.
169 content::PageType NavigateAndGetPageType(const GURL& url) {
clamy1d7a4112018-06-15 15:47:16170 return Navigate(url)
171 ->GetController()
172 .GetLastCommittedEntry()
173 ->GetPageType();
kalman6f984ae2015-09-18 17:21:58174 }
175
176 // Extracts the innerText from |contents|.
177 std::string ExtractInnerText(content::WebContents* contents) {
178 std::string inner_text;
179 if (!content::ExecuteScriptAndExtractString(
180 contents,
181 "window.domAutomationController.send(document.body.innerText)",
182 &inner_text)) {
183 ADD_FAILURE() << "Failed to get inner text for "
184 << contents->GetVisibleURL();
185 }
186 return inner_text;
187 }
188
189 // Navigates the browser to |url|, then returns the innerText of the new
190 // tab's WebContents' main frame.
191 std::string NavigateAndExtractInnerText(const GURL& url) {
192 return ExtractInnerText(Navigate(url));
193 }
194
lazyboy4c82177a2016-10-18 00:04:09195 size_t GetWorkerRefCount(const GURL& origin) {
196 content::ServiceWorkerContext* sw_context =
197 content::BrowserContext::GetDefaultStoragePartition(
198 browser()->profile())
199 ->GetServiceWorkerContext();
200 base::RunLoop run_loop;
201 size_t ref_count = 0;
202 auto set_ref_count = [](size_t* ref_count, base::RunLoop* run_loop,
203 size_t external_request_count) {
204 *ref_count = external_request_count;
205 run_loop->Quit();
206 };
207 sw_context->CountExternalRequestsForTest(
Matt Falkenhagenc5cb4282017-09-07 08:43:42208 origin, base::BindOnce(set_ref_count, &ref_count, &run_loop));
lazyboy4c82177a2016-10-18 00:04:09209 run_loop.Run();
210 return ref_count;
211 }
212
annekao38685502015-07-14 17:46:39213 private:
lazyboy20167c22016-05-18 00:59:30214 // Sets the channel to "stable".
215 // Not useful after we've opened extension Service Workers to stable
216 // channel.
217 // TODO(lazyboy): Remove this when ExtensionServiceWorkersEnabled() is
218 // removed.
annekao38685502015-07-14 17:46:39219 ScopedCurrentChannel current_channel_;
kalman6f984ae2015-09-18 17:21:58220
annekao38685502015-07-14 17:46:39221 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTest);
222};
223
Istiaque Ahmedccb444022018-06-19 02:11:12224class ServiceWorkerBasedBackgroundTest : public ServiceWorkerTest {
225 public:
226 ServiceWorkerBasedBackgroundTest()
227 : ServiceWorkerTest(
228 // Extensions APIs from SW are only enabled on trunk.
229 // It is important to set the channel early so that this change is
230 // visible in renderers running with service workers (and no
231 // extension).
232 version_info::Channel::UNKNOWN) {}
233 ~ServiceWorkerBasedBackgroundTest() override {}
234
235 void SetUpOnMainThread() override {
236 host_resolver()->AddRule("*", "127.0.0.1");
237 ASSERT_TRUE(embedded_test_server()->Start());
238 ServiceWorkerTest::SetUpOnMainThread();
239 }
240
Istiaque Ahmedd4b67ee2019-03-02 10:53:20241 // Returns the only running worker id for |extension_id|.
242 // Returns base::nullopt if there isn't any worker running or more than one
243 // worker is running for |extension_id|.
244 base::Optional<WorkerId> GetUniqueRunningWorkerId(
245 const ExtensionId& extension_id) {
246 ProcessManager* process_manager = ProcessManager::Get(profile());
247 std::vector<WorkerId> all_workers =
248 process_manager->GetAllWorkersIdsForTesting();
249 base::Optional<WorkerId> running_worker_id;
250 for (const WorkerId& worker_id : all_workers) {
251 if (worker_id.extension_id == extension_id) {
252 if (running_worker_id) // More than one worker present.
253 return base::nullopt;
254 running_worker_id = worker_id;
255 }
256 }
257 return running_worker_id;
258 }
259
Istiaque Ahmedccb444022018-06-19 02:11:12260 private:
261 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBasedBackgroundTest);
262};
263
264// Tests that Service Worker based background pages can be loaded and they can
265// receive extension events.
266// The extension is installed and loaded during this step and it registers
267// an event listener for tabs.onCreated event. The step also verifies that tab
268// creation correctly fires the listener.
Devlin Cronin242d19d22019-03-12 18:08:48269IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, PRE_Basic) {
Istiaque Ahmedccb444022018-06-19 02:11:12270 ExtensionTestMessageListener newtab_listener("CREATED", false);
271 newtab_listener.set_failure_message("CREATE_FAILED");
272 ExtensionTestMessageListener worker_listener("WORKER_RUNNING", false);
273 worker_listener.set_failure_message("NON_WORKER_SCOPE");
274 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
275 "service_worker/worker_based_background/basic"));
276 ASSERT_TRUE(extension);
277 const ExtensionId extension_id = extension->id();
278 EXPECT_TRUE(worker_listener.WaitUntilSatisfied());
279
280 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
281 content::WebContents* new_web_contents = AddTab(browser(), url);
282 EXPECT_TRUE(new_web_contents);
283 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
284
285 // Service Worker extension does not have ExtensionHost.
286 EXPECT_FALSE(process_manager()->GetBackgroundHostForExtension(extension_id));
287}
288
289// After browser restarts, this test step ensures that opening a tab fires
290// tabs.onCreated event listener to the extension without explicitly loading the
291// extension. This is because the extension registered a listener before browser
292// restarted in PRE_Basic.
Devlin Cronin242d19d22019-03-12 18:08:48293IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, Basic) {
Istiaque Ahmedccb444022018-06-19 02:11:12294 ExtensionTestMessageListener newtab_listener("CREATED", false);
295 newtab_listener.set_failure_message("CREATE_FAILED");
296 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
297 content::WebContents* new_web_contents = AddTab(browser(), url);
298 EXPECT_TRUE(new_web_contents);
299 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
300}
301
Istiaque Ahmedbf08f952018-10-02 01:22:04302// Tests chrome.runtime.onInstalled fires for extension service workers.
Devlin Cronin242d19d22019-03-12 18:08:48303IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, OnInstalledEvent) {
Istiaque Ahmedbf08f952018-10-02 01:22:04304 ASSERT_TRUE(RunExtensionTest(
305 "service_worker/worker_based_background/events_on_installed"))
306 << message_;
307}
308
David Bertoni69982832019-02-13 21:24:21309// Tests chrome.storage APIs.
Devlin Cronin242d19d22019-03-12 18:08:48310IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, StorageSetAndGet) {
David Bertoni69982832019-02-13 21:24:21311 ASSERT_TRUE(
312 RunExtensionTest("service_worker/worker_based_background/storage"))
313 << message_;
314}
315
David Bertoni0665c892019-02-14 00:27:26316// Tests chrome.storage.local and chrome.storage.local APIs.
Devlin Cronin242d19d22019-03-12 18:08:48317IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, StorageNoPermissions) {
David Bertoni0665c892019-02-14 00:27:26318 ASSERT_TRUE(RunExtensionTest(
319 "service_worker/worker_based_background/storage_no_permissions"))
320 << message_;
321}
322
David Bertoni30809312019-02-28 22:56:05323// Tests chrome.tabs APIs.
Devlin Cronin242d19d22019-03-12 18:08:48324IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, TabsBasic) {
David Bertoni30809312019-02-28 22:56:05325 ASSERT_TRUE(
326 RunExtensionTest("service_worker/worker_based_background/tabs_basic"))
327 << message_;
328}
329
David Bertoni46d698892019-02-26 00:29:10330// Tests chrome.tabs events.
Devlin Cronin242d19d22019-03-12 18:08:48331IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, TabsEvents) {
David Bertoni46d698892019-02-26 00:29:10332 ASSERT_TRUE(
333 RunExtensionTest("service_worker/worker_based_background/tabs_events"))
334 << message_;
335}
336
David Bertoni4c7dfcc2019-03-27 23:49:34337// Tests chrome.tabs APIs.
338IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, TabsExecuteScript) {
339 ASSERT_TRUE(RunExtensionTest(
340 "service_worker/worker_based_background/tabs_execute_script"))
341 << message_;
342}
343
David Bertoni37ae0222019-04-04 01:30:54344// Tests chrome.webRequest APIs.
David Bertoni3929f552019-03-28 22:10:36345IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, WebRequest) {
346 ASSERT_TRUE(
347 RunExtensionTest("service_worker/worker_based_background/web_request"))
348 << message_;
349}
350
David Bertoni37ae0222019-04-04 01:30:54351// Tests chrome.webRequest APIs in blocking mode.
352IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, WebRequestBlocking) {
353 // Try to load the page before installing the extension, which should work.
354 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
355 EXPECT_EQ(content::PAGE_TYPE_NORMAL, NavigateAndGetPageType(url));
356
357 // Install the extension and navigate again to the page.
358 ExtensionTestMessageListener ready_listener("ready", false);
359 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
360 "service_worker/worker_based_background/web_request_blocking")));
361 ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
362 EXPECT_EQ(content::PAGE_TYPE_ERROR, NavigateAndGetPageType(url));
363}
364
Istiaque Ahmed70f76ac2018-11-02 02:59:55365// Listens for |message| from extension Service Worker early so that tests can
366// wait for the message on startup (and not miss it).
367class ServiceWorkerWithEarlyMessageListenerTest
368 : public ServiceWorkerBasedBackgroundTest {
Istiaque Ahmedf70ab222018-10-02 03:08:24369 public:
Istiaque Ahmed70f76ac2018-11-02 02:59:55370 explicit ServiceWorkerWithEarlyMessageListenerTest(
371 const std::string& test_message)
372 : test_message_(test_message) {}
373 ~ServiceWorkerWithEarlyMessageListenerTest() override = default;
Istiaque Ahmedf70ab222018-10-02 03:08:24374
Istiaque Ahmed70f76ac2018-11-02 02:59:55375 bool WaitForMessage() { return listener_->WaitUntilSatisfied(); }
Istiaque Ahmedf70ab222018-10-02 03:08:24376
377 void CreatedBrowserMainParts(content::BrowserMainParts* main_parts) override {
378 // At this point, the notification service is initialized but the profile
379 // and extensions have not.
Istiaque Ahmed70f76ac2018-11-02 02:59:55380 listener_ =
381 std::make_unique<ExtensionTestMessageListener>(test_message_, false);
Istiaque Ahmedf70ab222018-10-02 03:08:24382 ServiceWorkerBasedBackgroundTest::CreatedBrowserMainParts(main_parts);
383 }
384
385 private:
Istiaque Ahmed70f76ac2018-11-02 02:59:55386 const std::string test_message_;
Istiaque Ahmedf70ab222018-10-02 03:08:24387 std::unique_ptr<ExtensionTestMessageListener> listener_;
388
Istiaque Ahmed70f76ac2018-11-02 02:59:55389 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerWithEarlyMessageListenerTest);
390};
391
392class ServiceWorkerOnStartupEventTest
393 : public ServiceWorkerWithEarlyMessageListenerTest {
394 public:
395 ServiceWorkerOnStartupEventTest()
396 : ServiceWorkerWithEarlyMessageListenerTest("onStartup event") {}
397 ~ServiceWorkerOnStartupEventTest() override = default;
398
399 private:
400 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerOnStartupEventTest);
Istiaque Ahmedf70ab222018-10-02 03:08:24401};
402
403// Tests "runtime.onStartup" for extension SW.
Devlin Cronin242d19d22019-03-12 18:08:48404IN_PROC_BROWSER_TEST_F(ServiceWorkerOnStartupEventTest, PRE_Event) {
Istiaque Ahmedf70ab222018-10-02 03:08:24405 ASSERT_TRUE(RunExtensionTest(
406 "service_worker/worker_based_background/on_startup_event"))
407 << message_;
408}
409
Devlin Cronin242d19d22019-03-12 18:08:48410IN_PROC_BROWSER_TEST_F(ServiceWorkerOnStartupEventTest, Event) {
Istiaque Ahmed70f76ac2018-11-02 02:59:55411 EXPECT_TRUE(WaitForMessage());
412}
413
414class ServiceWorkerRegistrationAtStartupTest
415 : public ServiceWorkerWithEarlyMessageListenerTest,
416 public ServiceWorkerTaskQueue::TestObserver {
417 public:
418 ServiceWorkerRegistrationAtStartupTest()
419 : ServiceWorkerWithEarlyMessageListenerTest("WORKER_RUNNING") {
420 ServiceWorkerTaskQueue::SetObserverForTest(this);
421 }
422 ~ServiceWorkerRegistrationAtStartupTest() override {
423 ServiceWorkerTaskQueue::SetObserverForTest(nullptr);
424 }
425
426 // ServiceWorkerTaskQueue::TestObserver:
427 void OnActivateExtension(const ExtensionId& extension_id,
428 bool will_register_service_worker) override {
429 if (extension_id != kExtensionId)
430 return;
431
432 will_register_service_worker_ = will_register_service_worker;
433
434 extension_activated_ = true;
435 if (run_loop_)
436 run_loop_->Quit();
437 }
438
439 void WaitForOnActivateExtension() {
440 if (extension_activated_)
441 return;
442 run_loop_ = std::make_unique<base::RunLoop>();
443 run_loop_->Run();
444 }
445
446 bool WillRegisterServiceWorker() {
447 return will_register_service_worker_.value();
448 }
449
450 protected:
451 static const char kExtensionId[];
452
453 private:
454 bool extension_activated_ = false;
455 base::Optional<bool> will_register_service_worker_;
456 std::unique_ptr<base::RunLoop> run_loop_;
457
458 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistrationAtStartupTest);
459};
460
461// Test extension id at
462// api_test/service_worker/worker_based_background/registration_at_startup/.
463const char ServiceWorkerRegistrationAtStartupTest::kExtensionId[] =
464 "gnchfmandajfaiajniicagenfmhdjila";
465
466// Tests that Service Worker registration for existing extension isn't issued
467// upon browser restart.
468// Regression test for https://crbug.com/889687.
Devlin Cronin242d19d22019-03-12 18:08:48469IN_PROC_BROWSER_TEST_F(ServiceWorkerRegistrationAtStartupTest,
Istiaque Ahmed70f76ac2018-11-02 02:59:55470 PRE_ExtensionActivationDoesNotReregister) {
471 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
472 "service_worker/worker_based_background/registration_at_startup"));
473 ASSERT_TRUE(extension);
474 EXPECT_EQ(kExtensionId, extension->id());
475 // Wait for "WORKER_RUNNING" message from the Service Worker.
476 EXPECT_TRUE(WaitForMessage());
477 EXPECT_TRUE(WillRegisterServiceWorker());
478}
479
Devlin Cronin242d19d22019-03-12 18:08:48480IN_PROC_BROWSER_TEST_F(ServiceWorkerRegistrationAtStartupTest,
Istiaque Ahmed70f76ac2018-11-02 02:59:55481 ExtensionActivationDoesNotReregister) {
482 // Since the extension has onStartup listener, the Service Worker will run on
483 // browser start and we'll see "WORKER_RUNNING" message from the worker.
484 EXPECT_TRUE(WaitForMessage());
485 // As the extension activated during first run on PRE_ step, it shouldn't
486 // re-register the Service Worker upon browser restart.
487 EXPECT_FALSE(WillRegisterServiceWorker());
Istiaque Ahmedf70ab222018-10-02 03:08:24488}
489
Istiaque Ahmeda14ec482018-08-25 01:02:18490// Class that dispatches an event to |extension_id| right after a
491// non-lazy listener to the event is added from the extension's Service Worker.
Istiaque Ahmed771aa8a22018-06-20 23:40:53492class EarlyWorkerMessageSender : public EventRouter::Observer {
493 public:
494 EarlyWorkerMessageSender(content::BrowserContext* browser_context,
Istiaque Ahmeda14ec482018-08-25 01:02:18495 const ExtensionId& extension_id,
496 std::unique_ptr<Event> event)
Istiaque Ahmed771aa8a22018-06-20 23:40:53497 : browser_context_(browser_context),
498 event_router_(EventRouter::EventRouter::Get(browser_context_)),
499 extension_id_(extension_id),
Istiaque Ahmeda14ec482018-08-25 01:02:18500 event_(std::move(event)),
Istiaque Ahmed771aa8a22018-06-20 23:40:53501 listener_("PASS", false) {
502 DCHECK(browser_context_);
503 listener_.set_failure_message("FAIL");
Istiaque Ahmeda14ec482018-08-25 01:02:18504 event_router_->RegisterObserver(this, event_->event_name);
Istiaque Ahmed771aa8a22018-06-20 23:40:53505 }
506
507 ~EarlyWorkerMessageSender() override {
508 event_router_->UnregisterObserver(this);
509 }
510
511 // EventRouter::Observer:
512 void OnListenerAdded(const EventListenerInfo& details) override {
Istiaque Ahmeda14ec482018-08-25 01:02:18513 if (!event_ || extension_id_ != details.extension_id ||
514 event_->event_name != details.event_name) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53515 return;
Istiaque Ahmeda14ec482018-08-25 01:02:18516 }
517
Istiaque Ahmed771aa8a22018-06-20 23:40:53518 const bool is_lazy_listener = details.browser_context == nullptr;
519 if (is_lazy_listener) {
520 // Wait for the non-lazy listener as we want to exercise the code to
521 // dispatch the event right after the Service Worker registration is
522 // completing.
523 return;
524 }
Istiaque Ahmeda14ec482018-08-25 01:02:18525 DispatchEvent(std::move(event_));
Istiaque Ahmed771aa8a22018-06-20 23:40:53526 }
527
528 bool SendAndWait() { return listener_.WaitUntilSatisfied(); }
529
530 private:
531 static constexpr const char* const kTestOnMessageEventName = "test.onMessage";
532
Istiaque Ahmeda14ec482018-08-25 01:02:18533 void DispatchEvent(std::unique_ptr<Event> event) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53534 EventRouter::Get(browser_context_)
535 ->DispatchEventToExtension(extension_id_, std::move(event));
536 }
537
538 content::BrowserContext* const browser_context_ = nullptr;
539 EventRouter* const event_router_ = nullptr;
540 const ExtensionId extension_id_;
Istiaque Ahmeda14ec482018-08-25 01:02:18541 std::unique_ptr<Event> event_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53542 ExtensionTestMessageListener listener_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53543
544 DISALLOW_COPY_AND_ASSIGN(EarlyWorkerMessageSender);
545};
546
547// Tests that extension event dispatch works correctly right after extension
548// installation registers its Service Worker.
549// Regression test for: https://crbug.com/850792.
Devlin Cronin242d19d22019-03-12 18:08:48550IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, EarlyEventDispatch) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53551 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
Istiaque Ahmeda14ec482018-08-25 01:02:18552
553 // Build "test.onMessage" event for dispatch.
554 auto event = std::make_unique<Event>(
555 events::FOR_TEST, extensions::api::test::OnMessage::kEventName,
Lei Zhang582ecd12019-02-13 20:28:54556 base::ListValue::From(base::JSONReader::ReadDeprecated(
Istiaque Ahmeda14ec482018-08-25 01:02:18557 R"([{"data": "hello", "lastMessage": true}])")),
558 profile());
559
560 EarlyWorkerMessageSender sender(profile(), kId, std::move(event));
Istiaque Ahmed771aa8a22018-06-20 23:40:53561 // pkplfbidichfdicaijlchgnapepdginl
562 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
563 "service_worker/worker_based_background/early_event_dispatch"));
564 CHECK(extension);
565 EXPECT_EQ(kId, extension->id());
566 EXPECT_TRUE(sender.SendAndWait());
567}
568
Istiaque Ahmeda14ec482018-08-25 01:02:18569// Tests that filtered events dispatches correctly right after a non-lazy
570// listener is registered for that event (and before the corresponding lazy
571// listener is registered).
Devlin Cronin242d19d22019-03-12 18:08:48572IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest,
Istiaque Ahmeda14ec482018-08-25 01:02:18573 EarlyFilteredEventDispatch) {
574 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
575
576 // Add minimal details required to dispatch webNavigation.onCommitted event:
577 extensions::api::web_navigation::OnCommitted::Details details;
578 details.transition_type =
579 extensions::api::web_navigation::TRANSITION_TYPE_TYPED;
580
581 // Build a dummy onCommited event to dispatch.
582 auto on_committed_event = std::make_unique<Event>(
583 events::WEB_NAVIGATION_ON_COMMITTED, "webNavigation.onCommitted",
584 api::web_navigation::OnCommitted::Create(details), profile());
585 // The filter will match the listener filter registered from the extension.
586 EventFilteringInfo info;
587 info.url = GURL("http://foo.com/a.html");
588 on_committed_event->filter_info = info;
589
590 EarlyWorkerMessageSender sender(profile(), kId,
591 std::move(on_committed_event));
592
593 // pkplfbidichfdicaijlchgnapepdginl
594 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
595 "service_worker/worker_based_background/early_filtered_event_dispatch"));
596 ASSERT_TRUE(extension);
597 EXPECT_EQ(kId, extension->id());
598 EXPECT_TRUE(sender.SendAndWait());
599}
600
lazyboybd325ae2015-11-18 21:35:26601class ServiceWorkerBackgroundSyncTest : public ServiceWorkerTest {
602 public:
603 ServiceWorkerBackgroundSyncTest() {}
604 ~ServiceWorkerBackgroundSyncTest() override {}
605
606 void SetUpCommandLine(base::CommandLine* command_line) override {
607 // ServiceWorkerRegistration.sync requires experimental flag.
608 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16609 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboybd325ae2015-11-18 21:35:26610 ServiceWorkerTest::SetUpCommandLine(command_line);
611 }
612
613 void SetUp() override {
Robbie McElrathdb12d8e2018-09-18 21:20:40614 content::background_sync_test_util::SetIgnoreNetworkChanges(true);
lazyboybd325ae2015-11-18 21:35:26615 ServiceWorkerTest::SetUp();
616 }
617
618 private:
619 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBackgroundSyncTest);
620};
621
lazyboy561b7de2015-11-19 19:27:30622class ServiceWorkerPushMessagingTest : public ServiceWorkerTest {
623 public:
624 ServiceWorkerPushMessagingTest()
Sylvain Defresne212b4b02018-10-11 16:32:05625 : scoped_testing_factory_installer_(
626 base::BindRepeating(&gcm::FakeGCMProfileService::Build)),
627 gcm_driver_(nullptr),
628 push_service_(nullptr) {}
629
lazyboy561b7de2015-11-19 19:27:30630 ~ServiceWorkerPushMessagingTest() override {}
631
632 void GrantNotificationPermissionForTest(const GURL& url) {
Peter Beverloodd4ef1e2018-06-21 15:41:04633 NotificationPermissionContext::UpdatePermission(profile(), url.GetOrigin(),
634 CONTENT_SETTING_ALLOW);
lazyboy561b7de2015-11-19 19:27:30635 }
636
637 PushMessagingAppIdentifier GetAppIdentifierForServiceWorkerRegistration(
avia2f4804a2015-12-24 23:11:13638 int64_t service_worker_registration_id,
lazyboy561b7de2015-11-19 19:27:30639 const GURL& origin) {
640 PushMessagingAppIdentifier app_identifier =
641 PushMessagingAppIdentifier::FindByServiceWorker(
642 profile(), origin, service_worker_registration_id);
643
644 EXPECT_FALSE(app_identifier.is_null());
645 return app_identifier;
646 }
647
648 // ExtensionApiTest overrides.
649 void SetUpCommandLine(base::CommandLine* command_line) override {
peter9de96272015-12-04 15:23:27650 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16651 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboy561b7de2015-11-19 19:27:30652 ServiceWorkerTest::SetUpCommandLine(command_line);
653 }
Tanja Gornak89128fd2018-09-18 08:49:34654
lazyboy561b7de2015-11-19 19:27:30655 void SetUpOnMainThread() override {
miguelg9b502862017-04-24 18:13:53656 NotificationDisplayServiceFactory::GetInstance()->SetTestingFactory(
Sylvain Defresne711ff6b2018-10-04 12:33:54657 profile(),
658 base::BindRepeating(&StubNotificationDisplayService::FactoryForTests));
miguelg9b502862017-04-24 18:13:53659
johnmea5045732016-09-08 17:23:29660 gcm::FakeGCMProfileService* gcm_service =
661 static_cast<gcm::FakeGCMProfileService*>(
Tanja Gornak89128fd2018-09-18 08:49:34662 gcm::GCMProfileServiceFactory::GetForProfile(profile()));
johnmea5045732016-09-08 17:23:29663 gcm_driver_ = static_cast<instance_id::FakeGCMDriverForInstanceID*>(
664 gcm_service->driver());
lazyboy561b7de2015-11-19 19:27:30665 push_service_ = PushMessagingServiceFactory::GetForProfile(profile());
666
667 ServiceWorkerTest::SetUpOnMainThread();
668 }
669
johnmea5045732016-09-08 17:23:29670 instance_id::FakeGCMDriverForInstanceID* gcm_driver() const {
671 return gcm_driver_;
672 }
lazyboy561b7de2015-11-19 19:27:30673 PushMessagingServiceImpl* push_service() const { return push_service_; }
674
675 private:
Sylvain Defresne212b4b02018-10-11 16:32:05676 gcm::GCMProfileServiceFactory::ScopedTestingFactoryInstaller
677 scoped_testing_factory_installer_;
678
johnmea5045732016-09-08 17:23:29679 instance_id::FakeGCMDriverForInstanceID* gcm_driver_;
lazyboy561b7de2015-11-19 19:27:30680 PushMessagingServiceImpl* push_service_;
681
682 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPushMessagingTest);
683};
684
Istiaque Ahmed805f6a83b2017-10-05 01:23:26685class ServiceWorkerLazyBackgroundTest : public ServiceWorkerTest {
686 public:
Istiaque Ahmed7105f2a2017-10-07 01:11:59687 ServiceWorkerLazyBackgroundTest()
688 : ServiceWorkerTest(
689 // Extensions APIs from SW are only enabled on trunk.
690 // It is important to set the channel early so that this change is
691 // visible in renderers running with service workers (and no
692 // extension).
693 version_info::Channel::UNKNOWN) {}
Istiaque Ahmed805f6a83b2017-10-05 01:23:26694 ~ServiceWorkerLazyBackgroundTest() override {}
695
696 void SetUpCommandLine(base::CommandLine* command_line) override {
697 ServiceWorkerTest::SetUpCommandLine(command_line);
698 // Disable background network activity as it can suddenly bring the Lazy
699 // Background Page alive.
700 command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
701 command_line->AppendSwitch(::switches::kNoProxyServer);
702 }
703
704 void SetUpInProcessBrowserTestFixture() override {
705 ServiceWorkerTest::SetUpInProcessBrowserTestFixture();
706 // Set shorter delays to prevent test timeouts.
707 ProcessManager::SetEventPageIdleTimeForTesting(1);
708 ProcessManager::SetEventPageSuspendingTimeForTesting(1);
709 }
710
711 private:
712 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerLazyBackgroundTest);
713};
714
Devlin Cronin242d19d22019-03-12 18:08:48715IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, RegisterSucceeds) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22716 StartTestFromBackgroundPage("register.js");
annekao38685502015-07-14 17:46:39717}
718
Devlin Cronin242d19d22019-03-12 18:08:48719IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, UpdateRefreshesServiceWorker) {
Francois Doraye6fb2d02017-10-18 21:29:13720 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboyc3e763a2015-12-09 23:09:58721 base::ScopedTempDir scoped_temp_dir;
722 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
723 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
724 .AppendASCII("update")
725 .AppendASCII("service_worker.pem");
vabr9142fe22016-09-08 13:19:22726 base::FilePath path_v1 =
727 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
728 .AppendASCII("update")
729 .AppendASCII("v1"),
730 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
731 pem_path, base::FilePath());
732 base::FilePath path_v2 =
733 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
734 .AppendASCII("update")
735 .AppendASCII("v2"),
736 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
737 pem_path, base::FilePath());
lazyboyc3e763a2015-12-09 23:09:58738 const char* kId = "hfaanndiiilofhfokeanhddpkfffchdi";
739
740 ExtensionTestMessageListener listener_v1("Pong from version 1", false);
741 listener_v1.set_failure_message("FAILURE_V1");
742 // Install version 1.0 of the extension.
743 ASSERT_TRUE(InstallExtension(path_v1, 1));
744 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
745 ->enabled_extensions()
746 .GetByID(kId));
747 EXPECT_TRUE(listener_v1.WaitUntilSatisfied());
748
749 ExtensionTestMessageListener listener_v2("Pong from version 2", false);
750 listener_v2.set_failure_message("FAILURE_V2");
751
752 // Update to version 2.0.
753 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
754 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
755 ->enabled_extensions()
756 .GetByID(kId));
757 EXPECT_TRUE(listener_v2.WaitUntilSatisfied());
758}
759
[email protected]2ef85d562017-09-15 18:41:52760// TODO(crbug.com/765736) Fix the test.
Devlin Cronin242d19d22019-03-12 18:08:48761IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, DISABLED_UpdateWithoutSkipWaiting) {
Francois Doraye6fb2d02017-10-18 21:29:13762 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboy22eddc712015-12-10 21:16:26763 base::ScopedTempDir scoped_temp_dir;
764 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
765 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
766 .AppendASCII("update_without_skip_waiting")
767 .AppendASCII("update_without_skip_waiting.pem");
vabr9142fe22016-09-08 13:19:22768 base::FilePath path_v1 =
769 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
770 .AppendASCII("update_without_skip_waiting")
771 .AppendASCII("v1"),
772 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
773 pem_path, base::FilePath());
774 base::FilePath path_v2 =
775 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
776 .AppendASCII("update_without_skip_waiting")
777 .AppendASCII("v2"),
778 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
779 pem_path, base::FilePath());
lazyboy22eddc712015-12-10 21:16:26780 const char* kId = "mhnnnflgagdakldgjpfcofkiocpdmogl";
781
782 // Install version 1.0 of the extension.
783 ASSERT_TRUE(InstallExtension(path_v1, 1));
784 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
785 ->enabled_extensions()
786 .GetByID(kId));
787 const Extension* extension = extensions::ExtensionRegistry::Get(profile())
788 ->enabled_extensions()
789 .GetByID(kId);
790
791 ExtensionTestMessageListener listener1("Pong from version 1", false);
792 listener1.set_failure_message("FAILURE");
793 content::WebContents* web_contents =
794 AddTab(browser(), extension->GetResourceURL("page.html"));
795 EXPECT_TRUE(listener1.WaitUntilSatisfied());
796
797 // Update to version 2.0.
798 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
799 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
800 ->enabled_extensions()
801 .GetByID(kId));
802 const Extension* extension_after_update =
803 extensions::ExtensionRegistry::Get(profile())
804 ->enabled_extensions()
805 .GetByID(kId);
806
807 // Service worker version 2 would be installed but it won't be controlling
808 // the extension page yet.
809 ExtensionTestMessageListener listener2("Pong from version 1", false);
810 listener2.set_failure_message("FAILURE");
811 web_contents =
812 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
813 EXPECT_TRUE(listener2.WaitUntilSatisfied());
814
815 // Navigate the tab away from the extension page so that no clients are
816 // using the service worker.
817 // Note that just closing the tab with WebContentsDestroyedWatcher doesn't
818 // seem to be enough because it returns too early.
819 WebContentsLoadStopObserver navigate_away_observer(web_contents);
820 web_contents->GetController().LoadURL(
821 GURL(url::kAboutBlankURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED,
822 std::string());
823 navigate_away_observer.WaitForLoadStop();
824
825 // Now expect service worker version 2 to control the extension page.
826 ExtensionTestMessageListener listener3("Pong from version 2", false);
827 listener3.set_failure_message("FAILURE");
828 web_contents =
829 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
830 EXPECT_TRUE(listener3.WaitUntilSatisfied());
831}
832
Devlin Cronin242d19d22019-03-12 18:08:48833IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, FetchArbitraryPaths) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22834 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
annekao1db36fd2015-07-29 17:09:16835
kalman6f984ae2015-09-18 17:21:58836 // Open some arbirary paths. Their contents should be what the service worker
837 // responds with, which in this case is the path of the fetch.
838 EXPECT_EQ(
839 "Caught a fetch for /index.html",
840 NavigateAndExtractInnerText(extension->GetResourceURL("index.html")));
841 EXPECT_EQ("Caught a fetch for /path/to/other.html",
842 NavigateAndExtractInnerText(
843 extension->GetResourceURL("path/to/other.html")));
844 EXPECT_EQ("Caught a fetch for /some/text/file.txt",
845 NavigateAndExtractInnerText(
846 extension->GetResourceURL("some/text/file.txt")));
847 EXPECT_EQ("Caught a fetch for /no/file/extension",
848 NavigateAndExtractInnerText(
849 extension->GetResourceURL("no/file/extension")));
850 EXPECT_EQ("Caught a fetch for /",
851 NavigateAndExtractInnerText(extension->GetResourceURL("")));
annekao1db36fd2015-07-29 17:09:16852}
853
Devlin Cronin242d19d22019-03-12 18:08:48854IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
Kenichi Ishibashi773b82972018-08-30 07:02:03855 FetchExtensionResourceFromServiceWorker) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22856 const Extension* extension = StartTestFromBackgroundPage("fetch_from_sw.js");
Kenichi Ishibashi773b82972018-08-30 07:02:03857 ASSERT_TRUE(extension);
858
859 // The service worker in this test tries to load 'hello.txt' via fetch()
860 // and sends back the content of the file, which should be 'hello'.
861 const char* kScript = R"(
862 let channel = new MessageChannel();
863 test.waitForMessage(channel.port1).then(message => {
864 window.domAutomationController.send(message);
865 });
866 test.registeredServiceWorker.postMessage(
867 {port: channel.port2}, [channel.port2]);
868 )";
869 EXPECT_EQ("hello", ExecuteScriptInBackgroundPage(extension->id(), kScript));
870}
871
Kenichi Ishibashi09ee5e72018-11-27 07:12:38872// Tests that fetch() from service worker and network fallback
873// go through webRequest.onBeforeRequest API.
Devlin Cronin242d19d22019-03-12 18:08:48874IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, OnBeforeRequest) {
Kenichi Ishibashi09ee5e72018-11-27 07:12:38875 const Extension* extension = LoadExtensionWithFlags(
876 test_data_dir_.AppendASCII("service_worker/webrequest"), kFlagNone);
877 ASSERT_TRUE(extension);
878 ASSERT_TRUE(StartEmbeddedTestServer());
879
880 // Start a service worker and make it control the page.
881 GURL page_url = embedded_test_server()->GetURL(
882 "/extensions/api_test/service_worker/"
883 "webrequest/webpage.html");
884 content::WebContents* web_contents =
885 browser()->tab_strip_model()->GetActiveWebContents();
886 ui_test_utils::NavigateToURL(browser(), page_url);
887 content::WaitForLoadStop(web_contents);
888
889 std::string result;
890 ASSERT_TRUE(content::ExecuteScriptAndExtractString(web_contents,
891 "register();", &result));
892 EXPECT_EQ("ready", result);
893
894 // Initiate a fetch that the service worker doesn't intercept
895 // (network fallback).
896 result.clear();
897 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
898 web_contents, "doFetch('hello.txt?fallthrough');", &result));
899 EXPECT_EQ("hello", result);
900 EXPECT_EQ(
901 "/extensions/api_test/service_worker/webrequest/hello.txt?fallthrough",
902 ExecuteScriptInBackgroundPage(extension->id(), "getLastHookedPath()"));
903
904 // Initiate a fetch that results in calling fetch() in the service worker.
905 result.clear();
906 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
907 web_contents, "doFetch('hello.txt?respondWithFetch');", &result));
908 EXPECT_EQ("hello", result);
909 EXPECT_EQ(
910 "/extensions/api_test/service_worker/webrequest/"
911 "hello.txt?respondWithFetch",
912 ExecuteScriptInBackgroundPage(extension->id(), "getLastHookedPath()"));
913}
914
Devlin Cronin242d19d22019-03-12 18:08:48915IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, SWServedBackgroundPageReceivesEvent) {
lazyboy52c3bcf2016-01-08 00:11:29916 const Extension* extension =
Istiaque Ahmed93ff7f42018-08-31 01:42:22917 StartTestFromBackgroundPage("replace_background.js");
lazyboy52c3bcf2016-01-08 00:11:29918 ExtensionHost* background_page =
919 process_manager()->GetBackgroundHostForExtension(extension->id());
920 ASSERT_TRUE(background_page);
921
922 // Close the background page and start it again so that the service worker
923 // will start controlling pages.
924 background_page->Close();
925 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
926 background_page = nullptr;
Peter Kasting341e1fb2018-02-24 00:03:01927 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
lazyboy52c3bcf2016-01-08 00:11:29928 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
929
930 // Since the SW is now controlling the extension, the SW serves the background
931 // script. page.html sends a message to the background script and we verify
932 // that the SW served background script correctly receives the message/event.
933 ExtensionTestMessageListener listener("onMessage/SW BG.", false);
934 listener.set_failure_message("onMessage/original BG.");
935 content::WebContents* web_contents =
936 AddTab(browser(), extension->GetResourceURL("page.html"));
937 ASSERT_TRUE(web_contents);
938 EXPECT_TRUE(listener.WaitUntilSatisfied());
939}
940
Devlin Cronin242d19d22019-03-12 18:08:48941IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, SWServedBackgroundPage) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22942 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
annekao49241182015-08-18 17:14:01943
kalman6f984ae2015-09-18 17:21:58944 std::string kExpectedInnerText = "background.html contents for testing.";
annekao49241182015-08-18 17:14:01945
kalman6f984ae2015-09-18 17:21:58946 // Sanity check that the background page has the expected content.
947 ExtensionHost* background_page =
948 process_manager()->GetBackgroundHostForExtension(extension->id());
949 ASSERT_TRUE(background_page);
950 EXPECT_EQ(kExpectedInnerText,
951 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01952
kalman6f984ae2015-09-18 17:21:58953 // Close the background page.
954 background_page->Close();
955 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
956 background_page = nullptr;
957
958 // Start it again.
Peter Kasting341e1fb2018-02-24 00:03:01959 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
kalman6f984ae2015-09-18 17:21:58960 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
961
Matt Falkenhagena612fc02018-05-30 00:35:39962 // The service worker should get a fetch event for the background page.
kalman6f984ae2015-09-18 17:21:58963 background_page =
964 process_manager()->GetBackgroundHostForExtension(extension->id());
965 ASSERT_TRUE(background_page);
966 content::WaitForLoadStop(background_page->host_contents());
967
kalman6f984ae2015-09-18 17:21:58968 EXPECT_EQ("Caught a fetch for /background.html",
969 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01970}
971
Devlin Cronin242d19d22019-03-12 18:08:48972IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58973 ServiceWorkerPostsMessageToBackgroundClient) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22974 const Extension* extension =
975 StartTestFromBackgroundPage("post_message_to_background_client.js");
annekao533482222015-08-21 23:23:53976
kalman6f984ae2015-09-18 17:21:58977 // The service worker in this test simply posts a message to the background
978 // client it receives from getBackgroundClient().
979 const char* kScript =
980 "var messagePromise = null;\n"
981 "if (test.lastMessageFromServiceWorker) {\n"
982 " messagePromise = Promise.resolve(test.lastMessageFromServiceWorker);\n"
983 "} else {\n"
984 " messagePromise = test.waitForMessage(navigator.serviceWorker);\n"
985 "}\n"
986 "messagePromise.then(function(message) {\n"
987 " window.domAutomationController.send(String(message == 'success'));\n"
988 "})\n";
989 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53990}
991
Devlin Cronin242d19d22019-03-12 18:08:48992IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58993 BackgroundPagePostsMessageToServiceWorker) {
994 const Extension* extension =
Istiaque Ahmed93ff7f42018-08-31 01:42:22995 StartTestFromBackgroundPage("post_message_to_sw.js");
annekao533482222015-08-21 23:23:53996
kalman6f984ae2015-09-18 17:21:58997 // The service worker in this test waits for a message, then echoes it back
998 // by posting a message to the background page via getBackgroundClient().
999 const char* kScript =
1000 "var mc = new MessageChannel();\n"
1001 "test.waitForMessage(mc.port1).then(function(message) {\n"
1002 " window.domAutomationController.send(String(message == 'hello'));\n"
1003 "});\n"
1004 "test.registeredServiceWorker.postMessage(\n"
1005 " {message: 'hello', port: mc.port2}, [mc.port2])\n";
1006 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:531007}
1008
Devlin Cronin242d19d22019-03-12 18:08:481009IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
rdevlin.croninf5863da2015-09-10 19:21:451010 ServiceWorkerSuspensionOnExtensionUnload) {
kalman6f984ae2015-09-18 17:21:581011 // For this test, only hold onto the extension's ID and URL + a function to
1012 // get a resource URL, because we're going to be disabling and uninstalling
1013 // it, which will invalidate the pointer.
1014 std::string extension_id;
1015 GURL extension_url;
1016 {
Istiaque Ahmed93ff7f42018-08-31 01:42:221017 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
kalman6f984ae2015-09-18 17:21:581018 extension_id = extension->id();
1019 extension_url = extension->url();
1020 }
1021 auto get_resource_url = [&extension_url](const std::string& path) {
1022 return Extension::GetResourceURL(extension_url, path);
1023 };
rdevlin.croninf5863da2015-09-10 19:21:451024
kalman6f984ae2015-09-18 17:21:581025 // Fetch should route to the service worker.
1026 EXPECT_EQ("Caught a fetch for /index.html",
1027 NavigateAndExtractInnerText(get_resource_url("index.html")));
rdevlin.croninf5863da2015-09-10 19:21:451028
kalman6f984ae2015-09-18 17:21:581029 // Disable the extension. Opening the page should fail.
1030 extension_service()->DisableExtension(extension_id,
Minh X. Nguyen45479012017-08-18 21:35:361031 disable_reason::DISABLE_USER_ACTION);
rdevlin.croninf5863da2015-09-10 19:21:451032 base::RunLoop().RunUntilIdle();
rdevlin.croninf5863da2015-09-10 19:21:451033
kalman6f984ae2015-09-18 17:21:581034 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1035 NavigateAndGetPageType(get_resource_url("index.html")));
1036 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1037 NavigateAndGetPageType(get_resource_url("other.html")));
1038
1039 // Re-enable the extension. Opening pages should immediately start to succeed
1040 // again.
rdevlin.croninf5863da2015-09-10 19:21:451041 extension_service()->EnableExtension(extension_id);
1042 base::RunLoop().RunUntilIdle();
1043
kalman6f984ae2015-09-18 17:21:581044 EXPECT_EQ("Caught a fetch for /index.html",
1045 NavigateAndExtractInnerText(get_resource_url("index.html")));
1046 EXPECT_EQ("Caught a fetch for /other.html",
1047 NavigateAndExtractInnerText(get_resource_url("other.html")));
1048 EXPECT_EQ("Caught a fetch for /another.html",
1049 NavigateAndExtractInnerText(get_resource_url("another.html")));
rdevlin.croninf5863da2015-09-10 19:21:451050
kalman6f984ae2015-09-18 17:21:581051 // Uninstall the extension. Opening pages should fail again.
1052 base::string16 error;
1053 extension_service()->UninstallExtension(
Devlin Cronin218df7f2017-11-21 21:41:311054 extension_id, UninstallReason::UNINSTALL_REASON_FOR_TESTING, &error);
kalman6f984ae2015-09-18 17:21:581055 base::RunLoop().RunUntilIdle();
1056
1057 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1058 NavigateAndGetPageType(get_resource_url("index.html")));
1059 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1060 NavigateAndGetPageType(get_resource_url("other.html")));
1061 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1062 NavigateAndGetPageType(get_resource_url("anotherother.html")));
1063 EXPECT_EQ(content::PAGE_TYPE_ERROR,
1064 NavigateAndGetPageType(get_resource_url("final.html")));
1065}
1066
Devlin Cronin242d19d22019-03-12 18:08:481067IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, BackgroundPageIsWokenIfAsleep) {
Istiaque Ahmed93ff7f42018-08-31 01:42:221068 const Extension* extension = StartTestFromBackgroundPage("wake_on_fetch.js");
kalman6f984ae2015-09-18 17:21:581069
1070 // Navigate to special URLs that this test's service worker recognises, each
1071 // making a check then populating the response with either "true" or "false".
1072 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
1073 "background-client-is-awake")));
1074 EXPECT_EQ("true", NavigateAndExtractInnerText(
1075 extension->GetResourceURL("ping-background-client")));
1076 // Ping more than once for good measure.
1077 EXPECT_EQ("true", NavigateAndExtractInnerText(
1078 extension->GetResourceURL("ping-background-client")));
1079
1080 // Shut down the event page. The SW should detect that it's closed, but still
1081 // be able to ping it.
1082 ExtensionHost* background_page =
1083 process_manager()->GetBackgroundHostForExtension(extension->id());
1084 ASSERT_TRUE(background_page);
1085 background_page->Close();
1086 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
1087
1088 EXPECT_EQ("false", NavigateAndExtractInnerText(extension->GetResourceURL(
1089 "background-client-is-awake")));
1090 EXPECT_EQ("true", NavigateAndExtractInnerText(
1091 extension->GetResourceURL("ping-background-client")));
1092 EXPECT_EQ("true", NavigateAndExtractInnerText(
1093 extension->GetResourceURL("ping-background-client")));
1094 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
1095 "background-client-is-awake")));
1096}
1097
Devlin Cronin242d19d22019-03-12 18:08:481098IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:581099 GetBackgroundClientFailsWithNoBackgroundPage) {
1100 // This extension doesn't have a background page, only a tab at page.html.
1101 // The service worker it registers tries to call getBackgroundClient() and
1102 // should fail.
1103 // Note that this also tests that service workers can be registered from tabs.
1104 EXPECT_TRUE(RunExtensionSubtest("service_worker/no_background", "page.html"));
rdevlin.croninf5863da2015-09-10 19:21:451105}
1106
Devlin Cronin242d19d22019-03-12 18:08:481107IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, NotificationAPI) {
lazyboy6ddb7d62015-11-10 23:15:271108 EXPECT_TRUE(RunExtensionSubtest("service_worker/notifications/has_permission",
1109 "page.html"));
1110}
1111
Devlin Cronin242d19d22019-03-12 18:08:481112IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WebAccessibleResourcesFetch) {
lazyboyaea32c22016-01-04 21:37:071113 EXPECT_TRUE(RunExtensionSubtest(
1114 "service_worker/web_accessible_resources/fetch/", "page.html"));
1115}
1116
Devlin Cronin242d19d22019-03-12 18:08:481117IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, TabsCreate) {
lazyboyee4adef2016-05-24 00:55:161118 // Extensions APIs from SW are only enabled on trunk.
1119 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1120 const Extension* extension = LoadExtensionWithFlags(
1121 test_data_dir_.AppendASCII("service_worker/tabs_create"), kFlagNone);
1122 ASSERT_TRUE(extension);
1123 ui_test_utils::NavigateToURL(browser(),
1124 extension->GetResourceURL("page.html"));
1125 content::WebContents* web_contents =
1126 browser()->tab_strip_model()->GetActiveWebContents();
1127
1128 int starting_tab_count = browser()->tab_strip_model()->count();
1129 std::string result;
1130 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1131 web_contents, "window.runServiceWorker()", &result));
1132 ASSERT_EQ("chrome.tabs.create callback", result);
1133 EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count());
1134
1135 // Check extension shutdown path.
1136 UnloadExtension(extension->id());
1137 EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count());
1138}
1139
David Bertoni9026eff2019-05-01 18:04:311140// Tests that updating a packed extension with modified scripts works
1141// properly -- we expect that the new script will execute, rather than the
1142// previous one.
1143IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, UpdatePackedExtension) {
1144 // Extensions APIs from SW are only enabled on trunk.
1145 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1146 constexpr char kManifest1[] =
1147 R"({
1148 "name": "Test Extension",
1149 "manifest_version": 2,
1150 "version": "0.1",
1151 "background": {"service_worker": "script.js"}
1152 })";
1153 // This script installs an event listener for updates to the extension with
1154 // a callback that forces itself to reload.
1155 constexpr char kScript[] =
1156 R"(
1157 chrome.runtime.onUpdateAvailable.addListener(function(details) {
1158 chrome.runtime.reload();
1159 });
1160 chrome.test.sendMessage('ready1');
1161 )";
1162
1163 std::string id;
1164 TestExtensionDir test_dir;
1165
1166 // Write the manifest and script files and load the extension.
1167 test_dir.WriteManifest(kManifest1);
1168 test_dir.WriteFile(FILE_PATH_LITERAL("script.js"), kScript);
1169
1170 {
1171 ExtensionTestMessageListener ready_listener("ready1", false);
1172 base::FilePath path = test_dir.Pack();
1173 const Extension* extension = LoadExtension(path);
1174 ASSERT_TRUE(extension);
1175
1176 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1177 id = extension->id();
1178 }
1179
1180 constexpr char kManifest2[] =
1181 R"({
1182 "name": "Test Extension",
1183 "manifest_version": 2,
1184 "version": "0.2",
1185 "background": {"service_worker": "script.js"}
1186 })";
1187 // Rewrite the manifest and script files with a version change in the manifest
1188 // file. After reloading the extension, the old version of the extension
1189 // should detect the update, force the reload, and the new script should
1190 // execute.
1191 test_dir.WriteManifest(kManifest2);
1192 test_dir.WriteFile(FILE_PATH_LITERAL("script.js"),
1193 "chrome.test.sendMessage('ready2');");
1194 {
1195 ExtensionTestMessageListener ready_listener("ready2", false);
1196 base::FilePath path = test_dir.Pack();
1197 ExtensionService* const extension_service =
1198 ExtensionSystem::Get(profile())->extension_service();
1199 EXPECT_TRUE(extension_service->UpdateExtension(
1200 CRXFileInfo(id, GetTestVerifierFormat(), path), true, nullptr));
1201 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1202 EXPECT_EQ("0.2", ExtensionRegistry::Get(profile())
1203 ->enabled_extensions()
1204 .GetByID(id)
1205 ->version()
1206 .GetString());
1207 }
1208}
1209
David Bertoni1d646a152019-04-25 02:09:221210// Tests that updating an unpacked extension with modified scripts works
1211// properly -- we expect that the new script will execute, rather than the
1212// previous one.
1213IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, UpdateUnpackedExtension) {
1214 // Extensions APIs from SW are only enabled on trunk.
1215 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1216 constexpr char kManifest1[] =
1217 R"({
1218 "name": "Test Extension",
1219 "manifest_version": 2,
1220 "version": "0.1",
1221 "background": {"service_worker": "script.js"}
1222 })";
1223 constexpr char kManifest2[] =
1224 R"({
1225 "name": "Test Extension",
1226 "manifest_version": 2,
1227 "version": "0.2",
1228 "background": {"service_worker": "script.js"}
1229 })";
1230
1231 std::string id;
1232
1233 ExtensionService* const extension_service =
1234 ExtensionSystem::Get(profile())->extension_service();
1235 scoped_refptr<UnpackedInstaller> installer =
1236 UnpackedInstaller::Create(extension_service);
1237
1238 // Set a completion callback so we can get the ID of the extension.
1239 installer->set_completion_callback(base::BindLambdaForTesting(
1240 [&id](const Extension* extension, const base::FilePath& path,
1241 const std::string& error) {
1242 ASSERT_TRUE(extension);
1243 ASSERT_TRUE(error.empty());
1244 id = extension->id();
1245 }));
1246
1247 TestExtensionDir test_dir;
1248
1249 // Write the manifest and script files and load the extension.
1250 test_dir.WriteManifest(kManifest1);
1251 test_dir.WriteFile(FILE_PATH_LITERAL("script.js"),
1252 "chrome.test.sendMessage('ready1');");
1253 {
1254 ExtensionTestMessageListener ready_listener("ready1", false);
1255
1256 installer->Load(test_dir.UnpackedPath());
1257 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1258 ASSERT_FALSE(id.empty());
1259 }
1260
1261 // Rewrite the script file without a version change in the manifest and reload
1262 // the extension. The new script should execute.
1263 test_dir.WriteFile(FILE_PATH_LITERAL("script.js"),
1264 "chrome.test.sendMessage('ready2');");
1265 {
1266 ExtensionTestMessageListener ready_listener("ready2", false);
1267
1268 extension_service->ReloadExtension(id);
1269 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1270 }
1271
1272 // Rewrite the manifest and script files with a version change in the manifest
1273 // file. After reloading the extension, the new script should execute.
1274 test_dir.WriteManifest(kManifest2);
1275 test_dir.WriteFile(FILE_PATH_LITERAL("script.js"),
1276 "chrome.test.sendMessage('ready3');");
1277 {
1278 ExtensionTestMessageListener ready_listener("ready3", false);
1279
1280 extension_service->ReloadExtension(id);
1281 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1282 }
1283}
1284
Devlin Cronin242d19d22019-03-12 18:08:481285IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, Events) {
lazyboye7847242017-06-07 23:29:181286 // Extensions APIs from SW are only enabled on trunk.
1287 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1288 const Extension* extension = LoadExtensionWithFlags(
1289 test_data_dir_.AppendASCII("service_worker/events"), kFlagNone);
1290 ASSERT_TRUE(extension);
1291 ui_test_utils::NavigateToURL(browser(),
1292 extension->GetResourceURL("page.html"));
1293 content::WebContents* web_contents =
1294 browser()->tab_strip_model()->GetActiveWebContents();
1295 std::string result;
1296 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1297 web_contents, "window.runEventTest()", &result));
1298 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
1299}
1300
Devlin Cronin242d19d22019-03-12 18:08:481301IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, EventsToStoppedWorker) {
lazyboy63b994a2017-06-30 21:20:231302 // Extensions APIs from SW are only enabled on trunk.
1303 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1304 const Extension* extension = LoadExtensionWithFlags(
1305 test_data_dir_.AppendASCII("service_worker/events_to_stopped_worker"),
1306 kFlagNone);
1307 ASSERT_TRUE(extension);
1308 ui_test_utils::NavigateToURL(browser(),
1309 extension->GetResourceURL("page.html"));
1310 content::WebContents* web_contents =
1311 browser()->tab_strip_model()->GetActiveWebContents();
1312 {
1313 std::string result;
1314 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1315 web_contents, "window.runServiceWorker()", &result));
1316 ASSERT_EQ("ready", result);
1317
1318 base::RunLoop run_loop;
1319 content::StoragePartition* storage_partition =
1320 content::BrowserContext::GetDefaultStoragePartition(
1321 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001322 content::StopServiceWorkerForScope(
lazyboy63b994a2017-06-30 21:20:231323 storage_partition->GetServiceWorkerContext(),
1324 // The service worker is registered at the top level scope.
1325 extension->url(), run_loop.QuitClosure());
1326 run_loop.Run();
1327 }
1328
1329 std::string result;
1330 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1331 web_contents, "window.createTabThenUpdate()", &result));
1332 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
1333}
1334
Istiaque Ahmed805f6a83b2017-10-05 01:23:261335// Tests that events to service worker arrives correctly event if the owner
1336// extension of the worker is not running.
Devlin Cronin242d19d22019-03-12 18:08:481337IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmedb8e24bdb2018-09-13 15:17:251338 EventsToStoppedExtension) {
Istiaque Ahmed805f6a83b2017-10-05 01:23:261339 LazyBackgroundObserver lazy_observer;
1340 ResultCatcher catcher;
1341 const Extension* extension = LoadExtensionWithFlags(
1342 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
1343 kFlagNone);
1344 ASSERT_TRUE(extension);
1345 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1346
1347 ProcessManager* pm = ProcessManager::Get(browser()->profile());
1348 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:301349 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed805f6a83b2017-10-05 01:23:261350
1351 // |extension|'s background page opens a tab to its resource.
1352 content::WebContents* extension_web_contents =
1353 browser()->tab_strip_model()->GetActiveWebContents();
1354 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1355 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1356 extension_web_contents->GetURL().spec());
1357 {
1358 // Let the service worker start and register a listener to
1359 // chrome.tabs.onCreated event.
1360 ExtensionTestMessageListener add_listener_done("listener-added", false);
1361 content::ExecuteScriptAsync(extension_web_contents,
1362 "window.runServiceWorkerAsync()");
1363 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1364
1365 base::RunLoop run_loop;
1366 content::StoragePartition* storage_partition =
1367 content::BrowserContext::GetDefaultStoragePartition(
1368 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001369 content::StopServiceWorkerForScope(
Istiaque Ahmed805f6a83b2017-10-05 01:23:261370 storage_partition->GetServiceWorkerContext(),
1371 // The service worker is registered at the top level scope.
1372 extension->url(), run_loop.QuitClosure());
1373 run_loop.Run();
1374 }
1375
1376 // Close the tab to |extension|'s resource. This will also close the
1377 // extension's event page.
1378 browser()->tab_strip_model()->CloseWebContentsAt(
1379 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1380 lazy_observer.Wait();
1381
1382 // At this point both the extension worker and extension event page is not
1383 // running. Since the worker registered a listener for tabs.onCreated, it
1384 // will be started to dispatch the event once we create a tab.
1385 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1386 newtab_listener.set_failure_message("WRONG_NEWTAB");
1387 content::WebContents* new_web_contents =
Istiaque Ahmed7105f2a2017-10-07 01:11:591388 AddTab(browser(), GURL(url::kAboutBlankURL));
1389 EXPECT_TRUE(new_web_contents);
1390 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1391}
1392
1393// Tests that events to service worker correctly after browser restart.
1394// This test is similar to EventsToStoppedExtension, except that the event
1395// delivery is verified after a browser restart.
Devlin Cronin242d19d22019-03-12 18:08:481396IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmed7105f2a2017-10-07 01:11:591397 PRE_EventsAfterRestart) {
1398 LazyBackgroundObserver lazy_observer;
1399 ResultCatcher catcher;
1400 const Extension* extension = LoadExtensionWithFlags(
1401 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
1402 kFlagNone);
1403 ASSERT_TRUE(extension);
1404 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1405
1406 ProcessManager* pm = ProcessManager::Get(browser()->profile());
1407 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:301408 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed7105f2a2017-10-07 01:11:591409
1410 // |extension|'s background page opens a tab to its resource.
1411 content::WebContents* extension_web_contents =
1412 browser()->tab_strip_model()->GetActiveWebContents();
1413 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1414 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1415 extension_web_contents->GetURL().spec());
1416 {
1417 // Let the service worker start and register a listener to
1418 // chrome.tabs.onCreated event.
1419 ExtensionTestMessageListener add_listener_done("listener-added", false);
1420 content::ExecuteScriptAsync(extension_web_contents,
1421 "window.runServiceWorkerAsync()");
1422 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1423
1424 base::RunLoop run_loop;
1425 content::StoragePartition* storage_partition =
1426 content::BrowserContext::GetDefaultStoragePartition(
1427 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001428 content::StopServiceWorkerForScope(
Istiaque Ahmed7105f2a2017-10-07 01:11:591429 storage_partition->GetServiceWorkerContext(),
1430 // The service worker is registered at the top level scope.
1431 extension->url(), run_loop.QuitClosure());
1432 run_loop.Run();
1433 }
1434
1435 // Close the tab to |extension|'s resource. This will also close the
1436 // extension's event page.
1437 browser()->tab_strip_model()->CloseWebContentsAt(
1438 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1439 lazy_observer.Wait();
1440}
1441
Devlin Cronin242d19d22019-03-12 18:08:481442IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest, EventsAfterRestart) {
Istiaque Ahmed7105f2a2017-10-07 01:11:591443 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1444 content::WebContents* new_web_contents =
1445 AddTab(browser(), GURL(url::kAboutBlankURL));
Istiaque Ahmed805f6a83b2017-10-05 01:23:261446 EXPECT_TRUE(new_web_contents);
1447 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1448}
1449
lazyboy4c82177a2016-10-18 00:04:091450// Tests that worker ref count increments while extension API function is
1451// active.
Devlin Cronin242d19d22019-03-12 18:08:481452IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WorkerRefCount) {
lazyboy4c82177a2016-10-18 00:04:091453 // Extensions APIs from SW are only enabled on trunk.
1454 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1455 const Extension* extension = LoadExtensionWithFlags(
1456 test_data_dir_.AppendASCII("service_worker/api_worker_ref_count"),
1457 kFlagNone);
1458 ASSERT_TRUE(extension);
1459 ui_test_utils::NavigateToURL(browser(),
1460 extension->GetResourceURL("page.html"));
1461 content::WebContents* web_contents =
1462 browser()->tab_strip_model()->GetActiveWebContents();
1463
1464 ExtensionTestMessageListener worker_start_listener("WORKER STARTED", false);
1465 worker_start_listener.set_failure_message("FAILURE");
1466 ASSERT_TRUE(
1467 content::ExecuteScript(web_contents, "window.runServiceWorker()"));
1468 ASSERT_TRUE(worker_start_listener.WaitUntilSatisfied());
1469
1470 // Service worker should have no pending requests because it hasn't peformed
1471 // any extension API request yet.
1472 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1473
1474 ExtensionTestMessageListener worker_listener("CHECK_REF_COUNT", true);
1475 worker_listener.set_failure_message("FAILURE");
1476 ASSERT_TRUE(content::ExecuteScript(web_contents, "window.testSendMessage()"));
1477 ASSERT_TRUE(worker_listener.WaitUntilSatisfied());
1478
1479 // Service worker should have exactly one pending request because
1480 // chrome.test.sendMessage() API call is in-flight.
1481 EXPECT_EQ(1u, GetWorkerRefCount(extension->url()));
1482
1483 // Peform another extension API request while one is ongoing.
1484 {
1485 ExtensionTestMessageListener listener("CHECK_REF_COUNT", true);
1486 listener.set_failure_message("FAILURE");
1487 ASSERT_TRUE(
1488 content::ExecuteScript(web_contents, "window.testSendMessage()"));
1489 ASSERT_TRUE(listener.WaitUntilSatisfied());
1490
1491 // Service worker currently has two extension API requests in-flight.
1492 EXPECT_EQ(2u, GetWorkerRefCount(extension->url()));
1493 // Finish executing the nested chrome.test.sendMessage() first.
1494 listener.Reply("Hello world");
1495 }
1496
Istiaque Ahmedb57c9752017-08-20 19:08:571497 ExtensionTestMessageListener worker_completion_listener("SUCCESS_FROM_WORKER",
1498 false);
lazyboy4c82177a2016-10-18 00:04:091499 // Finish executing chrome.test.sendMessage().
1500 worker_listener.Reply("Hello world");
Istiaque Ahmedb57c9752017-08-20 19:08:571501 EXPECT_TRUE(worker_completion_listener.WaitUntilSatisfied());
1502
1503 // The following block makes sure we have received all the IPCs related to
1504 // ref-count from the worker.
1505 {
1506 // The following roundtrip:
1507 // browser->extension->worker->extension->browser
1508 // will ensure that the worker sent the relevant ref count IPCs.
1509 std::string result;
1510 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1511 web_contents, "window.roundtripToWorker();", &result));
1512 EXPECT_EQ("roundtrip-succeeded", result);
1513
1514 // Ensure IO thread IPCs run.
Gabriel Charette01507a22017-09-27 21:30:081515 content::RunAllTasksUntilIdle();
Istiaque Ahmedb57c9752017-08-20 19:08:571516 }
lazyboy4c82177a2016-10-18 00:04:091517
1518 // The ref count should drop to 0.
1519 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1520}
1521
lazyboyaea32c22016-01-04 21:37:071522// This test loads a web page that has an iframe pointing to a
1523// chrome-extension:// URL. The URL is listed in the extension's
1524// web_accessible_resources. Initially the iframe is served from the extension's
1525// resource file. After verifying that, we register a Service Worker that
1526// controls the extension. Further requests to the same resource as before
1527// should now be served by the Service Worker.
1528// This test also verifies that if the requested resource exists in the manifest
1529// but is not present in the extension directory, the Service Worker can still
1530// serve the resource file.
Devlin Cronin242d19d22019-03-12 18:08:481531IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WebAccessibleResourcesIframeSrc) {
lazyboyaea32c22016-01-04 21:37:071532 const Extension* extension = LoadExtensionWithFlags(
1533 test_data_dir_.AppendASCII(
1534 "service_worker/web_accessible_resources/iframe_src"),
1535 kFlagNone);
1536 ASSERT_TRUE(extension);
1537 ASSERT_TRUE(StartEmbeddedTestServer());
falkenad185092016-06-16 06:10:021538
1539 // Service workers can only control secure contexts
1540 // (https://w3c.github.io/webappsec-secure-contexts/). For documents, this
1541 // typically means the document must have a secure origin AND all its ancestor
1542 // frames must have documents with secure origins. However, extension pages
1543 // are considered secure, even if they have an ancestor document that is an
1544 // insecure context (see GetSchemesBypassingSecureContextCheckWhitelist). So
1545 // extension service workers must be able to control an extension page
1546 // embedded in an insecure context. To test this, set up an insecure
1547 // (non-localhost, non-https) URL for the web page. This page will create
1548 // iframes that load extension pages that must be controllable by service
1549 // worker.
falkenad185092016-06-16 06:10:021550 GURL page_url =
1551 embedded_test_server()->GetURL("a.com",
1552 "/extensions/api_test/service_worker/"
1553 "web_accessible_resources/webpage.html");
1554 EXPECT_FALSE(content::IsOriginSecure(page_url));
lazyboyaea32c22016-01-04 21:37:071555
1556 content::WebContents* web_contents = AddTab(browser(), page_url);
1557 std::string result;
1558 // webpage.html will create an iframe pointing to a resource from |extension|.
1559 // Expect the resource to be served by the extension.
1560 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1561 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1562 extension->id().c_str()),
1563 &result));
1564 EXPECT_EQ("FROM_EXTENSION_RESOURCE", result);
1565
1566 ExtensionTestMessageListener service_worker_ready_listener("SW_READY", false);
1567 EXPECT_TRUE(ExecuteScriptInBackgroundPageNoWait(
1568 extension->id(), "window.registerServiceWorker()"));
1569 EXPECT_TRUE(service_worker_ready_listener.WaitUntilSatisfied());
1570
1571 result.clear();
1572 // webpage.html will create another iframe pointing to a resource from
1573 // |extension| as before. But this time, the resource should be be served
1574 // from the Service Worker.
1575 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1576 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1577 extension->id().c_str()),
1578 &result));
1579 EXPECT_EQ("FROM_SW_RESOURCE", result);
1580
1581 result.clear();
1582 // webpage.html will create yet another iframe pointing to a resource that
1583 // exists in the extension manifest's web_accessible_resources, but is not
1584 // present in the extension directory. Expect the resources of the iframe to
1585 // be served by the Service Worker.
1586 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1587 web_contents,
1588 base::StringPrintf("window.testIframe('%s', 'iframe_non_existent.html')",
1589 extension->id().c_str()),
1590 &result));
1591 EXPECT_EQ("FROM_SW_RESOURCE", result);
1592}
1593
Devlin Cronin242d19d22019-03-12 18:08:481594IN_PROC_BROWSER_TEST_F(ServiceWorkerBackgroundSyncTest, Sync) {
lazyboybd325ae2015-11-18 21:35:261595 const Extension* extension = LoadExtensionWithFlags(
1596 test_data_dir_.AppendASCII("service_worker/sync"), kFlagNone);
1597 ASSERT_TRUE(extension);
1598 ui_test_utils::NavigateToURL(browser(),
1599 extension->GetResourceURL("page.html"));
1600 content::WebContents* web_contents =
1601 browser()->tab_strip_model()->GetActiveWebContents();
1602
1603 // Prevent firing by going offline.
1604 content::background_sync_test_util::SetOnline(web_contents, false);
1605
1606 ExtensionTestMessageListener sync_listener("SYNC: send-chats", false);
1607 sync_listener.set_failure_message("FAIL");
1608
1609 std::string result;
1610 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1611 web_contents, "window.runServiceWorker()", &result));
1612 ASSERT_EQ("SERVICE_WORKER_READY", result);
1613
1614 EXPECT_FALSE(sync_listener.was_satisfied());
1615 // Resume firing by going online.
1616 content::background_sync_test_util::SetOnline(web_contents, true);
1617 EXPECT_TRUE(sync_listener.WaitUntilSatisfied());
1618}
1619
Devlin Cronin242d19d22019-03-12 18:08:481620IN_PROC_BROWSER_TEST_F(ServiceWorkerTest,
horo1eeddde2015-11-19 05:59:251621 FetchFromContentScriptShouldNotGoToServiceWorkerOfPage) {
1622 ASSERT_TRUE(StartEmbeddedTestServer());
1623 GURL page_url = embedded_test_server()->GetURL(
1624 "/extensions/api_test/service_worker/content_script_fetch/"
1625 "controlled_page/index.html");
1626 content::WebContents* tab =
1627 browser()->tab_strip_model()->GetActiveWebContents();
1628 ui_test_utils::NavigateToURL(browser(), page_url);
1629 content::WaitForLoadStop(tab);
1630
1631 std::string value;
1632 ASSERT_TRUE(
1633 content::ExecuteScriptAndExtractString(tab, "register();", &value));
1634 EXPECT_EQ("SW controlled", value);
1635
1636 ASSERT_TRUE(RunExtensionTest("service_worker/content_script_fetch"))
1637 << message_;
1638}
1639
Devlin Cronin242d19d22019-03-12 18:08:481640IN_PROC_BROWSER_TEST_F(ServiceWorkerPushMessagingTest, OnPush) {
lazyboy561b7de2015-11-19 19:27:301641 const Extension* extension = LoadExtensionWithFlags(
1642 test_data_dir_.AppendASCII("service_worker/push_messaging"), kFlagNone);
1643 ASSERT_TRUE(extension);
1644 GURL extension_url = extension->url();
1645
Peter Beverloodd4ef1e2018-06-21 15:41:041646 GrantNotificationPermissionForTest(extension_url);
lazyboy561b7de2015-11-19 19:27:301647
1648 GURL url = extension->GetResourceURL("page.html");
1649 ui_test_utils::NavigateToURL(browser(), url);
1650
1651 content::WebContents* web_contents =
1652 browser()->tab_strip_model()->GetActiveWebContents();
1653
1654 // Start the ServiceWorker.
1655 ExtensionTestMessageListener ready_listener("SERVICE_WORKER_READY", false);
1656 ready_listener.set_failure_message("SERVICE_WORKER_FAILURE");
1657 const char* kScript = "window.runServiceWorker()";
1658 EXPECT_TRUE(content::ExecuteScript(web_contents->GetMainFrame(), kScript));
1659 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1660
1661 PushMessagingAppIdentifier app_identifier =
1662 GetAppIdentifierForServiceWorkerRegistration(0LL, extension_url);
johnmea5045732016-09-08 17:23:291663 ASSERT_EQ(app_identifier.app_id(), gcm_driver()->last_gettoken_app_id());
1664 EXPECT_EQ("1234567890", gcm_driver()->last_gettoken_authorized_entity());
lazyboy561b7de2015-11-19 19:27:301665
lazyboyd429e2582016-05-20 20:18:521666 base::RunLoop run_loop;
lazyboy561b7de2015-11-19 19:27:301667 // Send a push message via gcm and expect the ServiceWorker to receive it.
1668 ExtensionTestMessageListener push_message_listener("OK", false);
1669 push_message_listener.set_failure_message("FAIL");
1670 gcm::IncomingMessage message;
1671 message.sender_id = "1234567890";
1672 message.raw_data = "testdata";
1673 message.decrypted = true;
lazyboyd429e2582016-05-20 20:18:521674 push_service()->SetMessageCallbackForTesting(run_loop.QuitClosure());
lazyboy561b7de2015-11-19 19:27:301675 push_service()->OnMessage(app_identifier.app_id(), message);
1676 EXPECT_TRUE(push_message_listener.WaitUntilSatisfied());
lazyboyd429e2582016-05-20 20:18:521677 run_loop.Run(); // Wait until the message is handled by push service.
lazyboy561b7de2015-11-19 19:27:301678}
1679
Devlin Cronin242d19d22019-03-12 18:08:481680IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, FilteredEvents) {
Istiaque Ahmed9d1666182017-09-21 23:58:181681 // Extensions APIs from SW are only enabled on trunk.
1682 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1683 ASSERT_TRUE(RunExtensionTest("service_worker/filtered_events"));
1684}
1685
Devlin Cronin242d19d22019-03-12 18:08:481686IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, MimeHandlerView) {
Rob Wue89b90032018-02-16 19:46:081687 ASSERT_TRUE(RunExtensionTest("service_worker/mime_handler_view"));
1688}
1689
Devlin Cronin242d19d22019-03-12 18:08:481690IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmed9ce21b32017-10-10 20:43:181691 PRE_FilteredEventsAfterRestart) {
1692 LazyBackgroundObserver lazy_observer;
1693 ResultCatcher catcher;
1694 const Extension* extension = LoadExtensionWithFlags(
1695 test_data_dir_.AppendASCII(
1696 "service_worker/filtered_events_after_restart"),
1697 kFlagNone);
1698 ASSERT_TRUE(extension);
1699 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1700
1701 // |extension|'s background page opens a tab to its resource.
1702 content::WebContents* extension_web_contents =
1703 browser()->tab_strip_model()->GetActiveWebContents();
1704 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1705 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1706 extension_web_contents->GetURL().spec());
1707 {
1708 // Let the service worker start and register a filtered listener to
1709 // chrome.webNavigation.onCommitted event.
1710 ExtensionTestMessageListener add_listener_done("listener-added", false);
1711 add_listener_done.set_failure_message("FAILURE");
1712 content::ExecuteScriptAsync(extension_web_contents,
1713 "window.runServiceWorkerAsync()");
1714 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1715
1716 base::RunLoop run_loop;
1717 content::StoragePartition* storage_partition =
1718 content::BrowserContext::GetDefaultStoragePartition(
1719 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001720 content::StopServiceWorkerForScope(
Istiaque Ahmed9ce21b32017-10-10 20:43:181721 storage_partition->GetServiceWorkerContext(),
1722 // The service worker is registered at the top level scope.
1723 extension->url(), run_loop.QuitClosure());
1724 run_loop.Run();
1725 }
1726
1727 // Close the tab to |extension|'s resource. This will also close the
1728 // extension's event page.
1729 browser()->tab_strip_model()->CloseWebContentsAt(
1730 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1731 lazy_observer.Wait();
1732}
1733
Devlin Cronin242d19d22019-03-12 18:08:481734IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmedf5712522018-09-20 03:35:471735 FilteredEventsAfterRestart) {
Istiaque Ahmed9ce21b32017-10-10 20:43:181736 // Create a tab to a.html, expect it to navigate to b.html. The service worker
1737 // will see two webNavigation.onCommitted events.
1738 ASSERT_TRUE(StartEmbeddedTestServer());
1739 GURL page_url = embedded_test_server()->GetURL(
1740 "/extensions/api_test/service_worker/filtered_events_after_restart/"
1741 "a.html");
1742 ExtensionTestMessageListener worker_filtered_event_listener(
1743 "PASS_FROM_WORKER", false);
1744 worker_filtered_event_listener.set_failure_message("FAIL_FROM_WORKER");
1745 content::WebContents* web_contents = AddTab(browser(), page_url);
1746 EXPECT_TRUE(web_contents);
1747 EXPECT_TRUE(worker_filtered_event_listener.WaitUntilSatisfied());
1748}
1749
Devlin Cronin242d19d22019-03-12 18:08:481750IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest,
Istiaque Ahmedd4b67ee2019-03-02 10:53:201751 ProcessManagerRegistrationOnShutdown) {
1752 // Note that StopServiceWorkerForScope call below expects the worker to be
1753 // completely installed, so wait for the |extension| worker to see "activate"
1754 // event.
1755 ExtensionTestMessageListener activated_listener("WORKER_ACTIVATED", false);
1756 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
1757 "service_worker/worker_based_background/process_manager"));
1758 ASSERT_TRUE(extension);
1759 EXPECT_TRUE(activated_listener.WaitUntilSatisfied());
1760
1761 base::Optional<WorkerId> worker_id =
1762 GetUniqueRunningWorkerId(extension->id());
1763 ASSERT_TRUE(worker_id);
1764 {
1765 // Shutdown the worker.
1766 // TODO(lazyboy): Ideally we'd want to test worker shutdown on idle, do that
1767 // once //content API allows to override test timeouts for Service Workers.
1768 base::RunLoop run_loop;
1769 content::StoragePartition* storage_partition =
1770 content::BrowserContext::GetDefaultStoragePartition(
1771 browser()->profile());
1772 GURL scope = extension->url();
1773 content::StopServiceWorkerForScope(
1774 storage_partition->GetServiceWorkerContext(),
1775 // The service worker is registered at the top level scope.
1776 extension->url(), run_loop.QuitClosure());
1777 run_loop.Run();
1778 }
1779
1780 EXPECT_FALSE(ProcessManager::Get(profile())->HasServiceWorker(*worker_id));
1781}
1782
Devlin Cronin242d19d22019-03-12 18:08:481783IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest,
Istiaque Ahmedd4b67ee2019-03-02 10:53:201784 ProcessManagerRegistrationOnTerminate) {
1785 // NOTE: It is not necessary to wait for "activate" event from the worker
1786 // for this test, but we're lazily reusing the extension from
1787 // ProcessManagerRegistrationOnShutdown test.
1788 ExtensionTestMessageListener activated_listener("WORKER_ACTIVATED", false);
1789 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
1790 "service_worker/worker_based_background/process_manager"));
1791 ASSERT_TRUE(extension);
1792 EXPECT_TRUE(activated_listener.WaitUntilSatisfied());
1793
1794 base::Optional<WorkerId> worker_id =
1795 GetUniqueRunningWorkerId(extension->id());
1796 ASSERT_TRUE(worker_id);
1797 {
1798 // Terminate worker's RenderProcessHost.
1799 content::RenderProcessHost* worker_render_process_host =
1800 content::RenderProcessHost::FromID(worker_id->render_process_id);
1801 ASSERT_TRUE(worker_render_process_host);
1802 content::RenderProcessHostWatcher process_exit_observer(
1803 worker_render_process_host,
1804 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
1805 worker_render_process_host->Shutdown(content::RESULT_CODE_KILLED);
1806 process_exit_observer.Wait();
1807 }
1808
1809 EXPECT_FALSE(ProcessManager::Get(profile())->HasServiceWorker(*worker_id));
1810}
1811
Devlin Cronin59551d82019-03-05 01:28:591812// Tests that console messages logged by extension service workers, both via
1813// the typical console.* methods and via our custom bindings console, are
1814// passed through the normal ServiceWorker console messaging and are
1815// observable.
Devlin Cronin242d19d22019-03-12 18:08:481816IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest, ConsoleLogging) {
Devlin Cronin59551d82019-03-05 01:28:591817 // A helper class to wait for a particular message to be logged from a
1818 // ServiceWorker.
1819 class ConsoleMessageObserver : public content::ServiceWorkerContextObserver {
1820 public:
1821 ConsoleMessageObserver(content::BrowserContext* browser_context,
1822 const std::string& expected_message)
1823 : expected_message_(base::UTF8ToUTF16(expected_message)),
1824 scoped_observer_(this) {
1825 content::StoragePartition* partition =
1826 content::BrowserContext::GetDefaultStoragePartition(browser_context);
1827 scoped_observer_.Add(partition->GetServiceWorkerContext());
1828 }
1829 ~ConsoleMessageObserver() override = default;
1830
1831 void Wait() { run_loop_.Run(); }
1832
1833 private:
1834 // ServiceWorkerContextObserver:
1835 void OnReportConsoleMessage(
1836 int64_t version_id,
1837 const content::ConsoleMessage& message) override {
1838 // NOTE: We could check the version_id, but it shouldn't be necessary with
1839 // the expected messages we're verifying (they're uncommon enough).
1840 if (message.message != expected_message_)
1841 return;
1842 scoped_observer_.RemoveAll();
1843 run_loop_.QuitWhenIdle();
1844 }
1845
1846 base::string16 expected_message_;
1847 base::RunLoop run_loop_;
1848 ScopedObserver<content::ServiceWorkerContext,
1849 content::ServiceWorkerContextObserver>
1850 scoped_observer_;
1851
1852 DISALLOW_COPY_AND_ASSIGN(ConsoleMessageObserver);
1853 };
1854
1855 TestExtensionDir test_dir;
1856 test_dir.WriteManifest(
1857 R"({
1858 "name": "Test Extension",
1859 "manifest_version": 2,
1860 "version": "0.1",
David Bertoni630837d2019-04-02 21:22:101861 "background": {"service_worker": "script.js"}
Devlin Cronin59551d82019-03-05 01:28:591862 })");
1863 constexpr char kScript[] =
1864 R"(// First, log a message using the normal, built-in blink console.
1865 console.log('test message');
1866 chrome.test.runTests([
1867 function justATest() {
1868 // Next, we use the "Console" object from
1869 // extensions/renderer/console.cc, which is used by custom bindings
1870 // so that it isn't tampered with by untrusted script. The test
1871 // custom bindings log a message whenever a test is passed, so we
1872 // force a log by just passing this test.
1873 chrome.test.succeed();
1874 }
1875 ]);)";
1876 test_dir.WriteFile(FILE_PATH_LITERAL("script.js"), kScript);
1877
1878 // The observer for the built-in blink console.
1879 ConsoleMessageObserver default_console_observer(profile(), "test message");
1880 // The observer for our custom extensions bindings console.
1881 ConsoleMessageObserver custom_console_observer(profile(),
1882 "[SUCCESS] justATest");
1883
1884 const Extension* extension = LoadExtension(test_dir.UnpackedPath());
1885 ASSERT_TRUE(extension);
1886
1887 default_console_observer.Wait();
1888 custom_console_observer.Wait();
1889 // If we receive both messages, we passed!
1890}
1891
annekao38685502015-07-14 17:46:391892} // namespace extensions