From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../test/fetch/cookie/cookie_test.js | 11 + dom/serviceworkers/test/fetch/cookie/register.html | 19 + .../test/fetch/cookie/unregister.html | 12 + dom/serviceworkers/test/fetch/deliver-gzip.sjs | 21 + dom/serviceworkers/test/fetch/fetch_tests.js | 716 +++++++++++++++++++++ .../test/fetch/fetch_worker_script.js | 28 + dom/serviceworkers/test/fetch/hsts/embedder.html | 7 + dom/serviceworkers/test/fetch/hsts/hsts_test.js | 11 + dom/serviceworkers/test/fetch/hsts/image-20px.png | Bin 0 -> 87 bytes dom/serviceworkers/test/fetch/hsts/image-40px.png | Bin 0 -> 123 bytes dom/serviceworkers/test/fetch/hsts/image.html | 13 + dom/serviceworkers/test/fetch/hsts/realindex.html | 8 + dom/serviceworkers/test/fetch/hsts/register.html | 14 + .../test/fetch/hsts/register.html^headers^ | 2 + dom/serviceworkers/test/fetch/hsts/unregister.html | 12 + .../test/fetch/https/clonedresponse/https_test.js | 19 + .../test/fetch/https/clonedresponse/index.html | 4 + .../test/fetch/https/clonedresponse/register.html | 14 + .../fetch/https/clonedresponse/unregister.html | 12 + dom/serviceworkers/test/fetch/https/https_test.js | 31 + dom/serviceworkers/test/fetch/https/index.html | 4 + dom/serviceworkers/test/fetch/https/register.html | 20 + .../test/fetch/https/unregister.html | 12 + .../test/fetch/imagecache-maxage/image-20px.png | Bin 0 -> 87 bytes .../test/fetch/imagecache-maxage/image-40px.png | Bin 0 -> 123 bytes .../test/fetch/imagecache-maxage/index.html | 29 + .../test/fetch/imagecache-maxage/maxage_test.js | 45 ++ .../test/fetch/imagecache-maxage/register.html | 14 + .../test/fetch/imagecache-maxage/unregister.html | 12 + .../test/fetch/imagecache/image-20px.png | Bin 0 -> 87 bytes .../test/fetch/imagecache/image-40px.png | Bin 0 -> 123 bytes .../test/fetch/imagecache/imagecache_test.js | 15 + .../test/fetch/imagecache/index.html | 20 + .../test/fetch/imagecache/postmortem.html | 9 + .../test/fetch/imagecache/register.html | 16 + .../test/fetch/imagecache/unregister.html | 12 + .../fetch/importscript-mixedcontent/https_test.js | 31 + .../fetch/importscript-mixedcontent/register.html | 14 + .../importscript-mixedcontent/unregister.html | 12 + dom/serviceworkers/test/fetch/index.html | 191 ++++++ dom/serviceworkers/test/fetch/interrupt.sjs | 20 + .../test/fetch/origin/https/index-https.sjs | 8 + .../test/fetch/origin/https/origin_test.js | 29 + .../test/fetch/origin/https/realindex.html | 6 + .../fetch/origin/https/realindex.html^headers^ | 1 + .../test/fetch/origin/https/register.html | 14 + .../test/fetch/origin/https/unregister.html | 12 + .../test/fetch/origin/index-to-https.sjs | 8 + dom/serviceworkers/test/fetch/origin/index.sjs | 8 + .../test/fetch/origin/origin_test.js | 38 ++ .../test/fetch/origin/realindex.html | 6 + .../test/fetch/origin/realindex.html^headers^ | 1 + dom/serviceworkers/test/fetch/origin/register.html | 14 + .../test/fetch/origin/unregister.html | 12 + dom/serviceworkers/test/fetch/plugin/plugins.html | 43 ++ dom/serviceworkers/test/fetch/plugin/worker.js | 15 + dom/serviceworkers/test/fetch/real-file.txt | 1 + dom/serviceworkers/test/fetch/redirect.sjs | 4 + .../test/fetch/requesturl/index.html | 7 + .../test/fetch/requesturl/redirect.sjs | 8 + .../test/fetch/requesturl/redirector.html | 2 + .../test/fetch/requesturl/register.html | 14 + .../test/fetch/requesturl/requesturl_test.js | 21 + .../test/fetch/requesturl/secret.html | 5 + .../test/fetch/requesturl/unregister.html | 12 + dom/serviceworkers/test/fetch/sandbox/index.html | 5 + .../test/fetch/sandbox/intercepted_index.html | 5 + .../test/fetch/sandbox/register.html | 14 + .../test/fetch/sandbox/sandbox_test.js | 5 + .../test/fetch/sandbox/unregister.html | 12 + .../test/fetch/upgrade-insecure/embedder.html | 10 + .../fetch/upgrade-insecure/embedder.html^headers^ | 1 + .../test/fetch/upgrade-insecure/image-20px.png | Bin 0 -> 87 bytes .../test/fetch/upgrade-insecure/image-40px.png | Bin 0 -> 123 bytes .../test/fetch/upgrade-insecure/image.html | 13 + .../test/fetch/upgrade-insecure/realindex.html | 4 + .../test/fetch/upgrade-insecure/register.html | 14 + .../test/fetch/upgrade-insecure/unregister.html | 12 + .../upgrade-insecure/upgrade-insecure_test.js | 11 + 79 files changed, 1825 insertions(+) create mode 100644 dom/serviceworkers/test/fetch/cookie/cookie_test.js create mode 100644 dom/serviceworkers/test/fetch/cookie/register.html create mode 100644 dom/serviceworkers/test/fetch/cookie/unregister.html create mode 100644 dom/serviceworkers/test/fetch/deliver-gzip.sjs create mode 100644 dom/serviceworkers/test/fetch/fetch_tests.js create mode 100644 dom/serviceworkers/test/fetch/fetch_worker_script.js create mode 100644 dom/serviceworkers/test/fetch/hsts/embedder.html create mode 100644 dom/serviceworkers/test/fetch/hsts/hsts_test.js create mode 100644 dom/serviceworkers/test/fetch/hsts/image-20px.png create mode 100644 dom/serviceworkers/test/fetch/hsts/image-40px.png create mode 100644 dom/serviceworkers/test/fetch/hsts/image.html create mode 100644 dom/serviceworkers/test/fetch/hsts/realindex.html create mode 100644 dom/serviceworkers/test/fetch/hsts/register.html create mode 100644 dom/serviceworkers/test/fetch/hsts/register.html^headers^ create mode 100644 dom/serviceworkers/test/fetch/hsts/unregister.html create mode 100644 dom/serviceworkers/test/fetch/https/clonedresponse/https_test.js create mode 100644 dom/serviceworkers/test/fetch/https/clonedresponse/index.html create mode 100644 dom/serviceworkers/test/fetch/https/clonedresponse/register.html create mode 100644 dom/serviceworkers/test/fetch/https/clonedresponse/unregister.html create mode 100644 dom/serviceworkers/test/fetch/https/https_test.js create mode 100644 dom/serviceworkers/test/fetch/https/index.html create mode 100644 dom/serviceworkers/test/fetch/https/register.html create mode 100644 dom/serviceworkers/test/fetch/https/unregister.html create mode 100644 dom/serviceworkers/test/fetch/imagecache-maxage/image-20px.png create mode 100644 dom/serviceworkers/test/fetch/imagecache-maxage/image-40px.png create mode 100644 dom/serviceworkers/test/fetch/imagecache-maxage/index.html create mode 100644 dom/serviceworkers/test/fetch/imagecache-maxage/maxage_test.js create mode 100644 dom/serviceworkers/test/fetch/imagecache-maxage/register.html create mode 100644 dom/serviceworkers/test/fetch/imagecache-maxage/unregister.html create mode 100644 dom/serviceworkers/test/fetch/imagecache/image-20px.png create mode 100644 dom/serviceworkers/test/fetch/imagecache/image-40px.png create mode 100644 dom/serviceworkers/test/fetch/imagecache/imagecache_test.js create mode 100644 dom/serviceworkers/test/fetch/imagecache/index.html create mode 100644 dom/serviceworkers/test/fetch/imagecache/postmortem.html create mode 100644 dom/serviceworkers/test/fetch/imagecache/register.html create mode 100644 dom/serviceworkers/test/fetch/imagecache/unregister.html create mode 100644 dom/serviceworkers/test/fetch/importscript-mixedcontent/https_test.js create mode 100644 dom/serviceworkers/test/fetch/importscript-mixedcontent/register.html create mode 100644 dom/serviceworkers/test/fetch/importscript-mixedcontent/unregister.html create mode 100644 dom/serviceworkers/test/fetch/index.html create mode 100644 dom/serviceworkers/test/fetch/interrupt.sjs create mode 100644 dom/serviceworkers/test/fetch/origin/https/index-https.sjs create mode 100644 dom/serviceworkers/test/fetch/origin/https/origin_test.js create mode 100644 dom/serviceworkers/test/fetch/origin/https/realindex.html create mode 100644 dom/serviceworkers/test/fetch/origin/https/realindex.html^headers^ create mode 100644 dom/serviceworkers/test/fetch/origin/https/register.html create mode 100644 dom/serviceworkers/test/fetch/origin/https/unregister.html create mode 100644 dom/serviceworkers/test/fetch/origin/index-to-https.sjs create mode 100644 dom/serviceworkers/test/fetch/origin/index.sjs create mode 100644 dom/serviceworkers/test/fetch/origin/origin_test.js create mode 100644 dom/serviceworkers/test/fetch/origin/realindex.html create mode 100644 dom/serviceworkers/test/fetch/origin/realindex.html^headers^ create mode 100644 dom/serviceworkers/test/fetch/origin/register.html create mode 100644 dom/serviceworkers/test/fetch/origin/unregister.html create mode 100644 dom/serviceworkers/test/fetch/plugin/plugins.html create mode 100644 dom/serviceworkers/test/fetch/plugin/worker.js create mode 100644 dom/serviceworkers/test/fetch/real-file.txt create mode 100644 dom/serviceworkers/test/fetch/redirect.sjs create mode 100644 dom/serviceworkers/test/fetch/requesturl/index.html create mode 100644 dom/serviceworkers/test/fetch/requesturl/redirect.sjs create mode 100644 dom/serviceworkers/test/fetch/requesturl/redirector.html create mode 100644 dom/serviceworkers/test/fetch/requesturl/register.html create mode 100644 dom/serviceworkers/test/fetch/requesturl/requesturl_test.js create mode 100644 dom/serviceworkers/test/fetch/requesturl/secret.html create mode 100644 dom/serviceworkers/test/fetch/requesturl/unregister.html create mode 100644 dom/serviceworkers/test/fetch/sandbox/index.html create mode 100644 dom/serviceworkers/test/fetch/sandbox/intercepted_index.html create mode 100644 dom/serviceworkers/test/fetch/sandbox/register.html create mode 100644 dom/serviceworkers/test/fetch/sandbox/sandbox_test.js create mode 100644 dom/serviceworkers/test/fetch/sandbox/unregister.html create mode 100644 dom/serviceworkers/test/fetch/upgrade-insecure/embedder.html create mode 100644 dom/serviceworkers/test/fetch/upgrade-insecure/embedder.html^headers^ create mode 100644 dom/serviceworkers/test/fetch/upgrade-insecure/image-20px.png create mode 100644 dom/serviceworkers/test/fetch/upgrade-insecure/image-40px.png create mode 100644 dom/serviceworkers/test/fetch/upgrade-insecure/image.html create mode 100644 dom/serviceworkers/test/fetch/upgrade-insecure/realindex.html create mode 100644 dom/serviceworkers/test/fetch/upgrade-insecure/register.html create mode 100644 dom/serviceworkers/test/fetch/upgrade-insecure/unregister.html create mode 100644 dom/serviceworkers/test/fetch/upgrade-insecure/upgrade-insecure_test.js (limited to 'dom/serviceworkers/test/fetch') diff --git a/dom/serviceworkers/test/fetch/cookie/cookie_test.js b/dom/serviceworkers/test/fetch/cookie/cookie_test.js new file mode 100644 index 0000000000..4102b4b341 --- /dev/null +++ b/dom/serviceworkers/test/fetch/cookie/cookie_test.js @@ -0,0 +1,11 @@ +self.addEventListener("fetch", function (event) { + if (event.request.url.includes("synth.html")) { + var body = + ""; + event.respondWith( + new Response(body, { headers: { "Content-Type": "text/html" } }) + ); + } +}); diff --git a/dom/serviceworkers/test/fetch/cookie/register.html b/dom/serviceworkers/test/fetch/cookie/register.html new file mode 100644 index 0000000000..99eabaf0a2 --- /dev/null +++ b/dom/serviceworkers/test/fetch/cookie/register.html @@ -0,0 +1,19 @@ + + + diff --git a/dom/serviceworkers/test/fetch/cookie/unregister.html b/dom/serviceworkers/test/fetch/cookie/unregister.html new file mode 100644 index 0000000000..1f13508fa7 --- /dev/null +++ b/dom/serviceworkers/test/fetch/cookie/unregister.html @@ -0,0 +1,12 @@ + + diff --git a/dom/serviceworkers/test/fetch/deliver-gzip.sjs b/dom/serviceworkers/test/fetch/deliver-gzip.sjs new file mode 100644 index 0000000000..d7cbdef06e --- /dev/null +++ b/dom/serviceworkers/test/fetch/deliver-gzip.sjs @@ -0,0 +1,21 @@ +"use strict"; + +function handleRequest(request, response) { + // The string "hello" repeated 10 times followed by newline. Compressed using gzip. + // prettier-ignore + let bytes = [0x1f, 0x8b, 0x08, 0x08, 0x4d, 0xe2, 0xf9, 0x54, 0x00, 0x03, 0x68, + 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0xcb, 0x48, 0xcd, 0xc9, 0xc9, 0xcf, + 0x20, 0x85, 0xe0, 0x02, 0x00, 0xf5, 0x4b, 0x38, 0xcf, 0x33, 0x00, + 0x00, 0x00]; + + response.setHeader("Content-Encoding", "gzip", false); + response.setHeader("Content-Length", "" + bytes.length, false); + response.setHeader("Content-Type", "text/plain", false); + + let bos = Components.classes[ + "@mozilla.org/binaryoutputstream;1" + ].createInstance(Components.interfaces.nsIBinaryOutputStream); + bos.setOutputStream(response.bodyOutputStream); + + bos.writeByteArray(bytes); +} diff --git a/dom/serviceworkers/test/fetch/fetch_tests.js b/dom/serviceworkers/test/fetch/fetch_tests.js new file mode 100644 index 0000000000..69b8a89679 --- /dev/null +++ b/dom/serviceworkers/test/fetch/fetch_tests.js @@ -0,0 +1,716 @@ +var origin = "http://mochi.test:8888"; + +function fetchXHRWithMethod(name, method, onload, onerror, headers) { + expectAsyncResult(); + + onload = + onload || + function () { + my_ok(false, "XHR load should not complete successfully"); + finish(); + }; + onerror = + onerror || + function () { + my_ok( + false, + "XHR load for " + name + " should be intercepted successfully" + ); + finish(); + }; + + var x = new XMLHttpRequest(); + x.open(method, name, true); + x.onload = function () { + onload(x); + }; + x.onerror = function () { + onerror(x); + }; + headers = headers || []; + headers.forEach(function (header) { + x.setRequestHeader(header[0], header[1]); + }); + x.send(); +} + +var corsServerPath = + "/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs"; +var corsServerURL = "http://example.com" + corsServerPath; + +function redirectURL(hops) { + return ( + hops[0].server + + corsServerPath + + "?hop=1&hops=" + + encodeURIComponent(JSON.stringify(hops)) + ); +} + +function fetchXHR(name, onload, onerror, headers) { + return fetchXHRWithMethod(name, "GET", onload, onerror, headers); +} + +fetchXHR("bare-synthesized.txt", function (xhr) { + my_ok(xhr.status == 200, "load should be successful"); + my_ok( + xhr.responseText == "synthesized response body", + "load should have synthesized response" + ); + finish(); +}); + +fetchXHR("test-respondwith-response.txt", function (xhr) { + my_ok( + xhr.status == 200, + "test-respondwith-response load should be successful" + ); + my_ok( + xhr.responseText == "test-respondwith-response response body", + "load should have response" + ); + finish(); +}); + +fetchXHR("synthesized-404.txt", function (xhr) { + my_ok(xhr.status == 404, "load should 404"); + my_ok( + xhr.responseText == "synthesized response body", + "404 load should have synthesized response" + ); + finish(); +}); + +fetchXHR("synthesized-headers.txt", function (xhr) { + my_ok(xhr.status == 200, "load should be successful"); + my_ok( + xhr.getResponseHeader("X-Custom-Greeting") === "Hello", + "custom header should be set" + ); + my_ok( + xhr.responseText == "synthesized response body", + "custom header load should have synthesized response" + ); + finish(); +}); + +fetchXHR("synthesized-redirect-real-file.txt", function (xhr) { + dump("Got status AARRGH " + xhr.status + " " + xhr.responseText + "\n"); + my_ok(xhr.status == 200, "load should be successful"); + my_ok( + xhr.responseText == "This is a real file.\n", + "Redirect to real file should complete." + ); + finish(); +}); + +fetchXHR("synthesized-redirect-twice-real-file.txt", function (xhr) { + my_ok(xhr.status == 200, "load should be successful"); + my_ok( + xhr.responseText == "This is a real file.\n", + "Redirect to real file (twice) should complete." + ); + finish(); +}); + +fetchXHR("synthesized-redirect-synthesized.txt", function (xhr) { + my_ok(xhr.status == 200, "synth+redirect+synth load should be successful"); + my_ok( + xhr.responseText == "synthesized response body", + "load should have redirected+synthesized response" + ); + finish(); +}); + +fetchXHR("synthesized-redirect-twice-synthesized.txt", function (xhr) { + my_ok( + xhr.status == 200, + "synth+redirect+synth (twice) load should be successful" + ); + my_ok( + xhr.responseText == "synthesized response body", + "load should have redirected+synthesized (twice) response" + ); + finish(); +}); + +fetchXHR("redirect.sjs", function (xhr) { + my_ok(xhr.status == 404, "redirected load should be uninterrupted"); + finish(); +}); + +fetchXHR("ignored.txt", function (xhr) { + my_ok(xhr.status == 404, "load should be uninterrupted"); + finish(); +}); + +fetchXHR("rejected.txt", null, function (xhr) { + my_ok(xhr.status == 0, "load should not complete"); + finish(); +}); + +fetchXHR("nonresponse.txt", null, function (xhr) { + my_ok(xhr.status == 0, "load should not complete"); + finish(); +}); + +fetchXHR("nonresponse2.txt", null, function (xhr) { + my_ok(xhr.status == 0, "load should not complete"); + finish(); +}); + +fetchXHR("nonpromise.txt", null, function (xhr) { + my_ok(xhr.status == 0, "load should not complete"); + finish(); +}); + +fetchXHR( + "headers.txt", + function (xhr) { + my_ok(xhr.status == 200, "load should be successful"); + my_ok(xhr.responseText == "1", "request header checks should have passed"); + finish(); + }, + null, + [ + ["X-Test1", "header1"], + ["X-Test2", "header2"], + ] +); + +fetchXHR("http://user:pass@mochi.test:8888/user-pass", function (xhr) { + my_ok(xhr.status == 200, "load should be successful"); + my_ok( + xhr.responseText == "http://user:pass@mochi.test:8888/user-pass", + "The username and password should be preserved" + ); + finish(); +}); + +fetchXHR("readable-stream.txt", function (xhr) { + my_ok(xhr.status == 200, "loading completed"); + my_ok(xhr.responseText == "Hello!", "The message is correct!"); + finish(); +}); + +fetchXHR( + "readable-stream-locked.txt", + function (xhr) { + my_ok(false, "This should not be called!"); + finish(); + }, + function () { + my_ok(true, "The exception has been correctly handled!"); + finish(); + } +); + +fetchXHR( + "readable-stream-with-exception.txt", + function (xhr) { + my_ok(false, "This should not be called!"); + finish(); + }, + function () { + my_ok(true, "The exception has been correctly handled!"); + finish(); + } +); + +fetchXHR( + "readable-stream-with-exception2.txt", + function (xhr) { + my_ok(false, "This should not be called!"); + finish(); + }, + function () { + my_ok(true, "The exception has been correctly handled!"); + finish(); + } +); + +fetchXHR( + "readable-stream-already-consumed.txt", + function (xhr) { + my_ok(false, "This should not be called!"); + finish(); + }, + function () { + my_ok(true, "The exception has been correctly handled!"); + finish(); + } +); + +var expectedUncompressedResponse = ""; +for (let i = 0; i < 10; ++i) { + expectedUncompressedResponse += "hello"; +} +expectedUncompressedResponse += "\n"; + +// ServiceWorker does not intercept, at which point the network request should +// be correctly decoded. +fetchXHR("deliver-gzip.sjs", function (xhr) { + my_ok(xhr.status == 200, "network gzip load should be successful"); + my_ok( + xhr.responseText == expectedUncompressedResponse, + "network gzip load should have synthesized response." + ); + my_ok( + xhr.getResponseHeader("Content-Encoding") == "gzip", + "network Content-Encoding should be gzip." + ); + my_ok( + xhr.getResponseHeader("Content-Length") == "35", + "network Content-Length should be of original gzipped file." + ); + finish(); +}); + +fetchXHR("hello.gz", function (xhr) { + my_ok(xhr.status == 200, "gzip load should be successful"); + my_ok( + xhr.responseText == expectedUncompressedResponse, + "gzip load should have synthesized response." + ); + my_ok( + xhr.getResponseHeader("Content-Encoding") == "gzip", + "Content-Encoding should be gzip." + ); + my_ok( + xhr.getResponseHeader("Content-Length") == "35", + "Content-Length should be of original gzipped file." + ); + finish(); +}); + +fetchXHR("hello-after-extracting.gz", function (xhr) { + my_ok(xhr.status == 200, "gzip load after extracting should be successful"); + my_ok( + xhr.responseText == expectedUncompressedResponse, + "gzip load after extracting should have synthesized response." + ); + my_ok( + xhr.getResponseHeader("Content-Encoding") == "gzip", + "Content-Encoding after extracting should be gzip." + ); + my_ok( + xhr.getResponseHeader("Content-Length") == "35", + "Content-Length after extracting should be of original gzipped file." + ); + finish(); +}); + +fetchXHR(corsServerURL + "?status=200&allowOrigin=*", function (xhr) { + my_ok( + xhr.status == 200, + "cross origin load with correct headers should be successful" + ); + my_ok( + xhr.getResponseHeader("access-control-allow-origin") == null, + "cors headers should be filtered out" + ); + finish(); +}); + +// Verify origin header is sent properly even when we have a no-intercept SW. +var uriOrigin = encodeURIComponent(origin); +fetchXHR( + "http://example.org" + + corsServerPath + + "?ignore&status=200&origin=" + + uriOrigin + + "&allowOrigin=" + + uriOrigin, + function (xhr) { + my_ok( + xhr.status == 200, + "cross origin load with correct headers should be successful" + ); + my_ok( + xhr.getResponseHeader("access-control-allow-origin") == null, + "cors headers should be filtered out" + ); + finish(); + } +); + +// Verify that XHR is considered CORS tainted even when original URL is same-origin +// redirected to cross-origin. +fetchXHR( + redirectURL([ + { server: origin }, + { server: "http://example.org", allowOrigin: origin }, + ]), + function (xhr) { + my_ok( + xhr.status == 200, + "cross origin load with correct headers should be successful" + ); + my_ok( + xhr.getResponseHeader("access-control-allow-origin") == null, + "cors headers should be filtered out" + ); + finish(); + } +); + +// Test that CORS preflight requests cannot be intercepted. Performs a +// cross-origin XHR that the SW chooses not to intercept. This requires a +// preflight request, which the SW must not be allowed to intercept. +fetchXHR( + corsServerURL + "?status=200&allowOrigin=*", + null, + function (xhr) { + my_ok( + xhr.status == 0, + "cross origin load with incorrect headers should be a failure" + ); + finish(); + }, + [["X-Unsafe", "unsafe"]] +); + +// Test that CORS preflight requests cannot be intercepted. Performs a +// cross-origin XHR that the SW chooses to intercept and respond with a +// cross-origin fetch. This requires a preflight request, which the SW must not +// be allowed to intercept. +fetchXHR( + "http://example.org" + corsServerPath + "?status=200&allowOrigin=*", + null, + function (xhr) { + my_ok( + xhr.status == 0, + "cross origin load with incorrect headers should be a failure" + ); + finish(); + }, + [["X-Unsafe", "unsafe"]] +); + +// Test that when the page fetches a url the controlling SW forces a redirect to +// another location. This other location fetch should also be intercepted by +// the SW. +fetchXHR("something.txt", function (xhr) { + my_ok(xhr.status == 200, "load should be successful"); + my_ok( + xhr.responseText == "something else response body", + "load should have something else" + ); + finish(); +}); + +// Test fetch will internally get it's SkipServiceWorker flag set. The request is +// made from the SW through fetch(). fetch() fetches a server-side JavaScript +// file that force a redirect. The redirect location fetch does not go through +// the SW. +fetchXHR("redirect_serviceworker.sjs", function (xhr) { + my_ok(xhr.status == 200, "load should be successful"); + my_ok( + xhr.responseText == "// empty worker, always succeed!\n", + "load should have redirection content" + ); + finish(); +}); + +fetchXHR( + "empty-header", + function (xhr) { + my_ok(xhr.status == 200, "load should be successful"); + my_ok( + xhr.responseText == "emptyheader", + "load should have the expected content" + ); + finish(); + }, + null, + [["emptyheader", ""]] +); + +expectAsyncResult(); +fetch( + "http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200&allowOrigin=*" +).then( + function (res) { + my_ok(res.ok, "Valid CORS request should receive valid response"); + my_ok(res.type == "cors", "Response type should be CORS"); + res.text().then(function (body) { + my_ok( + body === "hello pass\n", + "cors response body should match" + ); + finish(); + }); + }, + function (e) { + my_ok(false, "CORS Fetch failed"); + finish(); + } +); + +expectAsyncResult(); +fetch( + "http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200", + { mode: "no-cors" } +).then( + function (res) { + my_ok(res.type == "opaque", "Response type should be opaque"); + my_ok(res.status == 0, "Status should be 0"); + res.text().then(function (body) { + my_ok(body === "", "opaque response body should be empty"); + finish(); + }); + }, + function (e) { + my_ok(false, "no-cors Fetch failed"); + finish(); + } +); + +expectAsyncResult(); +fetch("opaque-on-same-origin").then( + function (res) { + my_ok( + false, + "intercepted opaque response for non no-cors request should fail." + ); + finish(); + }, + function (e) { + my_ok( + true, + "intercepted opaque response for non no-cors request should fail." + ); + finish(); + } +); + +expectAsyncResult(); +fetch("http://example.com/opaque-no-cors", { mode: "no-cors" }).then( + function (res) { + my_ok( + res.type == "opaque", + "intercepted opaque response for no-cors request should have type opaque." + ); + finish(); + }, + function (e) { + my_ok( + false, + "intercepted opaque response for no-cors request should pass." + ); + finish(); + } +); + +expectAsyncResult(); +fetch("http://example.com/cors-for-no-cors", { mode: "no-cors" }).then( + function (res) { + my_ok( + res.type == "cors", + "synthesize CORS response should result in outer CORS response" + ); + finish(); + }, + function (e) { + my_ok(false, "cors-for-no-cors request should not reject"); + finish(); + } +); + +function arrayBufferFromString(str) { + var arr = new Uint8Array(str.length); + for (let i = 0; i < str.length; ++i) { + arr[i] = str.charCodeAt(i); + } + return arr; +} + +expectAsyncResult(); +fetch(new Request("body-simple", { method: "POST", body: "my body" })) + .then(function (res) { + return res.text(); + }) + .then(function (body) { + my_ok( + body == "my bodymy body", + "the body of the intercepted fetch should be visible in the SW" + ); + finish(); + }); + +expectAsyncResult(); +fetch( + new Request("body-arraybufferview", { + method: "POST", + body: arrayBufferFromString("my body"), + }) +) + .then(function (res) { + return res.text(); + }) + .then(function (body) { + my_ok( + body == "my bodymy body", + "the ArrayBufferView body of the intercepted fetch should be visible in the SW" + ); + finish(); + }); + +expectAsyncResult(); +fetch( + new Request("body-arraybuffer", { + method: "POST", + body: arrayBufferFromString("my body").buffer, + }) +) + .then(function (res) { + return res.text(); + }) + .then(function (body) { + my_ok( + body == "my bodymy body", + "the ArrayBuffer body of the intercepted fetch should be visible in the SW" + ); + finish(); + }); + +expectAsyncResult(); +var usp = new URLSearchParams(); +usp.set("foo", "bar"); +usp.set("baz", "qux"); +fetch(new Request("body-urlsearchparams", { method: "POST", body: usp })) + .then(function (res) { + return res.text(); + }) + .then(function (body) { + my_ok( + body == "foo=bar&baz=quxfoo=bar&baz=qux", + "the URLSearchParams body of the intercepted fetch should be visible in the SW" + ); + finish(); + }); + +expectAsyncResult(); +var fd = new FormData(); +fd.set("foo", "bar"); +fd.set("baz", "qux"); +fetch(new Request("body-formdata", { method: "POST", body: fd })) + .then(function (res) { + return res.text(); + }) + .then(function (body) { + my_ok( + body.indexOf('Content-Disposition: form-data; name="foo"\r\n\r\nbar') < + body.indexOf('Content-Disposition: form-data; name="baz"\r\n\r\nqux'), + "the FormData body of the intercepted fetch should be visible in the SW" + ); + finish(); + }); + +expectAsyncResult(); +fetch( + new Request("body-blob", { + method: "POST", + body: new Blob(new String("my body")), + }) +) + .then(function (res) { + return res.text(); + }) + .then(function (body) { + my_ok( + body == "my bodymy body", + "the Blob body of the intercepted fetch should be visible in the SW" + ); + finish(); + }); + +expectAsyncResult(); +fetch("interrupt.sjs").then( + function (res) { + my_ok(true, "interrupted fetch succeeded"); + res.text().then( + function (body) { + my_ok(false, "interrupted fetch shouldn't have complete body"); + finish(); + }, + function () { + my_ok(true, "interrupted fetch shouldn't have complete body"); + finish(); + } + ); + }, + function (e) { + my_ok(false, "interrupted fetch failed"); + finish(); + } +); + +["DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT"].forEach(function (method) { + fetchXHRWithMethod("xhr-method-test.txt", method, function (xhr) { + my_ok(xhr.status == 200, method + " load should be successful"); + if (method === "HEAD") { + my_ok( + xhr.responseText == "", + method + "load should not have synthesized response" + ); + } else { + my_ok( + xhr.responseText == "intercepted " + method, + method + " load should have synthesized response" + ); + } + finish(); + }); +}); + +expectAsyncResult(); +fetch(new Request("empty-header", { headers: { emptyheader: "" } })) + .then(function (res) { + return res.text(); + }) + .then( + function (body) { + my_ok( + body == "emptyheader", + "The empty header was observed in the fetch event" + ); + finish(); + }, + function (err) { + my_ok(false, "A promise was rejected with " + err); + finish(); + } + ); + +expectAsyncResult(); +fetch("fetchevent-extendable") + .then(function (res) { + return res.text(); + }) + .then( + function (body) { + my_ok(body == "extendable", "FetchEvent inherits from ExtendableEvent"); + finish(); + }, + function (err) { + my_ok(false, "A promise was rejected with " + err); + finish(); + } + ); + +expectAsyncResult(); +fetch("fetchevent-request") + .then(function (res) { + return res.text(); + }) + .then( + function (body) { + my_ok(body == "non-nullable", "FetchEvent.request must be non-nullable"); + finish(); + }, + function (err) { + my_ok(false, "A promise was rejected with " + err); + finish(); + } + ); diff --git a/dom/serviceworkers/test/fetch/fetch_worker_script.js b/dom/serviceworkers/test/fetch/fetch_worker_script.js new file mode 100644 index 0000000000..6eb0b18a77 --- /dev/null +++ b/dom/serviceworkers/test/fetch/fetch_worker_script.js @@ -0,0 +1,28 @@ +function my_ok(v, msg) { + postMessage({ type: "ok", value: v, msg }); +} + +function finish() { + postMessage("finish"); +} + +function expectAsyncResult() { + postMessage("expect"); +} + +expectAsyncResult(); +try { + var success = false; + importScripts("nonexistent_imported_script.js"); +} catch (x) {} + +my_ok(success, "worker imported script should be intercepted"); +finish(); + +function check_intercepted_script() { + success = true; +} + +importScripts("fetch_tests.js"); + +finish(); //corresponds to the gExpected increment before creating this worker diff --git a/dom/serviceworkers/test/fetch/hsts/embedder.html b/dom/serviceworkers/test/fetch/hsts/embedder.html new file mode 100644 index 0000000000..ad44809042 --- /dev/null +++ b/dom/serviceworkers/test/fetch/hsts/embedder.html @@ -0,0 +1,7 @@ + + + diff --git a/dom/serviceworkers/test/fetch/hsts/hsts_test.js b/dom/serviceworkers/test/fetch/hsts/hsts_test.js new file mode 100644 index 0000000000..74b9ed23ba --- /dev/null +++ b/dom/serviceworkers/test/fetch/hsts/hsts_test.js @@ -0,0 +1,11 @@ +self.addEventListener("fetch", function (event) { + if (event.request.url.includes("index.html")) { + event.respondWith(fetch("realindex.html")); + } else if (event.request.url.includes("image-20px.png")) { + if (event.request.url.indexOf("https://") == 0) { + event.respondWith(fetch("image-40px.png")); + } else { + event.respondWith(Response.error()); + } + } +}); diff --git a/dom/serviceworkers/test/fetch/hsts/image-20px.png b/dom/serviceworkers/test/fetch/hsts/image-20px.png new file mode 100644 index 0000000000..ae6a8a6b88 Binary files /dev/null and b/dom/serviceworkers/test/fetch/hsts/image-20px.png differ diff --git a/dom/serviceworkers/test/fetch/hsts/image-40px.png b/dom/serviceworkers/test/fetch/hsts/image-40px.png new file mode 100644 index 0000000000..fe391dc8a2 Binary files /dev/null and b/dom/serviceworkers/test/fetch/hsts/image-40px.png differ diff --git a/dom/serviceworkers/test/fetch/hsts/image.html b/dom/serviceworkers/test/fetch/hsts/image.html new file mode 100644 index 0000000000..7036ea954e --- /dev/null +++ b/dom/serviceworkers/test/fetch/hsts/image.html @@ -0,0 +1,13 @@ + + diff --git a/dom/serviceworkers/test/fetch/hsts/realindex.html b/dom/serviceworkers/test/fetch/hsts/realindex.html new file mode 100644 index 0000000000..e7d282fe83 --- /dev/null +++ b/dom/serviceworkers/test/fetch/hsts/realindex.html @@ -0,0 +1,8 @@ + + diff --git a/dom/serviceworkers/test/fetch/hsts/register.html b/dom/serviceworkers/test/fetch/hsts/register.html new file mode 100644 index 0000000000..bcdc146aec --- /dev/null +++ b/dom/serviceworkers/test/fetch/hsts/register.html @@ -0,0 +1,14 @@ + + diff --git a/dom/serviceworkers/test/fetch/hsts/register.html^headers^ b/dom/serviceworkers/test/fetch/hsts/register.html^headers^ new file mode 100644 index 0000000000..a46bf65bd9 --- /dev/null +++ b/dom/serviceworkers/test/fetch/hsts/register.html^headers^ @@ -0,0 +1,2 @@ +Cache-Control: no-cache +Strict-Transport-Security: max-age=60 diff --git a/dom/serviceworkers/test/fetch/hsts/unregister.html b/dom/serviceworkers/test/fetch/hsts/unregister.html new file mode 100644 index 0000000000..1f13508fa7 --- /dev/null +++ b/dom/serviceworkers/test/fetch/hsts/unregister.html @@ -0,0 +1,12 @@ + + diff --git a/dom/serviceworkers/test/fetch/https/clonedresponse/https_test.js b/dom/serviceworkers/test/fetch/https/clonedresponse/https_test.js new file mode 100644 index 0000000000..8ab34123af --- /dev/null +++ b/dom/serviceworkers/test/fetch/https/clonedresponse/https_test.js @@ -0,0 +1,19 @@ +self.addEventListener("install", function (event) { + event.waitUntil( + caches.open("cache").then(function (cache) { + return cache.add("index.html"); + }) + ); +}); + +self.addEventListener("fetch", function (event) { + if (event.request.url.includes("index.html")) { + event.respondWith( + new Promise(function (resolve, reject) { + caches.match(event.request).then(function (response) { + resolve(response.clone()); + }); + }) + ); + } +}); diff --git a/dom/serviceworkers/test/fetch/https/clonedresponse/index.html b/dom/serviceworkers/test/fetch/https/clonedresponse/index.html new file mode 100644 index 0000000000..a435548443 --- /dev/null +++ b/dom/serviceworkers/test/fetch/https/clonedresponse/index.html @@ -0,0 +1,4 @@ + + diff --git a/dom/serviceworkers/test/fetch/https/clonedresponse/register.html b/dom/serviceworkers/test/fetch/https/clonedresponse/register.html new file mode 100644 index 0000000000..41774f70d1 --- /dev/null +++ b/dom/serviceworkers/test/fetch/https/clonedresponse/register.html @@ -0,0 +1,14 @@ + + diff --git a/dom/serviceworkers/test/fetch/https/clonedresponse/unregister.html b/dom/serviceworkers/test/fetch/https/clonedresponse/unregister.html new file mode 100644 index 0000000000..1f13508fa7 --- /dev/null +++ b/dom/serviceworkers/test/fetch/https/clonedresponse/unregister.html @@ -0,0 +1,12 @@ + + diff --git a/dom/serviceworkers/test/fetch/https/https_test.js b/dom/serviceworkers/test/fetch/https/https_test.js new file mode 100644 index 0000000000..5f20690bb5 --- /dev/null +++ b/dom/serviceworkers/test/fetch/https/https_test.js @@ -0,0 +1,31 @@ +self.addEventListener("install", function (event) { + event.waitUntil( + caches.open("cache").then(function (cache) { + var synth = new Response( + '', + { headers: { "Content-Type": "text/html" } } + ); + return Promise.all([ + cache.add("index.html"), + cache.put("synth-sw.html", synth), + ]); + }) + ); +}); + +self.addEventListener("fetch", function (event) { + if (event.request.url.includes("index.html")) { + event.respondWith(caches.match(event.request)); + } else if (event.request.url.includes("synth-sw.html")) { + event.respondWith(caches.match(event.request)); + } else if (event.request.url.includes("synth-window.html")) { + event.respondWith(caches.match(event.request)); + } else if (event.request.url.includes("synth.html")) { + event.respondWith( + new Response( + '', + { headers: { "Content-Type": "text/html" } } + ) + ); + } +}); diff --git a/dom/serviceworkers/test/fetch/https/index.html b/dom/serviceworkers/test/fetch/https/index.html new file mode 100644 index 0000000000..a435548443 --- /dev/null +++ b/dom/serviceworkers/test/fetch/https/index.html @@ -0,0 +1,4 @@ + + diff --git a/dom/serviceworkers/test/fetch/https/register.html b/dom/serviceworkers/test/fetch/https/register.html new file mode 100644 index 0000000000..fa666fe957 --- /dev/null +++ b/dom/serviceworkers/test/fetch/https/register.html @@ -0,0 +1,20 @@ + + diff --git a/dom/serviceworkers/test/fetch/https/unregister.html b/dom/serviceworkers/test/fetch/https/unregister.html new file mode 100644 index 0000000000..1f13508fa7 --- /dev/null +++ b/dom/serviceworkers/test/fetch/https/unregister.html @@ -0,0 +1,12 @@ + + diff --git a/dom/serviceworkers/test/fetch/imagecache-maxage/image-20px.png b/dom/serviceworkers/test/fetch/imagecache-maxage/image-20px.png new file mode 100644 index 0000000000..ae6a8a6b88 Binary files /dev/null and b/dom/serviceworkers/test/fetch/imagecache-maxage/image-20px.png differ diff --git a/dom/serviceworkers/test/fetch/imagecache-maxage/image-40px.png b/dom/serviceworkers/test/fetch/imagecache-maxage/image-40px.png new file mode 100644 index 0000000000..fe391dc8a2 Binary files /dev/null and b/dom/serviceworkers/test/fetch/imagecache-maxage/image-40px.png differ diff --git a/dom/serviceworkers/test/fetch/imagecache-maxage/index.html b/dom/serviceworkers/test/fetch/imagecache-maxage/index.html new file mode 100644 index 0000000000..0d4c52eedd --- /dev/null +++ b/dom/serviceworkers/test/fetch/imagecache-maxage/index.html @@ -0,0 +1,29 @@ + + + + diff --git a/dom/serviceworkers/test/fetch/imagecache-maxage/maxage_test.js b/dom/serviceworkers/test/fetch/imagecache-maxage/maxage_test.js new file mode 100644 index 0000000000..c664e07c28 --- /dev/null +++ b/dom/serviceworkers/test/fetch/imagecache-maxage/maxage_test.js @@ -0,0 +1,45 @@ +function synthesizeImage(suffix) { + // Serve image-20px for the first page, and image-40px for the second page. + return clients + .matchAll() + .then(clients => { + var url = "image-20px.png"; + clients.forEach(client => { + if (client.url.indexOf("?new") > 0) { + url = "image-40px.png"; + } + client.postMessage({ suffix, url }); + }); + return fetch(url); + }) + .then(response => { + return response.arrayBuffer(); + }) + .then(ab => { + var headers; + if (suffix == "") { + headers = { + "Content-Type": "image/png", + Date: "Tue, 1 Jan 1990 01:02:03 GMT", + "Cache-Control": "max-age=1", + }; + } else { + headers = { + "Content-Type": "image/png", + "Cache-Control": "no-cache", + }; + } + return new Response(ab, { + status: 200, + headers, + }); + }); +} + +self.addEventListener("fetch", function (event) { + if (event.request.url.includes("image.png")) { + event.respondWith(synthesizeImage("")); + } else if (event.request.url.includes("image2.png")) { + event.respondWith(synthesizeImage("2")); + } +}); diff --git a/dom/serviceworkers/test/fetch/imagecache-maxage/register.html b/dom/serviceworkers/test/fetch/imagecache-maxage/register.html new file mode 100644 index 0000000000..af4dde2e29 --- /dev/null +++ b/dom/serviceworkers/test/fetch/imagecache-maxage/register.html @@ -0,0 +1,14 @@ + + diff --git a/dom/serviceworkers/test/fetch/imagecache-maxage/unregister.html b/dom/serviceworkers/test/fetch/imagecache-maxage/unregister.html new file mode 100644 index 0000000000..1f13508fa7 --- /dev/null +++ b/dom/serviceworkers/test/fetch/imagecache-maxage/unregister.html @@ -0,0 +1,12 @@ + + diff --git a/dom/serviceworkers/test/fetch/imagecache/image-20px.png b/dom/serviceworkers/test/fetch/imagecache/image-20px.png new file mode 100644 index 0000000000..ae6a8a6b88 Binary files /dev/null and b/dom/serviceworkers/test/fetch/imagecache/image-20px.png differ diff --git a/dom/serviceworkers/test/fetch/imagecache/image-40px.png b/dom/serviceworkers/test/fetch/imagecache/image-40px.png new file mode 100644 index 0000000000..fe391dc8a2 Binary files /dev/null and b/dom/serviceworkers/test/fetch/imagecache/image-40px.png differ diff --git a/dom/serviceworkers/test/fetch/imagecache/imagecache_test.js b/dom/serviceworkers/test/fetch/imagecache/imagecache_test.js new file mode 100644 index 0000000000..cd8f522728 --- /dev/null +++ b/dom/serviceworkers/test/fetch/imagecache/imagecache_test.js @@ -0,0 +1,15 @@ +function synthesizeImage() { + return clients.matchAll().then(clients => { + var url = "image-40px.png"; + clients.forEach(client => { + client.postMessage(url); + }); + return fetch(url); + }); +} + +self.addEventListener("fetch", function (event) { + if (event.request.url.includes("image-20px.png")) { + event.respondWith(synthesizeImage()); + } +}); diff --git a/dom/serviceworkers/test/fetch/imagecache/index.html b/dom/serviceworkers/test/fetch/imagecache/index.html new file mode 100644 index 0000000000..f634f68bb7 --- /dev/null +++ b/dom/serviceworkers/test/fetch/imagecache/index.html @@ -0,0 +1,20 @@ + + + diff --git a/dom/serviceworkers/test/fetch/imagecache/postmortem.html b/dom/serviceworkers/test/fetch/imagecache/postmortem.html new file mode 100644 index 0000000000..53356cd02c --- /dev/null +++ b/dom/serviceworkers/test/fetch/imagecache/postmortem.html @@ -0,0 +1,9 @@ + + + diff --git a/dom/serviceworkers/test/fetch/imagecache/register.html b/dom/serviceworkers/test/fetch/imagecache/register.html new file mode 100644 index 0000000000..f6d1eb382f --- /dev/null +++ b/dom/serviceworkers/test/fetch/imagecache/register.html @@ -0,0 +1,16 @@ + + + + diff --git a/dom/serviceworkers/test/fetch/imagecache/unregister.html b/dom/serviceworkers/test/fetch/imagecache/unregister.html new file mode 100644 index 0000000000..1f13508fa7 --- /dev/null +++ b/dom/serviceworkers/test/fetch/imagecache/unregister.html @@ -0,0 +1,12 @@ + + diff --git a/dom/serviceworkers/test/fetch/importscript-mixedcontent/https_test.js b/dom/serviceworkers/test/fetch/importscript-mixedcontent/https_test.js new file mode 100644 index 0000000000..138ca768aa --- /dev/null +++ b/dom/serviceworkers/test/fetch/importscript-mixedcontent/https_test.js @@ -0,0 +1,31 @@ +function sendResponseToParent(response) { + return ` + + + `; +} + +self.addEventListener("fetch", function (event) { + if (event.request.url.includes("index.html")) { + var response = "good"; + try { + importScripts("http://example.org/tests/dom/workers/test/foreign.js"); + } catch (e) { + dump("Got error " + e + " when importing the script\n"); + } + if (response === "good") { + try { + importScripts("/tests/dom/workers/test/redirect_to_foreign.sjs"); + } catch (e) { + dump("Got error " + e + " when importing the script\n"); + } + } + event.respondWith( + new Response(sendResponseToParent(response), { + headers: { "Content-Type": "text/html" }, + }) + ); + } +}); diff --git a/dom/serviceworkers/test/fetch/importscript-mixedcontent/register.html b/dom/serviceworkers/test/fetch/importscript-mixedcontent/register.html new file mode 100644 index 0000000000..41774f70d1 --- /dev/null +++ b/dom/serviceworkers/test/fetch/importscript-mixedcontent/register.html @@ -0,0 +1,14 @@ + + diff --git a/dom/serviceworkers/test/fetch/importscript-mixedcontent/unregister.html b/dom/serviceworkers/test/fetch/importscript-mixedcontent/unregister.html new file mode 100644 index 0000000000..1f13508fa7 --- /dev/null +++ b/dom/serviceworkers/test/fetch/importscript-mixedcontent/unregister.html @@ -0,0 +1,12 @@ + + diff --git a/dom/serviceworkers/test/fetch/index.html b/dom/serviceworkers/test/fetch/index.html new file mode 100644 index 0000000000..693810c6fc --- /dev/null +++ b/dom/serviceworkers/test/fetch/index.html @@ -0,0 +1,191 @@ + + + + + Bug 94048 - test install event. + + + + +

+ +
+

+
+
+
+
+
+
diff --git a/dom/serviceworkers/test/fetch/interrupt.sjs b/dom/serviceworkers/test/fetch/interrupt.sjs
new file mode 100644
index 0000000000..6e5deeb832
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/interrupt.sjs
@@ -0,0 +1,20 @@
+function handleRequest(request, response) {
+  var body = "a";
+  for (var i = 0; i < 20; i++) {
+    body += body;
+  }
+
+  response.seizePower();
+  response.write("HTTP/1.1 200 OK\r\n");
+  var count = 10;
+  response.write("Content-Length: " + body.length * count + "\r\n");
+  response.write("Content-Type: text/plain; charset=utf-8\r\n");
+  response.write("Cache-Control: no-cache, must-revalidate\r\n");
+  response.write("\r\n");
+
+  for (var i = 0; i < count; i++) {
+    response.write(body);
+  }
+
+  throw Components.Exception("", Components.results.NS_BINDING_ABORTED);
+}
diff --git a/dom/serviceworkers/test/fetch/origin/https/index-https.sjs b/dom/serviceworkers/test/fetch/origin/https/index-https.sjs
new file mode 100644
index 0000000000..5250467ec7
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/https/index-https.sjs
@@ -0,0 +1,8 @@
+function handleRequest(request, response) {
+  response.setStatusLine(null, 308, "Permanent Redirect");
+  response.setHeader(
+    "Location",
+    "https://example.org/tests/dom/serviceworkers/test/fetch/origin/https/realindex.html",
+    false
+  );
+}
diff --git a/dom/serviceworkers/test/fetch/origin/https/origin_test.js b/dom/serviceworkers/test/fetch/origin/https/origin_test.js
new file mode 100644
index 0000000000..d148de2d83
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/https/origin_test.js
@@ -0,0 +1,29 @@
+var prefix = "/tests/dom/serviceworkers/test/fetch/origin/https/";
+
+function addOpaqueRedirect(cache, file) {
+  return fetch(new Request(prefix + file, { redirect: "manual" })).then(
+    function (response) {
+      return cache.put(prefix + file, response);
+    }
+  );
+}
+
+self.addEventListener("install", function (event) {
+  event.waitUntil(
+    self.caches.open("origin-cache").then(c => {
+      return addOpaqueRedirect(c, "index-https.sjs");
+    })
+  );
+});
+
+self.addEventListener("fetch", function (event) {
+  if (event.request.url.includes("index-cached-https.sjs")) {
+    event.respondWith(
+      self.caches.open("origin-cache").then(c => {
+        return c.match(prefix + "index-https.sjs");
+      })
+    );
+  } else {
+    event.respondWith(fetch(event.request));
+  }
+});
diff --git a/dom/serviceworkers/test/fetch/origin/https/realindex.html b/dom/serviceworkers/test/fetch/origin/https/realindex.html
new file mode 100644
index 0000000000..87f3489455
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/https/realindex.html
@@ -0,0 +1,6 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/origin/https/realindex.html^headers^ b/dom/serviceworkers/test/fetch/origin/https/realindex.html^headers^
new file mode 100644
index 0000000000..5ed82fd065
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/https/realindex.html^headers^
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: https://example.com
diff --git a/dom/serviceworkers/test/fetch/origin/https/register.html b/dom/serviceworkers/test/fetch/origin/https/register.html
new file mode 100644
index 0000000000..2e99adba53
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/https/register.html
@@ -0,0 +1,14 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/origin/https/unregister.html b/dom/serviceworkers/test/fetch/origin/https/unregister.html
new file mode 100644
index 0000000000..1f13508fa7
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/https/unregister.html
@@ -0,0 +1,12 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/origin/index-to-https.sjs b/dom/serviceworkers/test/fetch/origin/index-to-https.sjs
new file mode 100644
index 0000000000..2505c03686
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/index-to-https.sjs
@@ -0,0 +1,8 @@
+function handleRequest(request, response) {
+  response.setStatusLine(null, 308, "Permanent Redirect");
+  response.setHeader(
+    "Location",
+    "https://example.org/tests/dom/serviceworkers/test/fetch/origin/realindex.html",
+    false
+  );
+}
diff --git a/dom/serviceworkers/test/fetch/origin/index.sjs b/dom/serviceworkers/test/fetch/origin/index.sjs
new file mode 100644
index 0000000000..ca11827792
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/index.sjs
@@ -0,0 +1,8 @@
+function handleRequest(request, response) {
+  response.setStatusLine(null, 308, "Permanent Redirect");
+  response.setHeader(
+    "Location",
+    "http://example.org/tests/dom/serviceworkers/test/fetch/origin/realindex.html",
+    false
+  );
+}
diff --git a/dom/serviceworkers/test/fetch/origin/origin_test.js b/dom/serviceworkers/test/fetch/origin/origin_test.js
new file mode 100644
index 0000000000..d57f10cc2a
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/origin_test.js
@@ -0,0 +1,38 @@
+var prefix = "/tests/dom/serviceworkers/test/fetch/origin/";
+
+function addOpaqueRedirect(cache, file) {
+  return fetch(new Request(prefix + file, { redirect: "manual" })).then(
+    function (response) {
+      return cache.put(prefix + file, response);
+    }
+  );
+}
+
+self.addEventListener("install", function (event) {
+  event.waitUntil(
+    self.caches.open("origin-cache").then(c => {
+      return Promise.all([
+        addOpaqueRedirect(c, "index.sjs"),
+        addOpaqueRedirect(c, "index-to-https.sjs"),
+      ]);
+    })
+  );
+});
+
+self.addEventListener("fetch", function (event) {
+  if (event.request.url.includes("index-cached.sjs")) {
+    event.respondWith(
+      self.caches.open("origin-cache").then(c => {
+        return c.match(prefix + "index.sjs");
+      })
+    );
+  } else if (event.request.url.includes("index-to-https-cached.sjs")) {
+    event.respondWith(
+      self.caches.open("origin-cache").then(c => {
+        return c.match(prefix + "index-to-https.sjs");
+      })
+    );
+  } else {
+    event.respondWith(fetch(event.request));
+  }
+});
diff --git a/dom/serviceworkers/test/fetch/origin/realindex.html b/dom/serviceworkers/test/fetch/origin/realindex.html
new file mode 100644
index 0000000000..87f3489455
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/realindex.html
@@ -0,0 +1,6 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/origin/realindex.html^headers^ b/dom/serviceworkers/test/fetch/origin/realindex.html^headers^
new file mode 100644
index 0000000000..3a6a85d894
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/realindex.html^headers^
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: http://mochi.test:8888
diff --git a/dom/serviceworkers/test/fetch/origin/register.html b/dom/serviceworkers/test/fetch/origin/register.html
new file mode 100644
index 0000000000..2e99adba53
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/register.html
@@ -0,0 +1,14 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/origin/unregister.html b/dom/serviceworkers/test/fetch/origin/unregister.html
new file mode 100644
index 0000000000..1f13508fa7
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/origin/unregister.html
@@ -0,0 +1,12 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/plugin/plugins.html b/dom/serviceworkers/test/fetch/plugin/plugins.html
new file mode 100644
index 0000000000..b268f6d99e
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/plugin/plugins.html
@@ -0,0 +1,43 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/plugin/worker.js b/dom/serviceworkers/test/fetch/plugin/worker.js
new file mode 100644
index 0000000000..9849c9e0d5
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/plugin/worker.js
@@ -0,0 +1,15 @@
+self.addEventListener("fetch", function (event) {
+  var resource = event.request.url.split("/").pop();
+  event.waitUntil(
+    clients.matchAll().then(clients => {
+      clients.forEach(client => {
+        if (client.url.includes("plugins.html")) {
+          client.postMessage({
+            destination: event.request.destination,
+            resource,
+          });
+        }
+      });
+    })
+  );
+});
diff --git a/dom/serviceworkers/test/fetch/real-file.txt b/dom/serviceworkers/test/fetch/real-file.txt
new file mode 100644
index 0000000000..3ca2088ec0
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/real-file.txt
@@ -0,0 +1 @@
+This is a real file.
diff --git a/dom/serviceworkers/test/fetch/redirect.sjs b/dom/serviceworkers/test/fetch/redirect.sjs
new file mode 100644
index 0000000000..dab558f4a8
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/redirect.sjs
@@ -0,0 +1,4 @@
+function handleRequest(request, response) {
+  response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
+  response.setHeader("Location", "synthesized-redirect-twice-real-file.txt");
+}
diff --git a/dom/serviceworkers/test/fetch/requesturl/index.html b/dom/serviceworkers/test/fetch/requesturl/index.html
new file mode 100644
index 0000000000..bc3e400a94
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/requesturl/index.html
@@ -0,0 +1,7 @@
+
+
+
diff --git a/dom/serviceworkers/test/fetch/requesturl/redirect.sjs b/dom/serviceworkers/test/fetch/requesturl/redirect.sjs
new file mode 100644
index 0000000000..ae50a78aef
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/requesturl/redirect.sjs
@@ -0,0 +1,8 @@
+function handleRequest(request, response) {
+  response.setStatusLine(null, 308, "Permanent Redirect");
+  response.setHeader(
+    "Location",
+    "http://example.org/tests/dom/serviceworkers/test/fetch/requesturl/secret.html",
+    false
+  );
+}
diff --git a/dom/serviceworkers/test/fetch/requesturl/redirector.html b/dom/serviceworkers/test/fetch/requesturl/redirector.html
new file mode 100644
index 0000000000..0a3afab9ee
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/requesturl/redirector.html
@@ -0,0 +1,2 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/requesturl/register.html b/dom/serviceworkers/test/fetch/requesturl/register.html
new file mode 100644
index 0000000000..19a2e022c2
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/requesturl/register.html
@@ -0,0 +1,14 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/requesturl/requesturl_test.js b/dom/serviceworkers/test/fetch/requesturl/requesturl_test.js
new file mode 100644
index 0000000000..4d2680538f
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/requesturl/requesturl_test.js
@@ -0,0 +1,21 @@
+addEventListener("fetch", event => {
+  var url = event.request.url;
+  var badURL = url.indexOf("secret.html") > -1;
+  event.respondWith(
+    new Promise(resolve => {
+      clients.matchAll().then(clients => {
+        for (var client of clients) {
+          if (client.url.indexOf("index.html") > -1) {
+            client.postMessage({
+              status: "ok",
+              result: !badURL,
+              message: "Should not find a bad URL (" + url + ")",
+            });
+            break;
+          }
+        }
+        resolve(fetch(event.request));
+      });
+    })
+  );
+});
diff --git a/dom/serviceworkers/test/fetch/requesturl/secret.html b/dom/serviceworkers/test/fetch/requesturl/secret.html
new file mode 100644
index 0000000000..694c336355
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/requesturl/secret.html
@@ -0,0 +1,5 @@
+
+secret stuff
+
diff --git a/dom/serviceworkers/test/fetch/requesturl/unregister.html b/dom/serviceworkers/test/fetch/requesturl/unregister.html
new file mode 100644
index 0000000000..1f13508fa7
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/requesturl/unregister.html
@@ -0,0 +1,12 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/sandbox/index.html b/dom/serviceworkers/test/fetch/sandbox/index.html
new file mode 100644
index 0000000000..1094a3995d
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/sandbox/index.html
@@ -0,0 +1,5 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/sandbox/intercepted_index.html b/dom/serviceworkers/test/fetch/sandbox/intercepted_index.html
new file mode 100644
index 0000000000..87261a495f
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/sandbox/intercepted_index.html
@@ -0,0 +1,5 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/sandbox/register.html b/dom/serviceworkers/test/fetch/sandbox/register.html
new file mode 100644
index 0000000000..427b1a8da9
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/sandbox/register.html
@@ -0,0 +1,14 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/sandbox/sandbox_test.js b/dom/serviceworkers/test/fetch/sandbox/sandbox_test.js
new file mode 100644
index 0000000000..310cea0d16
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/sandbox/sandbox_test.js
@@ -0,0 +1,5 @@
+self.addEventListener("fetch", function (event) {
+  if (event.request.url.includes("index.html")) {
+    event.respondWith(fetch("intercepted_index.html"));
+  }
+});
diff --git a/dom/serviceworkers/test/fetch/sandbox/unregister.html b/dom/serviceworkers/test/fetch/sandbox/unregister.html
new file mode 100644
index 0000000000..1f13508fa7
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/sandbox/unregister.html
@@ -0,0 +1,12 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/upgrade-insecure/embedder.html b/dom/serviceworkers/test/fetch/upgrade-insecure/embedder.html
new file mode 100644
index 0000000000..e99209aa4d
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/upgrade-insecure/embedder.html
@@ -0,0 +1,10 @@
+
+
+
diff --git a/dom/serviceworkers/test/fetch/upgrade-insecure/embedder.html^headers^ b/dom/serviceworkers/test/fetch/upgrade-insecure/embedder.html^headers^
new file mode 100644
index 0000000000..602d9dc38d
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/upgrade-insecure/embedder.html^headers^
@@ -0,0 +1 @@
+Content-Security-Policy: upgrade-insecure-requests
diff --git a/dom/serviceworkers/test/fetch/upgrade-insecure/image-20px.png b/dom/serviceworkers/test/fetch/upgrade-insecure/image-20px.png
new file mode 100644
index 0000000000..ae6a8a6b88
Binary files /dev/null and b/dom/serviceworkers/test/fetch/upgrade-insecure/image-20px.png differ
diff --git a/dom/serviceworkers/test/fetch/upgrade-insecure/image-40px.png b/dom/serviceworkers/test/fetch/upgrade-insecure/image-40px.png
new file mode 100644
index 0000000000..fe391dc8a2
Binary files /dev/null and b/dom/serviceworkers/test/fetch/upgrade-insecure/image-40px.png differ
diff --git a/dom/serviceworkers/test/fetch/upgrade-insecure/image.html b/dom/serviceworkers/test/fetch/upgrade-insecure/image.html
new file mode 100644
index 0000000000..dfcfd80014
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/upgrade-insecure/image.html
@@ -0,0 +1,13 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/upgrade-insecure/realindex.html b/dom/serviceworkers/test/fetch/upgrade-insecure/realindex.html
new file mode 100644
index 0000000000..aaa255aad3
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/upgrade-insecure/realindex.html
@@ -0,0 +1,4 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/upgrade-insecure/register.html b/dom/serviceworkers/test/fetch/upgrade-insecure/register.html
new file mode 100644
index 0000000000..6309b9b218
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/upgrade-insecure/register.html
@@ -0,0 +1,14 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/upgrade-insecure/unregister.html b/dom/serviceworkers/test/fetch/upgrade-insecure/unregister.html
new file mode 100644
index 0000000000..1f13508fa7
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/upgrade-insecure/unregister.html
@@ -0,0 +1,12 @@
+
+
diff --git a/dom/serviceworkers/test/fetch/upgrade-insecure/upgrade-insecure_test.js b/dom/serviceworkers/test/fetch/upgrade-insecure/upgrade-insecure_test.js
new file mode 100644
index 0000000000..74b9ed23ba
--- /dev/null
+++ b/dom/serviceworkers/test/fetch/upgrade-insecure/upgrade-insecure_test.js
@@ -0,0 +1,11 @@
+self.addEventListener("fetch", function (event) {
+  if (event.request.url.includes("index.html")) {
+    event.respondWith(fetch("realindex.html"));
+  } else if (event.request.url.includes("image-20px.png")) {
+    if (event.request.url.indexOf("https://") == 0) {
+      event.respondWith(fetch("image-40px.png"));
+    } else {
+      event.respondWith(Response.error());
+    }
+  }
+});
-- 
cgit v1.2.3