зеркало из https://github.com/mozilla/gecko-dev.git
303 строки
10 KiB
HTML
303 строки
10 KiB
HTML
<!DOCTYPE HTML>
|
|
<html>
|
|
<!--
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=786347
|
|
-->
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Test for Bug 786347</title>
|
|
<script type="application/javascript" 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();
|
|
|
|
var Cu = Components.utils;
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
Cu.import("resource://gre/modules/NetUtil.jsm");
|
|
Cu.import("resource://testing-common/httpd.js");
|
|
|
|
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) {
|
|
is(request.getHeader("Referer"), headers.referrer, "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>
|