blob: 83b163dc891ce4b1014dfed2a49be5de00e68f5f [file] [log] [blame]
annekao38685502015-07-14 17:46:391// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avia2f4804a2015-12-24 23:11:135#include <stdint.h>
6
kalman6f984ae2015-09-18 17:21:587#include "base/bind_helpers.h"
Istiaque Ahmeda14ec482018-08-25 01:02:188#include "base/json/json_reader.h"
avia2f4804a2015-12-24 23:11:139#include "base/macros.h"
Gabriel Charette078e3662017-08-28 22:59:0410#include "base/run_loop.h"
kalman6f984ae2015-09-18 17:21:5811#include "base/strings/stringprintf.h"
horo1eeddde2015-11-19 05:59:2512#include "base/strings/utf_string_conversions.h"
jam3f2d3932017-04-26 20:28:5113#include "base/threading/thread_restrictions.h"
Olga Sharonova3e13cd92018-02-08 16:43:5614#include "build/build_config.h"
annekao38685502015-07-14 17:46:3915#include "chrome/browser/extensions/extension_apitest.h"
rdevlin.croninf5863da2015-09-10 19:21:4516#include "chrome/browser/extensions/extension_service.h"
Istiaque Ahmed805f6a83b2017-10-05 01:23:2617#include "chrome/browser/extensions/lazy_background_page_test_util.h"
peter9f4490a2017-01-27 00:58:3618#include "chrome/browser/gcm/gcm_profile_service_factory.h"
miguelg9b502862017-04-24 18:13:5319#include "chrome/browser/notifications/notification_display_service_factory.h"
Peter Beverloodd4ef1e2018-06-21 15:41:0420#include "chrome/browser/notifications/notification_permission_context.h"
miguelg9b502862017-04-24 18:13:5321#include "chrome/browser/notifications/stub_notification_display_service.h"
lshang106c1772016-06-06 01:43:2322#include "chrome/browser/permissions/permission_manager.h"
timlohc6911802017-03-01 05:37:0323#include "chrome/browser/permissions/permission_result.h"
lazyboy561b7de2015-11-19 19:27:3024#include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
25#include "chrome/browser/push_messaging/push_messaging_service_factory.h"
26#include "chrome/browser/push_messaging/push_messaging_service_impl.h"
annekao1db36fd2015-07-29 17:09:1627#include "chrome/browser/ui/tabs/tab_strip_model.h"
Elly Fong-Jones4a4f21d2018-05-30 15:04:1628#include "chrome/browser/ui/views_mode_controller.h"
Trent Apted4267b942017-10-27 03:25:3629#include "chrome/common/chrome_switches.h"
Istiaque Ahmeda14ec482018-08-25 01:02:1830#include "chrome/common/extensions/api/web_navigation.h"
rdevlin.croninf5863da2015-09-10 19:21:4531#include "chrome/test/base/ui_test_utils.h"
timloh9a180ad2017-02-20 07:15:2332#include "components/content_settings/core/common/content_settings_types.h"
Peter Beverloo34139462018-04-10 14:18:0633#include "components/gcm_driver/fake_gcm_profile_service.h"
johnmea5045732016-09-08 17:23:2934#include "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h"
sdefresne9fb67692015-08-03 18:48:2235#include "components/version_info/version_info.h"
kalman6f984ae2015-09-18 17:21:5836#include "content/public/browser/navigation_controller.h"
rdevlin.croninf5863da2015-09-10 19:21:4537#include "content/public/browser/navigation_entry.h"
lazyboy4c82177a2016-10-18 00:04:0938#include "content/public/browser/service_worker_context.h"
39#include "content/public/browser/storage_partition.h"
kalman6f984ae2015-09-18 17:21:5840#include "content/public/browser/web_contents.h"
lazyboybd325ae2015-11-18 21:35:2641#include "content/public/common/content_switches.h"
falkenad185092016-06-16 06:10:0242#include "content/public/common/origin_util.h"
kalman6f984ae2015-09-18 17:21:5843#include "content/public/common/page_type.h"
lazyboybd325ae2015-11-18 21:35:2644#include "content/public/test/background_sync_test_util.h"
annekao1db36fd2015-07-29 17:09:1645#include "content/public/test/browser_test_utils.h"
lazyboy63b994a2017-06-30 21:20:2346#include "content/public/test/service_worker_test_helpers.h"
Istiaque Ahmed771aa8a22018-06-20 23:40:5347#include "extensions/browser/event_router.h"
kalman6f984ae2015-09-18 17:21:5848#include "extensions/browser/extension_host.h"
lazyboyc3e763a2015-12-09 23:09:5849#include "extensions/browser/extension_registry.h"
kalman6f984ae2015-09-18 17:21:5850#include "extensions/browser/process_manager.h"
Istiaque Ahmeda14ec482018-08-25 01:02:1851#include "extensions/common/api/test.h"
Devlin Cronina3fe3d602017-11-22 04:47:4352#include "extensions/common/extension_features.h"
Istiaque Ahmed771aa8a22018-06-20 23:40:5353#include "extensions/common/value_builder.h"
kalman6f984ae2015-09-18 17:21:5854#include "extensions/test/background_page_watcher.h"
annekao38685502015-07-14 17:46:3955#include "extensions/test/extension_test_message_listener.h"
Istiaque Ahmed805f6a83b2017-10-05 01:23:2656#include "extensions/test/result_catcher.h"
falkenad185092016-06-16 06:10:0257#include "net/dns/mock_host_resolver.h"
horo1eeddde2015-11-19 05:59:2558#include "net/test/embedded_test_server/embedded_test_server.h"
lazyboy63b994a2017-06-30 21:20:2359#include "url/url_constants.h"
annekao38685502015-07-14 17:46:3960
61namespace extensions {
62
kalman6f984ae2015-09-18 17:21:5863namespace {
64
lazyboy22eddc712015-12-10 21:16:2665// Returns the newly added WebContents.
66content::WebContents* AddTab(Browser* browser, const GURL& url) {
67 int starting_tab_count = browser->tab_strip_model()->count();
68 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:1969 browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
lazyboy22eddc712015-12-10 21:16:2670 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
71 int tab_count = browser->tab_strip_model()->count();
72 EXPECT_EQ(starting_tab_count + 1, tab_count);
73 return browser->tab_strip_model()->GetActiveWebContents();
74}
75
Istiaque Ahmedea5ed5042017-09-25 19:00:1676enum BindingsType { NATIVE_BINDINGS, JAVASCRIPT_BINDINGS };
77
lazyboy22eddc712015-12-10 21:16:2678class WebContentsLoadStopObserver : content::WebContentsObserver {
79 public:
80 explicit WebContentsLoadStopObserver(content::WebContents* web_contents)
81 : content::WebContentsObserver(web_contents),
82 load_stop_observed_(false) {}
83
84 void WaitForLoadStop() {
85 if (load_stop_observed_)
86 return;
87 message_loop_runner_ = new content::MessageLoopRunner;
88 message_loop_runner_->Run();
89 }
90
91 private:
92 void DidStopLoading() override {
93 load_stop_observed_ = true;
94 if (message_loop_runner_)
95 message_loop_runner_->Quit();
96 }
97
98 bool load_stop_observed_;
99 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
100
101 DISALLOW_COPY_AND_ASSIGN(WebContentsLoadStopObserver);
102};
103
Elly Fong-Jones4a4f21d2018-05-30 15:04:16104bool IsMacViewsMode() {
105// Some tests are flaky on Mac: <https://crbug.com/845979>. This helper function
106// is used to skip them.
107#if defined(OS_MACOSX)
108 return !views_mode_controller::IsViewsBrowserCocoa();
109#else
110 return false;
111#endif
112}
113
kalman6f984ae2015-09-18 17:21:58114} // namespace
115
Istiaque Ahmedea5ed5042017-09-25 19:00:16116class ServiceWorkerTest : public ExtensionApiTest,
117 public ::testing::WithParamInterface<BindingsType> {
annekao38685502015-07-14 17:46:39118 public:
lazyboy20167c22016-05-18 00:59:30119 ServiceWorkerTest() : current_channel_(version_info::Channel::STABLE) {}
Istiaque Ahmed7105f2a2017-10-07 01:11:59120 explicit ServiceWorkerTest(version_info::Channel channel)
121 : current_channel_(channel) {}
annekao38685502015-07-14 17:46:39122
123 ~ServiceWorkerTest() override {}
124
Devlin Cronina3fe3d602017-11-22 04:47:43125 void SetUp() override {
126 if (GetParam() == NATIVE_BINDINGS) {
Mostyn Bramley-Mooreb6a37c62018-09-04 21:43:35127 scoped_feature_list_.InitAndEnableFeature(
128 extensions_features::kNativeCrxBindings);
Devlin Cronina3fe3d602017-11-22 04:47:43129 } else {
130 DCHECK_EQ(JAVASCRIPT_BINDINGS, GetParam());
Mostyn Bramley-Mooreb6a37c62018-09-04 21:43:35131 scoped_feature_list_.InitAndDisableFeature(
132 extensions_features::kNativeCrxBindings);
Devlin Cronina3fe3d602017-11-22 04:47:43133 }
134 ExtensionApiTest::SetUp();
135 }
136
jam1a5b5582017-05-01 16:50:10137 void SetUpOnMainThread() override {
138 ExtensionApiTest::SetUpOnMainThread();
139 host_resolver()->AddRule("a.com", "127.0.0.1");
140 }
141
kalman6f984ae2015-09-18 17:21:58142 protected:
143 // Returns the ProcessManager for the test's profile.
144 ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
145
146 // Starts running a test from the background page test extension.
147 //
148 // This registers a service worker with |script_name|, and fetches the
149 // registration result.
Istiaque Ahmed93ff7f42018-08-31 01:42:22150 const Extension* StartTestFromBackgroundPage(const char* script_name) {
Istiaque Ahmed6475f542018-08-28 04:20:21151 ExtensionTestMessageListener ready_listener("ready", false);
kalman6f984ae2015-09-18 17:21:58152 const Extension* extension =
153 LoadExtension(test_data_dir_.AppendASCII("service_worker/background"));
154 CHECK(extension);
Istiaque Ahmed6475f542018-08-28 04:20:21155 CHECK(ready_listener.WaitUntilSatisfied());
156
kalman6f984ae2015-09-18 17:21:58157 ExtensionHost* background_host =
158 process_manager()->GetBackgroundHostForExtension(extension->id());
159 CHECK(background_host);
Istiaque Ahmed6475f542018-08-28 04:20:21160
kalman6f984ae2015-09-18 17:21:58161 std::string error;
162 CHECK(content::ExecuteScriptAndExtractString(
163 background_host->host_contents(),
164 base::StringPrintf("test.registerServiceWorker('%s')", script_name),
165 &error));
Istiaque Ahmed93ff7f42018-08-31 01:42:22166 if (!error.empty())
kalman6f984ae2015-09-18 17:21:58167 ADD_FAILURE() << "Got unexpected error " << error;
168 return extension;
169 }
170
171 // Navigates the browser to a new tab at |url|, waits for it to load, then
172 // returns it.
173 content::WebContents* Navigate(const GURL& url) {
174 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19175 browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
kalman6f984ae2015-09-18 17:21:58176 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
177 content::WebContents* web_contents =
178 browser()->tab_strip_model()->GetActiveWebContents();
179 content::WaitForLoadStop(web_contents);
180 return web_contents;
181 }
182
183 // Navigates the browser to |url| and returns the new tab's page type.
184 content::PageType NavigateAndGetPageType(const GURL& url) {
clamy1d7a4112018-06-15 15:47:16185 return Navigate(url)
186 ->GetController()
187 .GetLastCommittedEntry()
188 ->GetPageType();
kalman6f984ae2015-09-18 17:21:58189 }
190
191 // Extracts the innerText from |contents|.
192 std::string ExtractInnerText(content::WebContents* contents) {
193 std::string inner_text;
194 if (!content::ExecuteScriptAndExtractString(
195 contents,
196 "window.domAutomationController.send(document.body.innerText)",
197 &inner_text)) {
198 ADD_FAILURE() << "Failed to get inner text for "
199 << contents->GetVisibleURL();
200 }
201 return inner_text;
202 }
203
204 // Navigates the browser to |url|, then returns the innerText of the new
205 // tab's WebContents' main frame.
206 std::string NavigateAndExtractInnerText(const GURL& url) {
207 return ExtractInnerText(Navigate(url));
208 }
209
lazyboy4c82177a2016-10-18 00:04:09210 size_t GetWorkerRefCount(const GURL& origin) {
211 content::ServiceWorkerContext* sw_context =
212 content::BrowserContext::GetDefaultStoragePartition(
213 browser()->profile())
214 ->GetServiceWorkerContext();
215 base::RunLoop run_loop;
216 size_t ref_count = 0;
217 auto set_ref_count = [](size_t* ref_count, base::RunLoop* run_loop,
218 size_t external_request_count) {
219 *ref_count = external_request_count;
220 run_loop->Quit();
221 };
222 sw_context->CountExternalRequestsForTest(
Matt Falkenhagenc5cb4282017-09-07 08:43:42223 origin, base::BindOnce(set_ref_count, &ref_count, &run_loop));
lazyboy4c82177a2016-10-18 00:04:09224 run_loop.Run();
225 return ref_count;
226 }
227
annekao38685502015-07-14 17:46:39228 private:
lazyboy20167c22016-05-18 00:59:30229 // Sets the channel to "stable".
230 // Not useful after we've opened extension Service Workers to stable
231 // channel.
232 // TODO(lazyboy): Remove this when ExtensionServiceWorkersEnabled() is
233 // removed.
annekao38685502015-07-14 17:46:39234 ScopedCurrentChannel current_channel_;
kalman6f984ae2015-09-18 17:21:58235
Devlin Cronina3fe3d602017-11-22 04:47:43236 base::test::ScopedFeatureList scoped_feature_list_;
237
annekao38685502015-07-14 17:46:39238 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTest);
239};
240
Istiaque Ahmedccb444022018-06-19 02:11:12241class ServiceWorkerBasedBackgroundTest : public ServiceWorkerTest {
242 public:
243 ServiceWorkerBasedBackgroundTest()
244 : ServiceWorkerTest(
245 // Extensions APIs from SW are only enabled on trunk.
246 // It is important to set the channel early so that this change is
247 // visible in renderers running with service workers (and no
248 // extension).
249 version_info::Channel::UNKNOWN) {}
250 ~ServiceWorkerBasedBackgroundTest() override {}
251
252 void SetUpOnMainThread() override {
253 host_resolver()->AddRule("*", "127.0.0.1");
254 ASSERT_TRUE(embedded_test_server()->Start());
255 ServiceWorkerTest::SetUpOnMainThread();
256 }
257
258 private:
259 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBasedBackgroundTest);
260};
261
262// Tests that Service Worker based background pages can be loaded and they can
263// receive extension events.
264// The extension is installed and loaded during this step and it registers
265// an event listener for tabs.onCreated event. The step also verifies that tab
266// creation correctly fires the listener.
267IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, PRE_Basic) {
268 ExtensionTestMessageListener newtab_listener("CREATED", false);
269 newtab_listener.set_failure_message("CREATE_FAILED");
270 ExtensionTestMessageListener worker_listener("WORKER_RUNNING", false);
271 worker_listener.set_failure_message("NON_WORKER_SCOPE");
272 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
273 "service_worker/worker_based_background/basic"));
274 ASSERT_TRUE(extension);
275 const ExtensionId extension_id = extension->id();
276 EXPECT_TRUE(worker_listener.WaitUntilSatisfied());
277
278 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
279 content::WebContents* new_web_contents = AddTab(browser(), url);
280 EXPECT_TRUE(new_web_contents);
281 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
282
283 // Service Worker extension does not have ExtensionHost.
284 EXPECT_FALSE(process_manager()->GetBackgroundHostForExtension(extension_id));
285}
286
287// After browser restarts, this test step ensures that opening a tab fires
288// tabs.onCreated event listener to the extension without explicitly loading the
289// extension. This is because the extension registered a listener before browser
290// restarted in PRE_Basic.
Istiaque Ahmedad376e6b2018-09-13 22:48:25291IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, Basic) {
Istiaque Ahmedccb444022018-06-19 02:11:12292 ExtensionTestMessageListener newtab_listener("CREATED", false);
293 newtab_listener.set_failure_message("CREATE_FAILED");
294 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
295 content::WebContents* new_web_contents = AddTab(browser(), url);
296 EXPECT_TRUE(new_web_contents);
297 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
298}
299
Istiaque Ahmedbf08f952018-10-02 01:22:04300// Tests chrome.runtime.onInstalled fires for extension service workers.
301IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, OnInstalledEvent) {
302 ASSERT_TRUE(RunExtensionTest(
303 "service_worker/worker_based_background/events_on_installed"))
304 << message_;
305}
306
Istiaque Ahmeda14ec482018-08-25 01:02:18307// Class that dispatches an event to |extension_id| right after a
308// non-lazy listener to the event is added from the extension's Service Worker.
Istiaque Ahmed771aa8a22018-06-20 23:40:53309class EarlyWorkerMessageSender : public EventRouter::Observer {
310 public:
311 EarlyWorkerMessageSender(content::BrowserContext* browser_context,
Istiaque Ahmeda14ec482018-08-25 01:02:18312 const ExtensionId& extension_id,
313 std::unique_ptr<Event> event)
Istiaque Ahmed771aa8a22018-06-20 23:40:53314 : browser_context_(browser_context),
315 event_router_(EventRouter::EventRouter::Get(browser_context_)),
316 extension_id_(extension_id),
Istiaque Ahmeda14ec482018-08-25 01:02:18317 event_(std::move(event)),
Istiaque Ahmed771aa8a22018-06-20 23:40:53318 listener_("PASS", false) {
319 DCHECK(browser_context_);
320 listener_.set_failure_message("FAIL");
Istiaque Ahmeda14ec482018-08-25 01:02:18321 event_router_->RegisterObserver(this, event_->event_name);
Istiaque Ahmed771aa8a22018-06-20 23:40:53322 }
323
324 ~EarlyWorkerMessageSender() override {
325 event_router_->UnregisterObserver(this);
326 }
327
328 // EventRouter::Observer:
329 void OnListenerAdded(const EventListenerInfo& details) override {
Istiaque Ahmeda14ec482018-08-25 01:02:18330 if (!event_ || extension_id_ != details.extension_id ||
331 event_->event_name != details.event_name) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53332 return;
Istiaque Ahmeda14ec482018-08-25 01:02:18333 }
334
Istiaque Ahmed771aa8a22018-06-20 23:40:53335 const bool is_lazy_listener = details.browser_context == nullptr;
336 if (is_lazy_listener) {
337 // Wait for the non-lazy listener as we want to exercise the code to
338 // dispatch the event right after the Service Worker registration is
339 // completing.
340 return;
341 }
Istiaque Ahmeda14ec482018-08-25 01:02:18342 DispatchEvent(std::move(event_));
Istiaque Ahmed771aa8a22018-06-20 23:40:53343 }
344
345 bool SendAndWait() { return listener_.WaitUntilSatisfied(); }
346
347 private:
348 static constexpr const char* const kTestOnMessageEventName = "test.onMessage";
349
Istiaque Ahmeda14ec482018-08-25 01:02:18350 void DispatchEvent(std::unique_ptr<Event> event) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53351 EventRouter::Get(browser_context_)
352 ->DispatchEventToExtension(extension_id_, std::move(event));
353 }
354
355 content::BrowserContext* const browser_context_ = nullptr;
356 EventRouter* const event_router_ = nullptr;
357 const ExtensionId extension_id_;
Istiaque Ahmeda14ec482018-08-25 01:02:18358 std::unique_ptr<Event> event_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53359 ExtensionTestMessageListener listener_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53360
361 DISALLOW_COPY_AND_ASSIGN(EarlyWorkerMessageSender);
362};
363
364// Tests that extension event dispatch works correctly right after extension
365// installation registers its Service Worker.
366// Regression test for: https://crbug.com/850792.
367IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, EarlyEventDispatch) {
368 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
Istiaque Ahmeda14ec482018-08-25 01:02:18369
370 // Build "test.onMessage" event for dispatch.
371 auto event = std::make_unique<Event>(
372 events::FOR_TEST, extensions::api::test::OnMessage::kEventName,
373 base::ListValue::From(base::JSONReader::Read(
374 R"([{"data": "hello", "lastMessage": true}])")),
375 profile());
376
377 EarlyWorkerMessageSender sender(profile(), kId, std::move(event));
Istiaque Ahmed771aa8a22018-06-20 23:40:53378 // pkplfbidichfdicaijlchgnapepdginl
379 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
380 "service_worker/worker_based_background/early_event_dispatch"));
381 CHECK(extension);
382 EXPECT_EQ(kId, extension->id());
383 EXPECT_TRUE(sender.SendAndWait());
384}
385
Istiaque Ahmeda14ec482018-08-25 01:02:18386// Tests that filtered events dispatches correctly right after a non-lazy
387// listener is registered for that event (and before the corresponding lazy
388// listener is registered).
389IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest,
390 EarlyFilteredEventDispatch) {
391 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
392
393 // Add minimal details required to dispatch webNavigation.onCommitted event:
394 extensions::api::web_navigation::OnCommitted::Details details;
395 details.transition_type =
396 extensions::api::web_navigation::TRANSITION_TYPE_TYPED;
397
398 // Build a dummy onCommited event to dispatch.
399 auto on_committed_event = std::make_unique<Event>(
400 events::WEB_NAVIGATION_ON_COMMITTED, "webNavigation.onCommitted",
401 api::web_navigation::OnCommitted::Create(details), profile());
402 // The filter will match the listener filter registered from the extension.
403 EventFilteringInfo info;
404 info.url = GURL("http://foo.com/a.html");
405 on_committed_event->filter_info = info;
406
407 EarlyWorkerMessageSender sender(profile(), kId,
408 std::move(on_committed_event));
409
410 // pkplfbidichfdicaijlchgnapepdginl
411 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
412 "service_worker/worker_based_background/early_filtered_event_dispatch"));
413 ASSERT_TRUE(extension);
414 EXPECT_EQ(kId, extension->id());
415 EXPECT_TRUE(sender.SendAndWait());
416}
417
lazyboybd325ae2015-11-18 21:35:26418class ServiceWorkerBackgroundSyncTest : public ServiceWorkerTest {
419 public:
420 ServiceWorkerBackgroundSyncTest() {}
421 ~ServiceWorkerBackgroundSyncTest() override {}
422
423 void SetUpCommandLine(base::CommandLine* command_line) override {
424 // ServiceWorkerRegistration.sync requires experimental flag.
425 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16426 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboybd325ae2015-11-18 21:35:26427 ServiceWorkerTest::SetUpCommandLine(command_line);
428 }
429
430 void SetUp() override {
Robbie McElrathdb12d8e2018-09-18 21:20:40431 content::background_sync_test_util::SetIgnoreNetworkChanges(true);
lazyboybd325ae2015-11-18 21:35:26432 ServiceWorkerTest::SetUp();
433 }
434
435 private:
436 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBackgroundSyncTest);
437};
438
lazyboy561b7de2015-11-19 19:27:30439class ServiceWorkerPushMessagingTest : public ServiceWorkerTest {
440 public:
441 ServiceWorkerPushMessagingTest()
johnmea5045732016-09-08 17:23:29442 : gcm_driver_(nullptr), push_service_(nullptr) {}
lazyboy561b7de2015-11-19 19:27:30443 ~ServiceWorkerPushMessagingTest() override {}
444
445 void GrantNotificationPermissionForTest(const GURL& url) {
Peter Beverloodd4ef1e2018-06-21 15:41:04446 NotificationPermissionContext::UpdatePermission(profile(), url.GetOrigin(),
447 CONTENT_SETTING_ALLOW);
lazyboy561b7de2015-11-19 19:27:30448 }
449
450 PushMessagingAppIdentifier GetAppIdentifierForServiceWorkerRegistration(
avia2f4804a2015-12-24 23:11:13451 int64_t service_worker_registration_id,
lazyboy561b7de2015-11-19 19:27:30452 const GURL& origin) {
453 PushMessagingAppIdentifier app_identifier =
454 PushMessagingAppIdentifier::FindByServiceWorker(
455 profile(), origin, service_worker_registration_id);
456
457 EXPECT_FALSE(app_identifier.is_null());
458 return app_identifier;
459 }
460
461 // ExtensionApiTest overrides.
462 void SetUpCommandLine(base::CommandLine* command_line) override {
peter9de96272015-12-04 15:23:27463 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16464 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboy561b7de2015-11-19 19:27:30465 ServiceWorkerTest::SetUpCommandLine(command_line);
466 }
Tanja Gornak89128fd2018-09-18 08:49:34467
468 void SetUp() override {
469 gcm::GCMProfileServiceFactory::SetGlobalTestingFactory(
470 &gcm::FakeGCMProfileService::Build);
471 ServiceWorkerTest::SetUp();
472 }
473
lazyboy561b7de2015-11-19 19:27:30474 void SetUpOnMainThread() override {
miguelg9b502862017-04-24 18:13:53475 NotificationDisplayServiceFactory::GetInstance()->SetTestingFactory(
476 profile(), &StubNotificationDisplayService::FactoryForTests);
477
johnmea5045732016-09-08 17:23:29478 gcm::FakeGCMProfileService* gcm_service =
479 static_cast<gcm::FakeGCMProfileService*>(
Tanja Gornak89128fd2018-09-18 08:49:34480 gcm::GCMProfileServiceFactory::GetForProfile(profile()));
johnmea5045732016-09-08 17:23:29481 gcm_driver_ = static_cast<instance_id::FakeGCMDriverForInstanceID*>(
482 gcm_service->driver());
lazyboy561b7de2015-11-19 19:27:30483 push_service_ = PushMessagingServiceFactory::GetForProfile(profile());
484
485 ServiceWorkerTest::SetUpOnMainThread();
486 }
487
Tanja Gornak89128fd2018-09-18 08:49:34488 void TearDown() override {
489 gcm::GCMProfileServiceFactory::SetGlobalTestingFactory(nullptr);
490 ServiceWorkerTest::TearDown();
491 }
492
johnmea5045732016-09-08 17:23:29493 instance_id::FakeGCMDriverForInstanceID* gcm_driver() const {
494 return gcm_driver_;
495 }
lazyboy561b7de2015-11-19 19:27:30496 PushMessagingServiceImpl* push_service() const { return push_service_; }
497
498 private:
johnmea5045732016-09-08 17:23:29499 instance_id::FakeGCMDriverForInstanceID* gcm_driver_;
lazyboy561b7de2015-11-19 19:27:30500 PushMessagingServiceImpl* push_service_;
501
502 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPushMessagingTest);
503};
504
Istiaque Ahmed805f6a83b2017-10-05 01:23:26505class ServiceWorkerLazyBackgroundTest : public ServiceWorkerTest {
506 public:
Istiaque Ahmed7105f2a2017-10-07 01:11:59507 ServiceWorkerLazyBackgroundTest()
508 : ServiceWorkerTest(
509 // Extensions APIs from SW are only enabled on trunk.
510 // It is important to set the channel early so that this change is
511 // visible in renderers running with service workers (and no
512 // extension).
513 version_info::Channel::UNKNOWN) {}
Istiaque Ahmed805f6a83b2017-10-05 01:23:26514 ~ServiceWorkerLazyBackgroundTest() override {}
515
516 void SetUpCommandLine(base::CommandLine* command_line) override {
517 ServiceWorkerTest::SetUpCommandLine(command_line);
518 // Disable background network activity as it can suddenly bring the Lazy
519 // Background Page alive.
520 command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
521 command_line->AppendSwitch(::switches::kNoProxyServer);
522 }
523
524 void SetUpInProcessBrowserTestFixture() override {
525 ServiceWorkerTest::SetUpInProcessBrowserTestFixture();
526 // Set shorter delays to prevent test timeouts.
527 ProcessManager::SetEventPageIdleTimeForTesting(1);
528 ProcessManager::SetEventPageSuspendingTimeForTesting(1);
529 }
530
531 private:
532 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerLazyBackgroundTest);
533};
534
Istiaque Ahmedea5ed5042017-09-25 19:00:16535IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, RegisterSucceeds) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22536 StartTestFromBackgroundPage("register.js");
annekao38685502015-07-14 17:46:39537}
538
Istiaque Ahmedea5ed5042017-09-25 19:00:16539IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, UpdateRefreshesServiceWorker) {
Francois Doraye6fb2d02017-10-18 21:29:13540 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboyc3e763a2015-12-09 23:09:58541 base::ScopedTempDir scoped_temp_dir;
542 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
543 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
544 .AppendASCII("update")
545 .AppendASCII("service_worker.pem");
vabr9142fe22016-09-08 13:19:22546 base::FilePath path_v1 =
547 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
548 .AppendASCII("update")
549 .AppendASCII("v1"),
550 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
551 pem_path, base::FilePath());
552 base::FilePath path_v2 =
553 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
554 .AppendASCII("update")
555 .AppendASCII("v2"),
556 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
557 pem_path, base::FilePath());
lazyboyc3e763a2015-12-09 23:09:58558 const char* kId = "hfaanndiiilofhfokeanhddpkfffchdi";
559
560 ExtensionTestMessageListener listener_v1("Pong from version 1", false);
561 listener_v1.set_failure_message("FAILURE_V1");
562 // Install version 1.0 of the extension.
563 ASSERT_TRUE(InstallExtension(path_v1, 1));
564 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
565 ->enabled_extensions()
566 .GetByID(kId));
567 EXPECT_TRUE(listener_v1.WaitUntilSatisfied());
568
569 ExtensionTestMessageListener listener_v2("Pong from version 2", false);
570 listener_v2.set_failure_message("FAILURE_V2");
571
572 // Update to version 2.0.
573 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
574 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
575 ->enabled_extensions()
576 .GetByID(kId));
577 EXPECT_TRUE(listener_v2.WaitUntilSatisfied());
578}
579
[email protected]2ef85d562017-09-15 18:41:52580// TODO(crbug.com/765736) Fix the test.
Istiaque Ahmedea5ed5042017-09-25 19:00:16581IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, DISABLED_UpdateWithoutSkipWaiting) {
Francois Doraye6fb2d02017-10-18 21:29:13582 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboy22eddc712015-12-10 21:16:26583 base::ScopedTempDir scoped_temp_dir;
584 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
585 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
586 .AppendASCII("update_without_skip_waiting")
587 .AppendASCII("update_without_skip_waiting.pem");
vabr9142fe22016-09-08 13:19:22588 base::FilePath path_v1 =
589 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
590 .AppendASCII("update_without_skip_waiting")
591 .AppendASCII("v1"),
592 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
593 pem_path, base::FilePath());
594 base::FilePath path_v2 =
595 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
596 .AppendASCII("update_without_skip_waiting")
597 .AppendASCII("v2"),
598 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
599 pem_path, base::FilePath());
lazyboy22eddc712015-12-10 21:16:26600 const char* kId = "mhnnnflgagdakldgjpfcofkiocpdmogl";
601
602 // Install version 1.0 of the extension.
603 ASSERT_TRUE(InstallExtension(path_v1, 1));
604 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
605 ->enabled_extensions()
606 .GetByID(kId));
607 const Extension* extension = extensions::ExtensionRegistry::Get(profile())
608 ->enabled_extensions()
609 .GetByID(kId);
610
611 ExtensionTestMessageListener listener1("Pong from version 1", false);
612 listener1.set_failure_message("FAILURE");
613 content::WebContents* web_contents =
614 AddTab(browser(), extension->GetResourceURL("page.html"));
615 EXPECT_TRUE(listener1.WaitUntilSatisfied());
616
617 // Update to version 2.0.
618 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
619 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
620 ->enabled_extensions()
621 .GetByID(kId));
622 const Extension* extension_after_update =
623 extensions::ExtensionRegistry::Get(profile())
624 ->enabled_extensions()
625 .GetByID(kId);
626
627 // Service worker version 2 would be installed but it won't be controlling
628 // the extension page yet.
629 ExtensionTestMessageListener listener2("Pong from version 1", false);
630 listener2.set_failure_message("FAILURE");
631 web_contents =
632 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
633 EXPECT_TRUE(listener2.WaitUntilSatisfied());
634
635 // Navigate the tab away from the extension page so that no clients are
636 // using the service worker.
637 // Note that just closing the tab with WebContentsDestroyedWatcher doesn't
638 // seem to be enough because it returns too early.
639 WebContentsLoadStopObserver navigate_away_observer(web_contents);
640 web_contents->GetController().LoadURL(
641 GURL(url::kAboutBlankURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED,
642 std::string());
643 navigate_away_observer.WaitForLoadStop();
644
645 // Now expect service worker version 2 to control the extension page.
646 ExtensionTestMessageListener listener3("Pong from version 2", false);
647 listener3.set_failure_message("FAILURE");
648 web_contents =
649 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
650 EXPECT_TRUE(listener3.WaitUntilSatisfied());
651}
652
Istiaque Ahmedea5ed5042017-09-25 19:00:16653IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, FetchArbitraryPaths) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22654 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
annekao1db36fd2015-07-29 17:09:16655
kalman6f984ae2015-09-18 17:21:58656 // Open some arbirary paths. Their contents should be what the service worker
657 // responds with, which in this case is the path of the fetch.
658 EXPECT_EQ(
659 "Caught a fetch for /index.html",
660 NavigateAndExtractInnerText(extension->GetResourceURL("index.html")));
661 EXPECT_EQ("Caught a fetch for /path/to/other.html",
662 NavigateAndExtractInnerText(
663 extension->GetResourceURL("path/to/other.html")));
664 EXPECT_EQ("Caught a fetch for /some/text/file.txt",
665 NavigateAndExtractInnerText(
666 extension->GetResourceURL("some/text/file.txt")));
667 EXPECT_EQ("Caught a fetch for /no/file/extension",
668 NavigateAndExtractInnerText(
669 extension->GetResourceURL("no/file/extension")));
670 EXPECT_EQ("Caught a fetch for /",
671 NavigateAndExtractInnerText(extension->GetResourceURL("")));
annekao1db36fd2015-07-29 17:09:16672}
673
Kenichi Ishibashi773b82972018-08-30 07:02:03674IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
675 FetchExtensionResourceFromServiceWorker) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22676 const Extension* extension = StartTestFromBackgroundPage("fetch_from_sw.js");
Kenichi Ishibashi773b82972018-08-30 07:02:03677 ASSERT_TRUE(extension);
678
679 // The service worker in this test tries to load 'hello.txt' via fetch()
680 // and sends back the content of the file, which should be 'hello'.
681 const char* kScript = R"(
682 let channel = new MessageChannel();
683 test.waitForMessage(channel.port1).then(message => {
684 window.domAutomationController.send(message);
685 });
686 test.registeredServiceWorker.postMessage(
687 {port: channel.port2}, [channel.port2]);
688 )";
689 EXPECT_EQ("hello", ExecuteScriptInBackgroundPage(extension->id(), kScript));
690}
691
Istiaque Ahmedea5ed5042017-09-25 19:00:16692IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, SWServedBackgroundPageReceivesEvent) {
lazyboy52c3bcf2016-01-08 00:11:29693 const Extension* extension =
Istiaque Ahmed93ff7f42018-08-31 01:42:22694 StartTestFromBackgroundPage("replace_background.js");
lazyboy52c3bcf2016-01-08 00:11:29695 ExtensionHost* background_page =
696 process_manager()->GetBackgroundHostForExtension(extension->id());
697 ASSERT_TRUE(background_page);
698
699 // Close the background page and start it again so that the service worker
700 // will start controlling pages.
701 background_page->Close();
702 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
703 background_page = nullptr;
Peter Kasting341e1fb2018-02-24 00:03:01704 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
lazyboy52c3bcf2016-01-08 00:11:29705 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
706
707 // Since the SW is now controlling the extension, the SW serves the background
708 // script. page.html sends a message to the background script and we verify
709 // that the SW served background script correctly receives the message/event.
710 ExtensionTestMessageListener listener("onMessage/SW BG.", false);
711 listener.set_failure_message("onMessage/original BG.");
712 content::WebContents* web_contents =
713 AddTab(browser(), extension->GetResourceURL("page.html"));
714 ASSERT_TRUE(web_contents);
715 EXPECT_TRUE(listener.WaitUntilSatisfied());
716}
717
Matt Falkenhagena612fc02018-05-30 00:35:39718IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, SWServedBackgroundPage) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22719 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
annekao49241182015-08-18 17:14:01720
kalman6f984ae2015-09-18 17:21:58721 std::string kExpectedInnerText = "background.html contents for testing.";
annekao49241182015-08-18 17:14:01722
kalman6f984ae2015-09-18 17:21:58723 // Sanity check that the background page has the expected content.
724 ExtensionHost* background_page =
725 process_manager()->GetBackgroundHostForExtension(extension->id());
726 ASSERT_TRUE(background_page);
727 EXPECT_EQ(kExpectedInnerText,
728 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01729
kalman6f984ae2015-09-18 17:21:58730 // Close the background page.
731 background_page->Close();
732 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
733 background_page = nullptr;
734
735 // Start it again.
Peter Kasting341e1fb2018-02-24 00:03:01736 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
kalman6f984ae2015-09-18 17:21:58737 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
738
Matt Falkenhagena612fc02018-05-30 00:35:39739 // The service worker should get a fetch event for the background page.
kalman6f984ae2015-09-18 17:21:58740 background_page =
741 process_manager()->GetBackgroundHostForExtension(extension->id());
742 ASSERT_TRUE(background_page);
743 content::WaitForLoadStop(background_page->host_contents());
744
kalman6f984ae2015-09-18 17:21:58745 EXPECT_EQ("Caught a fetch for /background.html",
746 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01747}
748
Istiaque Ahmedea5ed5042017-09-25 19:00:16749IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58750 ServiceWorkerPostsMessageToBackgroundClient) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22751 const Extension* extension =
752 StartTestFromBackgroundPage("post_message_to_background_client.js");
annekao533482222015-08-21 23:23:53753
kalman6f984ae2015-09-18 17:21:58754 // The service worker in this test simply posts a message to the background
755 // client it receives from getBackgroundClient().
756 const char* kScript =
757 "var messagePromise = null;\n"
758 "if (test.lastMessageFromServiceWorker) {\n"
759 " messagePromise = Promise.resolve(test.lastMessageFromServiceWorker);\n"
760 "} else {\n"
761 " messagePromise = test.waitForMessage(navigator.serviceWorker);\n"
762 "}\n"
763 "messagePromise.then(function(message) {\n"
764 " window.domAutomationController.send(String(message == 'success'));\n"
765 "})\n";
766 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53767}
768
Istiaque Ahmedea5ed5042017-09-25 19:00:16769IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58770 BackgroundPagePostsMessageToServiceWorker) {
771 const Extension* extension =
Istiaque Ahmed93ff7f42018-08-31 01:42:22772 StartTestFromBackgroundPage("post_message_to_sw.js");
annekao533482222015-08-21 23:23:53773
kalman6f984ae2015-09-18 17:21:58774 // The service worker in this test waits for a message, then echoes it back
775 // by posting a message to the background page via getBackgroundClient().
776 const char* kScript =
777 "var mc = new MessageChannel();\n"
778 "test.waitForMessage(mc.port1).then(function(message) {\n"
779 " window.domAutomationController.send(String(message == 'hello'));\n"
780 "});\n"
781 "test.registeredServiceWorker.postMessage(\n"
782 " {message: 'hello', port: mc.port2}, [mc.port2])\n";
783 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53784}
785
Istiaque Ahmedea5ed5042017-09-25 19:00:16786IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
rdevlin.croninf5863da2015-09-10 19:21:45787 ServiceWorkerSuspensionOnExtensionUnload) {
kalman6f984ae2015-09-18 17:21:58788 // For this test, only hold onto the extension's ID and URL + a function to
789 // get a resource URL, because we're going to be disabling and uninstalling
790 // it, which will invalidate the pointer.
791 std::string extension_id;
792 GURL extension_url;
793 {
Istiaque Ahmed93ff7f42018-08-31 01:42:22794 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
kalman6f984ae2015-09-18 17:21:58795 extension_id = extension->id();
796 extension_url = extension->url();
797 }
798 auto get_resource_url = [&extension_url](const std::string& path) {
799 return Extension::GetResourceURL(extension_url, path);
800 };
rdevlin.croninf5863da2015-09-10 19:21:45801
kalman6f984ae2015-09-18 17:21:58802 // Fetch should route to the service worker.
803 EXPECT_EQ("Caught a fetch for /index.html",
804 NavigateAndExtractInnerText(get_resource_url("index.html")));
rdevlin.croninf5863da2015-09-10 19:21:45805
kalman6f984ae2015-09-18 17:21:58806 // Disable the extension. Opening the page should fail.
807 extension_service()->DisableExtension(extension_id,
Minh X. Nguyen45479012017-08-18 21:35:36808 disable_reason::DISABLE_USER_ACTION);
rdevlin.croninf5863da2015-09-10 19:21:45809 base::RunLoop().RunUntilIdle();
rdevlin.croninf5863da2015-09-10 19:21:45810
kalman6f984ae2015-09-18 17:21:58811 EXPECT_EQ(content::PAGE_TYPE_ERROR,
812 NavigateAndGetPageType(get_resource_url("index.html")));
813 EXPECT_EQ(content::PAGE_TYPE_ERROR,
814 NavigateAndGetPageType(get_resource_url("other.html")));
815
816 // Re-enable the extension. Opening pages should immediately start to succeed
817 // again.
rdevlin.croninf5863da2015-09-10 19:21:45818 extension_service()->EnableExtension(extension_id);
819 base::RunLoop().RunUntilIdle();
820
kalman6f984ae2015-09-18 17:21:58821 EXPECT_EQ("Caught a fetch for /index.html",
822 NavigateAndExtractInnerText(get_resource_url("index.html")));
823 EXPECT_EQ("Caught a fetch for /other.html",
824 NavigateAndExtractInnerText(get_resource_url("other.html")));
825 EXPECT_EQ("Caught a fetch for /another.html",
826 NavigateAndExtractInnerText(get_resource_url("another.html")));
rdevlin.croninf5863da2015-09-10 19:21:45827
kalman6f984ae2015-09-18 17:21:58828 // Uninstall the extension. Opening pages should fail again.
829 base::string16 error;
830 extension_service()->UninstallExtension(
Devlin Cronin218df7f2017-11-21 21:41:31831 extension_id, UninstallReason::UNINSTALL_REASON_FOR_TESTING, &error);
kalman6f984ae2015-09-18 17:21:58832 base::RunLoop().RunUntilIdle();
833
834 EXPECT_EQ(content::PAGE_TYPE_ERROR,
835 NavigateAndGetPageType(get_resource_url("index.html")));
836 EXPECT_EQ(content::PAGE_TYPE_ERROR,
837 NavigateAndGetPageType(get_resource_url("other.html")));
838 EXPECT_EQ(content::PAGE_TYPE_ERROR,
839 NavigateAndGetPageType(get_resource_url("anotherother.html")));
840 EXPECT_EQ(content::PAGE_TYPE_ERROR,
841 NavigateAndGetPageType(get_resource_url("final.html")));
842}
843
Istiaque Ahmedea5ed5042017-09-25 19:00:16844IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, BackgroundPageIsWokenIfAsleep) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22845 const Extension* extension = StartTestFromBackgroundPage("wake_on_fetch.js");
kalman6f984ae2015-09-18 17:21:58846
847 // Navigate to special URLs that this test's service worker recognises, each
848 // making a check then populating the response with either "true" or "false".
849 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
850 "background-client-is-awake")));
851 EXPECT_EQ("true", NavigateAndExtractInnerText(
852 extension->GetResourceURL("ping-background-client")));
853 // Ping more than once for good measure.
854 EXPECT_EQ("true", NavigateAndExtractInnerText(
855 extension->GetResourceURL("ping-background-client")));
856
857 // Shut down the event page. The SW should detect that it's closed, but still
858 // be able to ping it.
859 ExtensionHost* background_page =
860 process_manager()->GetBackgroundHostForExtension(extension->id());
861 ASSERT_TRUE(background_page);
862 background_page->Close();
863 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
864
865 EXPECT_EQ("false", NavigateAndExtractInnerText(extension->GetResourceURL(
866 "background-client-is-awake")));
867 EXPECT_EQ("true", NavigateAndExtractInnerText(
868 extension->GetResourceURL("ping-background-client")));
869 EXPECT_EQ("true", NavigateAndExtractInnerText(
870 extension->GetResourceURL("ping-background-client")));
871 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
872 "background-client-is-awake")));
873}
874
Istiaque Ahmedea5ed5042017-09-25 19:00:16875IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58876 GetBackgroundClientFailsWithNoBackgroundPage) {
877 // This extension doesn't have a background page, only a tab at page.html.
878 // The service worker it registers tries to call getBackgroundClient() and
879 // should fail.
880 // Note that this also tests that service workers can be registered from tabs.
881 EXPECT_TRUE(RunExtensionSubtest("service_worker/no_background", "page.html"));
rdevlin.croninf5863da2015-09-10 19:21:45882}
883
Istiaque Ahmedea5ed5042017-09-25 19:00:16884IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, NotificationAPI) {
lazyboy6ddb7d62015-11-10 23:15:27885 EXPECT_TRUE(RunExtensionSubtest("service_worker/notifications/has_permission",
886 "page.html"));
887}
888
Istiaque Ahmedea5ed5042017-09-25 19:00:16889IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WebAccessibleResourcesFetch) {
lazyboyaea32c22016-01-04 21:37:07890 EXPECT_TRUE(RunExtensionSubtest(
891 "service_worker/web_accessible_resources/fetch/", "page.html"));
892}
893
Istiaque Ahmed75ad1d92018-08-30 05:16:54894IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, TabsCreate) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:16895 if (IsMacViewsMode())
896 return;
lazyboyee4adef2016-05-24 00:55:16897 // Extensions APIs from SW are only enabled on trunk.
898 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
899 const Extension* extension = LoadExtensionWithFlags(
900 test_data_dir_.AppendASCII("service_worker/tabs_create"), kFlagNone);
901 ASSERT_TRUE(extension);
902 ui_test_utils::NavigateToURL(browser(),
903 extension->GetResourceURL("page.html"));
904 content::WebContents* web_contents =
905 browser()->tab_strip_model()->GetActiveWebContents();
906
907 int starting_tab_count = browser()->tab_strip_model()->count();
908 std::string result;
909 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
910 web_contents, "window.runServiceWorker()", &result));
911 ASSERT_EQ("chrome.tabs.create callback", result);
912 EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count());
913
914 // Check extension shutdown path.
915 UnloadExtension(extension->id());
916 EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count());
917}
918
Istiaque Ahmedea5ed5042017-09-25 19:00:16919IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, Events) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:16920 if (IsMacViewsMode())
921 return;
lazyboye7847242017-06-07 23:29:18922 // Extensions APIs from SW are only enabled on trunk.
923 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
924 const Extension* extension = LoadExtensionWithFlags(
925 test_data_dir_.AppendASCII("service_worker/events"), kFlagNone);
926 ASSERT_TRUE(extension);
927 ui_test_utils::NavigateToURL(browser(),
928 extension->GetResourceURL("page.html"));
929 content::WebContents* web_contents =
930 browser()->tab_strip_model()->GetActiveWebContents();
931 std::string result;
932 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
933 web_contents, "window.runEventTest()", &result));
934 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
935}
936
Istiaque Ahmedea5ed5042017-09-25 19:00:16937IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, EventsToStoppedWorker) {
lazyboy63b994a2017-06-30 21:20:23938 // Extensions APIs from SW are only enabled on trunk.
939 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
940 const Extension* extension = LoadExtensionWithFlags(
941 test_data_dir_.AppendASCII("service_worker/events_to_stopped_worker"),
942 kFlagNone);
943 ASSERT_TRUE(extension);
944 ui_test_utils::NavigateToURL(browser(),
945 extension->GetResourceURL("page.html"));
946 content::WebContents* web_contents =
947 browser()->tab_strip_model()->GetActiveWebContents();
948 {
949 std::string result;
950 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
951 web_contents, "window.runServiceWorker()", &result));
952 ASSERT_EQ("ready", result);
953
954 base::RunLoop run_loop;
955 content::StoragePartition* storage_partition =
956 content::BrowserContext::GetDefaultStoragePartition(
957 browser()->profile());
958 content::StopServiceWorkerForPattern(
959 storage_partition->GetServiceWorkerContext(),
960 // The service worker is registered at the top level scope.
961 extension->url(), run_loop.QuitClosure());
962 run_loop.Run();
963 }
964
965 std::string result;
966 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
967 web_contents, "window.createTabThenUpdate()", &result));
968 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
969}
970
Istiaque Ahmed805f6a83b2017-10-05 01:23:26971// Tests that events to service worker arrives correctly event if the owner
972// extension of the worker is not running.
973IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmedb8e24bdb2018-09-13 15:17:25974 EventsToStoppedExtension) {
Istiaque Ahmed805f6a83b2017-10-05 01:23:26975 LazyBackgroundObserver lazy_observer;
976 ResultCatcher catcher;
977 const Extension* extension = LoadExtensionWithFlags(
978 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
979 kFlagNone);
980 ASSERT_TRUE(extension);
981 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
982
983 ProcessManager* pm = ProcessManager::Get(browser()->profile());
984 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:30985 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed805f6a83b2017-10-05 01:23:26986
987 // |extension|'s background page opens a tab to its resource.
988 content::WebContents* extension_web_contents =
989 browser()->tab_strip_model()->GetActiveWebContents();
990 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
991 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
992 extension_web_contents->GetURL().spec());
993 {
994 // Let the service worker start and register a listener to
995 // chrome.tabs.onCreated event.
996 ExtensionTestMessageListener add_listener_done("listener-added", false);
997 content::ExecuteScriptAsync(extension_web_contents,
998 "window.runServiceWorkerAsync()");
999 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1000
1001 base::RunLoop run_loop;
1002 content::StoragePartition* storage_partition =
1003 content::BrowserContext::GetDefaultStoragePartition(
1004 browser()->profile());
1005 content::StopServiceWorkerForPattern(
1006 storage_partition->GetServiceWorkerContext(),
1007 // The service worker is registered at the top level scope.
1008 extension->url(), run_loop.QuitClosure());
1009 run_loop.Run();
1010 }
1011
1012 // Close the tab to |extension|'s resource. This will also close the
1013 // extension's event page.
1014 browser()->tab_strip_model()->CloseWebContentsAt(
1015 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1016 lazy_observer.Wait();
1017
1018 // At this point both the extension worker and extension event page is not
1019 // running. Since the worker registered a listener for tabs.onCreated, it
1020 // will be started to dispatch the event once we create a tab.
1021 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1022 newtab_listener.set_failure_message("WRONG_NEWTAB");
1023 content::WebContents* new_web_contents =
Istiaque Ahmed7105f2a2017-10-07 01:11:591024 AddTab(browser(), GURL(url::kAboutBlankURL));
1025 EXPECT_TRUE(new_web_contents);
1026 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1027}
1028
1029// Tests that events to service worker correctly after browser restart.
1030// This test is similar to EventsToStoppedExtension, except that the event
1031// delivery is verified after a browser restart.
1032IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
1033 PRE_EventsAfterRestart) {
1034 LazyBackgroundObserver lazy_observer;
1035 ResultCatcher catcher;
1036 const Extension* extension = LoadExtensionWithFlags(
1037 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
1038 kFlagNone);
1039 ASSERT_TRUE(extension);
1040 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1041
1042 ProcessManager* pm = ProcessManager::Get(browser()->profile());
1043 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:301044 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed7105f2a2017-10-07 01:11:591045
1046 // |extension|'s background page opens a tab to its resource.
1047 content::WebContents* extension_web_contents =
1048 browser()->tab_strip_model()->GetActiveWebContents();
1049 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1050 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1051 extension_web_contents->GetURL().spec());
1052 {
1053 // Let the service worker start and register a listener to
1054 // chrome.tabs.onCreated event.
1055 ExtensionTestMessageListener add_listener_done("listener-added", false);
1056 content::ExecuteScriptAsync(extension_web_contents,
1057 "window.runServiceWorkerAsync()");
1058 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1059
1060 base::RunLoop run_loop;
1061 content::StoragePartition* storage_partition =
1062 content::BrowserContext::GetDefaultStoragePartition(
1063 browser()->profile());
1064 content::StopServiceWorkerForPattern(
1065 storage_partition->GetServiceWorkerContext(),
1066 // The service worker is registered at the top level scope.
1067 extension->url(), run_loop.QuitClosure());
1068 run_loop.Run();
1069 }
1070
1071 // Close the tab to |extension|'s resource. This will also close the
1072 // extension's event page.
1073 browser()->tab_strip_model()->CloseWebContentsAt(
1074 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1075 lazy_observer.Wait();
1076}
1077
Istiaque Ahmed99aa96d2018-09-13 23:22:081078IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest, EventsAfterRestart) {
Istiaque Ahmed7105f2a2017-10-07 01:11:591079 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1080 content::WebContents* new_web_contents =
1081 AddTab(browser(), GURL(url::kAboutBlankURL));
Istiaque Ahmed805f6a83b2017-10-05 01:23:261082 EXPECT_TRUE(new_web_contents);
1083 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1084}
1085
lazyboy4c82177a2016-10-18 00:04:091086// Tests that worker ref count increments while extension API function is
1087// active.
Istiaque Ahmedea5ed5042017-09-25 19:00:161088IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WorkerRefCount) {
lazyboy4c82177a2016-10-18 00:04:091089 // Extensions APIs from SW are only enabled on trunk.
1090 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1091 const Extension* extension = LoadExtensionWithFlags(
1092 test_data_dir_.AppendASCII("service_worker/api_worker_ref_count"),
1093 kFlagNone);
1094 ASSERT_TRUE(extension);
1095 ui_test_utils::NavigateToURL(browser(),
1096 extension->GetResourceURL("page.html"));
1097 content::WebContents* web_contents =
1098 browser()->tab_strip_model()->GetActiveWebContents();
1099
1100 ExtensionTestMessageListener worker_start_listener("WORKER STARTED", false);
1101 worker_start_listener.set_failure_message("FAILURE");
1102 ASSERT_TRUE(
1103 content::ExecuteScript(web_contents, "window.runServiceWorker()"));
1104 ASSERT_TRUE(worker_start_listener.WaitUntilSatisfied());
1105
1106 // Service worker should have no pending requests because it hasn't peformed
1107 // any extension API request yet.
1108 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1109
1110 ExtensionTestMessageListener worker_listener("CHECK_REF_COUNT", true);
1111 worker_listener.set_failure_message("FAILURE");
1112 ASSERT_TRUE(content::ExecuteScript(web_contents, "window.testSendMessage()"));
1113 ASSERT_TRUE(worker_listener.WaitUntilSatisfied());
1114
1115 // Service worker should have exactly one pending request because
1116 // chrome.test.sendMessage() API call is in-flight.
1117 EXPECT_EQ(1u, GetWorkerRefCount(extension->url()));
1118
1119 // Peform another extension API request while one is ongoing.
1120 {
1121 ExtensionTestMessageListener listener("CHECK_REF_COUNT", true);
1122 listener.set_failure_message("FAILURE");
1123 ASSERT_TRUE(
1124 content::ExecuteScript(web_contents, "window.testSendMessage()"));
1125 ASSERT_TRUE(listener.WaitUntilSatisfied());
1126
1127 // Service worker currently has two extension API requests in-flight.
1128 EXPECT_EQ(2u, GetWorkerRefCount(extension->url()));
1129 // Finish executing the nested chrome.test.sendMessage() first.
1130 listener.Reply("Hello world");
1131 }
1132
Istiaque Ahmedb57c9752017-08-20 19:08:571133 ExtensionTestMessageListener worker_completion_listener("SUCCESS_FROM_WORKER",
1134 false);
lazyboy4c82177a2016-10-18 00:04:091135 // Finish executing chrome.test.sendMessage().
1136 worker_listener.Reply("Hello world");
Istiaque Ahmedb57c9752017-08-20 19:08:571137 EXPECT_TRUE(worker_completion_listener.WaitUntilSatisfied());
1138
1139 // The following block makes sure we have received all the IPCs related to
1140 // ref-count from the worker.
1141 {
1142 // The following roundtrip:
1143 // browser->extension->worker->extension->browser
1144 // will ensure that the worker sent the relevant ref count IPCs.
1145 std::string result;
1146 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1147 web_contents, "window.roundtripToWorker();", &result));
1148 EXPECT_EQ("roundtrip-succeeded", result);
1149
1150 // Ensure IO thread IPCs run.
Gabriel Charette01507a22017-09-27 21:30:081151 content::RunAllTasksUntilIdle();
Istiaque Ahmedb57c9752017-08-20 19:08:571152 }
lazyboy4c82177a2016-10-18 00:04:091153
1154 // The ref count should drop to 0.
1155 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1156}
1157
lazyboyaea32c22016-01-04 21:37:071158// This test loads a web page that has an iframe pointing to a
1159// chrome-extension:// URL. The URL is listed in the extension's
1160// web_accessible_resources. Initially the iframe is served from the extension's
1161// resource file. After verifying that, we register a Service Worker that
1162// controls the extension. Further requests to the same resource as before
1163// should now be served by the Service Worker.
1164// This test also verifies that if the requested resource exists in the manifest
1165// but is not present in the extension directory, the Service Worker can still
1166// serve the resource file.
Istiaque Ahmedea5ed5042017-09-25 19:00:161167IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WebAccessibleResourcesIframeSrc) {
lazyboyaea32c22016-01-04 21:37:071168 const Extension* extension = LoadExtensionWithFlags(
1169 test_data_dir_.AppendASCII(
1170 "service_worker/web_accessible_resources/iframe_src"),
1171 kFlagNone);
1172 ASSERT_TRUE(extension);
1173 ASSERT_TRUE(StartEmbeddedTestServer());
falkenad185092016-06-16 06:10:021174
1175 // Service workers can only control secure contexts
1176 // (https://w3c.github.io/webappsec-secure-contexts/). For documents, this
1177 // typically means the document must have a secure origin AND all its ancestor
1178 // frames must have documents with secure origins. However, extension pages
1179 // are considered secure, even if they have an ancestor document that is an
1180 // insecure context (see GetSchemesBypassingSecureContextCheckWhitelist). So
1181 // extension service workers must be able to control an extension page
1182 // embedded in an insecure context. To test this, set up an insecure
1183 // (non-localhost, non-https) URL for the web page. This page will create
1184 // iframes that load extension pages that must be controllable by service
1185 // worker.
falkenad185092016-06-16 06:10:021186 GURL page_url =
1187 embedded_test_server()->GetURL("a.com",
1188 "/extensions/api_test/service_worker/"
1189 "web_accessible_resources/webpage.html");
1190 EXPECT_FALSE(content::IsOriginSecure(page_url));
lazyboyaea32c22016-01-04 21:37:071191
1192 content::WebContents* web_contents = AddTab(browser(), page_url);
1193 std::string result;
1194 // webpage.html will create an iframe pointing to a resource from |extension|.
1195 // Expect the resource to be served by the extension.
1196 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1197 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1198 extension->id().c_str()),
1199 &result));
1200 EXPECT_EQ("FROM_EXTENSION_RESOURCE", result);
1201
1202 ExtensionTestMessageListener service_worker_ready_listener("SW_READY", false);
1203 EXPECT_TRUE(ExecuteScriptInBackgroundPageNoWait(
1204 extension->id(), "window.registerServiceWorker()"));
1205 EXPECT_TRUE(service_worker_ready_listener.WaitUntilSatisfied());
1206
1207 result.clear();
1208 // webpage.html will create another iframe pointing to a resource from
1209 // |extension| as before. But this time, the resource should be be served
1210 // from the Service Worker.
1211 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1212 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1213 extension->id().c_str()),
1214 &result));
1215 EXPECT_EQ("FROM_SW_RESOURCE", result);
1216
1217 result.clear();
1218 // webpage.html will create yet another iframe pointing to a resource that
1219 // exists in the extension manifest's web_accessible_resources, but is not
1220 // present in the extension directory. Expect the resources of the iframe to
1221 // be served by the Service Worker.
1222 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1223 web_contents,
1224 base::StringPrintf("window.testIframe('%s', 'iframe_non_existent.html')",
1225 extension->id().c_str()),
1226 &result));
1227 EXPECT_EQ("FROM_SW_RESOURCE", result);
1228}
1229
Istiaque Ahmedea5ed5042017-09-25 19:00:161230IN_PROC_BROWSER_TEST_P(ServiceWorkerBackgroundSyncTest, Sync) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:161231 if (IsMacViewsMode())
1232 return;
lazyboybd325ae2015-11-18 21:35:261233 const Extension* extension = LoadExtensionWithFlags(
1234 test_data_dir_.AppendASCII("service_worker/sync"), kFlagNone);
1235 ASSERT_TRUE(extension);
1236 ui_test_utils::NavigateToURL(browser(),
1237 extension->GetResourceURL("page.html"));
1238 content::WebContents* web_contents =
1239 browser()->tab_strip_model()->GetActiveWebContents();
1240
1241 // Prevent firing by going offline.
1242 content::background_sync_test_util::SetOnline(web_contents, false);
1243
1244 ExtensionTestMessageListener sync_listener("SYNC: send-chats", false);
1245 sync_listener.set_failure_message("FAIL");
1246
1247 std::string result;
1248 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1249 web_contents, "window.runServiceWorker()", &result));
1250 ASSERT_EQ("SERVICE_WORKER_READY", result);
1251
1252 EXPECT_FALSE(sync_listener.was_satisfied());
1253 // Resume firing by going online.
1254 content::background_sync_test_util::SetOnline(web_contents, true);
1255 EXPECT_TRUE(sync_listener.WaitUntilSatisfied());
1256}
1257
Istiaque Ahmedea5ed5042017-09-25 19:00:161258IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
horo1eeddde2015-11-19 05:59:251259 FetchFromContentScriptShouldNotGoToServiceWorkerOfPage) {
1260 ASSERT_TRUE(StartEmbeddedTestServer());
1261 GURL page_url = embedded_test_server()->GetURL(
1262 "/extensions/api_test/service_worker/content_script_fetch/"
1263 "controlled_page/index.html");
1264 content::WebContents* tab =
1265 browser()->tab_strip_model()->GetActiveWebContents();
1266 ui_test_utils::NavigateToURL(browser(), page_url);
1267 content::WaitForLoadStop(tab);
1268
1269 std::string value;
1270 ASSERT_TRUE(
1271 content::ExecuteScriptAndExtractString(tab, "register();", &value));
1272 EXPECT_EQ("SW controlled", value);
1273
1274 ASSERT_TRUE(RunExtensionTest("service_worker/content_script_fetch"))
1275 << message_;
1276}
1277
Istiaque Ahmedea5ed5042017-09-25 19:00:161278IN_PROC_BROWSER_TEST_P(ServiceWorkerPushMessagingTest, OnPush) {
lazyboy561b7de2015-11-19 19:27:301279 const Extension* extension = LoadExtensionWithFlags(
1280 test_data_dir_.AppendASCII("service_worker/push_messaging"), kFlagNone);
1281 ASSERT_TRUE(extension);
1282 GURL extension_url = extension->url();
1283
Peter Beverloodd4ef1e2018-06-21 15:41:041284 GrantNotificationPermissionForTest(extension_url);
lazyboy561b7de2015-11-19 19:27:301285
1286 GURL url = extension->GetResourceURL("page.html");
1287 ui_test_utils::NavigateToURL(browser(), url);
1288
1289 content::WebContents* web_contents =
1290 browser()->tab_strip_model()->GetActiveWebContents();
1291
1292 // Start the ServiceWorker.
1293 ExtensionTestMessageListener ready_listener("SERVICE_WORKER_READY", false);
1294 ready_listener.set_failure_message("SERVICE_WORKER_FAILURE");
1295 const char* kScript = "window.runServiceWorker()";
1296 EXPECT_TRUE(content::ExecuteScript(web_contents->GetMainFrame(), kScript));
1297 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1298
1299 PushMessagingAppIdentifier app_identifier =
1300 GetAppIdentifierForServiceWorkerRegistration(0LL, extension_url);
johnmea5045732016-09-08 17:23:291301 ASSERT_EQ(app_identifier.app_id(), gcm_driver()->last_gettoken_app_id());
1302 EXPECT_EQ("1234567890", gcm_driver()->last_gettoken_authorized_entity());
lazyboy561b7de2015-11-19 19:27:301303
lazyboyd429e2582016-05-20 20:18:521304 base::RunLoop run_loop;
lazyboy561b7de2015-11-19 19:27:301305 // Send a push message via gcm and expect the ServiceWorker to receive it.
1306 ExtensionTestMessageListener push_message_listener("OK", false);
1307 push_message_listener.set_failure_message("FAIL");
1308 gcm::IncomingMessage message;
1309 message.sender_id = "1234567890";
1310 message.raw_data = "testdata";
1311 message.decrypted = true;
lazyboyd429e2582016-05-20 20:18:521312 push_service()->SetMessageCallbackForTesting(run_loop.QuitClosure());
lazyboy561b7de2015-11-19 19:27:301313 push_service()->OnMessage(app_identifier.app_id(), message);
1314 EXPECT_TRUE(push_message_listener.WaitUntilSatisfied());
lazyboyd429e2582016-05-20 20:18:521315 run_loop.Run(); // Wait until the message is handled by push service.
lazyboy561b7de2015-11-19 19:27:301316}
1317
Istiaque Ahmedea5ed5042017-09-25 19:00:161318IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, FilteredEvents) {
Istiaque Ahmed9d1666182017-09-21 23:58:181319 // Extensions APIs from SW are only enabled on trunk.
1320 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1321 ASSERT_TRUE(RunExtensionTest("service_worker/filtered_events"));
1322}
1323
Rob Wue89b90032018-02-16 19:46:081324IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, MimeHandlerView) {
1325 ASSERT_TRUE(RunExtensionTest("service_worker/mime_handler_view"));
1326}
1327
Istiaque Ahmed9ce21b32017-10-10 20:43:181328IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
1329 PRE_FilteredEventsAfterRestart) {
1330 LazyBackgroundObserver lazy_observer;
1331 ResultCatcher catcher;
1332 const Extension* extension = LoadExtensionWithFlags(
1333 test_data_dir_.AppendASCII(
1334 "service_worker/filtered_events_after_restart"),
1335 kFlagNone);
1336 ASSERT_TRUE(extension);
1337 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1338
1339 // |extension|'s background page opens a tab to its resource.
1340 content::WebContents* extension_web_contents =
1341 browser()->tab_strip_model()->GetActiveWebContents();
1342 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1343 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1344 extension_web_contents->GetURL().spec());
1345 {
1346 // Let the service worker start and register a filtered listener to
1347 // chrome.webNavigation.onCommitted event.
1348 ExtensionTestMessageListener add_listener_done("listener-added", false);
1349 add_listener_done.set_failure_message("FAILURE");
1350 content::ExecuteScriptAsync(extension_web_contents,
1351 "window.runServiceWorkerAsync()");
1352 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1353
1354 base::RunLoop run_loop;
1355 content::StoragePartition* storage_partition =
1356 content::BrowserContext::GetDefaultStoragePartition(
1357 browser()->profile());
1358 content::StopServiceWorkerForPattern(
1359 storage_partition->GetServiceWorkerContext(),
1360 // The service worker is registered at the top level scope.
1361 extension->url(), run_loop.QuitClosure());
1362 run_loop.Run();
1363 }
1364
1365 // Close the tab to |extension|'s resource. This will also close the
1366 // extension's event page.
1367 browser()->tab_strip_model()->CloseWebContentsAt(
1368 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1369 lazy_observer.Wait();
1370}
1371
Istiaque Ahmed9ce21b32017-10-10 20:43:181372IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmedf5712522018-09-20 03:35:471373 FilteredEventsAfterRestart) {
Istiaque Ahmed9ce21b32017-10-10 20:43:181374 // Create a tab to a.html, expect it to navigate to b.html. The service worker
1375 // will see two webNavigation.onCommitted events.
1376 ASSERT_TRUE(StartEmbeddedTestServer());
1377 GURL page_url = embedded_test_server()->GetURL(
1378 "/extensions/api_test/service_worker/filtered_events_after_restart/"
1379 "a.html");
1380 ExtensionTestMessageListener worker_filtered_event_listener(
1381 "PASS_FROM_WORKER", false);
1382 worker_filtered_event_listener.set_failure_message("FAIL_FROM_WORKER");
1383 content::WebContents* web_contents = AddTab(browser(), page_url);
1384 EXPECT_TRUE(web_contents);
1385 EXPECT_TRUE(worker_filtered_event_listener.WaitUntilSatisfied());
1386}
1387
Istiaque Ahmedea5ed5042017-09-25 19:00:161388// Run with both native and JS-based bindings. This ensures that both stable
1389// (JS) and experimental (native) phases work correctly with worker scripts
1390// while we launch native bindings to stable.
1391INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
1392 ServiceWorkerTest,
1393 ::testing::Values(NATIVE_BINDINGS));
1394INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
1395 ServiceWorkerTest,
1396 ::testing::Values(JAVASCRIPT_BINDINGS));
1397INSTANTIATE_TEST_CASE_P(ServiceWorkerBackgroundSyncTestWithNativeBindings,
1398 ServiceWorkerBackgroundSyncTest,
1399 ::testing::Values(NATIVE_BINDINGS));
1400INSTANTIATE_TEST_CASE_P(ServiceWorkerBackgroundSyncTestWithJSBindings,
1401 ServiceWorkerBackgroundSyncTest,
1402 ::testing::Values(JAVASCRIPT_BINDINGS));
1403INSTANTIATE_TEST_CASE_P(ServiceWorkerPushMessagingTestWithNativeBindings,
1404 ServiceWorkerPushMessagingTest,
1405 ::testing::Values(NATIVE_BINDINGS));
1406INSTANTIATE_TEST_CASE_P(ServiceWorkerPushMessagingTestWithJSBindings,
1407 ServiceWorkerPushMessagingTest,
1408 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmed805f6a83b2017-10-05 01:23:261409INSTANTIATE_TEST_CASE_P(ServiceWorkerLazyBackgroundTestWithNativeBindings,
1410 ServiceWorkerLazyBackgroundTest,
1411 ::testing::Values(NATIVE_BINDINGS));
1412INSTANTIATE_TEST_CASE_P(ServiceWorkerLazyBackgroundTestWithJSBindings,
1413 ServiceWorkerLazyBackgroundTest,
1414 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmedccb444022018-06-19 02:11:121415INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
1416 ServiceWorkerBasedBackgroundTest,
1417 ::testing::Values(NATIVE_BINDINGS));
1418INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
1419 ServiceWorkerBasedBackgroundTest,
1420 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmedea5ed5042017-09-25 19:00:161421
annekao38685502015-07-14 17:46:391422} // namespace extensions