diff options
Diffstat (limited to 'testing/web-platform/mozilla/tests/service-workers')
12 files changed, 256 insertions, 0 deletions
diff --git a/testing/web-platform/mozilla/tests/service-workers/bug1675097.https.html b/testing/web-platform/mozilla/tests/service-workers/bug1675097.https.html new file mode 100644 index 0000000000..e093f616c1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/bug1675097.https.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title>Controlled iframe with initial about:blank becomes sandboxed</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> +<body> +<script> + +// This test creates an iframe controlled by a service worker, which in turn has +// another iframe in it. The inner iframe's fetch is intercepted by the service +// worker, which notifies the outer iframe, which then adds the sandbox +// attribute to the inner iframe. The outer iframe then signals the service +// worker that it should evaluate self.clients.matchAll() and finally respond to +// the inner iframe's fetch. +// Evaluating self.clients.matchAll() causes the creation of the initial +// about:blank document for the inner iframe, and if the sandboxing flags used +// for that document are not the original flags for the inner iframe (i.e. none) +// then the document will have an opaque origin, a case that we need to handle +// properly. +promise_test(async t => { + const URL = 'resources/bug1675097-sw.js'; + const SCOPE = 'resources/'; + + const registration = await service_worker_unregister_and_register(t, URL, SCOPE); + t.add_cleanup(() => registration.unregister()); + + await wait_for_state(t, registration.installing, 'activated'); + + const outer = await with_iframe(SCOPE + 'bug1675097-iframe.html'); + t.add_cleanup(() => outer.remove()); +}, 'Regression test for bug 1675097'); + +</script> +</body> diff --git a/testing/web-platform/mozilla/tests/service-workers/no_intercept_for_crossorigin_media.https.html b/testing/web-platform/mozilla/tests/service-workers/no_intercept_for_crossorigin_media.https.html new file mode 100644 index 0000000000..245522f5fc --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/no_intercept_for_crossorigin_media.https.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Don't intercept cross-origin media requests</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"> +</script> +<body> +<script> + +'use strict'; + +const scope = './resources/'; + +/** + * Ensure service workers don't intercept cross-origin media range requests. + */ +promise_test(async t => { + const registration = await service_worker_unregister_and_register( + t, scope + 'intercept_media_sw.js', scope); + t.add_cleanup(() => registration.unregister()); + await wait_for_state(t, registration.installing, 'activated'); + + const frame = await with_iframe(scope + 'crossorigin_media_iframe.html'); + return frame.contentWindow.create_media_promise() +}, 'Service worker does not intercept a cross-origin media range request'); + +/** + * Ensure service workers do intercept cross-origin media non-range requests. + */ +promise_test(async t => { + const registration = await service_worker_unregister_and_register( + t, scope + 'intercept_media_sw.js', scope); + t.add_cleanup(() => registration.unregister()); + await wait_for_state(t, registration.installing, 'activated'); + + const frame = await with_iframe(scope + 'crossorigin_media_iframe_nonrange.html'); + return frame.contentWindow.create_media_promise() +}, 'Service worker intercepts a cross-origin non-range media request'); + +</script> +</body> diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/blank.html b/testing/web-platform/mozilla/tests/service-workers/resources/blank.html new file mode 100644 index 0000000000..a3c3a4689a --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/resources/blank.html @@ -0,0 +1,2 @@ +<!DOCTYPE html> +<title>Empty doc</title> diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-iframe.html b/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-iframe.html new file mode 100644 index 0000000000..5ad7b95594 --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-iframe.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<body> +<script> +let channel = new MessageChannel(); +channel.port1.onmessage = event => { + if (event.data === 'intercepted') { + const iframe = document.querySelector('iframe'); + iframe.sandbox = ''; + navigator.serviceWorker.controller.postMessage({ type: 'ack' }); + } +}; +navigator.serviceWorker.controller.postMessage({ type: 'register', port: channel.port2 }, [channel.port2]); +</script> +<iframe src='inner'></iframe> +</body> diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-sw.js b/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-sw.js new file mode 100644 index 0000000000..e2894e1032 --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-sw.js @@ -0,0 +1,26 @@ +// We use promises because the message and fetch events do not have a guaranteed +// order, since they come from different task sources. +var resolvePortPromise; +var portPromise = new Promise(resolve => resolvePortPromise = resolve); +var resolveResolveResponsePromise; +var resolveResponsePromise = new Promise(resolve => resolveResolveResponsePromise = resolve); + +self.addEventListener('fetch', event => { + if (event.request.url.indexOf('inner') !== -1) { + event.respondWith(new Promise(resolve => { + resolveResolveResponsePromise(resolve); + })); + portPromise.then(port => port.postMessage('intercepted')); + } +}); + +self.addEventListener('message', event => { + if (event.data.type === 'register') { + resolvePortPromise(event.data.port); + } + else if (event.data.type === 'ack') { + self.clients.matchAll() + .then(() => resolveResponsePromise) + .then(resolveResponse => resolveResponse(new Response('inner iframe'))); + } +}); diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe.html b/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe.html new file mode 100644 index 0000000000..54cdcaa8dd --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<body> +<script> + +'use strict'; + +function remoteize(relpath) { + let curdir = location.href.replace(/\/[^\/]*$/, '/') + return curdir.replace('://', '://www1.') + relpath +} + +function create_media_promise() { + return new Promise((resolve, reject) => { + let video = document.createElement('video') + video.autoplay = true + video.muted = true + video.onplay = () => resolve('ok') + video.onerror = () => reject('video error') + video.src = remoteize('fetch_video.py') + }) +} + +</script> +</body> diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe_nonrange.html b/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe_nonrange.html new file mode 100644 index 0000000000..8e3c20fdeb --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe_nonrange.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<body> +<script> + +'use strict'; + +function remoteize(relpath) { + let curdir = location.href.replace(/\/[^\/]*$/, '/') + return curdir.replace('://', '://www1.') + relpath +} + +function create_media_promise() { + return new Promise((resolve, reject) => { + let image = document.createElement('img') + image.onload = () => resolve('ok') + image.onerror = () => reject('image error') + image.src = remoteize('blank.html') // sw will replace with an image + }) +} + +</script> +</body> diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/empty.js b/testing/web-platform/mozilla/tests/service-workers/resources/empty.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/resources/empty.js diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/fetch_video.py b/testing/web-platform/mozilla/tests/service-workers/resources/fetch_video.py new file mode 100644 index 0000000000..541f00c019 --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/resources/fetch_video.py @@ -0,0 +1,14 @@ +import os + + +def main(request, response): + filename = os.path.join(request.doc_root, u"media", u"2x2-green.ogv") + body = open(filename, "rb").read() + length = len(body) + headers = [ + (b"Content-Type", b"video/ogg"), + (b"Accept-Ranges", b"bytes"), + (b"Content-Length", b"%d" % length), + (b"Content-Range", b"bytes 0-%d/%d" % (length - 1, length)), + ] + return headers, body diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/green.png b/testing/web-platform/mozilla/tests/service-workers/resources/green.png Binary files differnew file mode 100644 index 0000000000..28a1faab37 --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/resources/green.png diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/intercept_media_sw.js b/testing/web-platform/mozilla/tests/service-workers/resources/intercept_media_sw.js new file mode 100644 index 0000000000..6c373aa0de --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/resources/intercept_media_sw.js @@ -0,0 +1,14 @@ +'use strict'; + +self.addEventListener('fetch', event => { + if (event.request.url.indexOf('fetch_video.py') !== -1) { + // A no-cors media range request /should not/ be intercepted. + // Respond with some text to cause an error. + event.respondWith(new Response('intercepted')); + } + else if (event.request.url.indexOf('blank.html') !== -1) { + // A no-cors media non-range request /should/ be intercepted. + // Respond with an image to avoid an error. + event.respondWith(fetch('green.png')); + } +}); diff --git a/testing/web-platform/mozilla/tests/service-workers/update_completes_in_disconnected_global.https.html b/testing/web-platform/mozilla/tests/service-workers/update_completes_in_disconnected_global.https.html new file mode 100644 index 0000000000..371fa81161 --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/update_completes_in_disconnected_global.https.html @@ -0,0 +1,63 @@ +<!DOCTYPE html> +<title>Service Worker: Disconnected Global Update()</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> +<script> +'use strict'; + +/** + * Gecko-only pseudo-crash-test to verify that if we call + * ServiceWorkerRegistration.update() from a global that will be destroyed + * before any IPC call could return that we don't crash. + * + * We use an iframe to create a global that we can destroy on demand. + */ +promise_test(async function(t) { + const scope = 'resources/blank.html'; + const sw_url = 'resources/empty.js'; + + let reg = await service_worker_unregister_and_register(t, sw_url, scope); + t.add_cleanup(function() { + return service_worker_unregister(t, scope); + }); + + // Wait for the worker to be activated so that we are in a known state. + await wait_for_state(t, reg.installing, 'activated'); + + let f = await with_iframe(scope); + let f_global = f.contentWindow; + // The frame should be controlled, although it's not necessary for the test. + assert_true(!!f_global.navigator.serviceWorker.controller); + t.add_cleanup(function() { + if (f) { + f.remove(); + } + }); + + // Get a registration object that lives in the iframe's global. + let f_reg = await f_global.navigator.serviceWorker.getRegistration(reg.scope); + assert_true(!!f_reg, 'got registration'); + assert_equals(reg.scope, f_reg.scope, 'Right registration'); + + // Trigger the update and destroy the global. + let update_resolved = false; + let update_rejected = false; + + let update_promise = f_reg.update(); + update_promise.then( + () => { update_resolved = true; }, () => { update_rejected = true; }); + + f.remove(); + f = null; + f_global = null; + + // Now we want to wait on an update call that should fire strictly after the + // update call above. + await reg.update(); + + assert_false(update_resolved, "frame update() should not have resolved"); + assert_true(update_rejected, "frame update() should have rejected"); +}, 'ServiceWorkerRegistration.update() concluding in a disconnected global'); + +</script> |