blob: 676fb47e229559c000af887699047e574750b40b [file] [log] [blame]
annekao38685502015-07-14 17:46:391// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avia2f4804a2015-12-24 23:11:135#include <stdint.h>
6
Sylvain Defresne4fdc727fd2018-10-04 11:09:467#include "base/bind.h"
kalman6f984ae2015-09-18 17:21:588#include "base/bind_helpers.h"
Istiaque Ahmeda14ec482018-08-25 01:02:189#include "base/json/json_reader.h"
avia2f4804a2015-12-24 23:11:1310#include "base/macros.h"
Gabriel Charette078e3662017-08-28 22:59:0411#include "base/run_loop.h"
kalman6f984ae2015-09-18 17:21:5812#include "base/strings/stringprintf.h"
horo1eeddde2015-11-19 05:59:2513#include "base/strings/utf_string_conversions.h"
jam3f2d3932017-04-26 20:28:5114#include "base/threading/thread_restrictions.h"
Olga Sharonova3e13cd92018-02-08 16:43:5615#include "build/build_config.h"
annekao38685502015-07-14 17:46:3916#include "chrome/browser/extensions/extension_apitest.h"
rdevlin.croninf5863da2015-09-10 19:21:4517#include "chrome/browser/extensions/extension_service.h"
Istiaque Ahmed805f6a83b2017-10-05 01:23:2618#include "chrome/browser/extensions/lazy_background_page_test_util.h"
peter9f4490a2017-01-27 00:58:3619#include "chrome/browser/gcm/gcm_profile_service_factory.h"
miguelg9b502862017-04-24 18:13:5320#include "chrome/browser/notifications/notification_display_service_factory.h"
Peter Beverloodd4ef1e2018-06-21 15:41:0421#include "chrome/browser/notifications/notification_permission_context.h"
miguelg9b502862017-04-24 18:13:5322#include "chrome/browser/notifications/stub_notification_display_service.h"
lshang106c1772016-06-06 01:43:2323#include "chrome/browser/permissions/permission_manager.h"
timlohc6911802017-03-01 05:37:0324#include "chrome/browser/permissions/permission_result.h"
lazyboy561b7de2015-11-19 19:27:3025#include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
26#include "chrome/browser/push_messaging/push_messaging_service_factory.h"
27#include "chrome/browser/push_messaging/push_messaging_service_impl.h"
annekao1db36fd2015-07-29 17:09:1628#include "chrome/browser/ui/tabs/tab_strip_model.h"
Elly Fong-Jones4a4f21d2018-05-30 15:04:1629#include "chrome/browser/ui/views_mode_controller.h"
Trent Apted4267b942017-10-27 03:25:3630#include "chrome/common/chrome_switches.h"
Istiaque Ahmeda14ec482018-08-25 01:02:1831#include "chrome/common/extensions/api/web_navigation.h"
rdevlin.croninf5863da2015-09-10 19:21:4532#include "chrome/test/base/ui_test_utils.h"
timloh9a180ad2017-02-20 07:15:2333#include "components/content_settings/core/common/content_settings_types.h"
Peter Beverloo34139462018-04-10 14:18:0634#include "components/gcm_driver/fake_gcm_profile_service.h"
johnmea5045732016-09-08 17:23:2935#include "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h"
sdefresne9fb67692015-08-03 18:48:2236#include "components/version_info/version_info.h"
kalman6f984ae2015-09-18 17:21:5837#include "content/public/browser/navigation_controller.h"
rdevlin.croninf5863da2015-09-10 19:21:4538#include "content/public/browser/navigation_entry.h"
lazyboy4c82177a2016-10-18 00:04:0939#include "content/public/browser/service_worker_context.h"
40#include "content/public/browser/storage_partition.h"
kalman6f984ae2015-09-18 17:21:5841#include "content/public/browser/web_contents.h"
lazyboybd325ae2015-11-18 21:35:2642#include "content/public/common/content_switches.h"
falkenad185092016-06-16 06:10:0243#include "content/public/common/origin_util.h"
kalman6f984ae2015-09-18 17:21:5844#include "content/public/common/page_type.h"
lazyboybd325ae2015-11-18 21:35:2645#include "content/public/test/background_sync_test_util.h"
annekao1db36fd2015-07-29 17:09:1646#include "content/public/test/browser_test_utils.h"
lazyboy63b994a2017-06-30 21:20:2347#include "content/public/test/service_worker_test_helpers.h"
Istiaque Ahmed771aa8a22018-06-20 23:40:5348#include "extensions/browser/event_router.h"
kalman6f984ae2015-09-18 17:21:5849#include "extensions/browser/extension_host.h"
lazyboyc3e763a2015-12-09 23:09:5850#include "extensions/browser/extension_registry.h"
kalman6f984ae2015-09-18 17:21:5851#include "extensions/browser/process_manager.h"
Istiaque Ahmeda14ec482018-08-25 01:02:1852#include "extensions/common/api/test.h"
Devlin Cronina3fe3d602017-11-22 04:47:4353#include "extensions/common/extension_features.h"
Istiaque Ahmed771aa8a22018-06-20 23:40:5354#include "extensions/common/value_builder.h"
kalman6f984ae2015-09-18 17:21:5855#include "extensions/test/background_page_watcher.h"
annekao38685502015-07-14 17:46:3956#include "extensions/test/extension_test_message_listener.h"
Istiaque Ahmed805f6a83b2017-10-05 01:23:2657#include "extensions/test/result_catcher.h"
falkenad185092016-06-16 06:10:0258#include "net/dns/mock_host_resolver.h"
horo1eeddde2015-11-19 05:59:2559#include "net/test/embedded_test_server/embedded_test_server.h"
lazyboy63b994a2017-06-30 21:20:2360#include "url/url_constants.h"
annekao38685502015-07-14 17:46:3961
62namespace extensions {
63
kalman6f984ae2015-09-18 17:21:5864namespace {
65
lazyboy22eddc712015-12-10 21:16:2666// Returns the newly added WebContents.
67content::WebContents* AddTab(Browser* browser, const GURL& url) {
68 int starting_tab_count = browser->tab_strip_model()->count();
69 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:1970 browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
lazyboy22eddc712015-12-10 21:16:2671 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
72 int tab_count = browser->tab_strip_model()->count();
73 EXPECT_EQ(starting_tab_count + 1, tab_count);
74 return browser->tab_strip_model()->GetActiveWebContents();
75}
76
Istiaque Ahmedea5ed5042017-09-25 19:00:1677enum BindingsType { NATIVE_BINDINGS, JAVASCRIPT_BINDINGS };
78
lazyboy22eddc712015-12-10 21:16:2679class WebContentsLoadStopObserver : content::WebContentsObserver {
80 public:
81 explicit WebContentsLoadStopObserver(content::WebContents* web_contents)
82 : content::WebContentsObserver(web_contents),
83 load_stop_observed_(false) {}
84
85 void WaitForLoadStop() {
86 if (load_stop_observed_)
87 return;
88 message_loop_runner_ = new content::MessageLoopRunner;
89 message_loop_runner_->Run();
90 }
91
92 private:
93 void DidStopLoading() override {
94 load_stop_observed_ = true;
95 if (message_loop_runner_)
96 message_loop_runner_->Quit();
97 }
98
99 bool load_stop_observed_;
100 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
101
102 DISALLOW_COPY_AND_ASSIGN(WebContentsLoadStopObserver);
103};
104
Elly Fong-Jones4a4f21d2018-05-30 15:04:16105bool IsMacViewsMode() {
106// Some tests are flaky on Mac: <https://crbug.com/845979>. This helper function
107// is used to skip them.
108#if defined(OS_MACOSX)
109 return !views_mode_controller::IsViewsBrowserCocoa();
110#else
111 return false;
112#endif
113}
114
kalman6f984ae2015-09-18 17:21:58115} // namespace
116
Istiaque Ahmedea5ed5042017-09-25 19:00:16117class ServiceWorkerTest : public ExtensionApiTest,
118 public ::testing::WithParamInterface<BindingsType> {
annekao38685502015-07-14 17:46:39119 public:
lazyboy20167c22016-05-18 00:59:30120 ServiceWorkerTest() : current_channel_(version_info::Channel::STABLE) {}
Istiaque Ahmed7105f2a2017-10-07 01:11:59121 explicit ServiceWorkerTest(version_info::Channel channel)
122 : current_channel_(channel) {}
annekao38685502015-07-14 17:46:39123
124 ~ServiceWorkerTest() override {}
125
Devlin Cronina3fe3d602017-11-22 04:47:43126 void SetUp() override {
127 if (GetParam() == NATIVE_BINDINGS) {
Mostyn Bramley-Mooreb6a37c62018-09-04 21:43:35128 scoped_feature_list_.InitAndEnableFeature(
129 extensions_features::kNativeCrxBindings);
Devlin Cronina3fe3d602017-11-22 04:47:43130 } else {
131 DCHECK_EQ(JAVASCRIPT_BINDINGS, GetParam());
Mostyn Bramley-Mooreb6a37c62018-09-04 21:43:35132 scoped_feature_list_.InitAndDisableFeature(
133 extensions_features::kNativeCrxBindings);
Devlin Cronina3fe3d602017-11-22 04:47:43134 }
135 ExtensionApiTest::SetUp();
136 }
137
jam1a5b5582017-05-01 16:50:10138 void SetUpOnMainThread() override {
139 ExtensionApiTest::SetUpOnMainThread();
140 host_resolver()->AddRule("a.com", "127.0.0.1");
141 }
142
kalman6f984ae2015-09-18 17:21:58143 protected:
144 // Returns the ProcessManager for the test's profile.
145 ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
146
147 // Starts running a test from the background page test extension.
148 //
149 // This registers a service worker with |script_name|, and fetches the
150 // registration result.
Istiaque Ahmed93ff7f42018-08-31 01:42:22151 const Extension* StartTestFromBackgroundPage(const char* script_name) {
Istiaque Ahmed6475f542018-08-28 04:20:21152 ExtensionTestMessageListener ready_listener("ready", false);
kalman6f984ae2015-09-18 17:21:58153 const Extension* extension =
154 LoadExtension(test_data_dir_.AppendASCII("service_worker/background"));
155 CHECK(extension);
Istiaque Ahmed6475f542018-08-28 04:20:21156 CHECK(ready_listener.WaitUntilSatisfied());
157
kalman6f984ae2015-09-18 17:21:58158 ExtensionHost* background_host =
159 process_manager()->GetBackgroundHostForExtension(extension->id());
160 CHECK(background_host);
Istiaque Ahmed6475f542018-08-28 04:20:21161
kalman6f984ae2015-09-18 17:21:58162 std::string error;
163 CHECK(content::ExecuteScriptAndExtractString(
164 background_host->host_contents(),
165 base::StringPrintf("test.registerServiceWorker('%s')", script_name),
166 &error));
Istiaque Ahmed93ff7f42018-08-31 01:42:22167 if (!error.empty())
kalman6f984ae2015-09-18 17:21:58168 ADD_FAILURE() << "Got unexpected error " << error;
169 return extension;
170 }
171
172 // Navigates the browser to a new tab at |url|, waits for it to load, then
173 // returns it.
174 content::WebContents* Navigate(const GURL& url) {
175 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19176 browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
kalman6f984ae2015-09-18 17:21:58177 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
178 content::WebContents* web_contents =
179 browser()->tab_strip_model()->GetActiveWebContents();
180 content::WaitForLoadStop(web_contents);
181 return web_contents;
182 }
183
184 // Navigates the browser to |url| and returns the new tab's page type.
185 content::PageType NavigateAndGetPageType(const GURL& url) {
clamy1d7a4112018-06-15 15:47:16186 return Navigate(url)
187 ->GetController()
188 .GetLastCommittedEntry()
189 ->GetPageType();
kalman6f984ae2015-09-18 17:21:58190 }
191
192 // Extracts the innerText from |contents|.
193 std::string ExtractInnerText(content::WebContents* contents) {
194 std::string inner_text;
195 if (!content::ExecuteScriptAndExtractString(
196 contents,
197 "window.domAutomationController.send(document.body.innerText)",
198 &inner_text)) {
199 ADD_FAILURE() << "Failed to get inner text for "
200 << contents->GetVisibleURL();
201 }
202 return inner_text;
203 }
204
205 // Navigates the browser to |url|, then returns the innerText of the new
206 // tab's WebContents' main frame.
207 std::string NavigateAndExtractInnerText(const GURL& url) {
208 return ExtractInnerText(Navigate(url));
209 }
210
lazyboy4c82177a2016-10-18 00:04:09211 size_t GetWorkerRefCount(const GURL& origin) {
212 content::ServiceWorkerContext* sw_context =
213 content::BrowserContext::GetDefaultStoragePartition(
214 browser()->profile())
215 ->GetServiceWorkerContext();
216 base::RunLoop run_loop;
217 size_t ref_count = 0;
218 auto set_ref_count = [](size_t* ref_count, base::RunLoop* run_loop,
219 size_t external_request_count) {
220 *ref_count = external_request_count;
221 run_loop->Quit();
222 };
223 sw_context->CountExternalRequestsForTest(
Matt Falkenhagenc5cb4282017-09-07 08:43:42224 origin, base::BindOnce(set_ref_count, &ref_count, &run_loop));
lazyboy4c82177a2016-10-18 00:04:09225 run_loop.Run();
226 return ref_count;
227 }
228
annekao38685502015-07-14 17:46:39229 private:
lazyboy20167c22016-05-18 00:59:30230 // Sets the channel to "stable".
231 // Not useful after we've opened extension Service Workers to stable
232 // channel.
233 // TODO(lazyboy): Remove this when ExtensionServiceWorkersEnabled() is
234 // removed.
annekao38685502015-07-14 17:46:39235 ScopedCurrentChannel current_channel_;
kalman6f984ae2015-09-18 17:21:58236
Devlin Cronina3fe3d602017-11-22 04:47:43237 base::test::ScopedFeatureList scoped_feature_list_;
238
annekao38685502015-07-14 17:46:39239 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTest);
240};
241
Istiaque Ahmedccb444022018-06-19 02:11:12242class ServiceWorkerBasedBackgroundTest : public ServiceWorkerTest {
243 public:
244 ServiceWorkerBasedBackgroundTest()
245 : ServiceWorkerTest(
246 // Extensions APIs from SW are only enabled on trunk.
247 // It is important to set the channel early so that this change is
248 // visible in renderers running with service workers (and no
249 // extension).
250 version_info::Channel::UNKNOWN) {}
251 ~ServiceWorkerBasedBackgroundTest() override {}
252
253 void SetUpOnMainThread() override {
254 host_resolver()->AddRule("*", "127.0.0.1");
255 ASSERT_TRUE(embedded_test_server()->Start());
256 ServiceWorkerTest::SetUpOnMainThread();
257 }
258
259 private:
260 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBasedBackgroundTest);
261};
262
263// Tests that Service Worker based background pages can be loaded and they can
264// receive extension events.
265// The extension is installed and loaded during this step and it registers
266// an event listener for tabs.onCreated event. The step also verifies that tab
267// creation correctly fires the listener.
268IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, PRE_Basic) {
269 ExtensionTestMessageListener newtab_listener("CREATED", false);
270 newtab_listener.set_failure_message("CREATE_FAILED");
271 ExtensionTestMessageListener worker_listener("WORKER_RUNNING", false);
272 worker_listener.set_failure_message("NON_WORKER_SCOPE");
273 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
274 "service_worker/worker_based_background/basic"));
275 ASSERT_TRUE(extension);
276 const ExtensionId extension_id = extension->id();
277 EXPECT_TRUE(worker_listener.WaitUntilSatisfied());
278
279 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
280 content::WebContents* new_web_contents = AddTab(browser(), url);
281 EXPECT_TRUE(new_web_contents);
282 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
283
284 // Service Worker extension does not have ExtensionHost.
285 EXPECT_FALSE(process_manager()->GetBackgroundHostForExtension(extension_id));
286}
287
288// After browser restarts, this test step ensures that opening a tab fires
289// tabs.onCreated event listener to the extension without explicitly loading the
290// extension. This is because the extension registered a listener before browser
291// restarted in PRE_Basic.
Istiaque Ahmedad376e6b2018-09-13 22:48:25292IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, Basic) {
Istiaque Ahmedccb444022018-06-19 02:11:12293 ExtensionTestMessageListener newtab_listener("CREATED", false);
294 newtab_listener.set_failure_message("CREATE_FAILED");
295 const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
296 content::WebContents* new_web_contents = AddTab(browser(), url);
297 EXPECT_TRUE(new_web_contents);
298 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
299}
300
Istiaque Ahmedbf08f952018-10-02 01:22:04301// Tests chrome.runtime.onInstalled fires for extension service workers.
302IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, OnInstalledEvent) {
303 ASSERT_TRUE(RunExtensionTest(
304 "service_worker/worker_based_background/events_on_installed"))
305 << message_;
306}
307
Istiaque Ahmedf70ab222018-10-02 03:08:24308// Listens for "runtime.onStartup" event early so that tests can wait for the
309// event on startup (and not miss it).
310class ServiceWorkerOnStartupTest : public ServiceWorkerBasedBackgroundTest {
311 public:
312 ServiceWorkerOnStartupTest() = default;
313 ~ServiceWorkerOnStartupTest() override = default;
314
315 bool WaitForOnStartupEvent() { return listener_->WaitUntilSatisfied(); }
316
317 void CreatedBrowserMainParts(content::BrowserMainParts* main_parts) override {
318 // At this point, the notification service is initialized but the profile
319 // and extensions have not.
320 listener_ = std::make_unique<ExtensionTestMessageListener>(
321 "onStartup event", false);
322 ServiceWorkerBasedBackgroundTest::CreatedBrowserMainParts(main_parts);
323 }
324
325 private:
326 std::unique_ptr<ExtensionTestMessageListener> listener_;
327
328 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerOnStartupTest);
329};
330
331// Tests "runtime.onStartup" for extension SW.
332IN_PROC_BROWSER_TEST_P(ServiceWorkerOnStartupTest, PRE_Event) {
333 ASSERT_TRUE(RunExtensionTest(
334 "service_worker/worker_based_background/on_startup_event"))
335 << message_;
336}
337
338IN_PROC_BROWSER_TEST_P(ServiceWorkerOnStartupTest, Event) {
339 EXPECT_TRUE(WaitForOnStartupEvent());
340}
341
Istiaque Ahmeda14ec482018-08-25 01:02:18342// Class that dispatches an event to |extension_id| right after a
343// non-lazy listener to the event is added from the extension's Service Worker.
Istiaque Ahmed771aa8a22018-06-20 23:40:53344class EarlyWorkerMessageSender : public EventRouter::Observer {
345 public:
346 EarlyWorkerMessageSender(content::BrowserContext* browser_context,
Istiaque Ahmeda14ec482018-08-25 01:02:18347 const ExtensionId& extension_id,
348 std::unique_ptr<Event> event)
Istiaque Ahmed771aa8a22018-06-20 23:40:53349 : browser_context_(browser_context),
350 event_router_(EventRouter::EventRouter::Get(browser_context_)),
351 extension_id_(extension_id),
Istiaque Ahmeda14ec482018-08-25 01:02:18352 event_(std::move(event)),
Istiaque Ahmed771aa8a22018-06-20 23:40:53353 listener_("PASS", false) {
354 DCHECK(browser_context_);
355 listener_.set_failure_message("FAIL");
Istiaque Ahmeda14ec482018-08-25 01:02:18356 event_router_->RegisterObserver(this, event_->event_name);
Istiaque Ahmed771aa8a22018-06-20 23:40:53357 }
358
359 ~EarlyWorkerMessageSender() override {
360 event_router_->UnregisterObserver(this);
361 }
362
363 // EventRouter::Observer:
364 void OnListenerAdded(const EventListenerInfo& details) override {
Istiaque Ahmeda14ec482018-08-25 01:02:18365 if (!event_ || extension_id_ != details.extension_id ||
366 event_->event_name != details.event_name) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53367 return;
Istiaque Ahmeda14ec482018-08-25 01:02:18368 }
369
Istiaque Ahmed771aa8a22018-06-20 23:40:53370 const bool is_lazy_listener = details.browser_context == nullptr;
371 if (is_lazy_listener) {
372 // Wait for the non-lazy listener as we want to exercise the code to
373 // dispatch the event right after the Service Worker registration is
374 // completing.
375 return;
376 }
Istiaque Ahmeda14ec482018-08-25 01:02:18377 DispatchEvent(std::move(event_));
Istiaque Ahmed771aa8a22018-06-20 23:40:53378 }
379
380 bool SendAndWait() { return listener_.WaitUntilSatisfied(); }
381
382 private:
383 static constexpr const char* const kTestOnMessageEventName = "test.onMessage";
384
Istiaque Ahmeda14ec482018-08-25 01:02:18385 void DispatchEvent(std::unique_ptr<Event> event) {
Istiaque Ahmed771aa8a22018-06-20 23:40:53386 EventRouter::Get(browser_context_)
387 ->DispatchEventToExtension(extension_id_, std::move(event));
388 }
389
390 content::BrowserContext* const browser_context_ = nullptr;
391 EventRouter* const event_router_ = nullptr;
392 const ExtensionId extension_id_;
Istiaque Ahmeda14ec482018-08-25 01:02:18393 std::unique_ptr<Event> event_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53394 ExtensionTestMessageListener listener_;
Istiaque Ahmed771aa8a22018-06-20 23:40:53395
396 DISALLOW_COPY_AND_ASSIGN(EarlyWorkerMessageSender);
397};
398
399// Tests that extension event dispatch works correctly right after extension
400// installation registers its Service Worker.
401// Regression test for: https://crbug.com/850792.
402IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, EarlyEventDispatch) {
403 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
Istiaque Ahmeda14ec482018-08-25 01:02:18404
405 // Build "test.onMessage" event for dispatch.
406 auto event = std::make_unique<Event>(
407 events::FOR_TEST, extensions::api::test::OnMessage::kEventName,
408 base::ListValue::From(base::JSONReader::Read(
409 R"([{"data": "hello", "lastMessage": true}])")),
410 profile());
411
412 EarlyWorkerMessageSender sender(profile(), kId, std::move(event));
Istiaque Ahmed771aa8a22018-06-20 23:40:53413 // pkplfbidichfdicaijlchgnapepdginl
414 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
415 "service_worker/worker_based_background/early_event_dispatch"));
416 CHECK(extension);
417 EXPECT_EQ(kId, extension->id());
418 EXPECT_TRUE(sender.SendAndWait());
419}
420
Istiaque Ahmeda14ec482018-08-25 01:02:18421// Tests that filtered events dispatches correctly right after a non-lazy
422// listener is registered for that event (and before the corresponding lazy
423// listener is registered).
424IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest,
425 EarlyFilteredEventDispatch) {
426 const ExtensionId kId("pkplfbidichfdicaijlchgnapepdginl");
427
428 // Add minimal details required to dispatch webNavigation.onCommitted event:
429 extensions::api::web_navigation::OnCommitted::Details details;
430 details.transition_type =
431 extensions::api::web_navigation::TRANSITION_TYPE_TYPED;
432
433 // Build a dummy onCommited event to dispatch.
434 auto on_committed_event = std::make_unique<Event>(
435 events::WEB_NAVIGATION_ON_COMMITTED, "webNavigation.onCommitted",
436 api::web_navigation::OnCommitted::Create(details), profile());
437 // The filter will match the listener filter registered from the extension.
438 EventFilteringInfo info;
439 info.url = GURL("http://foo.com/a.html");
440 on_committed_event->filter_info = info;
441
442 EarlyWorkerMessageSender sender(profile(), kId,
443 std::move(on_committed_event));
444
445 // pkplfbidichfdicaijlchgnapepdginl
446 const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
447 "service_worker/worker_based_background/early_filtered_event_dispatch"));
448 ASSERT_TRUE(extension);
449 EXPECT_EQ(kId, extension->id());
450 EXPECT_TRUE(sender.SendAndWait());
451}
452
lazyboybd325ae2015-11-18 21:35:26453class ServiceWorkerBackgroundSyncTest : public ServiceWorkerTest {
454 public:
455 ServiceWorkerBackgroundSyncTest() {}
456 ~ServiceWorkerBackgroundSyncTest() override {}
457
458 void SetUpCommandLine(base::CommandLine* command_line) override {
459 // ServiceWorkerRegistration.sync requires experimental flag.
460 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16461 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboybd325ae2015-11-18 21:35:26462 ServiceWorkerTest::SetUpCommandLine(command_line);
463 }
464
465 void SetUp() override {
Robbie McElrathdb12d8e2018-09-18 21:20:40466 content::background_sync_test_util::SetIgnoreNetworkChanges(true);
lazyboybd325ae2015-11-18 21:35:26467 ServiceWorkerTest::SetUp();
468 }
469
470 private:
471 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBackgroundSyncTest);
472};
473
lazyboy561b7de2015-11-19 19:27:30474class ServiceWorkerPushMessagingTest : public ServiceWorkerTest {
475 public:
476 ServiceWorkerPushMessagingTest()
Sylvain Defresne212b4b02018-10-11 16:32:05477 : scoped_testing_factory_installer_(
478 base::BindRepeating(&gcm::FakeGCMProfileService::Build)),
479 gcm_driver_(nullptr),
480 push_service_(nullptr) {}
481
lazyboy561b7de2015-11-19 19:27:30482 ~ServiceWorkerPushMessagingTest() override {}
483
484 void GrantNotificationPermissionForTest(const GURL& url) {
Peter Beverloodd4ef1e2018-06-21 15:41:04485 NotificationPermissionContext::UpdatePermission(profile(), url.GetOrigin(),
486 CONTENT_SETTING_ALLOW);
lazyboy561b7de2015-11-19 19:27:30487 }
488
489 PushMessagingAppIdentifier GetAppIdentifierForServiceWorkerRegistration(
avia2f4804a2015-12-24 23:11:13490 int64_t service_worker_registration_id,
lazyboy561b7de2015-11-19 19:27:30491 const GURL& origin) {
492 PushMessagingAppIdentifier app_identifier =
493 PushMessagingAppIdentifier::FindByServiceWorker(
494 profile(), origin, service_worker_registration_id);
495
496 EXPECT_FALSE(app_identifier.is_null());
497 return app_identifier;
498 }
499
500 // ExtensionApiTest overrides.
501 void SetUpCommandLine(base::CommandLine* command_line) override {
peter9de96272015-12-04 15:23:27502 command_line->AppendSwitch(
Istiaque Ahmedea5ed5042017-09-25 19:00:16503 ::switches::kEnableExperimentalWebPlatformFeatures);
lazyboy561b7de2015-11-19 19:27:30504 ServiceWorkerTest::SetUpCommandLine(command_line);
505 }
Tanja Gornak89128fd2018-09-18 08:49:34506
lazyboy561b7de2015-11-19 19:27:30507 void SetUpOnMainThread() override {
miguelg9b502862017-04-24 18:13:53508 NotificationDisplayServiceFactory::GetInstance()->SetTestingFactory(
Sylvain Defresne711ff6b2018-10-04 12:33:54509 profile(),
510 base::BindRepeating(&StubNotificationDisplayService::FactoryForTests));
miguelg9b502862017-04-24 18:13:53511
johnmea5045732016-09-08 17:23:29512 gcm::FakeGCMProfileService* gcm_service =
513 static_cast<gcm::FakeGCMProfileService*>(
Tanja Gornak89128fd2018-09-18 08:49:34514 gcm::GCMProfileServiceFactory::GetForProfile(profile()));
johnmea5045732016-09-08 17:23:29515 gcm_driver_ = static_cast<instance_id::FakeGCMDriverForInstanceID*>(
516 gcm_service->driver());
lazyboy561b7de2015-11-19 19:27:30517 push_service_ = PushMessagingServiceFactory::GetForProfile(profile());
518
519 ServiceWorkerTest::SetUpOnMainThread();
520 }
521
johnmea5045732016-09-08 17:23:29522 instance_id::FakeGCMDriverForInstanceID* gcm_driver() const {
523 return gcm_driver_;
524 }
lazyboy561b7de2015-11-19 19:27:30525 PushMessagingServiceImpl* push_service() const { return push_service_; }
526
527 private:
Sylvain Defresne212b4b02018-10-11 16:32:05528 gcm::GCMProfileServiceFactory::ScopedTestingFactoryInstaller
529 scoped_testing_factory_installer_;
530
johnmea5045732016-09-08 17:23:29531 instance_id::FakeGCMDriverForInstanceID* gcm_driver_;
lazyboy561b7de2015-11-19 19:27:30532 PushMessagingServiceImpl* push_service_;
533
534 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPushMessagingTest);
535};
536
Istiaque Ahmed805f6a83b2017-10-05 01:23:26537class ServiceWorkerLazyBackgroundTest : public ServiceWorkerTest {
538 public:
Istiaque Ahmed7105f2a2017-10-07 01:11:59539 ServiceWorkerLazyBackgroundTest()
540 : ServiceWorkerTest(
541 // Extensions APIs from SW are only enabled on trunk.
542 // It is important to set the channel early so that this change is
543 // visible in renderers running with service workers (and no
544 // extension).
545 version_info::Channel::UNKNOWN) {}
Istiaque Ahmed805f6a83b2017-10-05 01:23:26546 ~ServiceWorkerLazyBackgroundTest() override {}
547
548 void SetUpCommandLine(base::CommandLine* command_line) override {
549 ServiceWorkerTest::SetUpCommandLine(command_line);
550 // Disable background network activity as it can suddenly bring the Lazy
551 // Background Page alive.
552 command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
553 command_line->AppendSwitch(::switches::kNoProxyServer);
554 }
555
556 void SetUpInProcessBrowserTestFixture() override {
557 ServiceWorkerTest::SetUpInProcessBrowserTestFixture();
558 // Set shorter delays to prevent test timeouts.
559 ProcessManager::SetEventPageIdleTimeForTesting(1);
560 ProcessManager::SetEventPageSuspendingTimeForTesting(1);
561 }
562
563 private:
564 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerLazyBackgroundTest);
565};
566
Istiaque Ahmedea5ed5042017-09-25 19:00:16567IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, RegisterSucceeds) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22568 StartTestFromBackgroundPage("register.js");
annekao38685502015-07-14 17:46:39569}
570
Istiaque Ahmedea5ed5042017-09-25 19:00:16571IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, UpdateRefreshesServiceWorker) {
Francois Doraye6fb2d02017-10-18 21:29:13572 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboyc3e763a2015-12-09 23:09:58573 base::ScopedTempDir scoped_temp_dir;
574 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
575 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
576 .AppendASCII("update")
577 .AppendASCII("service_worker.pem");
vabr9142fe22016-09-08 13:19:22578 base::FilePath path_v1 =
579 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
580 .AppendASCII("update")
581 .AppendASCII("v1"),
582 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
583 pem_path, base::FilePath());
584 base::FilePath path_v2 =
585 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
586 .AppendASCII("update")
587 .AppendASCII("v2"),
588 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
589 pem_path, base::FilePath());
lazyboyc3e763a2015-12-09 23:09:58590 const char* kId = "hfaanndiiilofhfokeanhddpkfffchdi";
591
592 ExtensionTestMessageListener listener_v1("Pong from version 1", false);
593 listener_v1.set_failure_message("FAILURE_V1");
594 // Install version 1.0 of the extension.
595 ASSERT_TRUE(InstallExtension(path_v1, 1));
596 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
597 ->enabled_extensions()
598 .GetByID(kId));
599 EXPECT_TRUE(listener_v1.WaitUntilSatisfied());
600
601 ExtensionTestMessageListener listener_v2("Pong from version 2", false);
602 listener_v2.set_failure_message("FAILURE_V2");
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 EXPECT_TRUE(listener_v2.WaitUntilSatisfied());
610}
611
[email protected]2ef85d562017-09-15 18:41:52612// TODO(crbug.com/765736) Fix the test.
Istiaque Ahmedea5ed5042017-09-25 19:00:16613IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, DISABLED_UpdateWithoutSkipWaiting) {
Francois Doraye6fb2d02017-10-18 21:29:13614 base::ScopedAllowBlockingForTesting allow_blocking;
lazyboy22eddc712015-12-10 21:16:26615 base::ScopedTempDir scoped_temp_dir;
616 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
617 base::FilePath pem_path = test_data_dir_.AppendASCII("service_worker")
618 .AppendASCII("update_without_skip_waiting")
619 .AppendASCII("update_without_skip_waiting.pem");
vabr9142fe22016-09-08 13:19:22620 base::FilePath path_v1 =
621 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
622 .AppendASCII("update_without_skip_waiting")
623 .AppendASCII("v1"),
624 scoped_temp_dir.GetPath().AppendASCII("v1.crx"),
625 pem_path, base::FilePath());
626 base::FilePath path_v2 =
627 PackExtensionWithOptions(test_data_dir_.AppendASCII("service_worker")
628 .AppendASCII("update_without_skip_waiting")
629 .AppendASCII("v2"),
630 scoped_temp_dir.GetPath().AppendASCII("v2.crx"),
631 pem_path, base::FilePath());
lazyboy22eddc712015-12-10 21:16:26632 const char* kId = "mhnnnflgagdakldgjpfcofkiocpdmogl";
633
634 // Install version 1.0 of the extension.
635 ASSERT_TRUE(InstallExtension(path_v1, 1));
636 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
637 ->enabled_extensions()
638 .GetByID(kId));
639 const Extension* extension = extensions::ExtensionRegistry::Get(profile())
640 ->enabled_extensions()
641 .GetByID(kId);
642
643 ExtensionTestMessageListener listener1("Pong from version 1", false);
644 listener1.set_failure_message("FAILURE");
645 content::WebContents* web_contents =
646 AddTab(browser(), extension->GetResourceURL("page.html"));
647 EXPECT_TRUE(listener1.WaitUntilSatisfied());
648
649 // Update to version 2.0.
650 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
651 EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())
652 ->enabled_extensions()
653 .GetByID(kId));
654 const Extension* extension_after_update =
655 extensions::ExtensionRegistry::Get(profile())
656 ->enabled_extensions()
657 .GetByID(kId);
658
659 // Service worker version 2 would be installed but it won't be controlling
660 // the extension page yet.
661 ExtensionTestMessageListener listener2("Pong from version 1", false);
662 listener2.set_failure_message("FAILURE");
663 web_contents =
664 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
665 EXPECT_TRUE(listener2.WaitUntilSatisfied());
666
667 // Navigate the tab away from the extension page so that no clients are
668 // using the service worker.
669 // Note that just closing the tab with WebContentsDestroyedWatcher doesn't
670 // seem to be enough because it returns too early.
671 WebContentsLoadStopObserver navigate_away_observer(web_contents);
672 web_contents->GetController().LoadURL(
673 GURL(url::kAboutBlankURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED,
674 std::string());
675 navigate_away_observer.WaitForLoadStop();
676
677 // Now expect service worker version 2 to control the extension page.
678 ExtensionTestMessageListener listener3("Pong from version 2", false);
679 listener3.set_failure_message("FAILURE");
680 web_contents =
681 AddTab(browser(), extension_after_update->GetResourceURL("page.html"));
682 EXPECT_TRUE(listener3.WaitUntilSatisfied());
683}
684
Istiaque Ahmedea5ed5042017-09-25 19:00:16685IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, FetchArbitraryPaths) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22686 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
annekao1db36fd2015-07-29 17:09:16687
kalman6f984ae2015-09-18 17:21:58688 // Open some arbirary paths. Their contents should be what the service worker
689 // responds with, which in this case is the path of the fetch.
690 EXPECT_EQ(
691 "Caught a fetch for /index.html",
692 NavigateAndExtractInnerText(extension->GetResourceURL("index.html")));
693 EXPECT_EQ("Caught a fetch for /path/to/other.html",
694 NavigateAndExtractInnerText(
695 extension->GetResourceURL("path/to/other.html")));
696 EXPECT_EQ("Caught a fetch for /some/text/file.txt",
697 NavigateAndExtractInnerText(
698 extension->GetResourceURL("some/text/file.txt")));
699 EXPECT_EQ("Caught a fetch for /no/file/extension",
700 NavigateAndExtractInnerText(
701 extension->GetResourceURL("no/file/extension")));
702 EXPECT_EQ("Caught a fetch for /",
703 NavigateAndExtractInnerText(extension->GetResourceURL("")));
annekao1db36fd2015-07-29 17:09:16704}
705
Kenichi Ishibashi773b82972018-08-30 07:02:03706IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
707 FetchExtensionResourceFromServiceWorker) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22708 const Extension* extension = StartTestFromBackgroundPage("fetch_from_sw.js");
Kenichi Ishibashi773b82972018-08-30 07:02:03709 ASSERT_TRUE(extension);
710
711 // The service worker in this test tries to load 'hello.txt' via fetch()
712 // and sends back the content of the file, which should be 'hello'.
713 const char* kScript = R"(
714 let channel = new MessageChannel();
715 test.waitForMessage(channel.port1).then(message => {
716 window.domAutomationController.send(message);
717 });
718 test.registeredServiceWorker.postMessage(
719 {port: channel.port2}, [channel.port2]);
720 )";
721 EXPECT_EQ("hello", ExecuteScriptInBackgroundPage(extension->id(), kScript));
722}
723
Istiaque Ahmedea5ed5042017-09-25 19:00:16724IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, SWServedBackgroundPageReceivesEvent) {
lazyboy52c3bcf2016-01-08 00:11:29725 const Extension* extension =
Istiaque Ahmed93ff7f42018-08-31 01:42:22726 StartTestFromBackgroundPage("replace_background.js");
lazyboy52c3bcf2016-01-08 00:11:29727 ExtensionHost* background_page =
728 process_manager()->GetBackgroundHostForExtension(extension->id());
729 ASSERT_TRUE(background_page);
730
731 // Close the background page and start it again so that the service worker
732 // will start controlling pages.
733 background_page->Close();
734 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
735 background_page = nullptr;
Peter Kasting341e1fb2018-02-24 00:03:01736 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
lazyboy52c3bcf2016-01-08 00:11:29737 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
738
739 // Since the SW is now controlling the extension, the SW serves the background
740 // script. page.html sends a message to the background script and we verify
741 // that the SW served background script correctly receives the message/event.
742 ExtensionTestMessageListener listener("onMessage/SW BG.", false);
743 listener.set_failure_message("onMessage/original BG.");
744 content::WebContents* web_contents =
745 AddTab(browser(), extension->GetResourceURL("page.html"));
746 ASSERT_TRUE(web_contents);
747 EXPECT_TRUE(listener.WaitUntilSatisfied());
748}
749
Matt Falkenhagena612fc02018-05-30 00:35:39750IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, SWServedBackgroundPage) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22751 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
annekao49241182015-08-18 17:14:01752
kalman6f984ae2015-09-18 17:21:58753 std::string kExpectedInnerText = "background.html contents for testing.";
annekao49241182015-08-18 17:14:01754
kalman6f984ae2015-09-18 17:21:58755 // Sanity check that the background page has the expected content.
756 ExtensionHost* background_page =
757 process_manager()->GetBackgroundHostForExtension(extension->id());
758 ASSERT_TRUE(background_page);
759 EXPECT_EQ(kExpectedInnerText,
760 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01761
kalman6f984ae2015-09-18 17:21:58762 // Close the background page.
763 background_page->Close();
764 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
765 background_page = nullptr;
766
767 // Start it again.
Peter Kasting341e1fb2018-02-24 00:03:01768 process_manager()->WakeEventPage(extension->id(), base::DoNothing());
kalman6f984ae2015-09-18 17:21:58769 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
770
Matt Falkenhagena612fc02018-05-30 00:35:39771 // The service worker should get a fetch event for the background page.
kalman6f984ae2015-09-18 17:21:58772 background_page =
773 process_manager()->GetBackgroundHostForExtension(extension->id());
774 ASSERT_TRUE(background_page);
775 content::WaitForLoadStop(background_page->host_contents());
776
kalman6f984ae2015-09-18 17:21:58777 EXPECT_EQ("Caught a fetch for /background.html",
778 ExtractInnerText(background_page->host_contents()));
annekao49241182015-08-18 17:14:01779}
780
Istiaque Ahmedea5ed5042017-09-25 19:00:16781IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58782 ServiceWorkerPostsMessageToBackgroundClient) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22783 const Extension* extension =
784 StartTestFromBackgroundPage("post_message_to_background_client.js");
annekao533482222015-08-21 23:23:53785
kalman6f984ae2015-09-18 17:21:58786 // The service worker in this test simply posts a message to the background
787 // client it receives from getBackgroundClient().
788 const char* kScript =
789 "var messagePromise = null;\n"
790 "if (test.lastMessageFromServiceWorker) {\n"
791 " messagePromise = Promise.resolve(test.lastMessageFromServiceWorker);\n"
792 "} else {\n"
793 " messagePromise = test.waitForMessage(navigator.serviceWorker);\n"
794 "}\n"
795 "messagePromise.then(function(message) {\n"
796 " window.domAutomationController.send(String(message == 'success'));\n"
797 "})\n";
798 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53799}
800
Istiaque Ahmedea5ed5042017-09-25 19:00:16801IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58802 BackgroundPagePostsMessageToServiceWorker) {
803 const Extension* extension =
Istiaque Ahmed93ff7f42018-08-31 01:42:22804 StartTestFromBackgroundPage("post_message_to_sw.js");
annekao533482222015-08-21 23:23:53805
kalman6f984ae2015-09-18 17:21:58806 // The service worker in this test waits for a message, then echoes it back
807 // by posting a message to the background page via getBackgroundClient().
808 const char* kScript =
809 "var mc = new MessageChannel();\n"
810 "test.waitForMessage(mc.port1).then(function(message) {\n"
811 " window.domAutomationController.send(String(message == 'hello'));\n"
812 "});\n"
813 "test.registeredServiceWorker.postMessage(\n"
814 " {message: 'hello', port: mc.port2}, [mc.port2])\n";
815 EXPECT_EQ("true", ExecuteScriptInBackgroundPage(extension->id(), kScript));
annekao533482222015-08-21 23:23:53816}
817
Istiaque Ahmedea5ed5042017-09-25 19:00:16818IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
rdevlin.croninf5863da2015-09-10 19:21:45819 ServiceWorkerSuspensionOnExtensionUnload) {
kalman6f984ae2015-09-18 17:21:58820 // For this test, only hold onto the extension's ID and URL + a function to
821 // get a resource URL, because we're going to be disabling and uninstalling
822 // it, which will invalidate the pointer.
823 std::string extension_id;
824 GURL extension_url;
825 {
Istiaque Ahmed93ff7f42018-08-31 01:42:22826 const Extension* extension = StartTestFromBackgroundPage("fetch.js");
kalman6f984ae2015-09-18 17:21:58827 extension_id = extension->id();
828 extension_url = extension->url();
829 }
830 auto get_resource_url = [&extension_url](const std::string& path) {
831 return Extension::GetResourceURL(extension_url, path);
832 };
rdevlin.croninf5863da2015-09-10 19:21:45833
kalman6f984ae2015-09-18 17:21:58834 // Fetch should route to the service worker.
835 EXPECT_EQ("Caught a fetch for /index.html",
836 NavigateAndExtractInnerText(get_resource_url("index.html")));
rdevlin.croninf5863da2015-09-10 19:21:45837
kalman6f984ae2015-09-18 17:21:58838 // Disable the extension. Opening the page should fail.
839 extension_service()->DisableExtension(extension_id,
Minh X. Nguyen45479012017-08-18 21:35:36840 disable_reason::DISABLE_USER_ACTION);
rdevlin.croninf5863da2015-09-10 19:21:45841 base::RunLoop().RunUntilIdle();
rdevlin.croninf5863da2015-09-10 19:21:45842
kalman6f984ae2015-09-18 17:21:58843 EXPECT_EQ(content::PAGE_TYPE_ERROR,
844 NavigateAndGetPageType(get_resource_url("index.html")));
845 EXPECT_EQ(content::PAGE_TYPE_ERROR,
846 NavigateAndGetPageType(get_resource_url("other.html")));
847
848 // Re-enable the extension. Opening pages should immediately start to succeed
849 // again.
rdevlin.croninf5863da2015-09-10 19:21:45850 extension_service()->EnableExtension(extension_id);
851 base::RunLoop().RunUntilIdle();
852
kalman6f984ae2015-09-18 17:21:58853 EXPECT_EQ("Caught a fetch for /index.html",
854 NavigateAndExtractInnerText(get_resource_url("index.html")));
855 EXPECT_EQ("Caught a fetch for /other.html",
856 NavigateAndExtractInnerText(get_resource_url("other.html")));
857 EXPECT_EQ("Caught a fetch for /another.html",
858 NavigateAndExtractInnerText(get_resource_url("another.html")));
rdevlin.croninf5863da2015-09-10 19:21:45859
kalman6f984ae2015-09-18 17:21:58860 // Uninstall the extension. Opening pages should fail again.
861 base::string16 error;
862 extension_service()->UninstallExtension(
Devlin Cronin218df7f2017-11-21 21:41:31863 extension_id, UninstallReason::UNINSTALL_REASON_FOR_TESTING, &error);
kalman6f984ae2015-09-18 17:21:58864 base::RunLoop().RunUntilIdle();
865
866 EXPECT_EQ(content::PAGE_TYPE_ERROR,
867 NavigateAndGetPageType(get_resource_url("index.html")));
868 EXPECT_EQ(content::PAGE_TYPE_ERROR,
869 NavigateAndGetPageType(get_resource_url("other.html")));
870 EXPECT_EQ(content::PAGE_TYPE_ERROR,
871 NavigateAndGetPageType(get_resource_url("anotherother.html")));
872 EXPECT_EQ(content::PAGE_TYPE_ERROR,
873 NavigateAndGetPageType(get_resource_url("final.html")));
874}
875
Istiaque Ahmedea5ed5042017-09-25 19:00:16876IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, BackgroundPageIsWokenIfAsleep) {
Istiaque Ahmed93ff7f42018-08-31 01:42:22877 const Extension* extension = StartTestFromBackgroundPage("wake_on_fetch.js");
kalman6f984ae2015-09-18 17:21:58878
879 // Navigate to special URLs that this test's service worker recognises, each
880 // making a check then populating the response with either "true" or "false".
881 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
882 "background-client-is-awake")));
883 EXPECT_EQ("true", NavigateAndExtractInnerText(
884 extension->GetResourceURL("ping-background-client")));
885 // Ping more than once for good measure.
886 EXPECT_EQ("true", NavigateAndExtractInnerText(
887 extension->GetResourceURL("ping-background-client")));
888
889 // Shut down the event page. The SW should detect that it's closed, but still
890 // be able to ping it.
891 ExtensionHost* background_page =
892 process_manager()->GetBackgroundHostForExtension(extension->id());
893 ASSERT_TRUE(background_page);
894 background_page->Close();
895 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
896
897 EXPECT_EQ("false", NavigateAndExtractInnerText(extension->GetResourceURL(
898 "background-client-is-awake")));
899 EXPECT_EQ("true", NavigateAndExtractInnerText(
900 extension->GetResourceURL("ping-background-client")));
901 EXPECT_EQ("true", NavigateAndExtractInnerText(
902 extension->GetResourceURL("ping-background-client")));
903 EXPECT_EQ("true", NavigateAndExtractInnerText(extension->GetResourceURL(
904 "background-client-is-awake")));
905}
906
Istiaque Ahmedea5ed5042017-09-25 19:00:16907IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
kalman6f984ae2015-09-18 17:21:58908 GetBackgroundClientFailsWithNoBackgroundPage) {
909 // This extension doesn't have a background page, only a tab at page.html.
910 // The service worker it registers tries to call getBackgroundClient() and
911 // should fail.
912 // Note that this also tests that service workers can be registered from tabs.
913 EXPECT_TRUE(RunExtensionSubtest("service_worker/no_background", "page.html"));
rdevlin.croninf5863da2015-09-10 19:21:45914}
915
Istiaque Ahmedea5ed5042017-09-25 19:00:16916IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, NotificationAPI) {
lazyboy6ddb7d62015-11-10 23:15:27917 EXPECT_TRUE(RunExtensionSubtest("service_worker/notifications/has_permission",
918 "page.html"));
919}
920
Istiaque Ahmedea5ed5042017-09-25 19:00:16921IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WebAccessibleResourcesFetch) {
lazyboyaea32c22016-01-04 21:37:07922 EXPECT_TRUE(RunExtensionSubtest(
923 "service_worker/web_accessible_resources/fetch/", "page.html"));
924}
925
Istiaque Ahmed75ad1d92018-08-30 05:16:54926IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, TabsCreate) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:16927 if (IsMacViewsMode())
928 return;
lazyboyee4adef2016-05-24 00:55:16929 // 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/tabs_create"), kFlagNone);
933 ASSERT_TRUE(extension);
934 ui_test_utils::NavigateToURL(browser(),
935 extension->GetResourceURL("page.html"));
936 content::WebContents* web_contents =
937 browser()->tab_strip_model()->GetActiveWebContents();
938
939 int starting_tab_count = browser()->tab_strip_model()->count();
940 std::string result;
941 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
942 web_contents, "window.runServiceWorker()", &result));
943 ASSERT_EQ("chrome.tabs.create callback", result);
944 EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count());
945
946 // Check extension shutdown path.
947 UnloadExtension(extension->id());
948 EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count());
949}
950
Istiaque Ahmedea5ed5042017-09-25 19:00:16951IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, Events) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:16952 if (IsMacViewsMode())
953 return;
lazyboye7847242017-06-07 23:29:18954 // Extensions APIs from SW are only enabled on trunk.
955 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
956 const Extension* extension = LoadExtensionWithFlags(
957 test_data_dir_.AppendASCII("service_worker/events"), kFlagNone);
958 ASSERT_TRUE(extension);
959 ui_test_utils::NavigateToURL(browser(),
960 extension->GetResourceURL("page.html"));
961 content::WebContents* web_contents =
962 browser()->tab_strip_model()->GetActiveWebContents();
963 std::string result;
964 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
965 web_contents, "window.runEventTest()", &result));
966 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
967}
968
Istiaque Ahmedea5ed5042017-09-25 19:00:16969IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, EventsToStoppedWorker) {
lazyboy63b994a2017-06-30 21:20:23970 // Extensions APIs from SW are only enabled on trunk.
971 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
972 const Extension* extension = LoadExtensionWithFlags(
973 test_data_dir_.AppendASCII("service_worker/events_to_stopped_worker"),
974 kFlagNone);
975 ASSERT_TRUE(extension);
976 ui_test_utils::NavigateToURL(browser(),
977 extension->GetResourceURL("page.html"));
978 content::WebContents* web_contents =
979 browser()->tab_strip_model()->GetActiveWebContents();
980 {
981 std::string result;
982 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
983 web_contents, "window.runServiceWorker()", &result));
984 ASSERT_EQ("ready", result);
985
986 base::RunLoop run_loop;
987 content::StoragePartition* storage_partition =
988 content::BrowserContext::GetDefaultStoragePartition(
989 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:00990 content::StopServiceWorkerForScope(
lazyboy63b994a2017-06-30 21:20:23991 storage_partition->GetServiceWorkerContext(),
992 // The service worker is registered at the top level scope.
993 extension->url(), run_loop.QuitClosure());
994 run_loop.Run();
995 }
996
997 std::string result;
998 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
999 web_contents, "window.createTabThenUpdate()", &result));
1000 ASSERT_EQ("chrome.tabs.onUpdated callback", result);
1001}
1002
Istiaque Ahmed805f6a83b2017-10-05 01:23:261003// Tests that events to service worker arrives correctly event if the owner
1004// extension of the worker is not running.
1005IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmedb8e24bdb2018-09-13 15:17:251006 EventsToStoppedExtension) {
Istiaque Ahmed805f6a83b2017-10-05 01:23:261007 LazyBackgroundObserver lazy_observer;
1008 ResultCatcher catcher;
1009 const Extension* extension = LoadExtensionWithFlags(
1010 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
1011 kFlagNone);
1012 ASSERT_TRUE(extension);
1013 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1014
1015 ProcessManager* pm = ProcessManager::Get(browser()->profile());
1016 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:301017 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed805f6a83b2017-10-05 01:23:261018
1019 // |extension|'s background page opens a tab to its resource.
1020 content::WebContents* extension_web_contents =
1021 browser()->tab_strip_model()->GetActiveWebContents();
1022 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1023 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1024 extension_web_contents->GetURL().spec());
1025 {
1026 // Let the service worker start and register a listener to
1027 // chrome.tabs.onCreated event.
1028 ExtensionTestMessageListener add_listener_done("listener-added", false);
1029 content::ExecuteScriptAsync(extension_web_contents,
1030 "window.runServiceWorkerAsync()");
1031 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1032
1033 base::RunLoop run_loop;
1034 content::StoragePartition* storage_partition =
1035 content::BrowserContext::GetDefaultStoragePartition(
1036 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001037 content::StopServiceWorkerForScope(
Istiaque Ahmed805f6a83b2017-10-05 01:23:261038 storage_partition->GetServiceWorkerContext(),
1039 // The service worker is registered at the top level scope.
1040 extension->url(), run_loop.QuitClosure());
1041 run_loop.Run();
1042 }
1043
1044 // Close the tab to |extension|'s resource. This will also close the
1045 // extension's event page.
1046 browser()->tab_strip_model()->CloseWebContentsAt(
1047 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1048 lazy_observer.Wait();
1049
1050 // At this point both the extension worker and extension event page is not
1051 // running. Since the worker registered a listener for tabs.onCreated, it
1052 // will be started to dispatch the event once we create a tab.
1053 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1054 newtab_listener.set_failure_message("WRONG_NEWTAB");
1055 content::WebContents* new_web_contents =
Istiaque Ahmed7105f2a2017-10-07 01:11:591056 AddTab(browser(), GURL(url::kAboutBlankURL));
1057 EXPECT_TRUE(new_web_contents);
1058 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1059}
1060
1061// Tests that events to service worker correctly after browser restart.
1062// This test is similar to EventsToStoppedExtension, except that the event
1063// delivery is verified after a browser restart.
1064IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
1065 PRE_EventsAfterRestart) {
1066 LazyBackgroundObserver lazy_observer;
1067 ResultCatcher catcher;
1068 const Extension* extension = LoadExtensionWithFlags(
1069 test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
1070 kFlagNone);
1071 ASSERT_TRUE(extension);
1072 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1073
1074 ProcessManager* pm = ProcessManager::Get(browser()->profile());
1075 EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
David Bertoni3e1e9fa2018-08-29 20:39:301076 EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
Istiaque Ahmed7105f2a2017-10-07 01:11:591077
1078 // |extension|'s background page opens a tab to its resource.
1079 content::WebContents* extension_web_contents =
1080 browser()->tab_strip_model()->GetActiveWebContents();
1081 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1082 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1083 extension_web_contents->GetURL().spec());
1084 {
1085 // Let the service worker start and register a listener to
1086 // chrome.tabs.onCreated event.
1087 ExtensionTestMessageListener add_listener_done("listener-added", false);
1088 content::ExecuteScriptAsync(extension_web_contents,
1089 "window.runServiceWorkerAsync()");
1090 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1091
1092 base::RunLoop run_loop;
1093 content::StoragePartition* storage_partition =
1094 content::BrowserContext::GetDefaultStoragePartition(
1095 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001096 content::StopServiceWorkerForScope(
Istiaque Ahmed7105f2a2017-10-07 01:11:591097 storage_partition->GetServiceWorkerContext(),
1098 // The service worker is registered at the top level scope.
1099 extension->url(), run_loop.QuitClosure());
1100 run_loop.Run();
1101 }
1102
1103 // Close the tab to |extension|'s resource. This will also close the
1104 // extension's event page.
1105 browser()->tab_strip_model()->CloseWebContentsAt(
1106 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1107 lazy_observer.Wait();
1108}
1109
Istiaque Ahmed99aa96d2018-09-13 23:22:081110IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest, EventsAfterRestart) {
Istiaque Ahmed7105f2a2017-10-07 01:11:591111 ExtensionTestMessageListener newtab_listener("hello-newtab", false);
1112 content::WebContents* new_web_contents =
1113 AddTab(browser(), GURL(url::kAboutBlankURL));
Istiaque Ahmed805f6a83b2017-10-05 01:23:261114 EXPECT_TRUE(new_web_contents);
1115 EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
1116}
1117
lazyboy4c82177a2016-10-18 00:04:091118// Tests that worker ref count increments while extension API function is
1119// active.
Istiaque Ahmedea5ed5042017-09-25 19:00:161120IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WorkerRefCount) {
lazyboy4c82177a2016-10-18 00:04:091121 // Extensions APIs from SW are only enabled on trunk.
1122 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1123 const Extension* extension = LoadExtensionWithFlags(
1124 test_data_dir_.AppendASCII("service_worker/api_worker_ref_count"),
1125 kFlagNone);
1126 ASSERT_TRUE(extension);
1127 ui_test_utils::NavigateToURL(browser(),
1128 extension->GetResourceURL("page.html"));
1129 content::WebContents* web_contents =
1130 browser()->tab_strip_model()->GetActiveWebContents();
1131
1132 ExtensionTestMessageListener worker_start_listener("WORKER STARTED", false);
1133 worker_start_listener.set_failure_message("FAILURE");
1134 ASSERT_TRUE(
1135 content::ExecuteScript(web_contents, "window.runServiceWorker()"));
1136 ASSERT_TRUE(worker_start_listener.WaitUntilSatisfied());
1137
1138 // Service worker should have no pending requests because it hasn't peformed
1139 // any extension API request yet.
1140 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1141
1142 ExtensionTestMessageListener worker_listener("CHECK_REF_COUNT", true);
1143 worker_listener.set_failure_message("FAILURE");
1144 ASSERT_TRUE(content::ExecuteScript(web_contents, "window.testSendMessage()"));
1145 ASSERT_TRUE(worker_listener.WaitUntilSatisfied());
1146
1147 // Service worker should have exactly one pending request because
1148 // chrome.test.sendMessage() API call is in-flight.
1149 EXPECT_EQ(1u, GetWorkerRefCount(extension->url()));
1150
1151 // Peform another extension API request while one is ongoing.
1152 {
1153 ExtensionTestMessageListener listener("CHECK_REF_COUNT", true);
1154 listener.set_failure_message("FAILURE");
1155 ASSERT_TRUE(
1156 content::ExecuteScript(web_contents, "window.testSendMessage()"));
1157 ASSERT_TRUE(listener.WaitUntilSatisfied());
1158
1159 // Service worker currently has two extension API requests in-flight.
1160 EXPECT_EQ(2u, GetWorkerRefCount(extension->url()));
1161 // Finish executing the nested chrome.test.sendMessage() first.
1162 listener.Reply("Hello world");
1163 }
1164
Istiaque Ahmedb57c9752017-08-20 19:08:571165 ExtensionTestMessageListener worker_completion_listener("SUCCESS_FROM_WORKER",
1166 false);
lazyboy4c82177a2016-10-18 00:04:091167 // Finish executing chrome.test.sendMessage().
1168 worker_listener.Reply("Hello world");
Istiaque Ahmedb57c9752017-08-20 19:08:571169 EXPECT_TRUE(worker_completion_listener.WaitUntilSatisfied());
1170
1171 // The following block makes sure we have received all the IPCs related to
1172 // ref-count from the worker.
1173 {
1174 // The following roundtrip:
1175 // browser->extension->worker->extension->browser
1176 // will ensure that the worker sent the relevant ref count IPCs.
1177 std::string result;
1178 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1179 web_contents, "window.roundtripToWorker();", &result));
1180 EXPECT_EQ("roundtrip-succeeded", result);
1181
1182 // Ensure IO thread IPCs run.
Gabriel Charette01507a22017-09-27 21:30:081183 content::RunAllTasksUntilIdle();
Istiaque Ahmedb57c9752017-08-20 19:08:571184 }
lazyboy4c82177a2016-10-18 00:04:091185
1186 // The ref count should drop to 0.
1187 EXPECT_EQ(0u, GetWorkerRefCount(extension->url()));
1188}
1189
lazyboyaea32c22016-01-04 21:37:071190// This test loads a web page that has an iframe pointing to a
1191// chrome-extension:// URL. The URL is listed in the extension's
1192// web_accessible_resources. Initially the iframe is served from the extension's
1193// resource file. After verifying that, we register a Service Worker that
1194// controls the extension. Further requests to the same resource as before
1195// should now be served by the Service Worker.
1196// This test also verifies that if the requested resource exists in the manifest
1197// but is not present in the extension directory, the Service Worker can still
1198// serve the resource file.
Istiaque Ahmedea5ed5042017-09-25 19:00:161199IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, WebAccessibleResourcesIframeSrc) {
lazyboyaea32c22016-01-04 21:37:071200 const Extension* extension = LoadExtensionWithFlags(
1201 test_data_dir_.AppendASCII(
1202 "service_worker/web_accessible_resources/iframe_src"),
1203 kFlagNone);
1204 ASSERT_TRUE(extension);
1205 ASSERT_TRUE(StartEmbeddedTestServer());
falkenad185092016-06-16 06:10:021206
1207 // Service workers can only control secure contexts
1208 // (https://w3c.github.io/webappsec-secure-contexts/). For documents, this
1209 // typically means the document must have a secure origin AND all its ancestor
1210 // frames must have documents with secure origins. However, extension pages
1211 // are considered secure, even if they have an ancestor document that is an
1212 // insecure context (see GetSchemesBypassingSecureContextCheckWhitelist). So
1213 // extension service workers must be able to control an extension page
1214 // embedded in an insecure context. To test this, set up an insecure
1215 // (non-localhost, non-https) URL for the web page. This page will create
1216 // iframes that load extension pages that must be controllable by service
1217 // worker.
falkenad185092016-06-16 06:10:021218 GURL page_url =
1219 embedded_test_server()->GetURL("a.com",
1220 "/extensions/api_test/service_worker/"
1221 "web_accessible_resources/webpage.html");
1222 EXPECT_FALSE(content::IsOriginSecure(page_url));
lazyboyaea32c22016-01-04 21:37:071223
1224 content::WebContents* web_contents = AddTab(browser(), page_url);
1225 std::string result;
1226 // webpage.html will create an iframe pointing to a resource from |extension|.
1227 // Expect the resource to be served by the extension.
1228 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1229 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1230 extension->id().c_str()),
1231 &result));
1232 EXPECT_EQ("FROM_EXTENSION_RESOURCE", result);
1233
1234 ExtensionTestMessageListener service_worker_ready_listener("SW_READY", false);
1235 EXPECT_TRUE(ExecuteScriptInBackgroundPageNoWait(
1236 extension->id(), "window.registerServiceWorker()"));
1237 EXPECT_TRUE(service_worker_ready_listener.WaitUntilSatisfied());
1238
1239 result.clear();
1240 // webpage.html will create another iframe pointing to a resource from
1241 // |extension| as before. But this time, the resource should be be served
1242 // from the Service Worker.
1243 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1244 web_contents, base::StringPrintf("window.testIframe('%s', 'iframe.html')",
1245 extension->id().c_str()),
1246 &result));
1247 EXPECT_EQ("FROM_SW_RESOURCE", result);
1248
1249 result.clear();
1250 // webpage.html will create yet another iframe pointing to a resource that
1251 // exists in the extension manifest's web_accessible_resources, but is not
1252 // present in the extension directory. Expect the resources of the iframe to
1253 // be served by the Service Worker.
1254 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1255 web_contents,
1256 base::StringPrintf("window.testIframe('%s', 'iframe_non_existent.html')",
1257 extension->id().c_str()),
1258 &result));
1259 EXPECT_EQ("FROM_SW_RESOURCE", result);
1260}
1261
Istiaque Ahmedea5ed5042017-09-25 19:00:161262IN_PROC_BROWSER_TEST_P(ServiceWorkerBackgroundSyncTest, Sync) {
Elly Fong-Jones4a4f21d2018-05-30 15:04:161263 if (IsMacViewsMode())
1264 return;
lazyboybd325ae2015-11-18 21:35:261265 const Extension* extension = LoadExtensionWithFlags(
1266 test_data_dir_.AppendASCII("service_worker/sync"), kFlagNone);
1267 ASSERT_TRUE(extension);
1268 ui_test_utils::NavigateToURL(browser(),
1269 extension->GetResourceURL("page.html"));
1270 content::WebContents* web_contents =
1271 browser()->tab_strip_model()->GetActiveWebContents();
1272
1273 // Prevent firing by going offline.
1274 content::background_sync_test_util::SetOnline(web_contents, false);
1275
1276 ExtensionTestMessageListener sync_listener("SYNC: send-chats", false);
1277 sync_listener.set_failure_message("FAIL");
1278
1279 std::string result;
1280 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1281 web_contents, "window.runServiceWorker()", &result));
1282 ASSERT_EQ("SERVICE_WORKER_READY", result);
1283
1284 EXPECT_FALSE(sync_listener.was_satisfied());
1285 // Resume firing by going online.
1286 content::background_sync_test_util::SetOnline(web_contents, true);
1287 EXPECT_TRUE(sync_listener.WaitUntilSatisfied());
1288}
1289
Istiaque Ahmedea5ed5042017-09-25 19:00:161290IN_PROC_BROWSER_TEST_P(ServiceWorkerTest,
horo1eeddde2015-11-19 05:59:251291 FetchFromContentScriptShouldNotGoToServiceWorkerOfPage) {
1292 ASSERT_TRUE(StartEmbeddedTestServer());
1293 GURL page_url = embedded_test_server()->GetURL(
1294 "/extensions/api_test/service_worker/content_script_fetch/"
1295 "controlled_page/index.html");
1296 content::WebContents* tab =
1297 browser()->tab_strip_model()->GetActiveWebContents();
1298 ui_test_utils::NavigateToURL(browser(), page_url);
1299 content::WaitForLoadStop(tab);
1300
1301 std::string value;
1302 ASSERT_TRUE(
1303 content::ExecuteScriptAndExtractString(tab, "register();", &value));
1304 EXPECT_EQ("SW controlled", value);
1305
1306 ASSERT_TRUE(RunExtensionTest("service_worker/content_script_fetch"))
1307 << message_;
1308}
1309
Istiaque Ahmedea5ed5042017-09-25 19:00:161310IN_PROC_BROWSER_TEST_P(ServiceWorkerPushMessagingTest, OnPush) {
lazyboy561b7de2015-11-19 19:27:301311 const Extension* extension = LoadExtensionWithFlags(
1312 test_data_dir_.AppendASCII("service_worker/push_messaging"), kFlagNone);
1313 ASSERT_TRUE(extension);
1314 GURL extension_url = extension->url();
1315
Peter Beverloodd4ef1e2018-06-21 15:41:041316 GrantNotificationPermissionForTest(extension_url);
lazyboy561b7de2015-11-19 19:27:301317
1318 GURL url = extension->GetResourceURL("page.html");
1319 ui_test_utils::NavigateToURL(browser(), url);
1320
1321 content::WebContents* web_contents =
1322 browser()->tab_strip_model()->GetActiveWebContents();
1323
1324 // Start the ServiceWorker.
1325 ExtensionTestMessageListener ready_listener("SERVICE_WORKER_READY", false);
1326 ready_listener.set_failure_message("SERVICE_WORKER_FAILURE");
1327 const char* kScript = "window.runServiceWorker()";
1328 EXPECT_TRUE(content::ExecuteScript(web_contents->GetMainFrame(), kScript));
1329 EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
1330
1331 PushMessagingAppIdentifier app_identifier =
1332 GetAppIdentifierForServiceWorkerRegistration(0LL, extension_url);
johnmea5045732016-09-08 17:23:291333 ASSERT_EQ(app_identifier.app_id(), gcm_driver()->last_gettoken_app_id());
1334 EXPECT_EQ("1234567890", gcm_driver()->last_gettoken_authorized_entity());
lazyboy561b7de2015-11-19 19:27:301335
lazyboyd429e2582016-05-20 20:18:521336 base::RunLoop run_loop;
lazyboy561b7de2015-11-19 19:27:301337 // Send a push message via gcm and expect the ServiceWorker to receive it.
1338 ExtensionTestMessageListener push_message_listener("OK", false);
1339 push_message_listener.set_failure_message("FAIL");
1340 gcm::IncomingMessage message;
1341 message.sender_id = "1234567890";
1342 message.raw_data = "testdata";
1343 message.decrypted = true;
lazyboyd429e2582016-05-20 20:18:521344 push_service()->SetMessageCallbackForTesting(run_loop.QuitClosure());
lazyboy561b7de2015-11-19 19:27:301345 push_service()->OnMessage(app_identifier.app_id(), message);
1346 EXPECT_TRUE(push_message_listener.WaitUntilSatisfied());
lazyboyd429e2582016-05-20 20:18:521347 run_loop.Run(); // Wait until the message is handled by push service.
lazyboy561b7de2015-11-19 19:27:301348}
1349
Istiaque Ahmedea5ed5042017-09-25 19:00:161350IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, FilteredEvents) {
Istiaque Ahmed9d1666182017-09-21 23:58:181351 // Extensions APIs from SW are only enabled on trunk.
1352 ScopedCurrentChannel current_channel_override(version_info::Channel::UNKNOWN);
1353 ASSERT_TRUE(RunExtensionTest("service_worker/filtered_events"));
1354}
1355
Rob Wue89b90032018-02-16 19:46:081356IN_PROC_BROWSER_TEST_P(ServiceWorkerTest, MimeHandlerView) {
1357 ASSERT_TRUE(RunExtensionTest("service_worker/mime_handler_view"));
1358}
1359
Istiaque Ahmed9ce21b32017-10-10 20:43:181360IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
1361 PRE_FilteredEventsAfterRestart) {
1362 LazyBackgroundObserver lazy_observer;
1363 ResultCatcher catcher;
1364 const Extension* extension = LoadExtensionWithFlags(
1365 test_data_dir_.AppendASCII(
1366 "service_worker/filtered_events_after_restart"),
1367 kFlagNone);
1368 ASSERT_TRUE(extension);
1369 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
1370
1371 // |extension|'s background page opens a tab to its resource.
1372 content::WebContents* extension_web_contents =
1373 browser()->tab_strip_model()->GetActiveWebContents();
1374 EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
1375 EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
1376 extension_web_contents->GetURL().spec());
1377 {
1378 // Let the service worker start and register a filtered listener to
1379 // chrome.webNavigation.onCommitted event.
1380 ExtensionTestMessageListener add_listener_done("listener-added", false);
1381 add_listener_done.set_failure_message("FAILURE");
1382 content::ExecuteScriptAsync(extension_web_contents,
1383 "window.runServiceWorkerAsync()");
1384 EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
1385
1386 base::RunLoop run_loop;
1387 content::StoragePartition* storage_partition =
1388 content::BrowserContext::GetDefaultStoragePartition(
1389 browser()->profile());
Zhuoyu Qian2266251f2018-10-13 02:59:001390 content::StopServiceWorkerForScope(
Istiaque Ahmed9ce21b32017-10-10 20:43:181391 storage_partition->GetServiceWorkerContext(),
1392 // The service worker is registered at the top level scope.
1393 extension->url(), run_loop.QuitClosure());
1394 run_loop.Run();
1395 }
1396
1397 // Close the tab to |extension|'s resource. This will also close the
1398 // extension's event page.
1399 browser()->tab_strip_model()->CloseWebContentsAt(
1400 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
1401 lazy_observer.Wait();
1402}
1403
1404IN_PROC_BROWSER_TEST_P(ServiceWorkerLazyBackgroundTest,
Istiaque Ahmedf5712522018-09-20 03:35:471405 FilteredEventsAfterRestart) {
Istiaque Ahmed9ce21b32017-10-10 20:43:181406 // Create a tab to a.html, expect it to navigate to b.html. The service worker
1407 // will see two webNavigation.onCommitted events.
1408 ASSERT_TRUE(StartEmbeddedTestServer());
1409 GURL page_url = embedded_test_server()->GetURL(
1410 "/extensions/api_test/service_worker/filtered_events_after_restart/"
1411 "a.html");
1412 ExtensionTestMessageListener worker_filtered_event_listener(
1413 "PASS_FROM_WORKER", false);
1414 worker_filtered_event_listener.set_failure_message("FAIL_FROM_WORKER");
1415 content::WebContents* web_contents = AddTab(browser(), page_url);
1416 EXPECT_TRUE(web_contents);
1417 EXPECT_TRUE(worker_filtered_event_listener.WaitUntilSatisfied());
1418}
1419
Istiaque Ahmedea5ed5042017-09-25 19:00:161420// Run with both native and JS-based bindings. This ensures that both stable
1421// (JS) and experimental (native) phases work correctly with worker scripts
1422// while we launch native bindings to stable.
1423INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
1424 ServiceWorkerTest,
1425 ::testing::Values(NATIVE_BINDINGS));
1426INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
1427 ServiceWorkerTest,
1428 ::testing::Values(JAVASCRIPT_BINDINGS));
1429INSTANTIATE_TEST_CASE_P(ServiceWorkerBackgroundSyncTestWithNativeBindings,
1430 ServiceWorkerBackgroundSyncTest,
1431 ::testing::Values(NATIVE_BINDINGS));
1432INSTANTIATE_TEST_CASE_P(ServiceWorkerBackgroundSyncTestWithJSBindings,
1433 ServiceWorkerBackgroundSyncTest,
1434 ::testing::Values(JAVASCRIPT_BINDINGS));
1435INSTANTIATE_TEST_CASE_P(ServiceWorkerPushMessagingTestWithNativeBindings,
1436 ServiceWorkerPushMessagingTest,
1437 ::testing::Values(NATIVE_BINDINGS));
1438INSTANTIATE_TEST_CASE_P(ServiceWorkerPushMessagingTestWithJSBindings,
1439 ServiceWorkerPushMessagingTest,
1440 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmed805f6a83b2017-10-05 01:23:261441INSTANTIATE_TEST_CASE_P(ServiceWorkerLazyBackgroundTestWithNativeBindings,
1442 ServiceWorkerLazyBackgroundTest,
1443 ::testing::Values(NATIVE_BINDINGS));
1444INSTANTIATE_TEST_CASE_P(ServiceWorkerLazyBackgroundTestWithJSBindings,
1445 ServiceWorkerLazyBackgroundTest,
1446 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmedccb444022018-06-19 02:11:121447INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
1448 ServiceWorkerBasedBackgroundTest,
1449 ::testing::Values(NATIVE_BINDINGS));
1450INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
1451 ServiceWorkerBasedBackgroundTest,
1452 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmedf70ab222018-10-02 03:08:241453INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
1454 ServiceWorkerOnStartupTest,
1455 ::testing::Values(NATIVE_BINDINGS));
1456INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
1457 ServiceWorkerOnStartupTest,
1458 ::testing::Values(JAVASCRIPT_BINDINGS));
Istiaque Ahmedea5ed5042017-09-25 19:00:161459
annekao38685502015-07-14 17:46:391460} // namespace extensions