mirror of
https://github.com/servo/servo.git
synced 2025-07-13 10:23:40 +01:00
188 lines
6.9 KiB
JavaScript
188 lines
6.9 KiB
JavaScript
// TODO: This function is currently placed and duplicated at:
|
|
// - mixed-content/generic/mixed-content-test-case.js
|
|
// - referrer-policy/generic/referrer-policy-test-case.js
|
|
// but should be moved to /common/security-features/resources/common.js.
|
|
function getSubresourceOrigin(originType) {
|
|
const httpProtocol = "http";
|
|
const httpsProtocol = "https";
|
|
const wsProtocol = "ws";
|
|
const wssProtocol = "wss";
|
|
|
|
const sameOriginHost = "{{host}}";
|
|
const crossOriginHost = "{{domains[www1]}}";
|
|
|
|
// These values can evaluate to either empty strings or a ":port" string.
|
|
const httpPort = getNormalizedPort(parseInt("{{ports[http][0]}}", 10));
|
|
const httpsPort = getNormalizedPort(parseInt("{{ports[https][0]}}", 10));
|
|
const wsPort = getNormalizedPort(parseInt("{{ports[ws][0]}}", 10));
|
|
const wssPort = getNormalizedPort(parseInt("{{ports[wss][0]}}", 10));
|
|
|
|
/**
|
|
@typedef OriginType
|
|
@type {string}
|
|
|
|
Represents the origin of the subresource request URL.
|
|
The keys of `originMap` below are the valid values.
|
|
|
|
Note that there can be redirects from the specified origin
|
|
(see RedirectionType), and thus the origin of the subresource
|
|
response URL might be different from what is specified by OriginType.
|
|
*/
|
|
const originMap = {
|
|
"same-https": httpsProtocol + "://" + sameOriginHost + httpsPort,
|
|
"same-http": httpProtocol + "://" + sameOriginHost + httpPort,
|
|
"cross-https": httpsProtocol + "://" + crossOriginHost + httpsPort,
|
|
"cross-http": httpProtocol + "://" + crossOriginHost + httpPort,
|
|
"same-wss": wssProtocol + "://" + sameOriginHost + wssPort,
|
|
"same-ws": wsProtocol + "://" + sameOriginHost + wsPort,
|
|
"cross-wss": wssProtocol + "://" + crossOriginHost + wssPort,
|
|
"cross-ws": wsProtocol + "://" + crossOriginHost + wsPort,
|
|
};
|
|
|
|
return originMap[originType];
|
|
}
|
|
|
|
// NOTE: This method only strips the fragment and is not in accordance to the
|
|
// recommended draft specification:
|
|
// https://w3c.github.io/webappsec/specs/referrer-policy/#null
|
|
// TODO(kristijanburnik): Implement this helper as defined by spec once added
|
|
// scenarios for URLs containing username/password/etc.
|
|
function stripUrlForUseAsReferrer(url) {
|
|
return url.replace(/#.*$/, "");
|
|
}
|
|
|
|
function ReferrerPolicyTestCase(scenario, testDescription, sanityChecker) {
|
|
// Pass and skip rest of the test if browser does not support fetch.
|
|
if (scenario.subresource == "fetch-request" && !window.fetch) {
|
|
// TODO(kristijanburnik): This should be refactored.
|
|
return {
|
|
start: function() {
|
|
test(function() { assert_true(true); },
|
|
"[ReferrerPolicyTestCase] Skipping test: Fetch is not supported.");
|
|
}
|
|
};
|
|
}
|
|
|
|
// This check is A NOOP in release.
|
|
sanityChecker.checkScenario(scenario);
|
|
|
|
const originTypeConversion = {
|
|
"same-origin-http": "same-http",
|
|
"same-origin-https": "same-https",
|
|
"cross-origin-http": "cross-http",
|
|
"cross-origin-https": "cross-https"
|
|
};
|
|
const urls = getRequestURLs(
|
|
scenario.subresource,
|
|
originTypeConversion[scenario.origin + '-' + scenario.target_protocol],
|
|
scenario.redirection);
|
|
|
|
const referrerUrlResolver = {
|
|
"omitted": function(sourceUrl) {
|
|
return undefined;
|
|
},
|
|
"origin": function(sourceUrl) {
|
|
return new URL(sourceUrl).origin + "/";
|
|
},
|
|
"stripped-referrer": function(sourceUrl) {
|
|
return stripUrlForUseAsReferrer(sourceUrl);
|
|
}
|
|
};
|
|
|
|
const checkResult = (expectedReferrerUrl, result) => {
|
|
// Check if the result is in valid format. NOOP in release.
|
|
sanityChecker.checkSubresourceResult(scenario, urls.testUrl, result);
|
|
|
|
// Check the reported URL.
|
|
assert_equals(result.referrer,
|
|
expectedReferrerUrl,
|
|
"Reported Referrer URL is '" +
|
|
scenario.referrer_url + "'.");
|
|
assert_equals(result.headers.referer,
|
|
expectedReferrerUrl,
|
|
"Reported Referrer URL from HTTP header is '" +
|
|
expectedReferrerUrl + "'");
|
|
};
|
|
|
|
function runTest() {
|
|
const deliveryTypeConversion = {
|
|
"attr-referrer": "attr",
|
|
"rel-noreferrer": "rel-noref",
|
|
// Other delivery methods such as "http-rp" are ignored here because
|
|
// they are already applied to the main document by generator.py.
|
|
};
|
|
|
|
/** @type {PolicyDelivery} */
|
|
const delivery = {
|
|
deliveryType: deliveryTypeConversion[scenario.delivery_method],
|
|
key: "referrerPolicy",
|
|
value: scenario.referrer_policy};
|
|
|
|
/** @type {Subresource} */
|
|
const subresource = {
|
|
subresourceType: scenario.subresource,
|
|
url: urls.testUrl,
|
|
policyDeliveries: [delivery]
|
|
};
|
|
|
|
const expectedReferrer =
|
|
referrerUrlResolver[scenario.referrer_url](location.toString());
|
|
|
|
// Request in the top-level document.
|
|
promise_test(_ => {
|
|
return invokeRequest(subresource, [])
|
|
.then(result => checkResult(expectedReferrer, result));
|
|
}, testDescription);
|
|
|
|
// We test requests from inside iframes only for <img> tags.
|
|
// This is just to preserve the previous test coverage.
|
|
// TODO(hiroshige): Enable iframe tests for all subresource types.
|
|
if (scenario.subresource !== "img-tag") {
|
|
return;
|
|
}
|
|
|
|
// Request in a `srcdoc` frame to ensure that it uses the referrer
|
|
// policy of its parent,
|
|
promise_test(_ => {
|
|
/** @type {Array<SourceContext>} */
|
|
const sourceContextList = [{sourceContextType: "srcdoc"}];
|
|
|
|
return invokeRequest(subresource, sourceContextList)
|
|
.then(result => checkResult(expectedReferrer, result));
|
|
}, testDescription + " (srcdoc iframe inherits parent)");
|
|
|
|
// Request in a `srcdoc` frame with its own referrer policy to
|
|
// override its parent.
|
|
promise_test(_ => {
|
|
// Give a srcdoc iframe a referrer policy different from the
|
|
// top-level page's policy.
|
|
const overridingPolicy =
|
|
scenario.referrer_policy === "no-referrer" ? "unsafe-url"
|
|
: "no-referrer";
|
|
const overrridingExpectedReferrer =
|
|
referrerUrlResolver[overridingPolicy === "no-referrer"
|
|
? "omitted"
|
|
: "stripped-referrer"](location.toString());
|
|
|
|
/** @type {Subresource} */
|
|
const subresourceWithoutDelivery = {
|
|
subresourceType: scenario.subresource,
|
|
url: urls.testUrl
|
|
};
|
|
|
|
// <iframe srcdoc> with overriding <meta> referrerPolicy.
|
|
/** @type {Array<SourceContext>} */
|
|
const sourceContextList = [{
|
|
sourceContextType: "srcdoc",
|
|
policyDeliveries: [{deliveryType: "meta",
|
|
key: "referrerPolicy",
|
|
value: overridingPolicy}]
|
|
}];
|
|
|
|
return invokeRequest(subresourceWithoutDelivery, sourceContextList)
|
|
.then(result => checkResult(overrridingExpectedReferrer, result));
|
|
}, testDescription + " (overridden by srcdoc iframe)");
|
|
}
|
|
|
|
return {start: runTest};
|
|
}
|