blob: b993b603cc416d0a4b28f20b6bb6c92430796026 [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) {
127 scoped_feature_list_.InitAndEnableFeature(features::kNativeCrxBindings);
128 } else {
129 DCHECK_EQ(JAVASCRIPT_BINDINGS, GetParam());
130 scoped_feature_list_.InitAndDisableFeature(features::kNativeCrxBindings);
131 }
132 ExtensionApiTest::SetUp();
133 }
134
jam1a5b5582017-05-01 16:50:10135 void SetUpOnMainThread() override {
136 ExtensionApiTest::SetUpOnMainThread();
137 host_resolver()->AddRule("a.com", "127.0.0.1");
138 }
139
kalman6f984ae2015-09-18 17:21:58140 protected:
141 // Returns the ProcessManager for the test's profile.
142 ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
143
144 // Starts running a test from the background page test extension.
145 //
146 // This registers a service worker with |script_name|, and fetches the
147 // registration result.
Istiaque Ahmed93ff7f42018-08-31 01:42:22148 const Extension* StartTestFromBackgroundPage(const char* script_name) {
Istiaque Ahmed6475f542018-08-28 04:20:21149 ExtensionTestMessageListener ready_listener("ready", false);
kalman6f984ae2015-09-18 17:21:58150 const Extension* extension =
151 LoadExtension(test_data_dir_.AppendASCII("service_worker/background"));
152 CHECK(extension);
Istiaque Ahmed6475f542018-08-28 04:20:21153 CHECK(ready_listener.WaitUntilSatisfied());
154
kalman6f984ae2015-09-18 17:21:58155 ExtensionHost* background_host =
156 process_manager()->GetBackgroundHostForExtension(extension->id());
157 CHECK(background_host);
Istiaque Ahmed6475f542018-08-28 04:20:21158
kalman6f984ae2015-09-18 17:21:58159 std::string error;
160 CHECK(content::ExecuteScriptAndExtractString(
161 background_host->host_contents(),
162 base::StringPrintf("test.registerServiceWorker('%s')", script_name),
163 &error));
Istiaque Ahmed93ff7f42018-08-31 01:42:22164 if (!error.empty())
kalman6f984ae2015-09-18 17:21:58165 ADD_FAILURE() << "Got unexpected error " << error;
166 return extension;
167 }
168
169 // Navigates the browser to a new tab at |url|, waits for it to load, then
170 // returns it.
171 content::WebContents* Navigate(const GURL& url) {
172 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19173 browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
kalman6f984ae2015-09-18 17:21:58174 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
175 content::WebContents* web_contents =
176 browser()->tab_strip_model()->GetActiveWebContents();
177 content::WaitForLoadStop(web_contents);
178 return web_contents;
179 }
180
181 // Navigates the browser to |url| and returns the new tab's page type.
182 content::PageType NavigateAndGetPageType(const GURL& url) {
clamy1d7a4112018-06-15 15:47:16183 return Navigate(url)
184 ->GetController()
185 .GetLastCommittedEntry()
186 ->GetPageType();
kalman6f984ae2015-09-18 17:21:58187 }
188
189 // Extracts the innerText from |contents|.
190 std::string ExtractInnerText(content::WebContents* contents) {
191 std::string inner_text;
192 if (!content::ExecuteScriptAndExtractString(
193 contents,
194 "window.domAutomationController.send(document.body.innerText)",
195 &inner_text)) {
196 ADD_FAILURE() << "Failed to get inner text for "
197 << contents->GetVisibleURL();
198 }
199 return inner_text;
200 }
201
202 // Navigates the browser to |url|, then returns the innerText of the new
203 // tab's WebContents' main frame.
204 std::string NavigateAndExtractInnerText(const GURL& url) {
205 return ExtractInnerText(Navigate(url));
206 }
207
lazyboy4c82177a2016-10-18 00:04:09208 size_t GetWorkerRefCount(const GURL& origin) {
209 content::ServiceWorkerContext* sw_context =
210 content::BrowserContext::GetDefaultStoragePartition(
211 browser()->profile())
212 ->GetServiceWorkerContext();
213 base::RunLoop run_loop;
214 size_t ref_count = 0;
215 auto set_ref_count = [](size_t* ref_count, base::RunLoop* run_loop,
216 size_t external_request_count) {
217 *ref_count = external_request_count;
218 run_loop->Quit();
219 };
220 sw_context->CountExternalRequestsForTest(
Matt Falkenhagenc5cb4282017-09-07 08:43:42221 origin, base::BindOnce(set_ref_count, &ref_count, &run_loop));
lazyboy4c82177a2016-10-18 00:04:09222 run_loop.Run();
223 return ref_count;
224 }
225
annekao38685502015-07-14 17:46:39226 private:
lazyboy20167c22016-05-18 00:59:30227 // Sets the channel to "stable".
228 // Not useful after we've opened extension Service Workers to stable
229 // channel.
230 // TODO(lazyboy): Remove this when ExtensionServiceWorkersEnabled() is
231 // removed.
annekao38685502015-07-14 17:46:39232 ScopedCurrentChannel current_channel_;
kalman6f984ae2015-09-18 17:21:58233
Devlin Cronina3fe3d602017-11-22 04:47:43234 base::test::ScopedFeatureList scoped_feature_list_;
235
annekao38685502015-07-14 17:46:39236 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTest);
237};
238
Istiaque Ahmedccb444022018-06-19 02:11:12239class ServiceWorkerBasedBackgroundTest : public ServiceWorkerTest {
240 public:
241 ServiceWorkerBasedBackgroundTest()
242 : ServiceWorkerTest(
243 // Extensions APIs from SW are only enabled on trunk.
244 // It is important to set the channel early so that this change is
245 // visible in renderers running with service workers (and no
246 // extension).
247 version_info::Channel::UNKNOWN) {}
248 ~ServiceWorkerBasedBackgroundTest() override {}
249
250 void SetUpOnMainThread() override {
251 host_resolver()->AddRule("*", "127.0.0.1");
252 ASSERT_TRUE(embedded_test_server()->Start());
253 ServiceWorkerTest::SetUpOnMainThread();
254 }
255
256 private:
257 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBasedBackgroundTest);
258};
259
260// Tests that Service Worker based background pages can be loaded and they can
261// receive extension events.
262// The extension is installed and loaded during this step and it registers
263// an event listener for tabs.onCreated event. The step also verifies that tab
264// creation correctly fires the listener.
265IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, PRE_Basic) {
266 ExtensionTestMessageListener newtab_listener("CREATED", false);
267 newtab_listener.set_failure_message("CREATE_FAILED");
268 ExtensionTestMessageListener worker_listener("WORKER_RUNNING", false);
269 worker_listener.set_failure_message("NON_WORKER_SCOPE");
270 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
271 "service_worker/worker_based_background/basic"));
272 ASSERT_TRUE(extension);
273 const ExtensionId extension_id = extension->id();
274 EXPECT_TRUE(worker_listener.WaitUntilSatisfied());
275
276 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
277 content::WebContents* new_web_contents = AddTab(browser(), url);
278 EXPECT_TRUE(new_web_contents);
279 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
280
281 // Service Worker extension does not have ExtensionHost.
282 EXPECT_FALSE(process_manager()->GetBackgroundHostForExtension(extension_id));
283}
284
Greg Thompsonb71a3172018-06-27 12:29:17285#if defined(OS_LINUX)
286// Disabled on Linux due to flakes; see https://crbug.com/855800.
287#define MAYBE_Basic DISABLED_Basic
288#else
289#define MAYBE_Basic Basic
290#endif
Istiaque Ahmedccb444022018-06-19 02:11:12291// After browser restarts, this test step ensures that opening a tab fires
292// tabs.onCreated event listener to the extension without explicitly loading the
293// extension. This is because the extension registered a listener before browser
294// restarted in PRE_Basic.
Greg Thompsonb71a3172018-06-27 12:29:17295IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, MAYBE_Basic) {
Istiaque Ahmedccb444022018-06-19 02:11:12296 ExtensionTestMessageListener newtab_listener("CREATED", false);
297 newtab_listener.set_failure_message("CREATE_FAILED");
298 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
299 content::WebContents* new_web_contents = AddTab(browser(), url);
300 EXPECT_TRUE(new_web_contents);
301 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
302}
303
Istiaque Ahmeda14ec482018-08-25 01:02:18304// Class that dispatches an event to |extension_id| right after a
305// non-lazy listener to the event is added from the extension's Service Worker.
Istiaque Ahmed771aa8a22018-06-20 23:40:53306class EarlyWorkerMessageSender : public EventRouter::Observer {
307 public:
308 EarlyWorkerMessageSender(content::BrowserContext* browser_context,
Istiaque Ahmeda14ec482018-08-25 01:02:18309 const ExtensionId& extension_id,
310 std::unique_ptr<Event> event)
Istiaque Ahmed771aa8a22018-06-20 23:40:53311 : browser_context_(browser_context),
312 event_router_(EventRouter::EventRouter::Get(browser_context_)),
313 extension_id_(extension_id),
Istiaque Ahmeda14ec482018-08-25 01:02:18314 event_(std::move(event)),
Istiaque Ahmed771aa8a22018-06-20 23:40:53315 listener_("PASS", false) {
316 DCHECK(browser_context_);
317 listener_.set_failure_message("FAIL");
Istiaque Ahmeda14ec482018-08-25 01:02:18318 event_router_->RegisterObserver(this, event_->event_name);
Istiaque Ahmed771aa8a22018-06-20 23:40:53319 }
320
321 ~EarlyWorkerMessageSender() override {
322 event_router_->UnregisterObserver(this);
323 }
324
325 // EventRouter::Observer:
326 void OnListenerAdded(const EventListenerInfo& details) override {
Istiaque Ahmeda14ec482018-08-25 01:02:18327 if (!event_ || extension_id_ != details.extension_id ||
328 event_->event_name != details.event_name) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53329 return;
Istiaque Ahmeda14ec482018-08-25 01:02:18330 }
331
Istiaque Ahmed771aa8a22018-06-20 23:40:53332 const bool is_lazy_listener = details.browser_context == nullptr;
333 if (is_lazy_listener) {
334 // Wait for the non-lazy listener as we want to exercise the code to
335 // dispatch the event right after the Service Worker registration is
336 // completing.
337 return;
338 }
Istiaque Ahmeda14ec482018-08-25 01:02:18339 DispatchEvent(std::move(event_));
Istiaque Ahmed771aa8a22018-06-20 23:40:53340 }
341
342 bool SendAndWait() { return listener_.WaitUntilSatisfied(); }
343
344 private:
345 static constexpr const char* const kTestOnMessageEventName = "test.onMessage";
346
Istiaque Ahmeda14ec482018-08-25 01:02:18347 void DispatchEvent(std::unique_ptr<Event> event) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53348 EventRouter::Get(browser_context_)
349 ->DispatchEventToExtension(extension_id_, std::move(event));
350 }
351
352 content::BrowserContext* const browser_context_ = nullptr;
353 EventRouter* const event_router_ = nullptr;
354 const ExtensionId extension_id_;
Istiaque Ahmeda14ec482018-08-25 01:02:18355 std::unique_ptr<Event> event_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53356 ExtensionTestMessageListener listener_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53357
358 DISALLOW_COPY_AND_ASSIGN(EarlyWorkerMessageSender);
359};
360
361// Tests that extension event dispatch works correctly right after extension
362// installation registers its Service Worker.
363// Regression test for: https://crbug.com/850792.
364IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, EarlyEventDispatch) {
365 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
Istiaque Ahmeda14ec482018-08-25 01:02:18366
367 // Build "test.onMessage" event for dispatch.
368 auto event = std::make_unique<Event>(
369 events::FOR_TEST, extensions::api::test::OnMessage::kEventName,
370 base::ListValue::From(base::JSONReader::Read(
371 R"([{"data": "hello", "lastMessage": true}])")),
372 profile());
373
374 EarlyWorkerMessageSender sender(profile(), kId, std::move(event));
Istiaque Ahmed771aa8a22018-06-20 23:40:53375 // pkplfbidichfdicaijlchgnapepdginl
376 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
377 "service_worker/worker_based_background/early_event_dispatch"));
378 CHECK(extension);
379 EXPECT_EQ(kId, extension->id());
380 EXPECT_TRUE(sender.SendAndWait());
381}
382
Istiaque Ahmeda14ec482018-08-25 01:02:18383// Tests that filtered events dispatches correctly right after a non-lazy
384// listener is registered for that event (and before the corresponding lazy
385// listener is registered).
386IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest,
387 EarlyFilteredEventDispatch) {
388 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
389
390 // Add minimal details required to dispatch webNavigation.onCommitted event:
391 extensions::api::web_navigation::OnCommitted::Details details;
392 details.transition_type =
393 extensions::api::web_navigation::TRANSITION_TYPE_TYPED;
394
395 // Build a dummy onCommited event to dispatch.
396 auto on_committed_event = std::make_unique<Event>(
397 events::WEB_NAVIGATION_ON_COMMITTED, "webNavigation.onCommitted",
398 api::web_navigation::OnCommitted::Create(details), profile());
399 // The filter will match the listener filter registered from the extension.
400 EventFilteringInfo info;
401 info.url = GURL("http://foo.com/a.html");
402 on_committed_event->filter_info = info;
403
404 EarlyWorkerMessageSender sender(profile(), kId,
405 std::move(on_committed_event));
406
407 // pkplfbidichfdicaijlchgnapepdginl
408 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
409 "service_worker/worker_based_background/early_filtered_event_dispatch"));
410 ASSERT_TRUE(extension);
411 EXPECT_EQ(kId, extension->id());
412 EXPECT_TRUE(sender.SendAndWait());
413}
414
lazyboybd325ae2015-11-18 21:35:26415class ServiceWorkerBackgroundSyncTest : public ServiceWorkerTest {
416 public:
417 ServiceWorkerBackgroundSyncTest() {}
418 ~ServiceWorkerBackgroundSyncTest() override {}
419
420 void SetUpCommandLine(base::CommandLine* command_line) override {
421 // ServiceWorkerRegistration.sync requires experimental flag.
422 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16423 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboybd325ae2015-11-18 21:35:26424 ServiceWorkerTest::SetUpCommandLine(command_line);
425 }
426
427 void SetUp() override {
428 content::background_sync_test_util::SetIgnoreNetworkChangeNotifier(true);
429 ServiceWorkerTest::SetUp();
430 }
431
432 private:
433 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBackgroundSyncTest);
434};
435
lazyboy561b7de2015-11-19 19:27:30436class ServiceWorkerPushMessagingTest : public ServiceWorkerTest {
437 public:
438 ServiceWorkerPushMessagingTest()
johnmea5045732016-09-08 17:23:29439 : gcm_driver_(nullptr), push_service_(nullptr) {}
lazyboy561b7de2015-11-19 19:27:30440 ~ServiceWorkerPushMessagingTest() override {}
441
442 void GrantNotificationPermissionForTest(const GURL& url) {
Peter Beverloodd4ef1e2018-06-21 15:41:04443 NotificationPermissionContext::UpdatePermission(profile(), url.GetOrigin(),
444 CONTENT_SETTING_ALLOW);
lazyboy561b7de2015-11-19 19:27:30445 }
446
447 PushMessagingAppIdentifier GetAppIdentifierForServiceWorkerRegistration(
avia2f4804a2015-12-24 23:11:13448 int64_t service_worker_registration_id,
lazyboy561b7de2015-11-19 19:27:30449 const GURL& origin) {
450 PushMessagingAppIdentifier app_identifier =
451 PushMessagingAppIdentifier::FindByServiceWorker(
452 profile(), origin, service_worker_registration_id);
453
454 EXPECT_FALSE(app_identifier.is_null());
455 return app_identifier;
456 }
457
458 // ExtensionApiTest overrides.
459 void SetUpCommandLine(base::CommandLine* command_line) override {
peter9de96272015-12-04 15:23:27460 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16461 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboy561b7de2015-11-19 19:27:30462 ServiceWorkerTest::SetUpCommandLine(command_line);
463 }
464 void SetUpOnMainThread() override {
miguelg9b502862017-04-24 18:13:53465 NotificationDisplayServiceFactory::GetInstance()->SetTestingFactory(
466 profile(), &StubNotificationDisplayService::FactoryForTests);
467
johnmea5045732016-09-08 17:23:29468 gcm::FakeGCMProfileService* gcm_service =
469 static_cast<gcm::FakeGCMProfileService*>(
470 gcm::GCMProfileServiceFactory::GetInstance()
471 ->SetTestingFactoryAndUse(profile(),
472 &gcm::FakeGCMProfileService::Build));
473 gcm_driver_ = static_cast<instance_id::FakeGCMDriverForInstanceID*>(
474 gcm_service->driver());
lazyboy561b7de2015-11-19 19:27:30475 push_service_ = PushMessagingServiceFactory::GetForProfile(profile());
476
477 ServiceWorkerTest::SetUpOnMainThread();
478 }
479
johnmea5045732016-09-08 17:23:29480 instance_id::FakeGCMDriverForInstanceID* gcm_driver() const {
481 return gcm_driver_;
482 }
lazyboy561b7de2015-11-19 19:27:30483 PushMessagingServiceImpl* push_service() const { return push_service_; }
484
485 private:
johnmea5045732016-09-08 17:23:29486 instance_id::FakeGCMDriverForInstanceID* gcm_driver_;
lazyboy561b7de2015-11-19 19:27:30487 PushMessagingServiceImpl* push_service_;
488
489 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPushMessagingTest);
490};
491
Istiaque Ahmed805f6a83b2017-10-05 01:23:26492class ServiceWorkerLazyBackgroundTest : public ServiceWorkerTest {
493 public:
Istiaque Ahmed7105f2a2017-10-07 01:11:59494 ServiceWorkerLazyBackgroundTest()
495 : ServiceWorkerTest(
496 // Extensions APIs from SW are only enabled on trunk.
497 // It is important to set the channel early so that this change is
498 // visible in renderers running with service workers (and no
499 // extension).
500 version_info::Channel::UNKNOWN) {}
Istiaque Ahmed805f6a83b2017-10-05 01:23:26501 ~ServiceWorkerLazyBackgroundTest() override {}
502
503 void SetUpCommandLine(base::CommandLine* command_line) override {
504 ServiceWorkerTest::SetUpCommandLine(command_line);
505 // Disable background network activity as it can suddenly bring the Lazy
506 // Background Page alive.
507 command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
508 command_line->AppendSwitch(::switches::kNoProxyServer);
509 }
510
511 void SetUpInProcessBrowserTestFixture() override {
512 ServiceWorkerTest::SetUpInProcessBrowserTestFixture();
513 // Set shorter delays to prevent test timeouts.
514 ProcessManager::SetEventPageIdleTimeForTesting(1);
515 ProcessManager::SetEventPageSuspendingTimeForTesting(1);
516 }
517
518 private:
519 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerLazyBackgroundTest);
520};
521
Istiaque Ahmedea5ed5042017-09-25 19:00:16522IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, RegisterSucceeds) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22523 StartTestFromBackgroundPage("register.js");
annekao38685502015-07-14 17:46:39524}
525
Istiaque Ahmedea5ed5042017-09-25 19:00:16526IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, UpdateRefreshesServiceWorker) {
Francois Doraye6fb2d02017-10-18 21:29:13527 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboyc3e763a2015-12-09 23:09:58528 base::ScopedTempDir scoped_temp_dir;
529 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
530 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
531 .AppendASCII("update")
532 .AppendASCII("service_worker.pem");
vabr9142fe22016-09-08 13:19:22533 base::FilePath path_v1 =
534 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
535 .AppendASCII("update")
536 .AppendASCII("v1"),
537 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
538 pem_path, base::FilePath());
539 base::FilePath path_v2 =
540 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
541 .AppendASCII("update")
542 .AppendASCII("v2"),
543 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
544 pem_path, base::FilePath());
lazyboyc3e763a2015-12-09 23:09:58545 const char* kId = "hfaanndiiilofhfokeanhddpkfffchdi";
546
547 ExtensionTestMessageListener listener_v1("Pong from version 1", false);
548 listener_v1.set_failure_message("FAILURE_V1");
549 // Install version 1.0 of the extension.
550 ASSERT_TRUE(InstallExtension(path_v1, 1));
551 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
552 ->enabled_extensions()
553 .GetByID(kId));
554 EXPECT_TRUE(listener_v1.WaitUntilSatisfied());
555
556 ExtensionTestMessageListener listener_v2("Pong from version 2", false);
557 listener_v2.set_failure_message("FAILURE_V2");
558
559 // Update to version 2.0.
560 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
561 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
562 ->enabled_extensions()
563 .GetByID(kId));
564 EXPECT_TRUE(listener_v2.WaitUntilSatisfied());
565}
566
[email protected]2ef85d562017-09-15 18:41:52567// TODO(crbug.com/765736) Fix the test.
Istiaque Ahmedea5ed5042017-09-25 19:00:16568IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, DISABLED_UpdateWithoutSkipWaiting) {
Francois Doraye6fb2d02017-10-18 21:29:13569 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboy22eddc712015-12-10 21:16:26570 base::ScopedTempDir scoped_temp_dir;
571 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
572 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
573 .AppendASCII("update_without_skip_waiting")
574 .AppendASCII("update_without_skip_waiting.pem");
vabr9142fe22016-09-08 13:19:22575 base::FilePath path_v1 =
576 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
577 .AppendASCII("update_without_skip_waiting")
578 .AppendASCII("v1"),
579 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
580 pem_path, base::FilePath());
581 base::FilePath path_v2 =
582 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
583 .AppendASCII("update_without_skip_waiting")
584 .AppendASCII("v2"),
585 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
586 pem_path, base::FilePath());
lazyboy22eddc712015-12-10 21:16:26587 const char* kId = "mhnnnflgagdakldgjpfcofkiocpdmogl";
588
589 // Install version 1.0 of the extension.
590 ASSERT_TRUE(InstallExtension(path_v1, 1));
591 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
592 ->enabled_extensions()
593 .GetByID(kId));
594 const Extension* extension = extensions::ExtensionRegistry::Get(profile())
595 ->enabled_extensions()
596 .GetByID(kId);
597
598 ExtensionTestMessageListener listener1("Pong from version 1", false);
599 listener1.set_failure_message("FAILURE");
600 content::WebContents* web_contents =
601 AddTab(browser(), extension->GetResourceURL("page.html"));
602 EXPECT_TRUE(listener1.WaitUntilSatisfied());
603
604 // Update to version 2.0.
605 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
606 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
607 ->enabled_extensions()
608 .GetByID(kId));
609 const Extension* extension_after_update =
610 extensions::ExtensionRegistry::Get(profile())
611 ->enabled_extensions()
612 .GetByID(kId);
613
614 // Service worker version 2 would be installed but it won't be controlling
615 // the extension page yet.
616 ExtensionTestMessageListener listener2("Pong from version 1", false);
617 listener2.set_failure_message("FAILURE");
618 web_contents =
619 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
620 EXPECT_TRUE(listener2.WaitUntilSatisfied());
621
622 // Navigate the tab away from the extension page so that no clients are
623 // using the service worker.
624 // Note that just closing the tab with WebContentsDestroyedWatcher doesn't
625 // seem to be enough because it returns too early.
626 WebContentsLoadStopObserver navigate_away_observer(web_contents);
627 web_contents->GetController().LoadURL(
628 GURL(url::kAboutBlankURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED,
629 std::string());
630 navigate_away_observer.WaitForLoadStop();
631
632 // Now expect service worker version 2 to control the extension page.
633 ExtensionTestMessageListener listener3("Pong from version 2", false);
634 listener3.set_failure_message("FAILURE");
635 web_contents =
636 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
637 EXPECT_TRUE(listener3.WaitUntilSatisfied());
638}
639
Istiaque Ahmedea5ed5042017-09-25 19:00:16640IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, FetchArbitraryPaths) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22641 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
annekao1db36fd2015-07-29 17:09:16642
kalman6f984ae2015-09-18 17:21:58643 // Open some arbirary paths. Their contents should be what the service worker
644 // responds with, which in this case is the path of the fetch.
645 EXPECT_EQ(
646 "Caught a fetch for /index.html",
647 NavigateAndExtractInnerText(extension->GetResourceURL("index.html")));
648 EXPECT_EQ("Caught a fetch for /path/to/other.html",
649 NavigateAndExtractInnerText(
650 extension->GetResourceURL("path/to/other.html")));
651 EXPECT_EQ("Caught a fetch for /some/text/file.txt",
652 NavigateAndExtractInnerText(
653 extension->GetResourceURL("some/text/file.txt")));
654 EXPECT_EQ("Caught a fetch for /no/file/extension",
655 NavigateAndExtractInnerText(
656 extension->GetResourceURL("no/file/extension")));
657 EXPECT_EQ("Caught a fetch for /",
658 NavigateAndExtractInnerText(extension->GetResourceURL("")));
annekao1db36fd2015-07-29 17:09:16659}
660
Kenichi Ishibashi773b82972018-08-30 07:02:03661IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
662 FetchExtensionResourceFromServiceWorker) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22663 const Extension* extension = StartTestFromBackgroundPage("fetch_from_sw.js");
Kenichi Ishibashi773b82972018-08-30 07:02:03664 ASSERT_TRUE(extension);
665
666 // The service worker in this test tries to load 'hello.txt' via fetch()
667 // and sends back the content of the file, which should be 'hello'.
668 const char* kScript = R"(
669 let channel = new MessageChannel();
670 test.waitForMessage(channel.port1).then(message => {
671 window.domAutomationController.send(message);
672 });
673 test.registeredServiceWorker.postMessage(
674 {port: channel.port2}, [channel.port2]);
675 )";
676 EXPECT_EQ("hello", ExecuteScriptInBackgroundPage(extension->id(), kScript));
677}
678
Istiaque Ahmedea5ed5042017-09-25 19:00:16679IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, SWServedBackgroundPageReceivesEvent) {
lazyboy52c3bcf2016-01-08 00:11:29680 const Extension* extension =
Istiaque Ahmed93ff7f42018-08-31 01:42:22681 StartTestFromBackgroundPage("replace_background.js");
lazyboy52c3bcf2016-01-08 00:11:29682 ExtensionHost* background_page =
683 process_manager()->GetBackgroundHostForExtension(extension->id());
684 ASSERT_TRUE(background_page);
685
686 // Close the background page and start it again so that the service worker
687 // will start controlling pages.
688 background_page->Close();
689 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
690 background_page = nullptr;
Peter Kasting341e1fb2018-02-24 00:03:01691 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
lazyboy52c3bcf2016-01-08 00:11:29692 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
693
694 // Since the SW is now controlling the extension, the SW serves the background
695 // script. page.html sends a message to the background script and we verify
696 // that the SW served background script correctly receives the message/event.
697 ExtensionTestMessageListener listener("onMessage/SW BG.", false);
698 listener.set_failure_message("onMessage/original BG.");
699 content::WebContents* web_contents =
700 AddTab(browser(), extension->GetResourceURL("page.html"));
701 ASSERT_TRUE(web_contents);
702 EXPECT_TRUE(listener.WaitUntilSatisfied());
703}
704
Matt Falkenhagena612fc02018-05-30 00:35:39705IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, SWServedBackgroundPage) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22706 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
annekao49241182015-08-18 17:14:01707
kalman6f984ae2015-09-18 17:21:58708 std::string kExpectedInnerText = "background.html contents for testing.";
annekao49241182015-08-18 17:14:01709
kalman6f984ae2015-09-18 17:21:58710 // Sanity check that the background page has the expected content.
711 ExtensionHost* background_page =
712 process_manager()->GetBackgroundHostForExtension(extension->id());
713 ASSERT_TRUE(background_page);
714 EXPECT_EQ(kExpectedInnerText,
715 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01716
kalman6f984ae2015-09-18 17:21:58717 // Close the background page.
718 background_page->Close();
719 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
720 background_page = nullptr;
721
722 // Start it again.
Peter Kasting341e1fb2018-02-24 00:03:01723 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
kalman6f984ae2015-09-18 17:21:58724 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
725
Matt Falkenhagena612fc02018-05-30 00:35:39726 // The service worker should get a fetch event for the background page.
kalman6f984ae2015-09-18 17:21:58727 background_page =
728 process_manager()->GetBackgroundHostForExtension(extension->id());
729 ASSERT_TRUE(background_page);
730 content::WaitForLoadStop(background_page->host_contents());
731
kalman6f984ae2015-09-18 17:21:58732 EXPECT_EQ("Caught a fetch for /background.html",
733 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01734}
735
Istiaque Ahmedea5ed5042017-09-25 19:00:16736IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58737 ServiceWorkerPostsMessageToBackgroundClient) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22738 const Extension* extension =
739 StartTestFromBackgroundPage("post_message_to_background_client.js");
annekao533482222015-08-21 23:23:53740
kalman6f984ae2015-09-18 17:21:58741 // The service worker in this test simply posts a message to the background
742 // client it receives from getBackgroundClient().
743 const char* kScript =
744 "var messagePromise = null;\n"
745 "if (test.lastMessageFromServiceWorker) {\n"
746 " messagePromise = Promise.resolve(test.lastMessageFromServiceWorker);\n"
747 "} else {\n"
748 " messagePromise = test.waitForMessage(navigator.serviceWorker);\n"
749 "}\n"
750 "messagePromise.then(function(message) {\n"
751 " window.domAutomationController.send(String(message == 'success'));\n"
752 "})\n";
753 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53754}
755
Istiaque Ahmedea5ed5042017-09-25 19:00:16756IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58757 BackgroundPagePostsMessageToServiceWorker) {
758 const Extension* extension =
Istiaque Ahmed93ff7f42018-08-31 01:42:22759 StartTestFromBackgroundPage("post_message_to_sw.js");
annekao533482222015-08-21 23:23:53760
kalman6f984ae2015-09-18 17:21:58761 // The service worker in this test waits for a message, then echoes it back
762 // by posting a message to the background page via getBackgroundClient().
763 const char* kScript =
764 "var mc = new MessageChannel();\n"
765 "test.waitForMessage(mc.port1).then(function(message) {\n"
766 " window.domAutomationController.send(String(message == 'hello'));\n"
767 "});\n"
768 "test.registeredServiceWorker.postMessage(\n"
769 " {message: 'hello', port: mc.port2}, [mc.port2])\n";
770 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53771}
772
Istiaque Ahmedea5ed5042017-09-25 19:00:16773IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
rdevlin.croninf5863da2015-09-10 19:21:45774 ServiceWorkerSuspensionOnExtensionUnload) {
kalman6f984ae2015-09-18 17:21:58775 // For this test, only hold onto the extension's ID and URL + a function to
776 // get a resource URL, because we're going to be disabling and uninstalling
777 // it, which will invalidate the pointer.
778 std::string extension_id;
779 GURL extension_url;
780 {
Istiaque Ahmed93ff7f42018-08-31 01:42:22781 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
kalman6f984ae2015-09-18 17:21:58782 extension_id = extension->id();
783 extension_url = extension->url();
784 }
785 auto get_resource_url = [&extension_url](const std::string& path) {
786 return Extension::GetResourceURL(extension_url, path);
787 };
rdevlin.croninf5863da2015-09-10 19:21:45788
kalman6f984ae2015-09-18 17:21:58789 // Fetch should route to the service worker.
790 EXPECT_EQ("Caught a fetch for /index.html",
791 NavigateAndExtractInnerText(get_resource_url("index.html")));
rdevlin.croninf5863da2015-09-10 19:21:45792
kalman6f984ae2015-09-18 17:21:58793 // Disable the extension. Opening the page should fail.
794 extension_service()->DisableExtension(extension_id,
Minh X. Nguyen45479012017-08-18 21:35:36795 disable_reason::DISABLE_USER_ACTION);
rdevlin.croninf5863da2015-09-10 19:21:45796 base::RunLoop().RunUntilIdle();
rdevlin.croninf5863da2015-09-10 19:21:45797
kalman6f984ae2015-09-18 17:21:58798 EXPECT_EQ(content::PAGE_TYPE_ERROR,
799 NavigateAndGetPageType(get_resource_url("index.html")));
800 EXPECT_EQ(content::PAGE_TYPE_ERROR,
801 NavigateAndGetPageType(get_resource_url("other.html")));
802
803 // Re-enable the extension. Opening pages should immediately start to succeed
804 // again.
rdevlin.croninf5863da2015-09-10 19:21:45805 extension_service()->EnableExtension(extension_id);
806 base::RunLoop().RunUntilIdle();
807
kalman6f984ae2015-09-18 17:21:58808 EXPECT_EQ("Caught a fetch for /index.html",
809 NavigateAndExtractInnerText(get_resource_url("index.html")));
810 EXPECT_EQ("Caught a fetch for /other.html",
811 NavigateAndExtractInnerText(get_resource_url("other.html")));
812 EXPECT_EQ("Caught a fetch for /another.html",
813 NavigateAndExtractInnerText(get_resource_url("another.html")));
rdevlin.croninf5863da2015-09-10 19:21:45814
kalman6f984ae2015-09-18 17:21:58815 // Uninstall the extension. Opening pages should fail again.
816 base::string16 error;
817 extension_service()->UninstallExtension(
Devlin Cronin218df7f2017-11-21 21:41:31818 extension_id, UninstallReason::UNINSTALL_REASON_FOR_TESTING, &error);
kalman6f984ae2015-09-18 17:21:58819 base::RunLoop().RunUntilIdle();
820
821 EXPECT_EQ(content::PAGE_TYPE_ERROR,
822 NavigateAndGetPageType(get_resource_url("index.html")));
823 EXPECT_EQ(content::PAGE_TYPE_ERROR,
824 NavigateAndGetPageType(get_resource_url("other.html")));
825 EXPECT_EQ(content::PAGE_TYPE_ERROR,
826 NavigateAndGetPageType(get_resource_url("anotherother.html")));
827 EXPECT_EQ(content::PAGE_TYPE_ERROR,
828 NavigateAndGetPageType(get_resource_url("final.html")));
829}
830
Istiaque Ahmedea5ed5042017-09-25 19:00:16831IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, BackgroundPageIsWokenIfAsleep) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22832 const Extension* extension = StartTestFromBackgroundPage("wake_on_fetch.js");
kalman6f984ae2015-09-18 17:21:58833
834 // Navigate to special URLs that this test's service worker recognises, each
835 // making a check then populating the response with either "true" or "false".
836 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
837 "background-client-is-awake")));
838 EXPECT_EQ("true", NavigateAndExtractInnerText(
839 extension->GetResourceURL("ping-background-client")));
840 // Ping more than once for good measure.
841 EXPECT_EQ("true", NavigateAndExtractInnerText(
842 extension->GetResourceURL("ping-background-client")));
843
844 // Shut down the event page. The SW should detect that it's closed, but still
845 // be able to ping it.
846 ExtensionHost* background_page =
847 process_manager()->GetBackgroundHostForExtension(extension->id());
848 ASSERT_TRUE(background_page);
849 background_page->Close();
850 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
851
852 EXPECT_EQ("false", NavigateAndExtractInnerText(extension->GetResourceURL(
853 "background-client-is-awake")));
854 EXPECT_EQ("true", NavigateAndExtractInnerText(
855 extension->GetResourceURL("ping-background-client")));
856 EXPECT_EQ("true", NavigateAndExtractInnerText(
857 extension->GetResourceURL("ping-background-client")));
858 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
859 "background-client-is-awake")));
860}
861
Istiaque Ahmedea5ed5042017-09-25 19:00:16862IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58863 GetBackgroundClientFailsWithNoBackgroundPage) {
864 // This extension doesn't have a background page, only a tab at page.html.
865 // The service worker it registers tries to call getBackgroundClient() and
866 // should fail.
867 // Note that this also tests that service workers can be registered from tabs.
868 EXPECT_TRUE(RunExtensionSubtest("service_worker/no_background", "page.html"));
rdevlin.croninf5863da2015-09-10 19:21:45869}
870
Istiaque Ahmedea5ed5042017-09-25 19:00:16871IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, NotificationAPI) {
lazyboy6ddb7d62015-11-10 23:15:27872 EXPECT_TRUE(RunExtensionSubtest("service_worker/notifications/has_permission",
873 "page.html"));
874}
875
Istiaque Ahmedea5ed5042017-09-25 19:00:16876IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WebAccessibleResourcesFetch) {
lazyboyaea32c22016-01-04 21:37:07877 EXPECT_TRUE(RunExtensionSubtest(
878 "service_worker/web_accessible_resources/fetch/", "page.html"));
879}
880
Istiaque Ahmed75ad1d92018-08-30 05:16:54881IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, TabsCreate) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:16882 if (IsMacViewsMode())
883 return;
lazyboyee4adef2016-05-24 00:55:16884 // Extensions APIs from SW are only enabled on trunk.
885 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
886 const Extension* extension = LoadExtensionWithFlags(
887 test_data_dir_.AppendASCII("service_worker/tabs_create"), kFlagNone);
888 ASSERT_TRUE(extension);
889 ui_test_utils::NavigateToURL(browser(),
890 extension->GetResourceURL("page.html"));
891 content::WebContents* web_contents =
892 browser()->tab_strip_model()->GetActiveWebContents();
893
894 int starting_tab_count = browser()->tab_strip_model()->count();
895 std::string result;
896 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
897 web_contents, "window.runServiceWorker()", &result));
898 ASSERT_EQ("chrome.tabs.create callback", result);
899 EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count());
900
901 // Check extension shutdown path.
902 UnloadExtension(extension->id());
903 EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count());
904}
905
Istiaque Ahmedea5ed5042017-09-25 19:00:16906IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, Events) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:16907 if (IsMacViewsMode())
908 return;
lazyboye7847242017-06-07 23:29:18909 // Extensions APIs from SW are only enabled on trunk.
910 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
911 const Extension* extension = LoadExtensionWithFlags(
912 test_data_dir_.AppendASCII("service_worker/events"), kFlagNone);
913 ASSERT_TRUE(extension);
914 ui_test_utils::NavigateToURL(browser(),
915 extension->GetResourceURL("page.html"));
916 content::WebContents* web_contents =
917 browser()->tab_strip_model()->GetActiveWebContents();
918 std::string result;
919 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
920 web_contents, "window.runEventTest()", &result));
921 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
922}
923
Istiaque Ahmedea5ed5042017-09-25 19:00:16924IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, EventsToStoppedWorker) {
lazyboy63b994a2017-06-30 21:20:23925 // Extensions APIs from SW are only enabled on trunk.
926 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
927 const Extension* extension = LoadExtensionWithFlags(
928 test_data_dir_.AppendASCII("service_worker/events_to_stopped_worker"),
929 kFlagNone);
930 ASSERT_TRUE(extension);
931 ui_test_utils::NavigateToURL(browser(),
932 extension->GetResourceURL("page.html"));
933 content::WebContents* web_contents =
934 browser()->tab_strip_model()->GetActiveWebContents();
935 {
936 std::string result;
937 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
938 web_contents, "window.runServiceWorker()", &result));
939 ASSERT_EQ("ready", result);
940
941 base::RunLoop run_loop;
942 content::StoragePartition* storage_partition =
943 content::BrowserContext::GetDefaultStoragePartition(
944 browser()->profile());
945 content::StopServiceWorkerForPattern(
946 storage_partition->GetServiceWorkerContext(),
947 // The service worker is registered at the top level scope.
948 extension->url(), run_loop.QuitClosure());
949 run_loop.Run();
950 }
951
952 std::string result;
953 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
954 web_contents, "window.createTabThenUpdate()", &result));
955 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
956}
957
Istiaque Ahmed805f6a83b2017-10-05 01:23:26958// Tests that events to service worker arrives correctly event if the owner
959// extension of the worker is not running.
960IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
Xida Chen1f18f462018-04-24 13:55:54961 DISABLED_EventsToStoppedExtension) {
Istiaque Ahmed805f6a83b2017-10-05 01:23:26962 LazyBackgroundObserver lazy_observer;
963 ResultCatcher catcher;
964 const Extension* extension = LoadExtensionWithFlags(
965 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
966 kFlagNone);
967 ASSERT_TRUE(extension);
968 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
969
970 ProcessManager* pm = ProcessManager::Get(browser()->profile());
971 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:30972 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed805f6a83b2017-10-05 01:23:26973
974 // |extension|'s background page opens a tab to its resource.
975 content::WebContents* extension_web_contents =
976 browser()->tab_strip_model()->GetActiveWebContents();
977 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
978 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
979 extension_web_contents->GetURL().spec());
980 {
981 // Let the service worker start and register a listener to
982 // chrome.tabs.onCreated event.
983 ExtensionTestMessageListener add_listener_done("listener-added", false);
984 content::ExecuteScriptAsync(extension_web_contents,
985 "window.runServiceWorkerAsync()");
986 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
987
988 base::RunLoop run_loop;
989 content::StoragePartition* storage_partition =
990 content::BrowserContext::GetDefaultStoragePartition(
991 browser()->profile());
992 content::StopServiceWorkerForPattern(
993 storage_partition->GetServiceWorkerContext(),
994 // The service worker is registered at the top level scope.
995 extension->url(), run_loop.QuitClosure());
996 run_loop.Run();
997 }
998
999 // Close the tab to |extension|'s resource. This will also close the
1000 // extension's event page.
1001 browser()->tab_strip_model()->CloseWebContentsAt(
1002 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1003 lazy_observer.Wait();
1004
1005 // At this point both the extension worker and extension event page is not
1006 // running. Since the worker registered a listener for tabs.onCreated, it
1007 // will be started to dispatch the event once we create a tab.
1008 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1009 newtab_listener.set_failure_message("WRONG_NEWTAB");
1010 content::WebContents* new_web_contents =
Istiaque Ahmed7105f2a2017-10-07 01:11:591011 AddTab(browser(), GURL(url::kAboutBlankURL));
1012 EXPECT_TRUE(new_web_contents);
1013 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1014}
1015
1016// Tests that events to service worker correctly after browser restart.
1017// This test is similar to EventsToStoppedExtension, except that the event
1018// delivery is verified after a browser restart.
1019IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
1020 PRE_EventsAfterRestart) {
1021 LazyBackgroundObserver lazy_observer;
1022 ResultCatcher catcher;
1023 const Extension* extension = LoadExtensionWithFlags(
1024 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
1025 kFlagNone);
1026 ASSERT_TRUE(extension);
1027 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1028
1029 ProcessManager* pm = ProcessManager::Get(browser()->profile());
1030 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:301031 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed7105f2a2017-10-07 01:11:591032
1033 // |extension|'s background page opens a tab to its resource.
1034 content::WebContents* extension_web_contents =
1035 browser()->tab_strip_model()->GetActiveWebContents();
1036 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1037 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1038 extension_web_contents->GetURL().spec());
1039 {
1040 // Let the service worker start and register a listener to
1041 // chrome.tabs.onCreated event.
1042 ExtensionTestMessageListener add_listener_done("listener-added", false);
1043 content::ExecuteScriptAsync(extension_web_contents,
1044 "window.runServiceWorkerAsync()");
1045 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1046
1047 base::RunLoop run_loop;
1048 content::StoragePartition* storage_partition =
1049 content::BrowserContext::GetDefaultStoragePartition(
1050 browser()->profile());
1051 content::StopServiceWorkerForPattern(
1052 storage_partition->GetServiceWorkerContext(),
1053 // The service worker is registered at the top level scope.
1054 extension->url(), run_loop.QuitClosure());
1055 run_loop.Run();
1056 }
1057
1058 // Close the tab to |extension|'s resource. This will also close the
1059 // extension's event page.
1060 browser()->tab_strip_model()->CloseWebContentsAt(
1061 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1062 lazy_observer.Wait();
1063}
1064
Han Leond717ddc2018-05-03 00:33:141065// Flaky: http://crbug/834200.
1066IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
1067 DISABLED_EventsAfterRestart) {
Istiaque Ahmed7105f2a2017-10-07 01:11:591068 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1069 content::WebContents* new_web_contents =
1070 AddTab(browser(), GURL(url::kAboutBlankURL));
Istiaque Ahmed805f6a83b2017-10-05 01:23:261071 EXPECT_TRUE(new_web_contents);
1072 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1073}
1074
lazyboy4c82177a2016-10-18 00:04:091075// Tests that worker ref count increments while extension API function is
1076// active.
Istiaque Ahmedea5ed5042017-09-25 19:00:161077IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WorkerRefCount) {
lazyboy4c82177a2016-10-18 00:04:091078 // Extensions APIs from SW are only enabled on trunk.
1079 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1080 const Extension* extension = LoadExtensionWithFlags(
1081 test_data_dir_.AppendASCII("service_worker/api_worker_ref_count"),
1082 kFlagNone);
1083 ASSERT_TRUE(extension);
1084 ui_test_utils::NavigateToURL(browser(),
1085 extension->GetResourceURL("page.html"));
1086 content::WebContents* web_contents =
1087 browser()->tab_strip_model()->GetActiveWebContents();
1088
1089 ExtensionTestMessageListener worker_start_listener("WORKER STARTED", false);
1090 worker_start_listener.set_failure_message("FAILURE");
1091 ASSERT_TRUE(
1092 content::ExecuteScript(web_contents, "window.runServiceWorker()"));
1093 ASSERT_TRUE(worker_start_listener.WaitUntilSatisfied());
1094
1095 // Service worker should have no pending requests because it hasn't peformed
1096 // any extension API request yet.
1097 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1098
1099 ExtensionTestMessageListener worker_listener("CHECK_REF_COUNT", true);
1100 worker_listener.set_failure_message("FAILURE");
1101 ASSERT_TRUE(content::ExecuteScript(web_contents, "window.testSendMessage()"));
1102 ASSERT_TRUE(worker_listener.WaitUntilSatisfied());
1103
1104 // Service worker should have exactly one pending request because
1105 // chrome.test.sendMessage() API call is in-flight.
1106 EXPECT_EQ(1u, GetWorkerRefCount(extension->url()));
1107
1108 // Peform another extension API request while one is ongoing.
1109 {
1110 ExtensionTestMessageListener listener("CHECK_REF_COUNT", true);
1111 listener.set_failure_message("FAILURE");
1112 ASSERT_TRUE(
1113 content::ExecuteScript(web_contents, "window.testSendMessage()"));
1114 ASSERT_TRUE(listener.WaitUntilSatisfied());
1115
1116 // Service worker currently has two extension API requests in-flight.
1117 EXPECT_EQ(2u, GetWorkerRefCount(extension->url()));
1118 // Finish executing the nested chrome.test.sendMessage() first.
1119 listener.Reply("Hello world");
1120 }
1121
Istiaque Ahmedb57c9752017-08-20 19:08:571122 ExtensionTestMessageListener worker_completion_listener("SUCCESS_FROM_WORKER",
1123 false);
lazyboy4c82177a2016-10-18 00:04:091124 // Finish executing chrome.test.sendMessage().
1125 worker_listener.Reply("Hello world");
Istiaque Ahmedb57c9752017-08-20 19:08:571126 EXPECT_TRUE(worker_completion_listener.WaitUntilSatisfied());
1127
1128 // The following block makes sure we have received all the IPCs related to
1129 // ref-count from the worker.
1130 {
1131 // The following roundtrip:
1132 // browser->extension->worker->extension->browser
1133 // will ensure that the worker sent the relevant ref count IPCs.
1134 std::string result;
1135 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1136 web_contents, "window.roundtripToWorker();", &result));
1137 EXPECT_EQ("roundtrip-succeeded", result);
1138
1139 // Ensure IO thread IPCs run.
Gabriel Charette01507a22017-09-27 21:30:081140 content::RunAllTasksUntilIdle();
Istiaque Ahmedb57c9752017-08-20 19:08:571141 }
lazyboy4c82177a2016-10-18 00:04:091142
1143 // The ref count should drop to 0.
1144 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1145}
1146
lazyboyaea32c22016-01-04 21:37:071147// This test loads a web page that has an iframe pointing to a
1148// chrome-extension:// URL. The URL is listed in the extension's
1149// web_accessible_resources. Initially the iframe is served from the extension's
1150// resource file. After verifying that, we register a Service Worker that
1151// controls the extension. Further requests to the same resource as before
1152// should now be served by the Service Worker.
1153// This test also verifies that if the requested resource exists in the manifest
1154// but is not present in the extension directory, the Service Worker can still
1155// serve the resource file.
Istiaque Ahmedea5ed5042017-09-25 19:00:161156IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WebAccessibleResourcesIframeSrc) {
lazyboyaea32c22016-01-04 21:37:071157 const Extension* extension = LoadExtensionWithFlags(
1158 test_data_dir_.AppendASCII(
1159 "service_worker/web_accessible_resources/iframe_src"),
1160 kFlagNone);
1161 ASSERT_TRUE(extension);
1162 ASSERT_TRUE(StartEmbeddedTestServer());
falkenad185092016-06-16 06:10:021163
1164 // Service workers can only control secure contexts
1165 // (https://w3c.github.io/webappsec-secure-contexts/). For documents, this
1166 // typically means the document must have a secure origin AND all its ancestor
1167 // frames must have documents with secure origins. However, extension pages
1168 // are considered secure, even if they have an ancestor document that is an
1169 // insecure context (see GetSchemesBypassingSecureContextCheckWhitelist). So
1170 // extension service workers must be able to control an extension page
1171 // embedded in an insecure context. To test this, set up an insecure
1172 // (non-localhost, non-https) URL for the web page. This page will create
1173 // iframes that load extension pages that must be controllable by service
1174 // worker.
falkenad185092016-06-16 06:10:021175 GURL page_url =
1176 embedded_test_server()->GetURL("a.com",
1177 "/extensions/api_test/service_worker/"
1178 "web_accessible_resources/webpage.html");
1179 EXPECT_FALSE(content::IsOriginSecure(page_url));
lazyboyaea32c22016-01-04 21:37:071180
1181 content::WebContents* web_contents = AddTab(browser(), page_url);
1182 std::string result;
1183 // webpage.html will create an iframe pointing to a resource from |extension|.
1184 // Expect the resource to be served by the extension.
1185 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1186 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1187 extension->id().c_str()),
1188 &result));
1189 EXPECT_EQ("FROM_EXTENSION_RESOURCE", result);
1190
1191 ExtensionTestMessageListener service_worker_ready_listener("SW_READY", false);
1192 EXPECT_TRUE(ExecuteScriptInBackgroundPageNoWait(
1193 extension->id(), "window.registerServiceWorker()"));
1194 EXPECT_TRUE(service_worker_ready_listener.WaitUntilSatisfied());
1195
1196 result.clear();
1197 // webpage.html will create another iframe pointing to a resource from
1198 // |extension| as before. But this time, the resource should be be served
1199 // from the Service Worker.
1200 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1201 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1202 extension->id().c_str()),
1203 &result));
1204 EXPECT_EQ("FROM_SW_RESOURCE", result);
1205
1206 result.clear();
1207 // webpage.html will create yet another iframe pointing to a resource that
1208 // exists in the extension manifest's web_accessible_resources, but is not
1209 // present in the extension directory. Expect the resources of the iframe to
1210 // be served by the Service Worker.
1211 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1212 web_contents,
1213 base::StringPrintf("window.testIframe('%s', 'iframe_non_existent.html')",
1214 extension->id().c_str()),
1215 &result));
1216 EXPECT_EQ("FROM_SW_RESOURCE", result);
1217}
1218
Istiaque Ahmedea5ed5042017-09-25 19:00:161219IN_PROC_BROWSER_TEST_P(ServiceWorkerBackgroundSyncTest, Sync) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:161220 if (IsMacViewsMode())
1221 return;
lazyboybd325ae2015-11-18 21:35:261222 const Extension* extension = LoadExtensionWithFlags(
1223 test_data_dir_.AppendASCII("service_worker/sync"), kFlagNone);
1224 ASSERT_TRUE(extension);
1225 ui_test_utils::NavigateToURL(browser(),
1226 extension->GetResourceURL("page.html"));
1227 content::WebContents* web_contents =
1228 browser()->tab_strip_model()->GetActiveWebContents();
1229
1230 // Prevent firing by going offline.
1231 content::background_sync_test_util::SetOnline(web_contents, false);
1232
1233 ExtensionTestMessageListener sync_listener("SYNC: send-chats", false);
1234 sync_listener.set_failure_message("FAIL");
1235
1236 std::string result;
1237 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1238 web_contents, "window.runServiceWorker()", &result));
1239 ASSERT_EQ("SERVICE_WORKER_READY", result);
1240
1241 EXPECT_FALSE(sync_listener.was_satisfied());
1242 // Resume firing by going online.
1243 content::background_sync_test_util::SetOnline(web_contents, true);
1244 EXPECT_TRUE(sync_listener.WaitUntilSatisfied());
1245}
1246
Istiaque Ahmedea5ed5042017-09-25 19:00:161247IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
horo1eeddde2015-11-19 05:59:251248 FetchFromContentScriptShouldNotGoToServiceWorkerOfPage) {
1249 ASSERT_TRUE(StartEmbeddedTestServer());
1250 GURL page_url = embedded_test_server()->GetURL(
1251 "/extensions/api_test/service_worker/content_script_fetch/"
1252 "controlled_page/index.html");
1253 content::WebContents* tab =
1254 browser()->tab_strip_model()->GetActiveWebContents();
1255 ui_test_utils::NavigateToURL(browser(), page_url);
1256 content::WaitForLoadStop(tab);
1257
1258 std::string value;
1259 ASSERT_TRUE(
1260 content::ExecuteScriptAndExtractString(tab, "register();", &value));
1261 EXPECT_EQ("SW controlled", value);
1262
1263 ASSERT_TRUE(RunExtensionTest("service_worker/content_script_fetch"))
1264 << message_;
1265}
1266
Istiaque Ahmedea5ed5042017-09-25 19:00:161267IN_PROC_BROWSER_TEST_P(ServiceWorkerPushMessagingTest, OnPush) {
lazyboy561b7de2015-11-19 19:27:301268 const Extension* extension = LoadExtensionWithFlags(
1269 test_data_dir_.AppendASCII("service_worker/push_messaging"), kFlagNone);
1270 ASSERT_TRUE(extension);
1271 GURL extension_url = extension->url();
1272
Peter Beverloodd4ef1e2018-06-21 15:41:041273 GrantNotificationPermissionForTest(extension_url);
lazyboy561b7de2015-11-19 19:27:301274
1275 GURL url = extension->GetResourceURL("page.html");
1276 ui_test_utils::NavigateToURL(browser(), url);
1277
1278 content::WebContents* web_contents =
1279 browser()->tab_strip_model()->GetActiveWebContents();
1280
1281 // Start the ServiceWorker.
1282 ExtensionTestMessageListener ready_listener("SERVICE_WORKER_READY", false);
1283 ready_listener.set_failure_message("SERVICE_WORKER_FAILURE");
1284 const char* kScript = "window.runServiceWorker()";
1285 EXPECT_TRUE(content::ExecuteScript(web_contents->GetMainFrame(), kScript));
1286 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1287
1288 PushMessagingAppIdentifier app_identifier =
1289 GetAppIdentifierForServiceWorkerRegistration(0LL, extension_url);
johnmea5045732016-09-08 17:23:291290 ASSERT_EQ(app_identifier.app_id(), gcm_driver()->last_gettoken_app_id());
1291 EXPECT_EQ("1234567890", gcm_driver()->last_gettoken_authorized_entity());
lazyboy561b7de2015-11-19 19:27:301292
lazyboyd429e2582016-05-20 20:18:521293 base::RunLoop run_loop;
lazyboy561b7de2015-11-19 19:27:301294 // Send a push message via gcm and expect the ServiceWorker to receive it.
1295 ExtensionTestMessageListener push_message_listener("OK", false);
1296 push_message_listener.set_failure_message("FAIL");
1297 gcm::IncomingMessage message;
1298 message.sender_id = "1234567890";
1299 message.raw_data = "testdata";
1300 message.decrypted = true;
lazyboyd429e2582016-05-20 20:18:521301 push_service()->SetMessageCallbackForTesting(run_loop.QuitClosure());
lazyboy561b7de2015-11-19 19:27:301302 push_service()->OnMessage(app_identifier.app_id(), message);
1303 EXPECT_TRUE(push_message_listener.WaitUntilSatisfied());
lazyboyd429e2582016-05-20 20:18:521304 run_loop.Run(); // Wait until the message is handled by push service.
lazyboy561b7de2015-11-19 19:27:301305}
1306
Istiaque Ahmedea5ed5042017-09-25 19:00:161307IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, FilteredEvents) {
Istiaque Ahmed9d1666182017-09-21 23:58:181308 // Extensions APIs from SW are only enabled on trunk.
1309 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1310 ASSERT_TRUE(RunExtensionTest("service_worker/filtered_events"));
1311}
1312
Rob Wue89b90032018-02-16 19:46:081313IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, MimeHandlerView) {
1314 ASSERT_TRUE(RunExtensionTest("service_worker/mime_handler_view"));
1315}
1316
Istiaque Ahmed9ce21b32017-10-10 20:43:181317IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
1318 PRE_FilteredEventsAfterRestart) {
1319 LazyBackgroundObserver lazy_observer;
1320 ResultCatcher catcher;
1321 const Extension* extension = LoadExtensionWithFlags(
1322 test_data_dir_.AppendASCII(
1323 "service_worker/filtered_events_after_restart"),
1324 kFlagNone);
1325 ASSERT_TRUE(extension);
1326 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1327
1328 // |extension|'s background page opens a tab to its resource.
1329 content::WebContents* extension_web_contents =
1330 browser()->tab_strip_model()->GetActiveWebContents();
1331 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1332 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1333 extension_web_contents->GetURL().spec());
1334 {
1335 // Let the service worker start and register a filtered listener to
1336 // chrome.webNavigation.onCommitted event.
1337 ExtensionTestMessageListener add_listener_done("listener-added", false);
1338 add_listener_done.set_failure_message("FAILURE");
1339 content::ExecuteScriptAsync(extension_web_contents,
1340 "window.runServiceWorkerAsync()");
1341 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1342
1343 base::RunLoop run_loop;
1344 content::StoragePartition* storage_partition =
1345 content::BrowserContext::GetDefaultStoragePartition(
1346 browser()->profile());
1347 content::StopServiceWorkerForPattern(
1348 storage_partition->GetServiceWorkerContext(),
1349 // The service worker is registered at the top level scope.
1350 extension->url(), run_loop.QuitClosure());
1351 run_loop.Run();
1352 }
1353
1354 // Close the tab to |extension|'s resource. This will also close the
1355 // extension's event page.
1356 browser()->tab_strip_model()->CloseWebContentsAt(
1357 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1358 lazy_observer.Wait();
1359}
1360
Trent Apted1d8b22d2018-05-28 03:12:381361// Flaky. See https://crbug.com/844821.
Istiaque Ahmed9ce21b32017-10-10 20:43:181362IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
Trent Apted1d8b22d2018-05-28 03:12:381363 DISABLED_FilteredEventsAfterRestart) {
Istiaque Ahmed9ce21b32017-10-10 20:43:181364 // Create a tab to a.html, expect it to navigate to b.html. The service worker
1365 // will see two webNavigation.onCommitted events.
1366 ASSERT_TRUE(StartEmbeddedTestServer());
1367 GURL page_url = embedded_test_server()->GetURL(
1368 "/extensions/api_test/service_worker/filtered_events_after_restart/"
1369 "a.html");
1370 ExtensionTestMessageListener worker_filtered_event_listener(
1371 "PASS_FROM_WORKER", false);
1372 worker_filtered_event_listener.set_failure_message("FAIL_FROM_WORKER");
1373 content::WebContents* web_contents = AddTab(browser(), page_url);
1374 EXPECT_TRUE(web_contents);
1375 EXPECT_TRUE(worker_filtered_event_listener.WaitUntilSatisfied());
1376}
1377
Istiaque Ahmedea5ed5042017-09-25 19:00:161378// Run with both native and JS-based bindings. This ensures that both stable
1379// (JS) and experimental (native) phases work correctly with worker scripts
1380// while we launch native bindings to stable.
1381INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
1382 ServiceWorkerTest,
1383 ::testing::Values(NATIVE_BINDINGS));
1384INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
1385 ServiceWorkerTest,
1386 ::testing::Values(JAVASCRIPT_BINDINGS));
1387INSTANTIATE_TEST_CASE_P(ServiceWorkerBackgroundSyncTestWithNativeBindings,
1388 ServiceWorkerBackgroundSyncTest,
1389 ::testing::Values(NATIVE_BINDINGS));
1390INSTANTIATE_TEST_CASE_P(ServiceWorkerBackgroundSyncTestWithJSBindings,
1391 ServiceWorkerBackgroundSyncTest,
1392 ::testing::Values(JAVASCRIPT_BINDINGS));
1393INSTANTIATE_TEST_CASE_P(ServiceWorkerPushMessagingTestWithNativeBindings,
1394 ServiceWorkerPushMessagingTest,
1395 ::testing::Values(NATIVE_BINDINGS));
1396INSTANTIATE_TEST_CASE_P(ServiceWorkerPushMessagingTestWithJSBindings,
1397 ServiceWorkerPushMessagingTest,
1398 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmed805f6a83b2017-10-05 01:23:261399INSTANTIATE_TEST_CASE_P(ServiceWorkerLazyBackgroundTestWithNativeBindings,
1400 ServiceWorkerLazyBackgroundTest,
1401 ::testing::Values(NATIVE_BINDINGS));
1402INSTANTIATE_TEST_CASE_P(ServiceWorkerLazyBackgroundTestWithJSBindings,
1403 ServiceWorkerLazyBackgroundTest,
1404 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmedccb444022018-06-19 02:11:121405INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
1406 ServiceWorkerBasedBackgroundTest,
1407 ::testing::Values(NATIVE_BINDINGS));
1408INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
1409 ServiceWorkerBasedBackgroundTest,
1410 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmedea5ed5042017-09-25 19:00:161411
annekao38685502015-07-14 17:46:391412} // namespace extensions