summaryrefslogtreecommitdiffstats
path: root/dom/workers/test/serviceworkers/fetch/context
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /dom/workers/test/serviceworkers/fetch/context
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/workers/test/serviceworkers/fetch/context')
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/beacon.sjs43
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/context_test.js135
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/csp-violate.sjs6
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/index.html422
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/parentsharedworker.js8
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/parentworker.js4
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/ping.html7
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/realaudio.oggbin0 -> 6416 bytes
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/realimg.jpgbin0 -> 3595 bytes
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/register.html14
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/sharedworker.js5
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/unregister.html12
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/worker.js1
-rw-r--r--dom/workers/test/serviceworkers/fetch/context/xml.xml3
14 files changed, 660 insertions, 0 deletions
diff --git a/dom/workers/test/serviceworkers/fetch/context/beacon.sjs b/dom/workers/test/serviceworkers/fetch/context/beacon.sjs
new file mode 100644
index 000000000..8401bc29b
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/beacon.sjs
@@ -0,0 +1,43 @@
+/*
+ * This is based on dom/tests/mochitest/beacon/beacon-originheader-handler.sjs.
+ */
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+
+ // case XHR-REQUEST: the xhr-request tries to query the
+ // stored context from the beacon request.
+ if (request.queryString == "queryContext") {
+ var context = getState("interceptContext");
+ // if the beacon already stored the context - return.
+ if (context) {
+ response.write(context);
+ setState("interceptContext", "");
+ return;
+ }
+ // otherwise wait for the beacon request
+ response.processAsync();
+ setObjectState("sw-xhr-response", response);
+ return;
+ }
+
+ // case BEACON-REQUEST: get the beacon context and
+ // store the context on the server.
+ var context = request.queryString;
+ setState("interceptContext", context);
+
+ // if there is an xhr-request waiting, return the context now.
+ try{
+ getObjectState("sw-xhr-response", function(xhrResponse) {
+ if (!xhrResponse) {
+ return;
+ }
+ setState("interceptContext", "");
+ xhrResponse.write(context);
+ xhrResponse.finish();
+ });
+ } catch(e) {
+ }
+}
diff --git a/dom/workers/test/serviceworkers/fetch/context/context_test.js b/dom/workers/test/serviceworkers/fetch/context/context_test.js
new file mode 100644
index 000000000..b98d2ab3c
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/context_test.js
@@ -0,0 +1,135 @@
+self.addEventListener("fetch", function(event) {
+ if (event.request.url.indexOf("index.html") >= 0 ||
+ event.request.url.indexOf("register.html") >= 0 ||
+ event.request.url.indexOf("unregister.html") >= 0 ||
+ event.request.url.indexOf("ping.html") >= 0 ||
+ event.request.url.indexOf("xml.xml") >= 0 ||
+ event.request.url.indexOf("csp-violate.sjs") >= 0) {
+ // Handle pass-through requests
+ event.respondWith(fetch(event.request));
+ } else if (event.request.url.indexOf("fetch.txt") >= 0) {
+ var body = event.request.context == "fetch" ?
+ "so fetch" : "so unfetch";
+ event.respondWith(new Response(body));
+ } else if (event.request.url.indexOf("img.jpg") >= 0) {
+ if (event.request.context == "image") {
+ event.respondWith(fetch("realimg.jpg"));
+ }
+ } else if (event.request.url.indexOf("responsive.jpg") >= 0) {
+ if (event.request.context == "imageset") {
+ event.respondWith(fetch("realimg.jpg"));
+ }
+ } else if (event.request.url.indexOf("audio.ogg") >= 0) {
+ if (event.request.context == "audio") {
+ event.respondWith(fetch("realaudio.ogg"));
+ }
+ } else if (event.request.url.indexOf("video.ogg") >= 0) {
+ if (event.request.context == "video") {
+ event.respondWith(fetch("realaudio.ogg"));
+ }
+ } else if (event.request.url.indexOf("beacon.sjs") >= 0) {
+ if (event.request.url.indexOf("queryContext") == -1) {
+ event.respondWith(fetch("beacon.sjs?" + event.request.context));
+ } else {
+ event.respondWith(fetch(event.request));
+ }
+ } else if (event.request.url.indexOf("csp-report.sjs") >= 0) {
+ respondToServiceWorker(event, "csp-report");
+ } else if (event.request.url.indexOf("embed") >= 0) {
+ respondToServiceWorker(event, "embed");
+ } else if (event.request.url.indexOf("object") >= 0) {
+ respondToServiceWorker(event, "object");
+ } else if (event.request.url.indexOf("font") >= 0) {
+ respondToServiceWorker(event, "font");
+ } else if (event.request.url.indexOf("iframe") >= 0) {
+ if (event.request.context == "iframe") {
+ event.respondWith(fetch("context_test.js"));
+ }
+ } else if (event.request.url.indexOf("frame") >= 0) {
+ if (event.request.context == "frame") {
+ event.respondWith(fetch("context_test.js"));
+ }
+ } else if (event.request.url.indexOf("newwindow") >= 0) {
+ respondToServiceWorker(event, "newwindow");
+ } else if (event.request.url.indexOf("ping") >= 0) {
+ respondToServiceWorker(event, "ping");
+ } else if (event.request.url.indexOf("plugin") >= 0) {
+ respondToServiceWorker(event, "plugin");
+ } else if (event.request.url.indexOf("script.js") >= 0) {
+ if (event.request.context == "script") {
+ event.respondWith(new Response(""));
+ }
+ } else if (event.request.url.indexOf("style.css") >= 0) {
+ respondToServiceWorker(event, "style");
+ } else if (event.request.url.indexOf("track") >= 0) {
+ respondToServiceWorker(event, "track");
+ } else if (event.request.url.indexOf("xhr") >= 0) {
+ if (event.request.context == "xmlhttprequest") {
+ event.respondWith(new Response(""));
+ }
+ } else if (event.request.url.indexOf("xslt") >= 0) {
+ respondToServiceWorker(event, "xslt");
+ } else if (event.request.url.indexOf("myworker") >= 0) {
+ if (event.request.context == "worker") {
+ event.respondWith(fetch("worker.js"));
+ }
+ } else if (event.request.url.indexOf("myparentworker") >= 0) {
+ if (event.request.context == "worker") {
+ event.respondWith(fetch("parentworker.js"));
+ }
+ } else if (event.request.url.indexOf("mysharedworker") >= 0) {
+ if (event.request.context == "sharedworker") {
+ event.respondWith(fetch("sharedworker.js"));
+ }
+ } else if (event.request.url.indexOf("myparentsharedworker") >= 0) {
+ if (event.request.context == "sharedworker") {
+ event.respondWith(fetch("parentsharedworker.js"));
+ }
+ } else if (event.request.url.indexOf("cache") >= 0) {
+ var cache;
+ var origContext = event.request.context;
+ event.respondWith(caches.open("cache")
+ .then(function(c) {
+ cache = c;
+ // Store the Request in the cache.
+ return cache.put(event.request, new Response("fake"));
+ }).then(function() {
+ // Read it back.
+ return cache.keys(event.request);
+ }).then(function(res) {
+ var req = res[0];
+ // Check to see if the context remained the same.
+ var success = req.context === origContext;
+ return clients.matchAll()
+ .then(function(clients) {
+ // Report it back to the main page.
+ clients.forEach(function(c) {
+ c.postMessage({data: "cache", success: success});
+ });
+ })}).then(function() {
+ // Cleanup.
+ return caches.delete("cache");
+ }).then(function() {
+ return new Response("ack");
+ }));
+ }
+ // Fail any request that we don't know about.
+ try {
+ event.respondWith(Promise.reject(event.request.url));
+ dump("Fetch event received invalid context value " + event.request.context +
+ " for " + event.request.url + "\n");
+ } catch(e) {
+ // Eat up the possible InvalidStateError exception that we may get if some
+ // code above has called respondWith too.
+ }
+});
+
+function respondToServiceWorker(event, data) {
+ event.respondWith(clients.matchAll()
+ .then(function(clients) {
+ clients.forEach(function(c) {
+ c.postMessage({data: data, context: event.request.context});
+ });
+ return new Response("ack");
+ }));
+}
diff --git a/dom/workers/test/serviceworkers/fetch/context/csp-violate.sjs b/dom/workers/test/serviceworkers/fetch/context/csp-violate.sjs
new file mode 100644
index 000000000..4c3e76d15
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/csp-violate.sjs
@@ -0,0 +1,6 @@
+function handleRequest(request, response)
+{
+ response.setHeader("Content-Security-Policy", "default-src 'none'; report-uri /tests/dom/workers/test/serviceworkers/fetch/context/csp-report.sjs", false);
+ response.setHeader("Content-Type", "text/html", false);
+ response.write("<link rel=stylesheet href=style.css>");
+}
diff --git a/dom/workers/test/serviceworkers/fetch/context/index.html b/dom/workers/test/serviceworkers/fetch/context/index.html
new file mode 100644
index 000000000..c6dfef99c
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/index.html
@@ -0,0 +1,422 @@
+<!DOCTYPE html>
+<script>
+ var isAndroid = navigator.userAgent.includes("Android");
+ var isB2G = !isAndroid && /Mobile|Tablet/.test(navigator.userAgent);
+
+ function ok(v, msg) {
+ window.parent.postMessage({status: "ok", result: !!v, message: msg}, "*");
+ }
+
+ function is(a, b, msg) {
+ ok(a === b, msg + ", expected '" + b + "', got '" + a + "'");
+ }
+
+ function todo(v, msg) {
+ window.parent.postMessage({status: "todo", result: !!v, message: msg}, "*");
+ }
+
+ function finish() {
+ window.parent.postMessage({status: "done"}, "*");
+ }
+
+ function testFetch() {
+ return fetch("fetch.txt").then(function(r) {
+ return r.text();
+ }).then(function(body) {
+ is(body, "so fetch", "A fetch() Request should have the 'fetch' context");
+ });
+ }
+
+ function testImage() {
+ return new Promise(function(resolve, reject) {
+ var img = document.createElement("img");
+ img.src = "img.jpg";
+ // The service worker will respond with an existing image only if the
+ // Request has the correct context, otherwise the Promise will get
+ // rejected and the test will fail.
+ img.onload = resolve;
+ img.onerror = reject;
+ });
+ }
+
+ function testImageSrcSet() {
+ return new Promise(function(resolve, reject) {
+ var img = document.createElement("img");
+ img.srcset = "responsive.jpg 100w";
+ // The service worker will respond with an existing image only if the
+ // Request has the correct context, otherwise the Promise will get
+ // rejected and the test will fail.
+ img.onload = resolve;
+ img.onerror = reject;
+ });
+ }
+
+ function testPicture() {
+ return new Promise(function(resolve, reject) {
+ var pic = document.createElement("picture");
+ var img = document.createElement("img");
+ pic.appendChild(img);
+ img.src = "responsive.jpg?picture";
+ // The service worker will respond with an existing image only if the
+ // Request has the correct context, otherwise the Promise will get
+ // rejected and the test will fail.
+ img.onload = resolve;
+ img.onerror = reject;
+ });
+ }
+
+ function testAudio() {
+ return new Promise(function(resolve, reject) {
+ var audio = document.createElement("audio");
+ audio.src = "audio.ogg";
+ audio.preload = "metadata";
+ // The service worker will respond with an existing audio only if the
+ // Request has the correct context, otherwise the Promise will get
+ // rejected and the test will fail.
+ audio.onloadedmetadata = resolve;
+ audio.onerror = reject;
+ });
+ }
+
+ function testVideo() {
+ return new Promise(function(resolve, reject) {
+ var video = document.createElement("video");
+ video.src = "video.ogg";
+ video.preload = "metadata";
+ // The service worker will respond with an existing video only if the
+ // Request has the correct context, otherwise the Promise will get
+ // rejected and the test will fail.
+ video.onloadedmetadata = resolve;
+ video.onerror = reject;
+ });
+ }
+
+ function testBeacon() {
+ ok(navigator.sendBeacon("beacon.sjs"), "Sending the beacon should succeed");
+ // query the context from beacon.sjs
+ return fetch("beacon.sjs?queryContext")
+ .then(function(r) {
+ return r.text();
+ }).then(function(body) {
+ is(body, "beacon", "The context for the intercepted beacon should be correct");
+ });
+ }
+
+ function testCSPReport() {
+ return new Promise(function(resolve, reject) {
+ var iframe = document.createElement("iframe");
+ iframe.src = "csp-violate.sjs";
+ document.documentElement.appendChild(iframe);
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "csp-report") {
+ is(e.data.context, "cspreport", "Expected the cspreport context on a CSP violation report");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ function testEmbed() {
+ return Promise.resolve().then(function() {
+ todo(false, "<embed> tag is not currently intercepted. See Bug 1168676.");
+ });
+
+ return new Promise(function(resolve, reject) {
+ var embed = document.createElement("embed");
+ embed.src = "embed";
+ document.documentElement.appendChild(embed);
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "embed") {
+ is(e.data.context, "embed", "Expected the object context on an embed");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ function testObject() {
+ return Promise.resolve().then(function() {
+ todo(false, "<object> tag is not currently intercepted. See Bug 1168676");
+ });
+
+ return new Promise(function(resolve, reject) {
+ var object = document.createElement("object");
+ object.data = "object";
+ document.documentElement.appendChild(object);
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "object") {
+ is(e.data.context, "object", "Expected the object context on an object");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ function testFont() {
+ return new Promise(function(resolve, reject) {
+ var css = '@font-face { font-family: "sw-font"; src: url("font"); }';
+ css += '* { font-family: "sw-font"; }';
+ var style = document.createElement("style");
+ style.appendChild(document.createTextNode(css));
+ document.documentElement.appendChild(style);
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "font") {
+ is(e.data.context, "font", "Expected the font context on an font");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ function testIFrame() {
+ return new Promise(function(resolve, reject) {
+ var iframe = document.createElement("iframe");
+ iframe.src = "iframe";
+ document.documentElement.appendChild(iframe);
+ // The service worker will respond with an existing document only if the
+ // Request has the correct context, otherwise the Promise will get
+ // rejected and the test will fail.
+ iframe.onload = resolve;
+ iframe.onerror = reject;
+ });
+ }
+
+ function testFrame() {
+ return new Promise(function(resolve, reject) {
+ var frame = document.createElement("frame");
+ frame.src = "frame";
+ document.documentElement.appendChild(frame);
+ // The service worker will respond with an existing document only if the
+ // Request has the correct context, otherwise the Promise will get
+ // rejected and the test will fail.
+ frame.onload = resolve;
+ frame.onerror = reject;
+ });
+ }
+
+ function testInternal() {
+ if (isB2G) {
+ // We can't open new windows on b2g, so skip this part of the test there.
+ return Promise.resolve();
+ }
+ return new Promise(function(resolve, reject) {
+ // Test this with a new window opened through script. There are of course
+ // other possible ways of testing this too.
+ var win = window.open("newwindow", "_blank", "width=100,height=100");
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "newwindow") {
+ is(e.data.context, "internal", "Expected the internal context on a newly opened window");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ win.close();
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ function testPing() {
+ return new Promise(function(resolve, reject) {
+ var iframe = document.createElement("iframe");
+ iframe.src = "ping.html";
+ document.documentElement.appendChild(iframe);
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "ping") {
+ is(e.data.context, "ping", "Expected the ping context on an anchor ping");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ function testPlugin() {
+ return Promise.resolve().then(function() {
+ todo(false, "plugins are not currently intercepted. See Bug 1168676.");
+ });
+
+ var isMobile = /Mobile|Tablet/.test(navigator.userAgent);
+ if (isMobile || parent.isMulet()) {
+ // We can't use plugins on mobile, so skip this part of the test there.
+ return Promise.resolve();
+ }
+
+ return new Promise(function(resolve, reject) {
+ var embed = document.createElement("embed");
+ embed.type = "application/x-test";
+ embed.setAttribute("posturl", "plugin");
+ embed.setAttribute("postmode", "stream");
+ embed.setAttribute("streammode", "normal");
+ embed.setAttribute("src", "fetch.txt");
+ document.documentElement.appendChild(embed);
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "plugin") {
+ is(e.data.context, "plugin", "Expected the plugin context on a request coming from a plugin");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ // Without this, the test leaks in e10s!
+ embed.parentNode.removeChild(embed);
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ function testScript() {
+ return new Promise(function(resolve, reject) {
+ var script = document.createElement("script");
+ script.src = "script.js";
+ document.documentElement.appendChild(script);
+ // The service worker will respond with an existing script only if the
+ // Request has the correct context, otherwise the Promise will get
+ // rejected and the test will fail.
+ script.onload = resolve;
+ script.onerror = reject;
+ });
+ }
+
+ function testStyle() {
+ return new Promise(function(resolve, reject) {
+ var link = document.createElement("link");
+ link.rel = "stylesheet";
+ link.href = "style.css";
+ document.documentElement.appendChild(link);
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "style") {
+ is(e.data.context, "style", "Expected the style context on a request coming from a stylesheet");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ function testTrack() {
+ return new Promise(function(resolve, reject) {
+ var video = document.createElement("video");
+ var track = document.createElement("track");
+ track.src = "track";
+ video.appendChild(track);
+ document.documentElement.appendChild(video);
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "track") {
+ is(e.data.context, "track", "Expected the track context on a request coming from a track");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ function testXHR() {
+ return new Promise(function(resolve, reject) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("get", "xhr", true);
+ xhr.send();
+ // The service worker will respond with an existing resource only if the
+ // Request has the correct context, otherwise the Promise will get
+ // rejected and the test will fail.
+ xhr.onload = resolve;
+ xhr.onerror = reject;
+ });
+ }
+
+ function testXSLT() {
+ return new Promise(function(resolve, reject) {
+ var iframe = document.createElement("iframe");
+ iframe.src = "xml.xml";
+ document.documentElement.appendChild(iframe);
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "xslt") {
+ is(e.data.context, "xslt", "Expected the xslt context on an XSLT stylesheet");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ // Without this, the test leaks in e10s!
+ iframe.parentNode.removeChild(iframe);
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ function testWorker() {
+ return new Promise(function(resolve, reject) {
+ var worker = new Worker("myworker");
+ worker.onmessage = function(e) {
+ if (e.data == "ack") {
+ worker.terminate();
+ resolve();
+ }
+ };
+ worker.onerror = reject;
+ });
+ }
+
+ function testNestedWorker() {
+ return new Promise(function(resolve, reject) {
+ var worker = new Worker("myparentworker");
+ worker.onmessage = function(e) {
+ if (e.data == "ack") {
+ worker.terminate();
+ resolve();
+ }
+ };
+ worker.onerror = reject;
+ });
+ }
+
+ function testSharedWorker() {
+ return new Promise(function(resolve, reject) {
+ var worker = new SharedWorker("mysharedworker");
+ worker.port.start();
+ worker.port.onmessage = function(e) {
+ if (e.data == "ack") {
+ resolve();
+ }
+ };
+ worker.onerror = reject;
+ });
+ }
+
+ function testNestedWorkerInSharedWorker() {
+ return new Promise(function(resolve, reject) {
+ var worker = new SharedWorker("myparentsharedworker");
+ worker.port.start();
+ worker.port.onmessage = function(e) {
+ if (e.data == "ack") {
+ resolve();
+ }
+ };
+ worker.onerror = reject;
+ });
+ }
+
+ function testCache() {
+ return new Promise(function(resolve, reject) {
+ // Issue an XHR that will be intercepted by the SW in order to start off
+ // the test with a RequestContext value that is not the default ("fetch").
+ // This needs to run inside a fetch event handler because synthesized
+ // RequestContext objects can only have the "fetch" context, and we'd
+ // prefer to test the more general case of some other RequestContext value.
+ var xhr = new XMLHttpRequest();
+ xhr.open("get", "cache", true);
+ xhr.send();
+ navigator.serviceWorker.addEventListener("message", function onMessage(e) {
+ if (e.data.data == "cache") {
+ ok(e.data.success, "The RequestContext can be persisted in the cache.");
+ navigator.serviceWorker.removeEventListener("message", onMessage);
+ resolve();
+ }
+ }, false);
+ });
+ }
+
+ var testName = location.search.substr(1);
+ window[testName]().then(function() {
+ finish();
+ }, function(e) {
+ ok(false, "A promise was rejected: " + e);
+ finish();
+ });
+</script>
diff --git a/dom/workers/test/serviceworkers/fetch/context/parentsharedworker.js b/dom/workers/test/serviceworkers/fetch/context/parentsharedworker.js
new file mode 100644
index 000000000..eac8d5e71
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/parentsharedworker.js
@@ -0,0 +1,8 @@
+onconnect = function(e) {
+ e.ports[0].start();
+ var worker = new Worker("myworker?shared");
+ worker.onmessage = function(e2) {
+ e.ports[0].postMessage(e2.data);
+ self.close();
+ };
+};
diff --git a/dom/workers/test/serviceworkers/fetch/context/parentworker.js b/dom/workers/test/serviceworkers/fetch/context/parentworker.js
new file mode 100644
index 000000000..839fb6640
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/parentworker.js
@@ -0,0 +1,4 @@
+var worker = new Worker("myworker");
+worker.onmessage = function(e) {
+ postMessage(e.data);
+};
diff --git a/dom/workers/test/serviceworkers/fetch/context/ping.html b/dom/workers/test/serviceworkers/fetch/context/ping.html
new file mode 100644
index 000000000..b1bebe41e
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/ping.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<script>
+ onload = function() {
+ document.querySelector("a").click();
+ };
+</script>
+<a ping="ping" href="fetch.txt">link</a>
diff --git a/dom/workers/test/serviceworkers/fetch/context/realaudio.ogg b/dom/workers/test/serviceworkers/fetch/context/realaudio.ogg
new file mode 100644
index 000000000..1a41623f8
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/realaudio.ogg
Binary files differ
diff --git a/dom/workers/test/serviceworkers/fetch/context/realimg.jpg b/dom/workers/test/serviceworkers/fetch/context/realimg.jpg
new file mode 100644
index 000000000..5b920f7c0
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/realimg.jpg
Binary files differ
diff --git a/dom/workers/test/serviceworkers/fetch/context/register.html b/dom/workers/test/serviceworkers/fetch/context/register.html
new file mode 100644
index 000000000..6528d0eae
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/register.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<script>
+ function ok(v, msg) {
+ window.parent.postMessage({status: "ok", result: !!v, message: msg}, "*");
+ }
+
+ function done(reg) {
+ ok(reg.active, "The active worker should be available.");
+ window.parent.postMessage({status: "registrationdone"}, "*");
+ }
+
+ navigator.serviceWorker.ready.then(done);
+ navigator.serviceWorker.register("context_test.js", {scope: "."});
+</script>
diff --git a/dom/workers/test/serviceworkers/fetch/context/sharedworker.js b/dom/workers/test/serviceworkers/fetch/context/sharedworker.js
new file mode 100644
index 000000000..94dca5839
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/sharedworker.js
@@ -0,0 +1,5 @@
+onconnect = function(e) {
+ e.ports[0].start();
+ e.ports[0].postMessage("ack");
+ self.close();
+};
diff --git a/dom/workers/test/serviceworkers/fetch/context/unregister.html b/dom/workers/test/serviceworkers/fetch/context/unregister.html
new file mode 100644
index 000000000..1f13508fa
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/unregister.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script>
+ navigator.serviceWorker.getRegistration(".").then(function(registration) {
+ registration.unregister().then(function(success) {
+ if (success) {
+ window.parent.postMessage({status: "unregistrationdone"}, "*");
+ }
+ }, function(e) {
+ dump("Unregistering the SW failed with " + e + "\n");
+ });
+ });
+</script>
diff --git a/dom/workers/test/serviceworkers/fetch/context/worker.js b/dom/workers/test/serviceworkers/fetch/context/worker.js
new file mode 100644
index 000000000..e26e5bc69
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/worker.js
@@ -0,0 +1 @@
+postMessage("ack");
diff --git a/dom/workers/test/serviceworkers/fetch/context/xml.xml b/dom/workers/test/serviceworkers/fetch/context/xml.xml
new file mode 100644
index 000000000..69c64adf1
--- /dev/null
+++ b/dom/workers/test/serviceworkers/fetch/context/xml.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="xslt"?>
+<root/>