diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /dom/html/test/test_anchor_ping.html | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/html/test/test_anchor_ping.html')
-rw-r--r-- | dom/html/test/test_anchor_ping.html | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/dom/html/test/test_anchor_ping.html b/dom/html/test/test_anchor_ping.html new file mode 100644 index 0000000000..513e5ee05f --- /dev/null +++ b/dom/html/test/test_anchor_ping.html @@ -0,0 +1,304 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=786347 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 786347</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 786347 **/ + +SimpleTest.waitForExplicitFinish(); + +const {NetUtil} = ChromeUtils.importESModule( + "resource://gre/modules/NetUtil.sys.mjs" +); +const {HttpServer} = ChromeUtils.importESModule( + "resource://testing-common/httpd.sys.mjs" +); + +addLoadEvent(function () { + (async function run_tests() { + while (tests.length) { + let test = tests.shift(); + info("-- running " + test.name); + await test(); + } + + SimpleTest.finish(); + })(); +}); + +let tests = [ + + // Ensure that sending pings is enabled. + function setup() { + Services.prefs.setBoolPref("browser.send_pings", true); + Services.prefs.setIntPref("browser.send_pings.max_per_link", -1); + + SimpleTest.registerCleanupFunction(() => { + Services.prefs.clearUserPref("browser.send_pings"); + Services.prefs.clearUserPref("browser.send_pings.max_per_link"); + }); + }, + + // If both the address of the document containing the hyperlink being audited + // and ping URL have the same origin then the request must include a Ping-From + // HTTP header with, as its value, the address of the document containing the + // hyperlink, and a Ping-To HTTP header with, as its value, the target URL. + // The request must not include a Referer (sic) HTTP header. + async function same_origin() { + let from = "/ping-from/" + Math.random(); + let to = "/ping-to/" + Math.random(); + let ping = "/ping/" + Math.random(); + + let base; + let server = new HttpServer(); + + // The page that contains the link. + createFromPathHandler(server, from, to, () => ping); + + // The page that the link's href points to. + let promiseHref = createToPathHandler(server, to); + + // The ping we want to receive. + let promisePing = createPingPathHandler(server, ping, () => { + return {from: base + from, to: base + to}; + }); + + // Start the server, get its base URL and run the test. + server.start(-1); + base = "http://localhost:" + server.identity.primaryPort; + navigate(base + from); + + // Wait until the target and ping url have loaded. + await Promise.all([promiseHref, promisePing]); + + // Cleanup. + await stopServer(server); + }, + + // If the origins are different, but the document containing the hyperlink + // being audited was not retrieved over an encrypted connection then the + // request must include a Referer (sic) HTTP header with, as its value, the + // address of the document containing the hyperlink, a Ping-From HTTP header + // with the same value, and a Ping-To HTTP header with, as its value, target + // URL. + async function diff_origin() { + let from = "/ping-from/" + Math.random(); + let to = "/ping-to/" + Math.random(); + let ping = "/ping/" + Math.random(); + + // We will use two servers to simulate two different origins. + let base, base2; + let server = new HttpServer(); + let server2 = new HttpServer(); + + // The page that contains the link. + createFromPathHandler(server, from, to, () => base2 + ping); + + // The page that the link's href points to. + let promiseHref = createToPathHandler(server, to); + + // Start the first server and get its base URL. + server.start(-1); + base = "http://localhost:" + server.identity.primaryPort; + + // The ping we want to receive. + let promisePing = createPingPathHandler(server2, ping, () => { + return {referrer: base + from, from: base + from, to: base + to}; + }); + + // Start the second server, get its base URL and run the test. + server2.start(-1); + base2 = "http://localhost:" + server2.identity.primaryPort; + navigate(base + from); + + // Wait until the target and ping url have loaded. + await Promise.all([promiseHref, promisePing]); + + // Cleanup. + await stopServer(server); + await stopServer(server2); + }, + + // If the origins are different and the document containing the hyperlink + // being audited was retrieved over an encrypted connection then the request + // must include a Ping-To HTTP header with, as its value, target URL. The + // request must neither include a Referer (sic) HTTP header nor include a + // Ping-From HTTP header. + async function diff_origin_secure_referrer() { + let ping = "/ping/" + Math.random(); + let server = new HttpServer(); + + // The ping we want to receive. + let promisePing = createPingPathHandler(server, ping, () => { + return {to: "https://example.com/"}; + }); + + // Start the server and run the test. + server.start(-1); + + // The referrer will be loaded using a secure channel. + navigate("https://example.com/chrome/dom/html/test/" + + "file_anchor_ping.html?" + "http://127.0.0.1:" + + server.identity.primaryPort + ping); + + // Wait until the ping has been sent. + await promisePing; + + // Cleanup. + await stopServer(server); + }, + + // Test that the <a ping> attribute is properly tokenized using ASCII white + // space characters as separators. + async function tokenize_white_space() { + let from = "/ping-from/" + Math.random(); + let to = "/ping-to/" + Math.random(); + + let base; + let server = new HttpServer(); + + let pings = [ + "/ping1/" + Math.random(), + "/ping2/" + Math.random(), + "/ping3/" + Math.random(), + "/ping4/" + Math.random() + ]; + + // The page that contains the link. + createFromPathHandler(server, from, to, () => { + return " " + pings[0] + " \r " + pings[1] + " \t " + + pings[2] + " \n " + pings[3] + " "; + }); + + // The page that the link's href points to. + let promiseHref = createToPathHandler(server, to); + + // The pings we want to receive. + let pingPathHandlers = createPingPathHandlers(server, pings, () => { + return {from: base + from, to: base + to}; + }); + + // Start the server, get its base URL and run the test. + server.start(-1); + base = "http://localhost:" + server.identity.primaryPort; + navigate(base + from); + + // Wait until the target and ping url have loaded. + await Promise.all([promiseHref, ...pingPathHandlers]); + + // Cleanup. + await stopServer(server); + } +]; + +// Navigate the iframe used for testing to a new URL. +function navigate(uri) { + document.getElementById("frame").src = uri; +} + +// Registers a path handler for the given server that will serve a page +// containing an <a ping> element. The page will automatically simulate +// clicking the link after it has loaded. +function createFromPathHandler(server, path, href, lazyPing) { + server.registerPathHandler(path, function (request, response) { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html;charset=utf-8", false); + response.setHeader("Cache-Control", "no-cache", false); + + let body = '<body onload="document.body.firstChild.click()">' + + '<a href="' + href + '" ping="' + lazyPing() + '"></a></body>'; + response.write(body); + }); +} + +// Registers a path handler for the given server that will serve a simple empty +// page we can use as the href attribute for links. It returns a promise that +// will be resolved once the page has been requested. +function createToPathHandler(server, path) { + return new Promise(resolve => { + + server.registerPathHandler(path, function (request, response) { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html;charset=utf-8", false); + response.setHeader("Cache-Control", "no-cache", false); + response.write("OK"); + + resolve(); + }); + + }); +} + +// Register multiple path handlers for the given server that will receive +// pings as sent when an <a ping> element is clicked. This method uses +// createPingPathHandler() defined below to ensure all headers are sent +// and received as expected. +function createPingPathHandlers(server, paths, lazyHeaders) { + return Array.from(paths, (path) => createPingPathHandler(server, path, lazyHeaders)); +} + +// Registers a path handler for the given server that will receive pings as +// sent when an <a ping> element has been clicked. It will check that the +// correct http method has been used, the post data is correct and all headers +// are given as expected. It returns a promise that will be resolved once the +// ping has been received. +function createPingPathHandler(server, path, lazyHeaders) { + return new Promise(resolve => { + + server.registerPathHandler(path, function (request, response) { + let headers = lazyHeaders(); + + is(request.method, "POST", "correct http method used"); + is(request.getHeader("Ping-To"), headers.to, "valid ping-to header"); + + if ("from" in headers) { + is(request.getHeader("Ping-From"), headers.from, "valid ping-from header"); + } else { + ok(!request.hasHeader("Ping-From"), "no ping-from header"); + } + + if ("referrer" in headers) { + let expectedReferrer = headers.referrer.match(/https?:\/\/[^\/]+\/?/i)[0]; + is(request.getHeader("Referer"), expectedReferrer, "valid referer header"); + } else { + ok(!request.hasHeader("Referer"), "no referer header"); + } + + let bs = request.bodyInputStream; + let body = NetUtil.readInputStreamToString(bs, bs.available()); + is(body, "PING", "correct body sent"); + + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html;charset=utf-8", false); + response.setHeader("Cache-Control", "no-cache", false); + response.write("OK"); + + resolve(); + }); + + }); +} + +// Returns a promise that is resolved when the given http server instance has +// been stopped. +function stopServer(server) { + return new Promise(resolve => { + server.stop(resolve); + }); +} + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786347">Mozilla Bug 786347</a> +<p id="display"></p> +<iframe id="frame" /> +</body> +</html> |