Worklet: Add WPT tests for ServiceWorker interception on addModule()
WPT Tests for ServiceWorker interception on dynamic import will be added in a
following CL.
Bug: 773778
Change-Id: I636b39f3e377adb36a664bac9cf2f50516a90ca0
Reviewed-on: https://chromium-review.googlesource.com/754422
Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#514332}
diff --git a/worklets/animation-worklet-service-worker-interception.https.html b/worklets/animation-worklet-service-worker-interception.https.html
new file mode 100644
index 0000000..33000ee
--- /dev/null
+++ b/worklets/animation-worklet-service-worker-interception.https.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/worklet-test-utils.js"></script>
+ <script src="resources/service-worker-interception-tests.js"></script>
+ <script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+</head>
+<body>
+<script>
+ runServiceWorkerInterceptionTests("animation");
+</script>
+</body>
+</html>
diff --git a/worklets/paint-worklet-service-worker-interception.https.html b/worklets/paint-worklet-service-worker-interception.https.html
new file mode 100644
index 0000000..fdce9ca
--- /dev/null
+++ b/worklets/paint-worklet-service-worker-interception.https.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/worklet-test-utils.js"></script>
+ <script src="resources/service-worker-interception-tests.js"></script>
+ <script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+</head>
+<body>
+<script>
+ runServiceWorkerInterceptionTests("paint");
+</script>
+</body>
+</html>
diff --git a/worklets/resources/addmodule-window.html b/worklets/resources/addmodule-window.html
new file mode 100644
index 0000000..6263e6e
--- /dev/null
+++ b/worklets/resources/addmodule-window.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Worklet: Referrer</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="worklet-test-utils.js"></script>
+</head>
+<body>
+<script>
+// Calls addModule() on a given worklet type with a script url.
+//
+// [Message Format]
+// - type: 'paint' (worklet types defined in get_worklet())
+// - script_url: 'worklet-script.js'
+window.onmessage = e => {
+ const worklet_type = e.data.type;
+ const script_url = e.data.script_url;
+ get_worklet(worklet_type).addModule(script_url)
+ .then(() => window.opener.postMessage('RESOLVED', '*'))
+ .catch(e => window.opener.postMessage('REJECTED', '*'));
+};
+
+window.opener.postMessage('LOADED', '*');
+</script>
+</body>
+</html>
diff --git a/worklets/resources/service-worker-interception-tests.js b/worklets/resources/service-worker-interception-tests.js
new file mode 100644
index 0000000..001707f
--- /dev/null
+++ b/worklets/resources/service-worker-interception-tests.js
@@ -0,0 +1,91 @@
+function openWindow(url) {
+ return new Promise(resolve => {
+ let win = window.open(url, '_blank');
+ add_result_callback(() => win.close());
+ window.onmessage = e => {
+ assert_equals(e.data, 'LOADED');
+ resolve(win);
+ };
+ });
+}
+
+// Runs a series of tests related to service worker interception for a worklet.
+//
+// Usage:
+// runServiceWorkerInterceptionTests("paint");
+function runServiceWorkerInterceptionTests(worklet_type) {
+ const worklet = get_worklet(worklet_type);
+
+ // Tests that a worklet should be controlled by the owner document's service
+ // worker.
+ //
+ // [Current document] registers a service worker for Window's URL.
+ // --(open)--> [Window] should be controlled by the service worker.
+ // --(addModule)--> [Worklet] should be controlled by the service worker.
+ promise_test(t => {
+ const kWindowURL = 'resources/addmodule-window.html';
+ const kServiceWorkerScriptURL = 'resources/service-worker.js';
+ // This doesn't contain the 'resources/' prefix because this will be
+ // imported from a html file under resources/.
+ const kWorkletScriptURL = 'non-existent-worklet-script.js';
+
+ return service_worker_unregister_and_register(
+ t, kServiceWorkerScriptURL, kWindowURL)
+ .then(r => {
+ add_result_callback(() => r.unregister());
+ return wait_for_state(t, r.installing, 'activated');
+ })
+ .then(() => openWindow(kWindowURL))
+ .then(win => {
+ assert_not_equals(win.navigator.serviceWorker.controller, null,
+ 'The document should be controlled.');
+ const promise = new Promise(r => window.onmessage = r);
+ // The worklet script on kWorkletScriptURL doesn't exist but the
+ // service worker serves it, so the addModule() should succeed.
+ win.postMessage({ type: worklet_type,
+ script_url: kWorkletScriptURL }, '*');
+ return promise;
+ })
+ .then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+ }, 'Importing a script from a controlled document should be intercepted ' +
+ 'by a service worker.');
+
+ // Tests that a worklet should not be controlled by a service worker other
+ // than the owner document's service worker.
+ //
+ // [Current document] registers a service worker for Worklet's URL.
+ // --(open)--> [Window] should not be controlled by the service worker.
+ // --(addModule)--> [Worklet] should not be controlled by the service
+ // worker.
+ promise_test(t => {
+ const kWindowURL = 'resources/addmodule-window.html';
+ const kServiceWorkerScriptURL = 'resources/service-worker.js';
+ // This doesn't contain the 'resources/' prefix because this will be
+ // imported from a html file under resources/.
+ const kWorkletScriptURL = 'non-existent-worklet-script.js';
+
+ return service_worker_unregister_and_register(
+ t, kServiceWorkerScriptURL, 'resources/' + kWorkletScriptURL)
+ .then(r => {
+ add_result_callback(() => r.unregister());
+ return wait_for_state(t, r.installing, 'activated');
+ })
+ .then(() => openWindow(kWindowURL))
+ .then(win => {
+ assert_equals(win.navigator.serviceWorker.controller, null,
+ 'The document should not be controlled.');
+ const promise = new Promise(r => window.onmessage = r);
+ // The worklet script on kWorkletScriptURL doesn't exist and the
+ // service worker doesn't serve it, so the addModule() should
+ // fail.
+ win.postMessage({ type: worklet_type,
+ script_url: kWorkletScriptURL }, '*');
+ return promise;
+ })
+ .then(msg_event => assert_equals(msg_event.data, 'REJECTED'));
+ }, 'Importing a script from a non-controlled document should not be ' +
+ 'intercepted by a service worker even if the script is under the ' +
+ 'service worker scope.');
+
+ // TODO(nhiroki): Add tests for dynamic import.
+}
diff --git a/worklets/resources/service-worker.js b/worklets/resources/service-worker.js
new file mode 100644
index 0000000..89765ca
--- /dev/null
+++ b/worklets/resources/service-worker.js
@@ -0,0 +1,4 @@
+self.addEventListener('fetch', e => {
+ if (e.request.url.indexOf('non-existent-worklet-script.js') != -1)
+ e.respondWith(fetch('empty-worklet-script.js'));
+});