diff options
Diffstat (limited to 'dom/tests/mochitest/beacon')
16 files changed, 875 insertions, 0 deletions
diff --git a/dom/tests/mochitest/beacon/beacon-frame.html b/dom/tests/mochitest/beacon/beacon-frame.html new file mode 100644 index 000000000..9dc4e4aab --- /dev/null +++ b/dom/tests/mochitest/beacon/beacon-frame.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Inner frame performing a basic sendBeacon from within an iframe</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<script type="text/javascript"> + +function sendBeacon() +{ + var frame = window.parent.document.getElementById("frame"); + var data = window.parent.beaconConvert(frame.getAttribute("data")); + + var result = navigator.sendBeacon("http://mochi.test:8888/tests/dom/tests/mochitest/beacon/beacon-handler.sjs", data); + window.parent.beaconSent(result); +} + +window.addEventListener("load", function() { setTimeout(sendBeacon, 0); }, false); + +</script> +</body> +</html> + diff --git a/dom/tests/mochitest/beacon/beacon-handler.sjs b/dom/tests/mochitest/beacon/beacon-handler.sjs new file mode 100644 index 000000000..a3b6f2593 --- /dev/null +++ b/dom/tests/mochitest/beacon/beacon-handler.sjs @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const CC = Components.Constructor; +const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream"); + +function DEBUG(str) +{ + // dump("********** " + str + "\n"); +} + +function setOurState(data) { + x = { data: data, QueryInterface: function(iid) { return this } }; + x.wrappedJSObject = x; + setObjectState("beacon-handler", x); + DEBUG("our state is " + data); +} + +function getOurState() { + var data; + getObjectState("beacon-handler", function(x) { + // x can be null if no one has set any state yet + if (x) { + data = x.wrappedJSObject.data; + } + }); + return data; +} + +function handleRequest(request, response) { + DEBUG("Entered request handler"); + response.setHeader("Cache-Control", "no-cache", false); + + function finishControlResponse(response) { + DEBUG("********* sending out the control GET response"); + var data = getState("beaconData"); + var mimetype = getState("beaconMimetype"); + DEBUG("GET was sending : " + data + "\n"); + DEBUG("GET was sending : " + mimetype + "\n"); + var result = { + "data": data, + "mimetype": mimetype, + }; + response.write(JSON.stringify(result)); + setOurState(null); + } + + if (request.method == "GET") { + DEBUG(" ------------ GET --------------- "); + response.setHeader("Content-Type", "application/json", false); + switch (request.queryString) { + case "getLastBeacon": + var state = getOurState(); + if (state === "unblocked") { + finishControlResponse(response); + } else { + DEBUG("GET has arrived, but POST has not, blocking response!"); + setOurState(response); + response.processAsync(); + } + break; + default: + response.setStatusLine(request.httpVersion, 400, "Bad Request"); + break; + } + return; + } + + if (request.method == "POST") { + DEBUG(" ------------ POST --------------- "); + var body = new BinaryInputStream(request.bodyInputStream); + var avail; + var bytes = []; + + while ((avail = body.available()) > 0) { + Array.prototype.push.apply(bytes, body.readByteArray(avail)); + } + + var data = ""; + for (var i=0; i < bytes.length; i++) { + // We are only passing strings at this point. + if (bytes[i] < 32) continue; + var charcode = String.fromCharCode(bytes[i]); + data += charcode; + } + + var mimetype = request.getHeader("Content-Type"); + + // check to see if this is form data. + if (mimetype.indexOf("multipart/form-data") != -1) { + + // trim the mime type to make testing easier. + mimetype = "multipart/form-data"; + // Extract only the form-data name. + + var pattern = /; name=\"(.+)\";/; + data = data.split(pattern)[1]; + } + + DEBUG("********** POST was sending : " + data + "\n"); + DEBUG("********** POST was sending : " + mimetype + "\n"); + setState("beaconData", data); + setState("beaconMimetype", mimetype); + + response.setHeader("Content-Type", "text/plain", false); + response.write('ok'); + + var blockedResponse = getOurState(); + if (typeof(blockedResponse) == "object" && blockedResponse) { + DEBUG("GET is already pending, finishing!"); + finishControlResponse(blockedResponse); + blockedResponse.finish(); + } else { + DEBUG("GET has not arrived, marking it as unblocked"); + setOurState("unblocked"); + } + + return; + } + + response.setStatusLine(request.httpVersion, 402, "Bad Request"); +} diff --git a/dom/tests/mochitest/beacon/beacon-originheader-handler.sjs b/dom/tests/mochitest/beacon/beacon-originheader-handler.sjs new file mode 100644 index 000000000..f6d70fa8a --- /dev/null +++ b/dom/tests/mochitest/beacon/beacon-originheader-handler.sjs @@ -0,0 +1,48 @@ +/* + * TestSever customized specifically for the needs of: + * Bug 1280692 - navigator.sendBeacon() should not send origin header + */ + +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 header from the beacon request. + if (request.queryString == "queryheader") { + var header = getState("originHeader"); + // if the beacon already stored the header - return. + if (header) { + response.write(header); + setState("originHeader", ""); + return; + } + // otherwise wait for the beacon request + response.processAsync(); + setObjectState("xhr-response", response); + return; + } + + // case BEACON-REQUEST: get the beacon header and + // store the header on the server. + var header = "reset"; + try { + header = request.getHeader("origin"); + } + catch(e) { + header = "no-header"; + } + setState("originHeader", header); + + + // if there is an xhr-request waiting, return the header now. + getObjectState("xhr-response", function(xhrResponse) { + if (!xhrResponse) { + return; + } + setState("originHeader", ""); + xhrResponse.write(header); + xhrResponse.finish(); + }); +} diff --git a/dom/tests/mochitest/beacon/beacon-preflight-handler.sjs b/dom/tests/mochitest/beacon/beacon-preflight-handler.sjs new file mode 100644 index 000000000..6a760cb84 --- /dev/null +++ b/dom/tests/mochitest/beacon/beacon-preflight-handler.sjs @@ -0,0 +1,39 @@ +function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache, must-revalidate", false);
+
+ if (request.queryString === "verify") {
+ var preflightState = getState("preflight");
+ response.write(preflightState === "done" ? "green" : "red");
+ return;
+ }
+
+ var originHeader = request.getHeader("origin");
+ response.setHeader("Access-Control-Allow-Headers", "content-type", false);
+ response.setHeader("Access-Control-Allow-Methods", "POST, GET", false);
+ response.setHeader("Access-Control-Allow-Origin", originHeader, false);
+ response.setHeader("Access-Control-Allow-Credentials", "true", false);
+
+ if (request.queryString === "beacon") {
+ if (request.method == "OPTIONS") {
+ setState("preflight", "done");
+ response.setStatusLine(null, 200, "OK");
+ return;
+ }
+ response.setStatusLine(null, 200, "OK");
+ response.write("DONE");
+ return;
+ }
+
+ if (request.queryString === "fail") {
+ if (request.method == "OPTIONS") {
+ setState("preflight", "done");
+ response.setStatusLine(null, 400, "Bad Request");
+ return;
+ }
+ setState("preflight", "oops");
+ response.setStatusLine(null, 200, "OK");
+ response.write("DONE");
+ return;
+ }
+}
diff --git a/dom/tests/mochitest/beacon/beacon-redirect-handler.sjs b/dom/tests/mochitest/beacon/beacon-redirect-handler.sjs new file mode 100644 index 000000000..bb7e50dba --- /dev/null +++ b/dom/tests/mochitest/beacon/beacon-redirect-handler.sjs @@ -0,0 +1,47 @@ +/*
+ * TestSever customized specifically for the needs of:
+ * Bug 1280692 - sendBeacon() should follow 30x redirect
+ *
+ * Here is a sequence of the test:
+ * [1] sendBeacon (identified by the queryString 'beacon') which gets redirected
+ * [2] redirected sendBeacon (identified by the queryString 'redirected') which
+ * updates the state idniciating that redirected sendBeacon succeeds.
+ * [3] xhr request (identified by the queryString 'verifyRedirectDidSucceed')
+ * which checks if the state was not changed from 'reset' to 'gree'. If the channel
+ * woulnd't be blocked correctly the redirected channel would set the state to 'red'.
+ *
+ */
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache, must-revalidate", false);
+
+ // [Sequence 3]
+ if (request.queryString === "verifyRedirectDidSucceed") {
+ var redirectState = getState("redirectState");
+ response.write(redirectState);
+ return;
+ }
+
+ // [Sequence 1]
+ if (request.queryString === "beacon") {
+ setState("redirectState", "reset");
+ var newLocation =
+ "http://mochi.test:8888/tests/dom/tests/mochitest/beacon/beacon-redirect-handler.sjs?redirected";
+ response.setStatusLine("1.1", 302, "Found");
+ response.setHeader("Location", newLocation, false);
+ return;
+ }
+
+ // [Sequence 2]
+ if (request.queryString === "redirected") {
+ setState("redirectState", "green");
+ response.setStatusLine(null, 200, "OK");
+ return;
+ }
+
+ // we should never get here, but just in case let's
+ // set the state to something unexpected
+ setState("redirectState", "red");
+ response.setStatusLine(null, 200, "OK");
+}
diff --git a/dom/tests/mochitest/beacon/beacon-set-cookie.sjs b/dom/tests/mochitest/beacon/beacon-set-cookie.sjs new file mode 100644 index 000000000..341620eae --- /dev/null +++ b/dom/tests/mochitest/beacon/beacon-set-cookie.sjs @@ -0,0 +1,8 @@ +function handleRequest(request, response) +{ + response.setHeader("Set-Cookie", "cookie="+ request.host + "~" + Math.random()); + response.setHeader("Content-Type", "text/plain", false); + response.setHeader("Cache-Control", "no-cache", false); + + response.setStatusLine(request.httpVersion, 200, "OK"); +} diff --git a/dom/tests/mochitest/beacon/chrome.ini b/dom/tests/mochitest/beacon/chrome.ini new file mode 100644 index 000000000..ff5afd546 --- /dev/null +++ b/dom/tests/mochitest/beacon/chrome.ini @@ -0,0 +1,6 @@ +[DEFAULT] +skip-if = os == 'android' + +[test_beaconCookies.html] +support-files = beacon-set-cookie.sjs + file_beaconCookies.html diff --git a/dom/tests/mochitest/beacon/file_beaconCookies.html b/dom/tests/mochitest/beacon/file_beaconCookies.html new file mode 100644 index 000000000..aeecb2263 --- /dev/null +++ b/dom/tests/mochitest/beacon/file_beaconCookies.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML> +<script class="testbody" type="text/javascript"> + +var beaconUrl = "http://mochi.test:8888/chrome/dom/tests/mochitest/beacon/beacon-set-cookie.sjs"; + +navigator.sendBeacon(beaconUrl, "ceci n'est pas une demande"); + +</script> diff --git a/dom/tests/mochitest/beacon/mochitest.ini b/dom/tests/mochitest/beacon/mochitest.ini new file mode 100644 index 000000000..0093ceed7 --- /dev/null +++ b/dom/tests/mochitest/beacon/mochitest.ini @@ -0,0 +1,13 @@ +[DEFAULT] +support-files = beacon-frame.html + beacon-handler.sjs + beacon-preflight-handler.sjs + beacon-originheader-handler.sjs + beacon-redirect-handler.sjs + +[test_beacon.html] +[test_beaconFrame.html] +[test_beaconPreflightWithCustomContentType.html] +[test_beaconContentPolicy.html] +[test_beaconOriginHeader.html] +[test_beaconRedirect.html] diff --git a/dom/tests/mochitest/beacon/test_beacon.html b/dom/tests/mochitest/beacon/test_beacon.html new file mode 100644 index 000000000..697431bca --- /dev/null +++ b/dom/tests/mochitest/beacon/test_beacon.html @@ -0,0 +1,60 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=936340 +--> +<head> + <title>Test whether sendBeacon fails for non-HTTP URIs and syntactically incorrect calls</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=936340">Mozilla Bug 936340</a> +<p id="display"></p> + +<div id="content"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({'set': [["beacon.enabled", true]]}, beginTest); + +function beginTest() { + var threw; + for(let scheme of ["bad", "ftp", "data"]) { + try { + is(false, navigator.sendBeacon(`${scheme}://example.com`, "0")); + threw = false; + } catch (ex) { + threw = true; + } + ok(threw, `sendBeacon not supported for ${scheme} scheme.`); + } + + for(let scheme of ["http", "https"]) { + try { + is(false, navigator.sendBeacon(`${scheme}://invalid:URL`, "0")); + threw = false; + } catch (ex) { + threw = true; + } + ok(threw, `sendBeacon not supported for invalid ${scheme} URLs.`); + } + + try { + is(false, navigator.sendBeacon()); + threw = false; + } catch (e) { + threw = true; + } + ok(threw, "sendBeacon needs more parameters."); + + SimpleTest.finish() +} + +</script> +</pre> +</body> +</html> + diff --git a/dom/tests/mochitest/beacon/test_beaconContentPolicy.html b/dom/tests/mochitest/beacon/test_beaconContentPolicy.html new file mode 100644 index 000000000..87e44ae64 --- /dev/null +++ b/dom/tests/mochitest/beacon/test_beaconContentPolicy.html @@ -0,0 +1,102 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=936340 +--> +<head> + <title>Test that sendBeacon obeys content policy directives</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=936340">Mozilla Bug 936340</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +var beaconUrl = "http://mochi.test:8888/tests/dom/tests/mochitest/beacon/beacon-handler.sjs"; + +const Cc = SpecialPowers.Cc; +const Ci = SpecialPowers.Ci; + +// not enabled by default yet. +SimpleTest.waitForExplicitFinish(); + +var policy; + +SpecialPowers.pushPrefEnv({'set': [["beacon.enabled", true]]}, beginTest); + +function setupPolicy() { + var policyID = SpecialPowers.wrap(SpecialPowers.Components).ID("{b80e19d0-878f-d41b-2654-194714a4115c}"); + var policyName = "@mozilla.org/testpolicy;1"; + var policy = { + // nsISupports implementation + QueryInterface: function(iid) { + iid = SpecialPowers.wrap(iid); + if (iid.equals(Ci.nsISupports) || + iid.equals(Ci.nsIFactory) || + iid.equals(Ci.nsIContentPolicy)) + return this; + throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE; + }, + + // nsIFactory implementation + createInstance: function(outer, iid) { + return this.QueryInterface(iid); + }, + + // nsIContentPolicy implementation + shouldLoad: function(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra) { + // Remember last content type seen for the test url + + if (SpecialPowers.wrap(contentLocation).spec == beaconUrl) { + is(contentType, Ci.nsIContentPolicy.TYPE_BEACON, "Beacon content type should match expected. is: " + contentType + " should be: " + Ci.nsIContentPolicy.TYPE_BEACON); + teardownPolicy(); + SimpleTest.finish(); + } + + return Ci.nsIContentPolicy.ACCEPT; + }, + + shouldProcess: function(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra) { + return Ci.nsIContentPolicy.ACCEPT; + } + } + policy = SpecialPowers.wrapCallbackObject(policy); + + // Register content policy + var componentManager = SpecialPowers.wrap(SpecialPowers.Components).manager.QueryInterface(Ci.nsIComponentRegistrar); + componentManager.registerFactory(policyID, "Test content policy", policyName, policy); + + var categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); + categoryManager.addCategoryEntry("content-policy", policyName, policyName, false, true); + + return { 'policy': policy, 'policyID': policyID, 'policyName': policyName }; +} + +function teardownPolicy() { + setTimeout(function() { + // policy will not be removed from the category correctly + var componentManager = SpecialPowers.wrap(SpecialPowers.Components).manager.QueryInterface(Ci.nsIComponentRegistrar); + componentManager.unregisterFactory(policy.policyID, policy.policy); + var categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); + categoryManager.deleteCategoryEntry("content-policy", policy.policyName, false); + }, 0); +} + +function beginTest() { + policy = setupPolicy(); + // Make sure to hit the event loop here in order to ensure that nsContentPolicy + // has been notified of the newly registered policy. + SimpleTest.executeSoon(function() { + navigator.sendBeacon(beaconUrl, "bacon would have been a better name than beacon"); + }); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/tests/mochitest/beacon/test_beaconCookies.html b/dom/tests/mochitest/beacon/test_beaconCookies.html new file mode 100644 index 000000000..e2c4f3b7d --- /dev/null +++ b/dom/tests/mochitest/beacon/test_beaconCookies.html @@ -0,0 +1,89 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=936340 +--> +<head> + <title>Test whether sendBeacon sets cookies</title> + <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=936340">Mozilla Bug 936340</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +// not enabled by default yet. +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({'set': [["beacon.enabled", true]]}, beginTest); + +var Ci = Components.interfaces; +var Cu = Components.utils; +Cu.import("resource://gre/modules/Services.jsm"); + +var baseURL = "http://mochi.test:8888/chrome/dom/tests/mochitest/beacon/"; + +function whenDelayedStartupFinished(aWindow, aCallback) { + Services.obs.addObserver(function observer(aSubject, aTopic) { + if (aWindow == aSubject) { + Services.obs.removeObserver(observer, aTopic); + setTimeout(aCallback, 0); + } + }, "browser-delayed-startup-finished", false); +} + +function testOnWindow(options, callback) { + var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShellTreeItem) + .rootTreeItem + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); + + var win = mainWindow.OpenBrowserWindow(options); + windowsToClose.push(win); + whenDelayedStartupFinished(win, function() { + callback(win); + }); +}; + +var windowsToClose = []; +var next; + +function beginTest() { + testOnWindow({}, function(aNormalWindow) { + Services.obs.addObserver(function waitCookie() { + Services.obs.removeObserver(waitCookie, "cookie-changed"); + ok(true, "cookie set by beacon request in normal window"); + testOnPrivateWindow(); + }, "cookie-changed", false); + aNormalWindow.gBrowser.selectedBrowser.loadURI(baseURL + "file_beaconCookies.html"); + }); +} + +function testOnPrivateWindow() { + testOnWindow({private: true}, function(aPrivateWindow) { + Services.obs.addObserver(function waitCookie() { + Services.obs.removeObserver(waitCookie, "private-cookie-changed"); + ok(true, "private cookie set by beacon request in private window"); + cleanup(); + }, "private-cookie-changed", false); + aPrivateWindow.gBrowser.selectedBrowser.loadURI(baseURL + "file_beaconCookies.html"); + }); +} + +function cleanup() { + for (var i = 0; i < windowsToClose.length; ++i) { + windowsToClose[i].close(); + } + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/tests/mochitest/beacon/test_beaconFrame.html b/dom/tests/mochitest/beacon/test_beaconFrame.html new file mode 100644 index 000000000..1bcdcca05 --- /dev/null +++ b/dom/tests/mochitest/beacon/test_beaconFrame.html @@ -0,0 +1,118 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=936340 +--> +<head> + <title>Test for beacon</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=936340">Mozilla Bug 936340</a> +<p id="display"></p> + +<div id="content"> +</div> + +<pre id="test"> +<script class="testbody" type="text/javascript"> + +// not enabled by default yet. +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({'set': [["beacon.enabled", true]]}, runNextTest); + +function getBeaconServerStatus(callback) { + var request = new XMLHttpRequest(); + request.open("GET", "http://mochi.test:8888/tests/dom/tests/mochitest/beacon/beacon-handler.sjs?getLastBeacon", true); + request.onload = function() { + if (request.readyState === request.DONE) { + callback(request.responseText); + } + }; + request.send(null); +} + +function createIframeWithData(data, mimetype, convert) { + beaconConvert = convert; + + var frame = document.createElement("IFRAME"); + frame.setAttribute("src", "beacon-frame.html"); + frame.id = "frame"; + frame.setAttribute("data", data.toString()); + frame.setAttribute("mimetype", mimetype); + var c = document.getElementById("content"); + c.appendChild(frame); +} + +function beaconSent(result) { + // This function gets called from beacon-frame.html in the inner frame + // Check that the beacon was actually sent + ok(result, "Beacon was not sent") + + // remove the frame. + var frame = document.getElementById("frame"); + var data = frame.getAttribute("data"); + var mimetype = frame.getAttribute("mimetype"); + + var c = document.getElementById("content"); + c.removeChild(frame); + + getBeaconServerStatus( function(response) { + console.log(response); + var result = JSON.parse(response); + + is(result.data, data, "Beacon status should match expected. is: " + result.data + " should be: " + data); + is(result.mimetype, mimetype, "Beacon mimetype should match expected. is: " + result.mimetype + " should be: " + mimetype); + + runNextTest(); + }); +} + +function runNextTest() { + var test = tests.shift(); + setTimeout(test, 0); +} + +var beaconConvert = function() {}; + +function stringToArrayBuffer(input) { + + var buffer = new ArrayBuffer(input.length * 2); + var array = new Uint16Array(buffer); + + // dumbly copy over the bytes + for (var i = 0, len = input.length; i < len; i++) { + array[i] = input.charCodeAt(i); + } + return array; +} + +function stringToBlob(input) { + var blob = new Blob([input], {type : 'text/html'}); + return blob; +} + +function stringToFormData(input) { + var formdata = new FormData(); + formdata.append(input, new Blob(['hi'])); + return formdata; +} + +function identity(data) { + return data; +} + +var tests = [ + function() { createIframeWithData("hi!", "text/plain;charset=UTF-8", identity); }, + function() { createIframeWithData("123", "application/octet-stream", stringToArrayBuffer); }, + function() { createIframeWithData("abc", "text/html", stringToBlob); }, + function() { createIframeWithData("qwerty", "multipart/form-data", stringToFormData); }, + function() { SimpleTest.finish(); }, +]; + +</script> +</pre> +</body> +</html> + diff --git a/dom/tests/mochitest/beacon/test_beaconOriginHeader.html b/dom/tests/mochitest/beacon/test_beaconOriginHeader.html new file mode 100644 index 000000000..4594b7a8b --- /dev/null +++ b/dom/tests/mochitest/beacon/test_beaconOriginHeader.html @@ -0,0 +1,67 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Bug 1280692 - navigator.sendBeacon() should not send origin header</title> + <!-- Including SimpleTest.js so we can use waitForExplicitFinish !--> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> + <p id="display"></p> + <div id="content" style="visibility: hidden"> + <iframe style="width:100%;" id="testframe"></iframe> + </div> + +<script class="testbody" type="text/javascript"> + +SimpleTest.waitForExplicitFinish(); + +const BEACON_URL = "http://example.com/tests/dom/tests/mochitest/beacon/beacon-originheader-handler.sjs"; +// no origin header should be sent with sendBeacon request; +// server returns any origin-header or 'no-header' if there is no header sent. +const ORIGIN_HEADER = "no-header"; + +/* Description of the test: + * We call sendBeacon() cross origin and make sure that the + * origin header is actually *not* set in the request. + * + * Since sendBeacon() does not expect any response, we are storing any + * header on the server (*.sjs) and use an XMLHttpRequest to actually + * retrieve the potentially set header back from the server. We assert + * that the header is indeed *not* sent with the request. Since sendBeacon() + * and also the XMLHttpRequest() are performed in an asynchronous fashion, + * there is no guarantee that the sendBeacon() is actually executed before + * the XMLHttpRequest(). + * Hence the xhr-response might be processed asynchronously. + */ + +SpecialPowers.pushPrefEnv({'set': [["beacon.enabled", true]]}, runTest); + +function queryHeaderFromServer() { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "beacon-originheader-handler.sjs?queryheader", true); + xhr.onload = function() { + is(xhr.responseText, ORIGIN_HEADER, "SendBeacon should not send origin header"); + SimpleTest.finish(); + }; + xhr.onerror = function() { + ok(false, "xhr request returned error"); + SimpleTest.finish(); + }; + xhr.send(); +} + +function runTest() { + // generate data and send beacon + var formData = new FormData(); + formData.append('name', 'value'); + navigator.sendBeacon(BEACON_URL, formData); + + // start quering the result from the server + queryHeaderFromServer(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/tests/mochitest/beacon/test_beaconPreflightWithCustomContentType.html b/dom/tests/mochitest/beacon/test_beaconPreflightWithCustomContentType.html new file mode 100644 index 000000000..e8e2add11 --- /dev/null +++ b/dom/tests/mochitest/beacon/test_beaconPreflightWithCustomContentType.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1210302 +--> +<head> + <title>Test for Bug 1210302</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1210302">Mozilla Bug 936340</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +var beaconUrl = "http://example.com/tests/dom/tests/mochitest/beacon/beacon-preflight-handler.sjs?beacon"; + +var intervalID = null; + +function queryIfBeaconSucceeded() { + clearInterval(intervalID); + var xhr = new XMLHttpRequest(); + xhr.open("GET", "beacon-preflight-handler.sjs?verify", true); + xhr.onload = function() { + is(xhr.responseText, "green", "SendBeacon should have succeeded after preflight!"); + SimpleTest.finish(); + }; + xhr.onerror = function() { + ok(false, "xhr request returned error"); + SimpleTest.finish(); + }; + xhr.send(); +} + +// not enabled by default yet. +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({'set': [["beacon.enabled", true]]}, beginTest); + +function beginTest() { + var abv = new Uint8Array([0,1,2,3]); + var blob = new Blob(abv, {type: "application/badness, text/plain"}); + var sent = navigator.sendBeacon(beaconUrl, blob); + ok(sent, "sending the beacon should start successfully"); + + // we have to make sure sending the beacon did not fail, so + // we have to wait for 2 seconds before we can query the result. + intervalID = setInterval(queryIfBeaconSucceeded, 2000); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/tests/mochitest/beacon/test_beaconRedirect.html b/dom/tests/mochitest/beacon/test_beaconRedirect.html new file mode 100644 index 000000000..614e3b5b3 --- /dev/null +++ b/dom/tests/mochitest/beacon/test_beaconRedirect.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Bug 1280692 - sendBeacon() should follow 30x redirect</title>
+ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+ <p id="display"></p>
+ <div id="content" style="visibility: hidden">
+ <iframe style="width:100%;" id="testframe"></iframe>
+ </div>
+
+<script class="testbody" type="text/javascript">
+
+/* Description of the test:
+ * We do perform a non simple sendBeacon request which should not use CORS and should follow
+ * a 30x cross origin redirect, which is allowed by the spec.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+const BEACON_URL = "http://example.com/tests/dom/tests/mochitest/beacon/beacon-redirect-handler.sjs?beacon";
+
+SpecialPowers.pushPrefEnv({'set': [["beacon.enabled", true]]}, runTest);
+
+var intervalID = null;
+
+function queryIfRedirectSucceeded() {
+ clearInterval(intervalID);
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "beacon-redirect-handler.sjs?verifyRedirectDidSucceed", true);
+ xhr.onload = function() {
+ is(xhr.responseText, "green", "SendBeacon should follow cross origin redirects!");
+ SimpleTest.finish();
+ };
+ xhr.onerror = function() {
+ ok(false, "xhr request returned error");
+ SimpleTest.finish();
+ };
+ xhr.send();
+}
+
+function runTest() {
+ var data = new Uint8Array([0,1,2,3]);
+ navigator.sendBeacon(BEACON_URL, data);
+
+ // we have to make sure the channel did follow the redirect hence
+ // we have to wait for a few seconds before we can query the result.
+ interval = 4000;
+ if (navigator.appVersion.indexOf("Android") >= 0) {
+ // Android Debug on an emulator can be very slow
+ interval = 10000;
+ }
+ intervalID = setInterval(queryIfRedirectSucceeded, interval);
+}
+
+</script>
+</pre>
+</body>
+</html>
|