blob: 7d778fb622e37bcb0508b80ea34592bc2c2a04c4 [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
65// Pass into ServiceWorkerTest::StartTestFromBackgroundPage to indicate that
66// registration is expected to succeed.
67std::string* const kExpectSuccess = nullptr;
68
lazyboy22eddc712015-12-10 21:16:2669// Returns the newly added WebContents.
70content::WebContents* AddTab(Browser* browser, const GURL& url) {
71 int starting_tab_count = browser->tab_strip_model()->count();
72 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:1973 browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
lazyboy22eddc712015-12-10 21:16:2674 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
75 int tab_count = browser->tab_strip_model()->count();
76 EXPECT_EQ(starting_tab_count + 1, tab_count);
77 return browser->tab_strip_model()->GetActiveWebContents();
78}
79
Istiaque Ahmedea5ed5042017-09-25 19:00:1680enum BindingsType { NATIVE_BINDINGS, JAVASCRIPT_BINDINGS };
81
lazyboy22eddc712015-12-10 21:16:2682class WebContentsLoadStopObserver : content::WebContentsObserver {
83 public:
84 explicit WebContentsLoadStopObserver(content::WebContents* web_contents)
85 : content::WebContentsObserver(web_contents),
86 load_stop_observed_(false) {}
87
88 void WaitForLoadStop() {
89 if (load_stop_observed_)
90 return;
91 message_loop_runner_ = new content::MessageLoopRunner;
92 message_loop_runner_->Run();
93 }
94
95 private:
96 void DidStopLoading() override {
97 load_stop_observed_ = true;
98 if (message_loop_runner_)
99 message_loop_runner_->Quit();
100 }
101
102 bool load_stop_observed_;
103 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
104
105 DISALLOW_COPY_AND_ASSIGN(WebContentsLoadStopObserver);
106};
107
Elly Fong-Jones4a4f21d2018-05-30 15:04:16108bool IsMacViewsMode() {
109// Some tests are flaky on Mac: <https://crbug.com/845979>. This helper function
110// is used to skip them.
111#if defined(OS_MACOSX)
112 return !views_mode_controller::IsViewsBrowserCocoa();
113#else
114 return false;
115#endif
116}
117
kalman6f984ae2015-09-18 17:21:58118} // namespace
119
Istiaque Ahmedea5ed5042017-09-25 19:00:16120class ServiceWorkerTest : public ExtensionApiTest,
121 public ::testing::WithParamInterface<BindingsType> {
annekao38685502015-07-14 17:46:39122 public:
lazyboy20167c22016-05-18 00:59:30123 ServiceWorkerTest() : current_channel_(version_info::Channel::STABLE) {}
Istiaque Ahmed7105f2a2017-10-07 01:11:59124 explicit ServiceWorkerTest(version_info::Channel channel)
125 : current_channel_(channel) {}
annekao38685502015-07-14 17:46:39126
127 ~ServiceWorkerTest() override {}
128
Devlin Cronina3fe3d602017-11-22 04:47:43129 void SetUp() override {
130 if (GetParam() == NATIVE_BINDINGS) {
131 scoped_feature_list_.InitAndEnableFeature(features::kNativeCrxBindings);
132 } else {
133 DCHECK_EQ(JAVASCRIPT_BINDINGS, GetParam());
134 scoped_feature_list_.InitAndDisableFeature(features::kNativeCrxBindings);
135 }
136 ExtensionApiTest::SetUp();
137 }
138
jam1a5b5582017-05-01 16:50:10139 void SetUpOnMainThread() override {
140 ExtensionApiTest::SetUpOnMainThread();
141 host_resolver()->AddRule("a.com", "127.0.0.1");
142 }
143
kalman6f984ae2015-09-18 17:21:58144 protected:
145 // Returns the ProcessManager for the test's profile.
146 ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
147
148 // Starts running a test from the background page test extension.
149 //
150 // This registers a service worker with |script_name|, and fetches the
151 // registration result.
152 //
153 // If |error_or_null| is null (kExpectSuccess), success is expected and this
154 // will fail if there is an error.
155 // If |error_or_null| is not null, nothing is assumed, and the error (which
156 // may be empty) is written to it.
157 const Extension* StartTestFromBackgroundPage(const char* script_name,
158 std::string* error_or_null) {
Istiaque Ahmed6475f542018-08-28 04:20:21159 ExtensionTestMessageListener ready_listener("ready", false);
kalman6f984ae2015-09-18 17:21:58160 const Extension* extension =
161 LoadExtension(test_data_dir_.AppendASCII("service_worker/background"));
162 CHECK(extension);
Istiaque Ahmed6475f542018-08-28 04:20:21163 CHECK(ready_listener.WaitUntilSatisfied());
164
kalman6f984ae2015-09-18 17:21:58165 ExtensionHost* background_host =
166 process_manager()->GetBackgroundHostForExtension(extension->id());
167 CHECK(background_host);
Istiaque Ahmed6475f542018-08-28 04:20:21168
kalman6f984ae2015-09-18 17:21:58169 std::string error;
170 CHECK(content::ExecuteScriptAndExtractString(
171 background_host->host_contents(),
172 base::StringPrintf("test.registerServiceWorker('%s')", script_name),
173 &error));
174 if (error_or_null)
175 *error_or_null = error;
176 else if (!error.empty())
177 ADD_FAILURE() << "Got unexpected error " << error;
178 return extension;
179 }
180
181 // Navigates the browser to a new tab at |url|, waits for it to load, then
182 // returns it.
183 content::WebContents* Navigate(const GURL& url) {
184 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19185 browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
kalman6f984ae2015-09-18 17:21:58186 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
187 content::WebContents* web_contents =
188 browser()->tab_strip_model()->GetActiveWebContents();
189 content::WaitForLoadStop(web_contents);
190 return web_contents;
191 }
192
193 // Navigates the browser to |url| and returns the new tab's page type.
194 content::PageType NavigateAndGetPageType(const GURL& url) {
clamy1d7a4112018-06-15 15:47:16195 return Navigate(url)
196 ->GetController()
197 .GetLastCommittedEntry()
198 ->GetPageType();
kalman6f984ae2015-09-18 17:21:58199 }
200
201 // Extracts the innerText from |contents|.
202 std::string ExtractInnerText(content::WebContents* contents) {
203 std::string inner_text;
204 if (!content::ExecuteScriptAndExtractString(
205 contents,
206 "window.domAutomationController.send(document.body.innerText)",
207 &inner_text)) {
208 ADD_FAILURE() << "Failed to get inner text for "
209 << contents->GetVisibleURL();
210 }
211 return inner_text;
212 }
213
214 // Navigates the browser to |url|, then returns the innerText of the new
215 // tab's WebContents' main frame.
216 std::string NavigateAndExtractInnerText(const GURL& url) {
217 return ExtractInnerText(Navigate(url));
218 }
219
lazyboy4c82177a2016-10-18 00:04:09220 size_t GetWorkerRefCount(const GURL& origin) {
221 content::ServiceWorkerContext* sw_context =
222 content::BrowserContext::GetDefaultStoragePartition(
223 browser()->profile())
224 ->GetServiceWorkerContext();
225 base::RunLoop run_loop;
226 size_t ref_count = 0;
227 auto set_ref_count = [](size_t* ref_count, base::RunLoop* run_loop,
228 size_t external_request_count) {
229 *ref_count = external_request_count;
230 run_loop->Quit();
231 };
232 sw_context->CountExternalRequestsForTest(
Matt Falkenhagenc5cb4282017-09-07 08:43:42233 origin, base::BindOnce(set_ref_count, &ref_count, &run_loop));
lazyboy4c82177a2016-10-18 00:04:09234 run_loop.Run();
235 return ref_count;
236 }
237
annekao38685502015-07-14 17:46:39238 private:
lazyboy20167c22016-05-18 00:59:30239 // Sets the channel to "stable".
240 // Not useful after we've opened extension Service Workers to stable
241 // channel.
242 // TODO(lazyboy): Remove this when ExtensionServiceWorkersEnabled() is
243 // removed.
annekao38685502015-07-14 17:46:39244 ScopedCurrentChannel current_channel_;
kalman6f984ae2015-09-18 17:21:58245
Devlin Cronina3fe3d602017-11-22 04:47:43246 base::test::ScopedFeatureList scoped_feature_list_;
247
annekao38685502015-07-14 17:46:39248 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTest);
249};
250
Istiaque Ahmedccb444022018-06-19 02:11:12251class ServiceWorkerBasedBackgroundTest : public ServiceWorkerTest {
252 public:
253 ServiceWorkerBasedBackgroundTest()
254 : ServiceWorkerTest(
255 // Extensions APIs from SW are only enabled on trunk.
256 // It is important to set the channel early so that this change is
257 // visible in renderers running with service workers (and no
258 // extension).
259 version_info::Channel::UNKNOWN) {}
260 ~ServiceWorkerBasedBackgroundTest() override {}
261
262 void SetUpOnMainThread() override {
263 host_resolver()->AddRule("*", "127.0.0.1");
264 ASSERT_TRUE(embedded_test_server()->Start());
265 ServiceWorkerTest::SetUpOnMainThread();
266 }
267
268 private:
269 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBasedBackgroundTest);
270};
271
272// Tests that Service Worker based background pages can be loaded and they can
273// receive extension events.
274// The extension is installed and loaded during this step and it registers
275// an event listener for tabs.onCreated event. The step also verifies that tab
276// creation correctly fires the listener.
277IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, PRE_Basic) {
278 ExtensionTestMessageListener newtab_listener("CREATED", false);
279 newtab_listener.set_failure_message("CREATE_FAILED");
280 ExtensionTestMessageListener worker_listener("WORKER_RUNNING", false);
281 worker_listener.set_failure_message("NON_WORKER_SCOPE");
282 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
283 "service_worker/worker_based_background/basic"));
284 ASSERT_TRUE(extension);
285 const ExtensionId extension_id = extension->id();
286 EXPECT_TRUE(worker_listener.WaitUntilSatisfied());
287
288 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
289 content::WebContents* new_web_contents = AddTab(browser(), url);
290 EXPECT_TRUE(new_web_contents);
291 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
292
293 // Service Worker extension does not have ExtensionHost.
294 EXPECT_FALSE(process_manager()->GetBackgroundHostForExtension(extension_id));
295}
296
Greg Thompsonb71a3172018-06-27 12:29:17297#if defined(OS_LINUX)
298// Disabled on Linux due to flakes; see https://crbug.com/855800.
299#define MAYBE_Basic DISABLED_Basic
300#else
301#define MAYBE_Basic Basic
302#endif
Istiaque Ahmedccb444022018-06-19 02:11:12303// After browser restarts, this test step ensures that opening a tab fires
304// tabs.onCreated event listener to the extension without explicitly loading the
305// extension. This is because the extension registered a listener before browser
306// restarted in PRE_Basic.
Greg Thompsonb71a3172018-06-27 12:29:17307IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, MAYBE_Basic) {
Istiaque Ahmedccb444022018-06-19 02:11:12308 ExtensionTestMessageListener newtab_listener("CREATED", false);
309 newtab_listener.set_failure_message("CREATE_FAILED");
310 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
311 content::WebContents* new_web_contents = AddTab(browser(), url);
312 EXPECT_TRUE(new_web_contents);
313 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
314}
315
Istiaque Ahmeda14ec482018-08-25 01:02:18316// Class that dispatches an event to |extension_id| right after a
317// non-lazy listener to the event is added from the extension's Service Worker.
Istiaque Ahmed771aa8a22018-06-20 23:40:53318class EarlyWorkerMessageSender : public EventRouter::Observer {
319 public:
320 EarlyWorkerMessageSender(content::BrowserContext* browser_context,
Istiaque Ahmeda14ec482018-08-25 01:02:18321 const ExtensionId& extension_id,
322 std::unique_ptr<Event> event)
Istiaque Ahmed771aa8a22018-06-20 23:40:53323 : browser_context_(browser_context),
324 event_router_(EventRouter::EventRouter::Get(browser_context_)),
325 extension_id_(extension_id),
Istiaque Ahmeda14ec482018-08-25 01:02:18326 event_(std::move(event)),
Istiaque Ahmed771aa8a22018-06-20 23:40:53327 listener_("PASS", false) {
328 DCHECK(browser_context_);
329 listener_.set_failure_message("FAIL");
Istiaque Ahmeda14ec482018-08-25 01:02:18330 event_router_->RegisterObserver(this, event_->event_name);
Istiaque Ahmed771aa8a22018-06-20 23:40:53331 }
332
333 ~EarlyWorkerMessageSender() override {
334 event_router_->UnregisterObserver(this);
335 }
336
337 // EventRouter::Observer:
338 void OnListenerAdded(const EventListenerInfo& details) override {
Istiaque Ahmeda14ec482018-08-25 01:02:18339 if (!event_ || extension_id_ != details.extension_id ||
340 event_->event_name != details.event_name) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53341 return;
Istiaque Ahmeda14ec482018-08-25 01:02:18342 }
343
Istiaque Ahmed771aa8a22018-06-20 23:40:53344 const bool is_lazy_listener = details.browser_context == nullptr;
345 if (is_lazy_listener) {
346 // Wait for the non-lazy listener as we want to exercise the code to
347 // dispatch the event right after the Service Worker registration is
348 // completing.
349 return;
350 }
Istiaque Ahmeda14ec482018-08-25 01:02:18351 DispatchEvent(std::move(event_));
Istiaque Ahmed771aa8a22018-06-20 23:40:53352 }
353
354 bool SendAndWait() { return listener_.WaitUntilSatisfied(); }
355
356 private:
357 static constexpr const char* const kTestOnMessageEventName = "test.onMessage";
358
Istiaque Ahmeda14ec482018-08-25 01:02:18359 void DispatchEvent(std::unique_ptr<Event> event) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53360 EventRouter::Get(browser_context_)
361 ->DispatchEventToExtension(extension_id_, std::move(event));
362 }
363
364 content::BrowserContext* const browser_context_ = nullptr;
365 EventRouter* const event_router_ = nullptr;
366 const ExtensionId extension_id_;
Istiaque Ahmeda14ec482018-08-25 01:02:18367 std::unique_ptr<Event> event_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53368 ExtensionTestMessageListener listener_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53369
370 DISALLOW_COPY_AND_ASSIGN(EarlyWorkerMessageSender);
371};
372
373// Tests that extension event dispatch works correctly right after extension
374// installation registers its Service Worker.
375// Regression test for: https://crbug.com/850792.
376IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, EarlyEventDispatch) {
377 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
Istiaque Ahmeda14ec482018-08-25 01:02:18378
379 // Build "test.onMessage" event for dispatch.
380 auto event = std::make_unique<Event>(
381 events::FOR_TEST, extensions::api::test::OnMessage::kEventName,
382 base::ListValue::From(base::JSONReader::Read(
383 R"([{"data": "hello", "lastMessage": true}])")),
384 profile());
385
386 EarlyWorkerMessageSender sender(profile(), kId, std::move(event));
Istiaque Ahmed771aa8a22018-06-20 23:40:53387 // pkplfbidichfdicaijlchgnapepdginl
388 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
389 "service_worker/worker_based_background/early_event_dispatch"));
390 CHECK(extension);
391 EXPECT_EQ(kId, extension->id());
392 EXPECT_TRUE(sender.SendAndWait());
393}
394
Istiaque Ahmeda14ec482018-08-25 01:02:18395// Tests that filtered events dispatches correctly right after a non-lazy
396// listener is registered for that event (and before the corresponding lazy
397// listener is registered).
398IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest,
399 EarlyFilteredEventDispatch) {
400 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
401
402 // Add minimal details required to dispatch webNavigation.onCommitted event:
403 extensions::api::web_navigation::OnCommitted::Details details;
404 details.transition_type =
405 extensions::api::web_navigation::TRANSITION_TYPE_TYPED;
406
407 // Build a dummy onCommited event to dispatch.
408 auto on_committed_event = std::make_unique<Event>(
409 events::WEB_NAVIGATION_ON_COMMITTED, "webNavigation.onCommitted",
410 api::web_navigation::OnCommitted::Create(details), profile());
411 // The filter will match the listener filter registered from the extension.
412 EventFilteringInfo info;
413 info.url = GURL("http://foo.com/a.html");
414 on_committed_event->filter_info = info;
415
416 EarlyWorkerMessageSender sender(profile(), kId,
417 std::move(on_committed_event));
418
419 // pkplfbidichfdicaijlchgnapepdginl
420 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
421 "service_worker/worker_based_background/early_filtered_event_dispatch"));
422 ASSERT_TRUE(extension);
423 EXPECT_EQ(kId, extension->id());
424 EXPECT_TRUE(sender.SendAndWait());
425}
426
lazyboybd325ae2015-11-18 21:35:26427class ServiceWorkerBackgroundSyncTest : public ServiceWorkerTest {
428 public:
429 ServiceWorkerBackgroundSyncTest() {}
430 ~ServiceWorkerBackgroundSyncTest() override {}
431
432 void SetUpCommandLine(base::CommandLine* command_line) override {
433 // ServiceWorkerRegistration.sync requires experimental flag.
434 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16435 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboybd325ae2015-11-18 21:35:26436 ServiceWorkerTest::SetUpCommandLine(command_line);
437 }
438
439 void SetUp() override {
440 content::background_sync_test_util::SetIgnoreNetworkChangeNotifier(true);
441 ServiceWorkerTest::SetUp();
442 }
443
444 private:
445 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBackgroundSyncTest);
446};
447
lazyboy561b7de2015-11-19 19:27:30448class ServiceWorkerPushMessagingTest : public ServiceWorkerTest {
449 public:
450 ServiceWorkerPushMessagingTest()
johnmea5045732016-09-08 17:23:29451 : gcm_driver_(nullptr), push_service_(nullptr) {}
lazyboy561b7de2015-11-19 19:27:30452 ~ServiceWorkerPushMessagingTest() override {}
453
454 void GrantNotificationPermissionForTest(const GURL& url) {
Peter Beverloodd4ef1e2018-06-21 15:41:04455 NotificationPermissionContext::UpdatePermission(profile(), url.GetOrigin(),
456 CONTENT_SETTING_ALLOW);
lazyboy561b7de2015-11-19 19:27:30457 }
458
459 PushMessagingAppIdentifier GetAppIdentifierForServiceWorkerRegistration(
avia2f4804a2015-12-24 23:11:13460 int64_t service_worker_registration_id,
lazyboy561b7de2015-11-19 19:27:30461 const GURL& origin) {
462 PushMessagingAppIdentifier app_identifier =
463 PushMessagingAppIdentifier::FindByServiceWorker(
464 profile(), origin, service_worker_registration_id);
465
466 EXPECT_FALSE(app_identifier.is_null());
467 return app_identifier;
468 }
469
470 // ExtensionApiTest overrides.
471 void SetUpCommandLine(base::CommandLine* command_line) override {
peter9de96272015-12-04 15:23:27472 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16473 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboy561b7de2015-11-19 19:27:30474 ServiceWorkerTest::SetUpCommandLine(command_line);
475 }
476 void SetUpOnMainThread() override {
miguelg9b502862017-04-24 18:13:53477 NotificationDisplayServiceFactory::GetInstance()->SetTestingFactory(
478 profile(), &StubNotificationDisplayService::FactoryForTests);
479
johnmea5045732016-09-08 17:23:29480 gcm::FakeGCMProfileService* gcm_service =
481 static_cast<gcm::FakeGCMProfileService*>(
482 gcm::GCMProfileServiceFactory::GetInstance()
483 ->SetTestingFactoryAndUse(profile(),
484 &gcm::FakeGCMProfileService::Build));
485 gcm_driver_ = static_cast<instance_id::FakeGCMDriverForInstanceID*>(
486 gcm_service->driver());
lazyboy561b7de2015-11-19 19:27:30487 push_service_ = PushMessagingServiceFactory::GetForProfile(profile());
488
489 ServiceWorkerTest::SetUpOnMainThread();
490 }
491
johnmea5045732016-09-08 17:23:29492 instance_id::FakeGCMDriverForInstanceID* gcm_driver() const {
493 return gcm_driver_;
494 }
lazyboy561b7de2015-11-19 19:27:30495 PushMessagingServiceImpl* push_service() const { return push_service_; }
496
497 private:
johnmea5045732016-09-08 17:23:29498 instance_id::FakeGCMDriverForInstanceID* gcm_driver_;
lazyboy561b7de2015-11-19 19:27:30499 PushMessagingServiceImpl* push_service_;
500
501 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPushMessagingTest);
502};
503
Istiaque Ahmed805f6a83b2017-10-05 01:23:26504class ServiceWorkerLazyBackgroundTest : public ServiceWorkerTest {
505 public:
Istiaque Ahmed7105f2a2017-10-07 01:11:59506 ServiceWorkerLazyBackgroundTest()
507 : ServiceWorkerTest(
508 // Extensions APIs from SW are only enabled on trunk.
509 // It is important to set the channel early so that this change is
510 // visible in renderers running with service workers (and no
511 // extension).
512 version_info::Channel::UNKNOWN) {}
Istiaque Ahmed805f6a83b2017-10-05 01:23:26513 ~ServiceWorkerLazyBackgroundTest() override {}
514
515 void SetUpCommandLine(base::CommandLine* command_line) override {
516 ServiceWorkerTest::SetUpCommandLine(command_line);
517 // Disable background network activity as it can suddenly bring the Lazy
518 // Background Page alive.
519 command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
520 command_line->AppendSwitch(::switches::kNoProxyServer);
521 }
522
523 void SetUpInProcessBrowserTestFixture() override {
524 ServiceWorkerTest::SetUpInProcessBrowserTestFixture();
525 // Set shorter delays to prevent test timeouts.
526 ProcessManager::SetEventPageIdleTimeForTesting(1);
527 ProcessManager::SetEventPageSuspendingTimeForTesting(1);
528 }
529
530 private:
531 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerLazyBackgroundTest);
532};
533
Istiaque Ahmedea5ed5042017-09-25 19:00:16534IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, RegisterSucceeds) {
kalman6f984ae2015-09-18 17:21:58535 StartTestFromBackgroundPage("register.js", kExpectSuccess);
annekao38685502015-07-14 17:46:39536}
537
Istiaque Ahmedea5ed5042017-09-25 19:00:16538IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, UpdateRefreshesServiceWorker) {
Francois Doraye6fb2d02017-10-18 21:29:13539 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboyc3e763a2015-12-09 23:09:58540 base::ScopedTempDir scoped_temp_dir;
541 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
542 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
543 .AppendASCII("update")
544 .AppendASCII("service_worker.pem");
vabr9142fe22016-09-08 13:19:22545 base::FilePath path_v1 =
546 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
547 .AppendASCII("update")
548 .AppendASCII("v1"),
549 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
550 pem_path, base::FilePath());
551 base::FilePath path_v2 =
552 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
553 .AppendASCII("update")
554 .AppendASCII("v2"),
555 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
556 pem_path, base::FilePath());
lazyboyc3e763a2015-12-09 23:09:58557 const char* kId = "hfaanndiiilofhfokeanhddpkfffchdi";
558
559 ExtensionTestMessageListener listener_v1("Pong from version 1", false);
560 listener_v1.set_failure_message("FAILURE_V1");
561 // Install version 1.0 of the extension.
562 ASSERT_TRUE(InstallExtension(path_v1, 1));
563 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
564 ->enabled_extensions()
565 .GetByID(kId));
566 EXPECT_TRUE(listener_v1.WaitUntilSatisfied());
567
568 ExtensionTestMessageListener listener_v2("Pong from version 2", false);
569 listener_v2.set_failure_message("FAILURE_V2");
570
571 // Update to version 2.0.
572 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
573 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
574 ->enabled_extensions()
575 .GetByID(kId));
576 EXPECT_TRUE(listener_v2.WaitUntilSatisfied());
577}
578
[email protected]2ef85d562017-09-15 18:41:52579// TODO(crbug.com/765736) Fix the test.
Istiaque Ahmedea5ed5042017-09-25 19:00:16580IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, DISABLED_UpdateWithoutSkipWaiting) {
Francois Doraye6fb2d02017-10-18 21:29:13581 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboy22eddc712015-12-10 21:16:26582 base::ScopedTempDir scoped_temp_dir;
583 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
584 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
585 .AppendASCII("update_without_skip_waiting")
586 .AppendASCII("update_without_skip_waiting.pem");
vabr9142fe22016-09-08 13:19:22587 base::FilePath path_v1 =
588 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
589 .AppendASCII("update_without_skip_waiting")
590 .AppendASCII("v1"),
591 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
592 pem_path, base::FilePath());
593 base::FilePath path_v2 =
594 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
595 .AppendASCII("update_without_skip_waiting")
596 .AppendASCII("v2"),
597 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
598 pem_path, base::FilePath());
lazyboy22eddc712015-12-10 21:16:26599 const char* kId = "mhnnnflgagdakldgjpfcofkiocpdmogl";
600
601 // Install version 1.0 of the extension.
602 ASSERT_TRUE(InstallExtension(path_v1, 1));
603 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
604 ->enabled_extensions()
605 .GetByID(kId));
606 const Extension* extension = extensions::ExtensionRegistry::Get(profile())
607 ->enabled_extensions()
608 .GetByID(kId);
609
610 ExtensionTestMessageListener listener1("Pong from version 1", false);
611 listener1.set_failure_message("FAILURE");
612 content::WebContents* web_contents =
613 AddTab(browser(), extension->GetResourceURL("page.html"));
614 EXPECT_TRUE(listener1.WaitUntilSatisfied());
615
616 // Update to version 2.0.
617 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
618 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
619 ->enabled_extensions()
620 .GetByID(kId));
621 const Extension* extension_after_update =
622 extensions::ExtensionRegistry::Get(profile())
623 ->enabled_extensions()
624 .GetByID(kId);
625
626 // Service worker version 2 would be installed but it won't be controlling
627 // the extension page yet.
628 ExtensionTestMessageListener listener2("Pong from version 1", false);
629 listener2.set_failure_message("FAILURE");
630 web_contents =
631 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
632 EXPECT_TRUE(listener2.WaitUntilSatisfied());
633
634 // Navigate the tab away from the extension page so that no clients are
635 // using the service worker.
636 // Note that just closing the tab with WebContentsDestroyedWatcher doesn't
637 // seem to be enough because it returns too early.
638 WebContentsLoadStopObserver navigate_away_observer(web_contents);
639 web_contents->GetController().LoadURL(
640 GURL(url::kAboutBlankURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED,
641 std::string());
642 navigate_away_observer.WaitForLoadStop();
643
644 // Now expect service worker version 2 to control the extension page.
645 ExtensionTestMessageListener listener3("Pong from version 2", false);
646 listener3.set_failure_message("FAILURE");
647 web_contents =
648 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
649 EXPECT_TRUE(listener3.WaitUntilSatisfied());
650}
651
Istiaque Ahmedea5ed5042017-09-25 19:00:16652IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, FetchArbitraryPaths) {
kalman6f984ae2015-09-18 17:21:58653 const Extension* extension =
654 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
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
Istiaque Ahmedea5ed5042017-09-25 19:00:16674IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, SWServedBackgroundPageReceivesEvent) {
lazyboy52c3bcf2016-01-08 00:11:29675 const Extension* extension =
676 StartTestFromBackgroundPage("replace_background.js", kExpectSuccess);
677 ExtensionHost* background_page =
678 process_manager()->GetBackgroundHostForExtension(extension->id());
679 ASSERT_TRUE(background_page);
680
681 // Close the background page and start it again so that the service worker
682 // will start controlling pages.
683 background_page->Close();
684 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
685 background_page = nullptr;
Peter Kasting341e1fb2018-02-24 00:03:01686 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
lazyboy52c3bcf2016-01-08 00:11:29687 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
688
689 // Since the SW is now controlling the extension, the SW serves the background
690 // script. page.html sends a message to the background script and we verify
691 // that the SW served background script correctly receives the message/event.
692 ExtensionTestMessageListener listener("onMessage/SW BG.", false);
693 listener.set_failure_message("onMessage/original BG.");
694 content::WebContents* web_contents =
695 AddTab(browser(), extension->GetResourceURL("page.html"));
696 ASSERT_TRUE(web_contents);
697 EXPECT_TRUE(listener.WaitUntilSatisfied());
698}
699
Matt Falkenhagena612fc02018-05-30 00:35:39700IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, SWServedBackgroundPage) {
kalman6f984ae2015-09-18 17:21:58701 const Extension* extension =
702 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
annekao49241182015-08-18 17:14:01703
kalman6f984ae2015-09-18 17:21:58704 std::string kExpectedInnerText = "background.html contents for testing.";
annekao49241182015-08-18 17:14:01705
kalman6f984ae2015-09-18 17:21:58706 // Sanity check that the background page has the expected content.
707 ExtensionHost* background_page =
708 process_manager()->GetBackgroundHostForExtension(extension->id());
709 ASSERT_TRUE(background_page);
710 EXPECT_EQ(kExpectedInnerText,
711 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01712
kalman6f984ae2015-09-18 17:21:58713 // Close the background page.
714 background_page->Close();
715 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
716 background_page = nullptr;
717
718 // Start it again.
Peter Kasting341e1fb2018-02-24 00:03:01719 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
kalman6f984ae2015-09-18 17:21:58720 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
721
Matt Falkenhagena612fc02018-05-30 00:35:39722 // The service worker should get a fetch event for the background page.
kalman6f984ae2015-09-18 17:21:58723 background_page =
724 process_manager()->GetBackgroundHostForExtension(extension->id());
725 ASSERT_TRUE(background_page);
726 content::WaitForLoadStop(background_page->host_contents());
727
kalman6f984ae2015-09-18 17:21:58728 EXPECT_EQ("Caught a fetch for /background.html",
729 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01730}
731
Istiaque Ahmedea5ed5042017-09-25 19:00:16732IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58733 ServiceWorkerPostsMessageToBackgroundClient) {
734 const Extension* extension = StartTestFromBackgroundPage(
735 "post_message_to_background_client.js", kExpectSuccess);
annekao533482222015-08-21 23:23:53736
kalman6f984ae2015-09-18 17:21:58737 // The service worker in this test simply posts a message to the background
738 // client it receives from getBackgroundClient().
739 const char* kScript =
740 "var messagePromise = null;\n"
741 "if (test.lastMessageFromServiceWorker) {\n"
742 " messagePromise = Promise.resolve(test.lastMessageFromServiceWorker);\n"
743 "} else {\n"
744 " messagePromise = test.waitForMessage(navigator.serviceWorker);\n"
745 "}\n"
746 "messagePromise.then(function(message) {\n"
747 " window.domAutomationController.send(String(message == 'success'));\n"
748 "})\n";
749 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53750}
751
Istiaque Ahmedea5ed5042017-09-25 19:00:16752IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58753 BackgroundPagePostsMessageToServiceWorker) {
754 const Extension* extension =
755 StartTestFromBackgroundPage("post_message_to_sw.js", kExpectSuccess);
annekao533482222015-08-21 23:23:53756
kalman6f984ae2015-09-18 17:21:58757 // The service worker in this test waits for a message, then echoes it back
758 // by posting a message to the background page via getBackgroundClient().
759 const char* kScript =
760 "var mc = new MessageChannel();\n"
761 "test.waitForMessage(mc.port1).then(function(message) {\n"
762 " window.domAutomationController.send(String(message == 'hello'));\n"
763 "});\n"
764 "test.registeredServiceWorker.postMessage(\n"
765 " {message: 'hello', port: mc.port2}, [mc.port2])\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,
rdevlin.croninf5863da2015-09-10 19:21:45770 ServiceWorkerSuspensionOnExtensionUnload) {
kalman6f984ae2015-09-18 17:21:58771 // For this test, only hold onto the extension's ID and URL + a function to
772 // get a resource URL, because we're going to be disabling and uninstalling
773 // it, which will invalidate the pointer.
774 std::string extension_id;
775 GURL extension_url;
776 {
777 const Extension* extension =
778 StartTestFromBackgroundPage("fetch.js", kExpectSuccess);
779 extension_id = extension->id();
780 extension_url = extension->url();
781 }
782 auto get_resource_url = [&extension_url](const std::string& path) {
783 return Extension::GetResourceURL(extension_url, path);
784 };
rdevlin.croninf5863da2015-09-10 19:21:45785
kalman6f984ae2015-09-18 17:21:58786 // Fetch should route to the service worker.
787 EXPECT_EQ("Caught a fetch for /index.html",
788 NavigateAndExtractInnerText(get_resource_url("index.html")));
rdevlin.croninf5863da2015-09-10 19:21:45789
kalman6f984ae2015-09-18 17:21:58790 // Disable the extension. Opening the page should fail.
791 extension_service()->DisableExtension(extension_id,
Minh X. Nguyen45479012017-08-18 21:35:36792 disable_reason::DISABLE_USER_ACTION);
rdevlin.croninf5863da2015-09-10 19:21:45793 base::RunLoop().RunUntilIdle();
rdevlin.croninf5863da2015-09-10 19:21:45794
kalman6f984ae2015-09-18 17:21:58795 EXPECT_EQ(content::PAGE_TYPE_ERROR,
796 NavigateAndGetPageType(get_resource_url("index.html")));
797 EXPECT_EQ(content::PAGE_TYPE_ERROR,
798 NavigateAndGetPageType(get_resource_url("other.html")));
799
800 // Re-enable the extension. Opening pages should immediately start to succeed
801 // again.
rdevlin.croninf5863da2015-09-10 19:21:45802 extension_service()->EnableExtension(extension_id);
803 base::RunLoop().RunUntilIdle();
804
kalman6f984ae2015-09-18 17:21:58805 EXPECT_EQ("Caught a fetch for /index.html",
806 NavigateAndExtractInnerText(get_resource_url("index.html")));
807 EXPECT_EQ("Caught a fetch for /other.html",
808 NavigateAndExtractInnerText(get_resource_url("other.html")));
809 EXPECT_EQ("Caught a fetch for /another.html",
810 NavigateAndExtractInnerText(get_resource_url("another.html")));
rdevlin.croninf5863da2015-09-10 19:21:45811
kalman6f984ae2015-09-18 17:21:58812 // Uninstall the extension. Opening pages should fail again.
813 base::string16 error;
814 extension_service()->UninstallExtension(
Devlin Cronin218df7f2017-11-21 21:41:31815 extension_id, UninstallReason::UNINSTALL_REASON_FOR_TESTING, &error);
kalman6f984ae2015-09-18 17:21:58816 base::RunLoop().RunUntilIdle();
817
818 EXPECT_EQ(content::PAGE_TYPE_ERROR,
819 NavigateAndGetPageType(get_resource_url("index.html")));
820 EXPECT_EQ(content::PAGE_TYPE_ERROR,
821 NavigateAndGetPageType(get_resource_url("other.html")));
822 EXPECT_EQ(content::PAGE_TYPE_ERROR,
823 NavigateAndGetPageType(get_resource_url("anotherother.html")));
824 EXPECT_EQ(content::PAGE_TYPE_ERROR,
825 NavigateAndGetPageType(get_resource_url("final.html")));
826}
827
Istiaque Ahmedea5ed5042017-09-25 19:00:16828IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, BackgroundPageIsWokenIfAsleep) {
kalman6f984ae2015-09-18 17:21:58829 const Extension* extension =
830 StartTestFromBackgroundPage("wake_on_fetch.js", kExpectSuccess);
831
832 // Navigate to special URLs that this test's service worker recognises, each
833 // making a check then populating the response with either "true" or "false".
834 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
835 "background-client-is-awake")));
836 EXPECT_EQ("true", NavigateAndExtractInnerText(
837 extension->GetResourceURL("ping-background-client")));
838 // Ping more than once for good measure.
839 EXPECT_EQ("true", NavigateAndExtractInnerText(
840 extension->GetResourceURL("ping-background-client")));
841
842 // Shut down the event page. The SW should detect that it's closed, but still
843 // be able to ping it.
844 ExtensionHost* background_page =
845 process_manager()->GetBackgroundHostForExtension(extension->id());
846 ASSERT_TRUE(background_page);
847 background_page->Close();
848 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
849
850 EXPECT_EQ("false", NavigateAndExtractInnerText(extension->GetResourceURL(
851 "background-client-is-awake")));
852 EXPECT_EQ("true", NavigateAndExtractInnerText(
853 extension->GetResourceURL("ping-background-client")));
854 EXPECT_EQ("true", NavigateAndExtractInnerText(
855 extension->GetResourceURL("ping-background-client")));
856 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
857 "background-client-is-awake")));
858}
859
Istiaque Ahmedea5ed5042017-09-25 19:00:16860IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58861 GetBackgroundClientFailsWithNoBackgroundPage) {
862 // This extension doesn't have a background page, only a tab at page.html.
863 // The service worker it registers tries to call getBackgroundClient() and
864 // should fail.
865 // Note that this also tests that service workers can be registered from tabs.
866 EXPECT_TRUE(RunExtensionSubtest("service_worker/no_background", "page.html"));
rdevlin.croninf5863da2015-09-10 19:21:45867}
868
Istiaque Ahmedea5ed5042017-09-25 19:00:16869IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, NotificationAPI) {
lazyboy6ddb7d62015-11-10 23:15:27870 EXPECT_TRUE(RunExtensionSubtest("service_worker/notifications/has_permission",
871 "page.html"));
872}
873
Istiaque Ahmedea5ed5042017-09-25 19:00:16874IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WebAccessibleResourcesFetch) {
lazyboyaea32c22016-01-04 21:37:07875 EXPECT_TRUE(RunExtensionSubtest(
876 "service_worker/web_accessible_resources/fetch/", "page.html"));
877}
878
Olga Sharonova3e13cd92018-02-08 16:43:56879// Flaky on Linux: http://crbug/810397.
880#if defined(OS_LINUX)
881#define MAYBE_TabsCreate DISABLED_TabsCreate
882#else
883#define MAYBE_TabsCreate TabsCreate
884#endif
885IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, MAYBE_TabsCreate) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:16886 if (IsMacViewsMode())
887 return;
lazyboyee4adef2016-05-24 00:55:16888 // Extensions APIs from SW are only enabled on trunk.
889 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
890 const Extension* extension = LoadExtensionWithFlags(
891 test_data_dir_.AppendASCII("service_worker/tabs_create"), kFlagNone);
892 ASSERT_TRUE(extension);
893 ui_test_utils::NavigateToURL(browser(),
894 extension->GetResourceURL("page.html"));
895 content::WebContents* web_contents =
896 browser()->tab_strip_model()->GetActiveWebContents();
897
898 int starting_tab_count = browser()->tab_strip_model()->count();
899 std::string result;
900 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
901 web_contents, "window.runServiceWorker()", &result));
902 ASSERT_EQ("chrome.tabs.create callback", result);
903 EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count());
904
905 // Check extension shutdown path.
906 UnloadExtension(extension->id());
907 EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count());
908}
909
Istiaque Ahmedea5ed5042017-09-25 19:00:16910IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, Events) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:16911 if (IsMacViewsMode())
912 return;
lazyboye7847242017-06-07 23:29:18913 // Extensions APIs from SW are only enabled on trunk.
914 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
915 const Extension* extension = LoadExtensionWithFlags(
916 test_data_dir_.AppendASCII("service_worker/events"), kFlagNone);
917 ASSERT_TRUE(extension);
918 ui_test_utils::NavigateToURL(browser(),
919 extension->GetResourceURL("page.html"));
920 content::WebContents* web_contents =
921 browser()->tab_strip_model()->GetActiveWebContents();
922 std::string result;
923 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
924 web_contents, "window.runEventTest()", &result));
925 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
926}
927
Istiaque Ahmedea5ed5042017-09-25 19:00:16928IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, EventsToStoppedWorker) {
lazyboy63b994a2017-06-30 21:20:23929 // Extensions APIs from SW are only enabled on trunk.
930 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
931 const Extension* extension = LoadExtensionWithFlags(
932 test_data_dir_.AppendASCII("service_worker/events_to_stopped_worker"),
933 kFlagNone);
934 ASSERT_TRUE(extension);
935 ui_test_utils::NavigateToURL(browser(),
936 extension->GetResourceURL("page.html"));
937 content::WebContents* web_contents =
938 browser()->tab_strip_model()->GetActiveWebContents();
939 {
940 std::string result;
941 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
942 web_contents, "window.runServiceWorker()", &result));
943 ASSERT_EQ("ready", result);
944
945 base::RunLoop run_loop;
946 content::StoragePartition* storage_partition =
947 content::BrowserContext::GetDefaultStoragePartition(
948 browser()->profile());
949 content::StopServiceWorkerForPattern(
950 storage_partition->GetServiceWorkerContext(),
951 // The service worker is registered at the top level scope.
952 extension->url(), run_loop.QuitClosure());
953 run_loop.Run();
954 }
955
956 std::string result;
957 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
958 web_contents, "window.createTabThenUpdate()", &result));
959 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
960}
961
Istiaque Ahmed805f6a83b2017-10-05 01:23:26962// Tests that events to service worker arrives correctly event if the owner
963// extension of the worker is not running.
964IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
Xida Chen1f18f462018-04-24 13:55:54965 DISABLED_EventsToStoppedExtension) {
Istiaque Ahmed805f6a83b2017-10-05 01:23:26966 LazyBackgroundObserver lazy_observer;
967 ResultCatcher catcher;
968 const Extension* extension = LoadExtensionWithFlags(
969 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
970 kFlagNone);
971 ASSERT_TRUE(extension);
972 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
973
974 ProcessManager* pm = ProcessManager::Get(browser()->profile());
975 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:30976 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed805f6a83b2017-10-05 01:23:26977
978 // |extension|'s background page opens a tab to its resource.
979 content::WebContents* extension_web_contents =
980 browser()->tab_strip_model()->GetActiveWebContents();
981 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
982 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
983 extension_web_contents->GetURL().spec());
984 {
985 // Let the service worker start and register a listener to
986 // chrome.tabs.onCreated event.
987 ExtensionTestMessageListener add_listener_done("listener-added", false);
988 content::ExecuteScriptAsync(extension_web_contents,
989 "window.runServiceWorkerAsync()");
990 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
991
992 base::RunLoop run_loop;
993 content::StoragePartition* storage_partition =
994 content::BrowserContext::GetDefaultStoragePartition(
995 browser()->profile());
996 content::StopServiceWorkerForPattern(
997 storage_partition->GetServiceWorkerContext(),
998 // The service worker is registered at the top level scope.
999 extension->url(), run_loop.QuitClosure());
1000 run_loop.Run();
1001 }
1002
1003 // Close the tab to |extension|'s resource. This will also close the
1004 // extension's event page.
1005 browser()->tab_strip_model()->CloseWebContentsAt(
1006 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1007 lazy_observer.Wait();
1008
1009 // At this point both the extension worker and extension event page is not
1010 // running. Since the worker registered a listener for tabs.onCreated, it
1011 // will be started to dispatch the event once we create a tab.
1012 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1013 newtab_listener.set_failure_message("WRONG_NEWTAB");
1014 content::WebContents* new_web_contents =
Istiaque Ahmed7105f2a2017-10-07 01:11:591015 AddTab(browser(), GURL(url::kAboutBlankURL));
1016 EXPECT_TRUE(new_web_contents);
1017 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1018}
1019
1020// Tests that events to service worker correctly after browser restart.
1021// This test is similar to EventsToStoppedExtension, except that the event
1022// delivery is verified after a browser restart.
1023IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
1024 PRE_EventsAfterRestart) {
1025 LazyBackgroundObserver lazy_observer;
1026 ResultCatcher catcher;
1027 const Extension* extension = LoadExtensionWithFlags(
1028 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
1029 kFlagNone);
1030 ASSERT_TRUE(extension);
1031 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1032
1033 ProcessManager* pm = ProcessManager::Get(browser()->profile());
1034 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:301035 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed7105f2a2017-10-07 01:11:591036
1037 // |extension|'s background page opens a tab to its resource.
1038 content::WebContents* extension_web_contents =
1039 browser()->tab_strip_model()->GetActiveWebContents();
1040 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1041 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1042 extension_web_contents->GetURL().spec());
1043 {
1044 // Let the service worker start and register a listener to
1045 // chrome.tabs.onCreated event.
1046 ExtensionTestMessageListener add_listener_done("listener-added", false);
1047 content::ExecuteScriptAsync(extension_web_contents,
1048 "window.runServiceWorkerAsync()");
1049 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1050
1051 base::RunLoop run_loop;
1052 content::StoragePartition* storage_partition =
1053 content::BrowserContext::GetDefaultStoragePartition(
1054 browser()->profile());
1055 content::StopServiceWorkerForPattern(
1056 storage_partition->GetServiceWorkerContext(),
1057 // The service worker is registered at the top level scope.
1058 extension->url(), run_loop.QuitClosure());
1059 run_loop.Run();
1060 }
1061
1062 // Close the tab to |extension|'s resource. This will also close the
1063 // extension's event page.
1064 browser()->tab_strip_model()->CloseWebContentsAt(
1065 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1066 lazy_observer.Wait();
1067}
1068
Han Leond717ddc2018-05-03 00:33:141069// Flaky: http://crbug/834200.
1070IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
1071 DISABLED_EventsAfterRestart) {
Istiaque Ahmed7105f2a2017-10-07 01:11:591072 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1073 content::WebContents* new_web_contents =
1074 AddTab(browser(), GURL(url::kAboutBlankURL));
Istiaque Ahmed805f6a83b2017-10-05 01:23:261075 EXPECT_TRUE(new_web_contents);
1076 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1077}
1078
lazyboy4c82177a2016-10-18 00:04:091079// Tests that worker ref count increments while extension API function is
1080// active.
Istiaque Ahmedea5ed5042017-09-25 19:00:161081IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WorkerRefCount) {
lazyboy4c82177a2016-10-18 00:04:091082 // Extensions APIs from SW are only enabled on trunk.
1083 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1084 const Extension* extension = LoadExtensionWithFlags(
1085 test_data_dir_.AppendASCII("service_worker/api_worker_ref_count"),
1086 kFlagNone);
1087 ASSERT_TRUE(extension);
1088 ui_test_utils::NavigateToURL(browser(),
1089 extension->GetResourceURL("page.html"));
1090 content::WebContents* web_contents =
1091 browser()->tab_strip_model()->GetActiveWebContents();
1092
1093 ExtensionTestMessageListener worker_start_listener("WORKER STARTED", false);
1094 worker_start_listener.set_failure_message("FAILURE");
1095 ASSERT_TRUE(
1096 content::ExecuteScript(web_contents, "window.runServiceWorker()"));
1097 ASSERT_TRUE(worker_start_listener.WaitUntilSatisfied());
1098
1099 // Service worker should have no pending requests because it hasn't peformed
1100 // any extension API request yet.
1101 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1102
1103 ExtensionTestMessageListener worker_listener("CHECK_REF_COUNT", true);
1104 worker_listener.set_failure_message("FAILURE");
1105 ASSERT_TRUE(content::ExecuteScript(web_contents, "window.testSendMessage()"));
1106 ASSERT_TRUE(worker_listener.WaitUntilSatisfied());
1107
1108 // Service worker should have exactly one pending request because
1109 // chrome.test.sendMessage() API call is in-flight.
1110 EXPECT_EQ(1u, GetWorkerRefCount(extension->url()));
1111
1112 // Peform another extension API request while one is ongoing.
1113 {
1114 ExtensionTestMessageListener listener("CHECK_REF_COUNT", true);
1115 listener.set_failure_message("FAILURE");
1116 ASSERT_TRUE(
1117 content::ExecuteScript(web_contents, "window.testSendMessage()"));
1118 ASSERT_TRUE(listener.WaitUntilSatisfied());
1119
1120 // Service worker currently has two extension API requests in-flight.
1121 EXPECT_EQ(2u, GetWorkerRefCount(extension->url()));
1122 // Finish executing the nested chrome.test.sendMessage() first.
1123 listener.Reply("Hello world");
1124 }
1125
Istiaque Ahmedb57c9752017-08-20 19:08:571126 ExtensionTestMessageListener worker_completion_listener("SUCCESS_FROM_WORKER",
1127 false);
lazyboy4c82177a2016-10-18 00:04:091128 // Finish executing chrome.test.sendMessage().
1129 worker_listener.Reply("Hello world");
Istiaque Ahmedb57c9752017-08-20 19:08:571130 EXPECT_TRUE(worker_completion_listener.WaitUntilSatisfied());
1131
1132 // The following block makes sure we have received all the IPCs related to
1133 // ref-count from the worker.
1134 {
1135 // The following roundtrip:
1136 // browser->extension->worker->extension->browser
1137 // will ensure that the worker sent the relevant ref count IPCs.
1138 std::string result;
1139 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1140 web_contents, "window.roundtripToWorker();", &result));
1141 EXPECT_EQ("roundtrip-succeeded", result);
1142
1143 // Ensure IO thread IPCs run.
Gabriel Charette01507a22017-09-27 21:30:081144 content::RunAllTasksUntilIdle();
Istiaque Ahmedb57c9752017-08-20 19:08:571145 }
lazyboy4c82177a2016-10-18 00:04:091146
1147 // The ref count should drop to 0.
1148 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1149}
1150
lazyboyaea32c22016-01-04 21:37:071151// This test loads a web page that has an iframe pointing to a
1152// chrome-extension:// URL. The URL is listed in the extension's
1153// web_accessible_resources. Initially the iframe is served from the extension's
1154// resource file. After verifying that, we register a Service Worker that
1155// controls the extension. Further requests to the same resource as before
1156// should now be served by the Service Worker.
1157// This test also verifies that if the requested resource exists in the manifest
1158// but is not present in the extension directory, the Service Worker can still
1159// serve the resource file.
Istiaque Ahmedea5ed5042017-09-25 19:00:161160IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WebAccessibleResourcesIframeSrc) {
lazyboyaea32c22016-01-04 21:37:071161 const Extension* extension = LoadExtensionWithFlags(
1162 test_data_dir_.AppendASCII(
1163 "service_worker/web_accessible_resources/iframe_src"),
1164 kFlagNone);
1165 ASSERT_TRUE(extension);
1166 ASSERT_TRUE(StartEmbeddedTestServer());
falkenad185092016-06-16 06:10:021167
1168 // Service workers can only control secure contexts
1169 // (https://w3c.github.io/webappsec-secure-contexts/). For documents, this
1170 // typically means the document must have a secure origin AND all its ancestor
1171 // frames must have documents with secure origins. However, extension pages
1172 // are considered secure, even if they have an ancestor document that is an
1173 // insecure context (see GetSchemesBypassingSecureContextCheckWhitelist). So
1174 // extension service workers must be able to control an extension page
1175 // embedded in an insecure context. To test this, set up an insecure
1176 // (non-localhost, non-https) URL for the web page. This page will create
1177 // iframes that load extension pages that must be controllable by service
1178 // worker.
falkenad185092016-06-16 06:10:021179 GURL page_url =
1180 embedded_test_server()->GetURL("a.com",
1181 "/extensions/api_test/service_worker/"
1182 "web_accessible_resources/webpage.html");
1183 EXPECT_FALSE(content::IsOriginSecure(page_url));
lazyboyaea32c22016-01-04 21:37:071184
1185 content::WebContents* web_contents = AddTab(browser(), page_url);
1186 std::string result;
1187 // webpage.html will create an iframe pointing to a resource from |extension|.
1188 // Expect the resource to be served by the extension.
1189 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1190 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1191 extension->id().c_str()),
1192 &result));
1193 EXPECT_EQ("FROM_EXTENSION_RESOURCE", result);
1194
1195 ExtensionTestMessageListener service_worker_ready_listener("SW_READY", false);
1196 EXPECT_TRUE(ExecuteScriptInBackgroundPageNoWait(
1197 extension->id(), "window.registerServiceWorker()"));
1198 EXPECT_TRUE(service_worker_ready_listener.WaitUntilSatisfied());
1199
1200 result.clear();
1201 // webpage.html will create another iframe pointing to a resource from
1202 // |extension| as before. But this time, the resource should be be served
1203 // from the Service Worker.
1204 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1205 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1206 extension->id().c_str()),
1207 &result));
1208 EXPECT_EQ("FROM_SW_RESOURCE", result);
1209
1210 result.clear();
1211 // webpage.html will create yet another iframe pointing to a resource that
1212 // exists in the extension manifest's web_accessible_resources, but is not
1213 // present in the extension directory. Expect the resources of the iframe to
1214 // be served by the Service Worker.
1215 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1216 web_contents,
1217 base::StringPrintf("window.testIframe('%s', 'iframe_non_existent.html')",
1218 extension->id().c_str()),
1219 &result));
1220 EXPECT_EQ("FROM_SW_RESOURCE", result);
1221}
1222
Istiaque Ahmedea5ed5042017-09-25 19:00:161223IN_PROC_BROWSER_TEST_P(ServiceWorkerBackgroundSyncTest, Sync) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:161224 if (IsMacViewsMode())
1225 return;
lazyboybd325ae2015-11-18 21:35:261226 const Extension* extension = LoadExtensionWithFlags(
1227 test_data_dir_.AppendASCII("service_worker/sync"), kFlagNone);
1228 ASSERT_TRUE(extension);
1229 ui_test_utils::NavigateToURL(browser(),
1230 extension->GetResourceURL("page.html"));
1231 content::WebContents* web_contents =
1232 browser()->tab_strip_model()->GetActiveWebContents();
1233
1234 // Prevent firing by going offline.
1235 content::background_sync_test_util::SetOnline(web_contents, false);
1236
1237 ExtensionTestMessageListener sync_listener("SYNC: send-chats", false);
1238 sync_listener.set_failure_message("FAIL");
1239
1240 std::string result;
1241 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1242 web_contents, "window.runServiceWorker()", &result));
1243 ASSERT_EQ("SERVICE_WORKER_READY", result);
1244
1245 EXPECT_FALSE(sync_listener.was_satisfied());
1246 // Resume firing by going online.
1247 content::background_sync_test_util::SetOnline(web_contents, true);
1248 EXPECT_TRUE(sync_listener.WaitUntilSatisfied());
1249}
1250
Istiaque Ahmedea5ed5042017-09-25 19:00:161251IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
horo1eeddde2015-11-19 05:59:251252 FetchFromContentScriptShouldNotGoToServiceWorkerOfPage) {
1253 ASSERT_TRUE(StartEmbeddedTestServer());
1254 GURL page_url = embedded_test_server()->GetURL(
1255 "/extensions/api_test/service_worker/content_script_fetch/"
1256 "controlled_page/index.html");
1257 content::WebContents* tab =
1258 browser()->tab_strip_model()->GetActiveWebContents();
1259 ui_test_utils::NavigateToURL(browser(), page_url);
1260 content::WaitForLoadStop(tab);
1261
1262 std::string value;
1263 ASSERT_TRUE(
1264 content::ExecuteScriptAndExtractString(tab, "register();", &value));
1265 EXPECT_EQ("SW controlled", value);
1266
1267 ASSERT_TRUE(RunExtensionTest("service_worker/content_script_fetch"))
1268 << message_;
1269}
1270
Istiaque Ahmedea5ed5042017-09-25 19:00:161271IN_PROC_BROWSER_TEST_P(ServiceWorkerPushMessagingTest, OnPush) {
lazyboy561b7de2015-11-19 19:27:301272 const Extension* extension = LoadExtensionWithFlags(
1273 test_data_dir_.AppendASCII("service_worker/push_messaging"), kFlagNone);
1274 ASSERT_TRUE(extension);
1275 GURL extension_url = extension->url();
1276
Peter Beverloodd4ef1e2018-06-21 15:41:041277 GrantNotificationPermissionForTest(extension_url);
lazyboy561b7de2015-11-19 19:27:301278
1279 GURL url = extension->GetResourceURL("page.html");
1280 ui_test_utils::NavigateToURL(browser(), url);
1281
1282 content::WebContents* web_contents =
1283 browser()->tab_strip_model()->GetActiveWebContents();
1284
1285 // Start the ServiceWorker.
1286 ExtensionTestMessageListener ready_listener("SERVICE_WORKER_READY", false);
1287 ready_listener.set_failure_message("SERVICE_WORKER_FAILURE");
1288 const char* kScript = "window.runServiceWorker()";
1289 EXPECT_TRUE(content::ExecuteScript(web_contents->GetMainFrame(), kScript));
1290 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1291
1292 PushMessagingAppIdentifier app_identifier =
1293 GetAppIdentifierForServiceWorkerRegistration(0LL, extension_url);
johnmea5045732016-09-08 17:23:291294 ASSERT_EQ(app_identifier.app_id(), gcm_driver()->last_gettoken_app_id());
1295 EXPECT_EQ("1234567890", gcm_driver()->last_gettoken_authorized_entity());
lazyboy561b7de2015-11-19 19:27:301296
lazyboyd429e2582016-05-20 20:18:521297 base::RunLoop run_loop;
lazyboy561b7de2015-11-19 19:27:301298 // Send a push message via gcm and expect the ServiceWorker to receive it.
1299 ExtensionTestMessageListener push_message_listener("OK", false);
1300 push_message_listener.set_failure_message("FAIL");
1301 gcm::IncomingMessage message;
1302 message.sender_id = "1234567890";
1303 message.raw_data = "testdata";
1304 message.decrypted = true;
lazyboyd429e2582016-05-20 20:18:521305 push_service()->SetMessageCallbackForTesting(run_loop.QuitClosure());
lazyboy561b7de2015-11-19 19:27:301306 push_service()->OnMessage(app_identifier.app_id(), message);
1307 EXPECT_TRUE(push_message_listener.WaitUntilSatisfied());
lazyboyd429e2582016-05-20 20:18:521308 run_loop.Run(); // Wait until the message is handled by push service.
lazyboy561b7de2015-11-19 19:27:301309}
1310
Istiaque Ahmedea5ed5042017-09-25 19:00:161311IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, FilteredEvents) {
Istiaque Ahmed9d1666182017-09-21 23:58:181312 // Extensions APIs from SW are only enabled on trunk.
1313 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1314 ASSERT_TRUE(RunExtensionTest("service_worker/filtered_events"));
1315}
1316
Rob Wue89b90032018-02-16 19:46:081317IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, MimeHandlerView) {
1318 ASSERT_TRUE(RunExtensionTest("service_worker/mime_handler_view"));
1319}
1320
Istiaque Ahmed9ce21b32017-10-10 20:43:181321IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
1322 PRE_FilteredEventsAfterRestart) {
1323 LazyBackgroundObserver lazy_observer;
1324 ResultCatcher catcher;
1325 const Extension* extension = LoadExtensionWithFlags(
1326 test_data_dir_.AppendASCII(
1327 "service_worker/filtered_events_after_restart"),
1328 kFlagNone);
1329 ASSERT_TRUE(extension);
1330 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1331
1332 // |extension|'s background page opens a tab to its resource.
1333 content::WebContents* extension_web_contents =
1334 browser()->tab_strip_model()->GetActiveWebContents();
1335 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1336 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1337 extension_web_contents->GetURL().spec());
1338 {
1339 // Let the service worker start and register a filtered listener to
1340 // chrome.webNavigation.onCommitted event.
1341 ExtensionTestMessageListener add_listener_done("listener-added", false);
1342 add_listener_done.set_failure_message("FAILURE");
1343 content::ExecuteScriptAsync(extension_web_contents,
1344 "window.runServiceWorkerAsync()");
1345 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1346
1347 base::RunLoop run_loop;
1348 content::StoragePartition* storage_partition =
1349 content::BrowserContext::GetDefaultStoragePartition(
1350 browser()->profile());
1351 content::StopServiceWorkerForPattern(
1352 storage_partition->GetServiceWorkerContext(),
1353 // The service worker is registered at the top level scope.
1354 extension->url(), run_loop.QuitClosure());
1355 run_loop.Run();
1356 }
1357
1358 // Close the tab to |extension|'s resource. This will also close the
1359 // extension's event page.
1360 browser()->tab_strip_model()->CloseWebContentsAt(
1361 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1362 lazy_observer.Wait();
1363}
1364
Trent Apted1d8b22d2018-05-28 03:12:381365// Flaky. See https://crbug.com/844821.
Istiaque Ahmed9ce21b32017-10-10 20:43:181366IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
Trent Apted1d8b22d2018-05-28 03:12:381367 DISABLED_FilteredEventsAfterRestart) {
Istiaque Ahmed9ce21b32017-10-10 20:43:181368 // Create a tab to a.html, expect it to navigate to b.html. The service worker
1369 // will see two webNavigation.onCommitted events.
1370 ASSERT_TRUE(StartEmbeddedTestServer());
1371 GURL page_url = embedded_test_server()->GetURL(
1372 "/extensions/api_test/service_worker/filtered_events_after_restart/"
1373 "a.html");
1374 ExtensionTestMessageListener worker_filtered_event_listener(
1375 "PASS_FROM_WORKER", false);
1376 worker_filtered_event_listener.set_failure_message("FAIL_FROM_WORKER");
1377 content::WebContents* web_contents = AddTab(browser(), page_url);
1378 EXPECT_TRUE(web_contents);
1379 EXPECT_TRUE(worker_filtered_event_listener.WaitUntilSatisfied());
1380}
1381
Istiaque Ahmedea5ed5042017-09-25 19:00:161382// Run with both native and JS-based bindings. This ensures that both stable
1383// (JS) and experimental (native) phases work correctly with worker scripts
1384// while we launch native bindings to stable.
1385INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
1386 ServiceWorkerTest,
1387 ::testing::Values(NATIVE_BINDINGS));
1388INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
1389 ServiceWorkerTest,
1390 ::testing::Values(JAVASCRIPT_BINDINGS));
1391INSTANTIATE_TEST_CASE_P(ServiceWorkerBackgroundSyncTestWithNativeBindings,
1392 ServiceWorkerBackgroundSyncTest,
1393 ::testing::Values(NATIVE_BINDINGS));
1394INSTANTIATE_TEST_CASE_P(ServiceWorkerBackgroundSyncTestWithJSBindings,
1395 ServiceWorkerBackgroundSyncTest,
1396 ::testing::Values(JAVASCRIPT_BINDINGS));
1397INSTANTIATE_TEST_CASE_P(ServiceWorkerPushMessagingTestWithNativeBindings,
1398 ServiceWorkerPushMessagingTest,
1399 ::testing::Values(NATIVE_BINDINGS));
1400INSTANTIATE_TEST_CASE_P(ServiceWorkerPushMessagingTestWithJSBindings,
1401 ServiceWorkerPushMessagingTest,
1402 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmed805f6a83b2017-10-05 01:23:261403INSTANTIATE_TEST_CASE_P(ServiceWorkerLazyBackgroundTestWithNativeBindings,
1404 ServiceWorkerLazyBackgroundTest,
1405 ::testing::Values(NATIVE_BINDINGS));
1406INSTANTIATE_TEST_CASE_P(ServiceWorkerLazyBackgroundTestWithJSBindings,
1407 ServiceWorkerLazyBackgroundTest,
1408 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmedccb444022018-06-19 02:11:121409INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
1410 ServiceWorkerBasedBackgroundTest,
1411 ::testing::Values(NATIVE_BINDINGS));
1412INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
1413 ServiceWorkerBasedBackgroundTest,
1414 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmedea5ed5042017-09-25 19:00:161415
annekao38685502015-07-14 17:46:391416} // namespace extensions