summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/referrer-policy/generic
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/referrer-policy/generic')
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/common.js212
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/referrer-policy-test-case.js125
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/sanity-checker.js52
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource-test/area-navigate.html39
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource-test/attr-referrer-invalid-value.html25
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource-test/fetch-messaging.html48
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource-test/iframe-messaging.html39
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource-test/image-decoding.html39
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource-test/link-navigate.html39
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource-test/script-messaging.html39
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource-test/worker-messaging.html39
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource-test/xhr-messaging.html39
-rwxr-xr-xtesting/web-platform/tests/referrer-policy/generic/subresource/__init__.py0
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource/document.py12
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource/image.py100
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource/script.py13
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource/subresource.py94
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/subresource/worker.py12
-rwxr-xr-xtesting/web-platform/tests/referrer-policy/generic/subresource/xhr.py15
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/template/disclaimer.template1
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/template/document.html.template16
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/template/script.js.template3
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/template/spec_json.js.template1
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/template/test.debug.html.template70
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/template/test.js.template15
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/template/test.release.html.template20
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/template/test_description.template5
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/template/worker.js.template3
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/tools/__init__.py0
-rwxr-xr-xtesting/web-platform/tests/referrer-policy/generic/tools/clean.py35
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/tools/common_paths.py52
-rwxr-xr-xtesting/web-platform/tests/referrer-policy/generic/tools/generate.py172
-rwxr-xr-xtesting/web-platform/tests/referrer-policy/generic/tools/regenerate3
-rwxr-xr-xtesting/web-platform/tests/referrer-policy/generic/tools/spec_validator.py166
-rw-r--r--testing/web-platform/tests/referrer-policy/generic/unsupported-csp-referrer-directive.html30
35 files changed, 1573 insertions, 0 deletions
diff --git a/testing/web-platform/tests/referrer-policy/generic/common.js b/testing/web-platform/tests/referrer-policy/generic/common.js
new file mode 100644
index 000000000..492031859
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/common.js
@@ -0,0 +1,212 @@
+// 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 parseUrlQueryString(queryString) {
+ var queries = queryString.replace(/^\?/, "").split("&");
+ var params = {};
+
+ for (var i in queries) {
+ var kvp = queries[i].split("=");
+ params[kvp[0]] = kvp[1];
+ }
+
+ return params;
+};
+
+function appendIframeToBody(url, attributes) {
+ var iframe = document.createElement("iframe");
+ iframe.src = url;
+ // Extend element with attributes. (E.g. "referrerPolicy" or "rel")
+ if (attributes) {
+ for (var attr in attributes) {
+ iframe[attr] = attributes[attr];
+ }
+ }
+ document.body.appendChild(iframe);
+
+ return iframe;
+}
+
+function loadImage(src, callback, attributes) {
+ var image = new Image();
+ image.crossOrigin = "Anonymous";
+ image.onload = function() {
+ callback(image);
+ }
+ image.src = src;
+ // Extend element with attributes. (E.g. "referrerPolicy" or "rel")
+ if (attributes) {
+ for (var attr in attributes) {
+ image[attr] = attributes[attr];
+ }
+ }
+ document.body.appendChild(image)
+}
+
+function decodeImageData(rgba) {
+ var rgb = new Uint8ClampedArray(rgba.length);
+
+ // RGBA -> RGB.
+ var rgb_length = 0;
+ for (var i = 0; i < rgba.length; ++i) {
+ // Skip alpha component.
+ if (i % 4 == 3)
+ continue;
+
+ // Zero is the string terminator.
+ if (rgba[i] == 0)
+ break;
+
+ rgb[rgb_length++] = rgba[i];
+ }
+
+ // Remove trailing nulls from data.
+ rgb = rgb.subarray(0, rgb_length);
+ var string_data = (new TextDecoder("ascii")).decode(rgb);
+
+ return JSON.parse(string_data);
+}
+
+function decodeImage(url, callback, referrer_policy) {
+ loadImage(url, function(img) {
+ var canvas = document.createElement("canvas");
+ var context = canvas.getContext('2d');
+ context.drawImage(img, 0, 0);
+ var imgData = context.getImageData(0, 0, img.clientWidth, img.clientHeight);
+ callback(decodeImageData(imgData.data))
+ }, referrer_policy);
+}
+
+function normalizePort(targetPort) {
+ var defaultPorts = [80, 443];
+ var isDefaultPortForProtocol = (defaultPorts.indexOf(targetPort) >= 0);
+
+ return (targetPort == "" || isDefaultPortForProtocol) ?
+ "" : ":" + targetPort;
+}
+
+function wrapResult(url, server_data) {
+ return {
+ location: url,
+ referrer: server_data.headers.referer,
+ headers: server_data.headers
+ }
+}
+
+function queryIframe(url, callback, referrer_policy) {
+ var iframe = appendIframeToBody(url, referrer_policy);
+ var listener = function(event) {
+ if (event.source != iframe.contentWindow)
+ return;
+
+ callback(event.data, url);
+ window.removeEventListener("message", listener);
+ }
+ window.addEventListener("message", listener);
+}
+
+function queryImage(url, callback, referrer_policy) {
+ decodeImage(url, function(server_data) {
+ callback(wrapResult(url, server_data), url);
+ }, referrer_policy)
+}
+
+function queryXhr(url, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.onreadystatechange = function(e) {
+ if (this.readyState == 4 && this.status == 200) {
+ var server_data = JSON.parse(this.responseText);
+ callback(wrapResult(url, server_data), url);
+ }
+ };
+ xhr.send();
+}
+
+function queryWorker(url, callback) {
+ var worker = new Worker(url);
+ worker.onmessage = function(event) {
+ var server_data = event.data;
+ callback(wrapResult(url, server_data), url);
+ };
+}
+
+function queryFetch(url, callback) {
+ fetch(url).then(function(response) {
+ response.json().then(function(server_data) {
+ callback(wrapResult(url, server_data), url);
+ });
+ }
+ );
+}
+
+function queryNavigable(element, url, callback, attributes) {
+ var navigable = element
+ navigable.href = url;
+ navigable.target = "helper-iframe";
+
+ var helperIframe = document.createElement("iframe")
+ helperIframe.name = "helper-iframe"
+ document.body.appendChild(helperIframe)
+
+ // Extend element with attributes. (E.g. "referrer_policy" or "rel")
+ if (attributes) {
+ for (var attr in attributes) {
+ navigable[attr] = attributes[attr];
+ }
+ }
+
+ var listener = function(event) {
+ if (event.source != helperIframe.contentWindow)
+ return;
+
+ callback(event.data, url);
+ window.removeEventListener("message", listener);
+ }
+ window.addEventListener("message", listener);
+
+ navigable.click();
+}
+
+function queryLink(url, callback, referrer_policy) {
+ var a = document.createElement("a");
+ a.innerHTML = "Link to subresource";
+ document.body.appendChild(a);
+ queryNavigable(a, url, callback, referrer_policy)
+}
+
+function queryAreaLink(url, callback, referrer_policy) {
+ var area = document.createElement("area");
+ // TODO(kristijanburnik): Append to map and add image.
+ document.body.appendChild(area);
+ queryNavigable(area, url, callback, referrer_policy)
+}
+
+function queryScript(url, callback) {
+ var script = document.createElement("script");
+ script.src = url;
+
+ var listener = function(event) {
+ var server_data = event.data;
+ callback(wrapResult(url, server_data), url);
+ window.removeEventListener("message", listener);
+ }
+ window.addEventListener("message", listener);
+
+ document.body.appendChild(script);
+}
+
+ // SanityChecker does nothing in release mode.
+function SanityChecker() {}
+SanityChecker.prototype.checkScenario = function() {};
+SanityChecker.prototype.checkSubresourceResult = function() {};
+
+// TODO(kristijanburnik): document.origin is supported since Chrome 41,
+// other browsers still don't support it. Remove once they do.
+document.origin = document.origin || (location.protocol + "//" + location.host);
diff --git a/testing/web-platform/tests/referrer-policy/generic/referrer-policy-test-case.js b/testing/web-platform/tests/referrer-policy/generic/referrer-policy-test-case.js
new file mode 100644
index 000000000..c4cf96fb0
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/referrer-policy-test-case.js
@@ -0,0 +1,125 @@
+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);
+
+ var subresourceInvoker = {
+ "a-tag": queryLink,
+ "area-tag": queryAreaLink,
+ "fetch-request": queryFetch,
+ "iframe-tag": queryIframe,
+ "img-tag": queryImage,
+ "script-tag": queryScript,
+ "worker-request": queryWorker,
+ "xhr-request": queryXhr
+ };
+
+ var referrerUrlResolver = {
+ "omitted": function() {
+ return undefined;
+ },
+ "origin": function() {
+ return document.origin + "/";
+ },
+ "stripped-referrer": function() {
+ return stripUrlForUseAsReferrer(location.toString());
+ }
+ };
+
+ var t = {
+ _scenario: scenario,
+ _testDescription: testDescription,
+ _subresourceUrl: null,
+ _expectedReferrerUrl: null,
+ _constructSubresourceUrl: function() {
+ // TODO(kristijanburnik): We should assert that these two domains are
+ // different. E.g. If someone runs the tets over www, this would fail.
+ var domainForOrigin = {
+ "cross-origin":"{{domains[www1]}}",
+ "same-origin": location.hostname
+ };
+
+ // Values obtained and replaced by the wptserve pipeline:
+ // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes
+ var portForProtocol = {
+ "http": parseInt("{{ports[http][0]}}"),
+ "https": parseInt("{{ports[https][0]}}")
+ }
+
+ var targetPort = portForProtocol[t._scenario.target_protocol];
+
+ t._subresourceUrl = t._scenario.target_protocol + "://" +
+ domainForOrigin[t._scenario.origin] +
+ normalizePort(targetPort) +
+ t._scenario["subresource_path"] +
+ "?redirection=" + t._scenario["redirection"] +
+ "&cache_destroyer=" + (new Date()).getTime();
+ },
+
+ _constructExpectedReferrerUrl: function() {
+ t._expectedReferrerUrl = referrerUrlResolver[t._scenario.referrer_url]();
+ },
+
+ _invokeSubresource: function(callback) {
+ var invoker = subresourceInvoker[t._scenario.subresource];
+
+ // Depending on the delivery method, extend the subresource element with
+ // these attributes.
+ var elementAttributesForDeliveryMethod = {
+ "attr-referrer": {referrerPolicy: t._scenario.referrer_policy},
+ "rel-noreferrer": {rel: "noreferrer"}
+ };
+
+ var delivery_method = t._scenario.delivery_method;
+
+ if (delivery_method in elementAttributesForDeliveryMethod) {
+ invoker(t._subresourceUrl,
+ callback,
+ elementAttributesForDeliveryMethod[delivery_method]);
+ } else {
+ invoker(t._subresourceUrl, callback);
+ }
+
+ },
+
+ start: function() {
+ t._constructSubresourceUrl();
+ t._constructExpectedReferrerUrl();
+
+ var test = async_test(t._testDescription);
+
+ t._invokeSubresource(function(result) {
+ // Check if the result is in valid format. NOOP in release.
+ sanityChecker.checkSubresourceResult(
+ test, t._scenario, t._subresourceUrl, result);
+
+ // Check the reported URL.
+ test.step(function() {
+ assert_equals(result.referrer,
+ t._expectedReferrerUrl,
+ "Reported Referrer URL is '" +
+ t._scenario.referrer_url + "'.");
+ assert_equals(result.headers.referer,
+ t._expectedReferrerUrl,
+ "Reported Referrer URL from HTTP header is '" +
+ t._expectedReferrerUrl + "'");
+ }, "Reported Referrer URL is as expected: " + t._scenario.referrer_url);
+
+ test.done();
+ })
+
+ }
+ }
+
+ return t;
+}
diff --git a/testing/web-platform/tests/referrer-policy/generic/sanity-checker.js b/testing/web-platform/tests/referrer-policy/generic/sanity-checker.js
new file mode 100644
index 000000000..e0714885f
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/sanity-checker.js
@@ -0,0 +1,52 @@
+// The SanityChecker is used in debug mode to identify problems with the
+// structure of the testsuite. In release mode it is mocked out to do nothing.
+
+function SanityChecker() {}
+
+SanityChecker.prototype.checkScenario = function(scenario) {
+ // Check if scenario is valid.
+ // TODO(kristijanburnik): Move to a sanity-checks.js for debug mode only.
+ test(function() {
+
+ // We extend the exsiting test_expansion_schema not to kill performance by
+ // copying.
+ var expectedFields = SPEC_JSON["test_expansion_schema"];
+ expectedFields["referrer_policy"] = SPEC_JSON["referrer_policy_schema"];
+
+ assert_own_property(scenario, "subresource_path",
+ "Scenario has the path to the subresource.");
+
+ for (var field in expectedFields) {
+ assert_own_property(scenario, field,
+ "The scenario contains field " + field)
+ assert_in_array(scenario[field], expectedFields[field],
+ "Scenario's " + field + " is one of: " +
+ expectedFields[field].join(", ")) + "."
+ }
+
+ // Check if the protocol is matched.
+ assert_equals(scenario["source_protocol"] + ":", location.protocol,
+ "Protocol of the test page should match the scenario.")
+
+ }, "[ReferrerPolicyTestCase] The test scenario is valid.");
+}
+
+SanityChecker.prototype.checkSubresourceResult = function(test,
+ scenario,
+ subresourceUrl,
+ result) {
+ test.step(function() {
+ assert_equals(Object.keys(result).length, 3);
+ assert_own_property(result, "location");
+ assert_own_property(result, "referrer");
+ assert_own_property(result, "headers");
+
+ // Skip location check for scripts.
+ if (scenario.subresource == "script-tag")
+ return;
+
+ // Sanity check: location of sub-resource matches reported location.
+ assert_equals(result.location, subresourceUrl,
+ "Subresource reported location.");
+ }, "Running a valid test scenario.");
+};
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/area-navigate.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/area-navigate.html
new file mode 100644
index 000000000..bca7e479f
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/area-navigate.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. -->
+<html>
+ <head>
+ <title>Area Link messaging - cross-origin Area Link navigation</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Common global functions for referrer-policy tests. -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ </head>
+ <body>
+ <h1>Area Link messaging - cross-origin Area Link navigation</h1>
+ <p>If you can read JSON encoded HTTP request headers of the Area link below,
+ the messaging works as expected.</p>
+
+ <pre id="received_message">Running...</pre>
+
+ <script>
+ var messaging_test = async_test("Area is responding with HTTP headers");
+ var urlPath = '/referrer-policy/generic/subresource/document.py';
+ var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+ urlPath;
+ queryAreaLink(url, function(message) {
+ var pre = document.getElementById('received_message')
+ var headers = message.headers;
+ pre.innerHTML = "";
+ pre.innerHTML += url + ":\n\n";
+ pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n"
+ messaging_test.step(function() {
+ assert_own_property(headers, "host")
+ assert_own_property(headers, "connection")
+ });
+ messaging_test.done();
+ });
+ </script>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/attr-referrer-invalid-value.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/attr-referrer-invalid-value.html
new file mode 100644
index 000000000..9bc74f54a
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/attr-referrer-invalid-value.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Invalid referrerPolicy attribute value</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Invalid referrerPolicy attribute value</h1>
+ <pre>Running...</pre>
+
+ <script>
+ test(function () {
+ var elements = ["iframe", "img", "a", "area", "link"];
+ for (var i = 0; i < elements.length; i++) {
+ var elem = document.createElement(elements[i]);
+ elem.referrerPolicy = "unsafe-url";
+ assert_equals(elem.referrerPolicy, "unsafe-url");
+ elem.referrerPolicy = "not-valid-value";
+ assert_equals(elem.referrerPolicy, "");
+ }
+ }, "Invalid referrerpolicy values not reflected");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/fetch-messaging.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/fetch-messaging.html
new file mode 100644
index 000000000..046b29e9a
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/fetch-messaging.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. -->
+<html>
+ <head>
+ <title>Fetch messaging - same-origin Fetch request</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Common global functions for referrer-policy tests. -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ </head>
+ <body>
+ <h1>Fetch messaging - same-origin Fetch request</h1>
+ <p>If you can read JSON encoded HTTP request headers of the Fetch below,
+ the messaging works as expected.</p>
+
+ <pre id="received_message">Running...</pre>
+
+ <script>
+ test(function() {
+ assert_true(!!window.fetch, "Fetch is not supported by this browser.");
+ }, "Fetch is supported by the browser.");
+
+ (function() {
+ if (!window.fetch)
+ return;
+
+ var fetch_test = async_test("Fetch is responding with HTTP headers");
+ var urlPath = '/referrer-policy/generic/subresource/xhr.py';
+ var url = location.protocol + "//" + location.hostname + ":" +
+ location.port + urlPath;
+ queryFetch(url, function(message) {
+ var pre = document.getElementById('received_message')
+ var headers = message.headers;
+ pre.innerHTML = "";
+ pre.innerHTML += url + ":\n\n";
+ pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n";
+ fetch_test.step(function() {
+ assert_own_property(headers, "host")
+ assert_own_property(headers, "connection")
+ });
+ fetch_test.done();
+ });
+ })();
+ </script>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/iframe-messaging.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/iframe-messaging.html
new file mode 100644
index 000000000..a3e55707c
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/iframe-messaging.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. -->
+<html>
+ <head>
+ <title>Iframe messaging - cross-origin iframe request</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Common global functions for referrer-policy tests. -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ </head>
+ <body>
+ <h1>Iframe messaging - cross-origin iframe request</h1>
+ <p>If you can read JSON encoded HTTP request headers of the iframe below,
+ the messaging works as expected.</p>
+
+ <pre id="received_message">Running...</pre>
+
+ <script>
+ var messaging_test = async_test("Iframe is responding with HTTP headers");
+ var urlPath = '/referrer-policy/generic/subresource/document.py';
+ var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+ urlPath;
+ queryIframe(url, function(message) {
+ var pre = document.getElementById('received_message')
+ var headers = message.headers;
+ pre.innerHTML = "";
+ pre.innerHTML += url + ":\n\n";
+ pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n"
+ messaging_test.step(function() {
+ assert_own_property(headers, "host")
+ assert_own_property(headers, "connection")
+ });
+ messaging_test.done();
+ });
+ </script>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/image-decoding.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/image-decoding.html
new file mode 100644
index 000000000..083fb829a
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/image-decoding.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. -->
+<html>
+ <head>
+ <title>Image decoding - cross-origin image request</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Common global functions for referrer-policy tests. -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ </head>
+ <body>
+ <h1>Image decoding - cross-origin image request</h1>
+ <p>If you can read JSON encoded HTTP headers of the image below,
+ the decoding works as expected.</p>
+
+ <pre id="received_message">Running...</pre>
+
+ <script>
+ var messaging_test = async_test("Image is encoding headers as JSON.");
+ var urlPath = '/referrer-policy/generic/subresource/image.py';
+ var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+ urlPath;
+ queryImage(url, function(message) {
+ var pre = document.getElementById('received_message')
+ var headers = message.headers;
+ pre.innerHTML = "";
+ pre.innerHTML += url + ":\n\n";
+ pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n"
+ messaging_test.step(function() {
+ assert_own_property(headers, "host")
+ assert_own_property(headers, "connection")
+ });
+ messaging_test.done();
+ });
+ </script>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/link-navigate.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/link-navigate.html
new file mode 100644
index 000000000..45e502004
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/link-navigate.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. -->
+<html>
+ <head>
+ <title>Link messaging - cross-origin Link navigation</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Common global functions for referrer-policy tests. -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ </head>
+ <body>
+ <h1>Link messaging - cross-origin Link navigation</h1>
+ <p>If you can read JSON encoded HTTP request headers of the Link below,
+ the messaging works as expected.</p>
+
+ <pre id="received_message">Running...</pre>
+
+ <script>
+ var messaging_test = async_test("Link is responding with HTTP headers");
+ var urlPath = '/referrer-policy/generic/subresource/document.py';
+ var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+ urlPath;
+ queryLink(url, function(message) {
+ var pre = document.getElementById('received_message')
+ var headers = message.headers;
+ pre.innerHTML = "";
+ pre.innerHTML += url + ":\n\n";
+ pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n"
+ messaging_test.step(function() {
+ assert_own_property(headers, "host")
+ assert_own_property(headers, "connection")
+ });
+ messaging_test.done();
+ });
+ </script>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/script-messaging.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/script-messaging.html
new file mode 100644
index 000000000..09c5db619
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/script-messaging.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. -->
+<html>
+ <head>
+ <title>Script messaging - cross-origin Script request</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Common global functions for referrer-policy tests. -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ </head>
+ <body>
+ <h1>Script messaging - cross-origin Script request</h1>
+ <p>If you can read JSON encoded HTTP request headers of the Script below,
+ the messaging works as expected.</p>
+
+ <pre id="received_message">Running...</pre>
+
+ <script>
+ var messaging_test = async_test("Script is responding with HTTP headers");
+ var urlPath = '/referrer-policy/generic/subresource/script.py';
+ var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+ urlPath;
+ queryScript(url, function(message) {
+ var pre = document.getElementById('received_message')
+ var headers = message.headers;
+ pre.innerHTML = "";
+ pre.innerHTML += url + ":\n\n";
+ pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n"
+ messaging_test.step(function() {
+ assert_own_property(headers, "host")
+ assert_own_property(headers, "connection")
+ });
+ messaging_test.done();
+ });
+ </script>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/worker-messaging.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/worker-messaging.html
new file mode 100644
index 000000000..6d34366b9
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/worker-messaging.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. -->
+<html>
+ <head>
+ <title>Worker messaging - same-origin Worker request</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Common global functions for referrer-policy tests. -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ </head>
+ <body>
+ <h1>Worker messaging - same-origin Worker request</h1>
+ <p>If you can read JSON encoded HTTP request headers of the Worker below,
+ the messaging works as expected.</p>
+
+ <pre id="received_message">Running...</pre>
+
+ <script>
+ var messaging_test = async_test("Worker is responding with HTTP headers");
+ var urlPath = '/referrer-policy/generic/subresource/worker.py';
+ var url = location.protocol + "//" + location.hostname + ":" +
+ location.port + urlPath;
+ queryWorker(url, function(message) {
+ var pre = document.getElementById('received_message')
+ var headers = message.headers;
+ pre.innerHTML = "";
+ pre.innerHTML += url + ":\n\n";
+ pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n"
+ messaging_test.step(function() {
+ assert_own_property(headers, "host")
+ assert_own_property(headers, "connection")
+ });
+ messaging_test.done();
+ });
+ </script>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/xhr-messaging.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/xhr-messaging.html
new file mode 100644
index 000000000..09f691400
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/xhr-messaging.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. -->
+<html>
+ <head>
+ <title>XHR messaging - cross-origin XHR request</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Common global functions for referrer-policy tests. -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ </head>
+ <body>
+ <h1>XHR messaging - cross-origin XHR request</h1>
+ <p>If you can read JSON encoded HTTP request headers of the XHR below,
+ the messaging works as expected.</p>
+
+ <pre id="received_message">Running...</pre>
+
+ <script>
+ var messaging_test = async_test("XHR is responding with HTTP headers");
+ var urlPath = '/referrer-policy/generic/subresource/xhr.py';
+ var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+ urlPath;
+ queryXhr(url, function(message) {
+ var pre = document.getElementById('received_message')
+ var headers = message.headers;
+ pre.innerHTML = "";
+ pre.innerHTML += url + ":\n\n";
+ pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n"
+ messaging_test.step(function() {
+ assert_own_property(headers, "host")
+ assert_own_property(headers, "connection")
+ });
+ messaging_test.done();
+ });
+ </script>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource/__init__.py b/testing/web-platform/tests/referrer-policy/generic/subresource/__init__.py
new file mode 100755
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource/__init__.py
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource/document.py b/testing/web-platform/tests/referrer-policy/generic/subresource/document.py
new file mode 100644
index 000000000..b2d6c4dfa
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource/document.py
@@ -0,0 +1,12 @@
+import os, json, sys
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
+import subresource
+
+def generate_payload(server_data):
+ return subresource.get_template("document.html.template") % server_data
+
+def main(request, response):
+ subresource.respond(request,
+ response,
+ payload_generator = generate_payload)
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource/image.py b/testing/web-platform/tests/referrer-policy/generic/subresource/image.py
new file mode 100644
index 000000000..b6306181e
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource/image.py
@@ -0,0 +1,100 @@
+import os, sys, array, json, math, StringIO
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+import subresource
+
+class Image:
+ """This class partially implements the interface of the PIL.Image.Image.
+ One day in the future WPT might support the PIL module or another imaging
+ library, so this hacky BMP implementation will no longer be required.
+ """
+ def __init__(self, width, height):
+ self.width = width
+ self.height = height
+ self.img = bytearray([0 for i in range(3 * width * height)])
+
+ @staticmethod
+ def new(mode, size, color=0):
+ return Image(size[0], size[1])
+
+ def _int_to_bytes(self, number):
+ packed_bytes = [0, 0, 0, 0]
+ for i in range(4):
+ packed_bytes[i] = number & 0xFF
+ number >>= 8
+
+ return packed_bytes
+
+ def putdata(self, color_data):
+ for y in range(self.height):
+ for x in range(self.width):
+ i = x + y * self.width
+ if i > len(color_data) - 1:
+ return
+
+ self.img[i * 3: i * 3 + 3] = color_data[i][::-1]
+
+ def save(self, f, type):
+ assert type == "BMP"
+ # 54 bytes of preambule + image color data.
+ filesize = 54 + 3 * self.width * self.height;
+ # 14 bytes of header.
+ bmpfileheader = bytearray(['B', 'M'] + self._int_to_bytes(filesize) +
+ [0, 0, 0, 0, 54, 0, 0, 0])
+ # 40 bytes of info.
+ bmpinfoheader = bytearray([40, 0, 0, 0] +
+ self._int_to_bytes(self.width) +
+ self._int_to_bytes(self.height) +
+ [1, 0, 24] + (25 * [0]))
+
+ padlength = (4 - (self.width * 3) % 4) % 4
+ bmppad = bytearray([0, 0, 0]);
+ padding = bmppad[0 : padlength]
+
+ f.write(bmpfileheader)
+ f.write(bmpinfoheader)
+
+ for i in range(self.height):
+ offset = self.width * (self.height - i - 1) * 3
+ f.write(self.img[offset : offset + 3 * self.width])
+ f.write(padding)
+
+def encode_string_as_bmp_image(string_data):
+ data_bytes = array.array("B", string_data)
+ num_bytes = len(data_bytes)
+
+ # Convert data bytes to color data (RGB).
+ color_data = []
+ num_components = 3
+ rgb = [0] * num_components
+ i = 0
+ for byte in data_bytes:
+ component_index = i % num_components
+ rgb[component_index] = byte
+ if component_index == (num_components - 1) or i == (num_bytes - 1):
+ color_data.append(tuple(rgb))
+ rgb = [0] * num_components
+ i += 1
+
+ # Render image.
+ num_pixels = len(color_data)
+ sqrt = int(math.ceil(math.sqrt(num_pixels)))
+ img = Image.new("RGB", (sqrt, sqrt), "black")
+ img.putdata(color_data)
+
+ # Flush image to string.
+ f = StringIO.StringIO()
+ img.save(f, "BMP")
+ f.seek(0)
+
+ return f.read()
+
+def generate_payload(server_data):
+ data = ('{"headers": %(headers)s}') % server_data
+ return encode_string_as_bmp_image(data)
+
+def main(request, response):
+ subresource.respond(request,
+ response,
+ payload_generator = generate_payload,
+ content_type = "image/bmp",
+ access_control_allow_origin = "*")
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource/script.py b/testing/web-platform/tests/referrer-policy/generic/subresource/script.py
new file mode 100644
index 000000000..efa1a955d
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource/script.py
@@ -0,0 +1,13 @@
+import os, sys, json
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+import subresource
+
+def generate_payload(server_data):
+ return subresource.get_template("script.js.template") % server_data
+
+def main(request, response):
+ subresource.respond(request,
+ response,
+ payload_generator = generate_payload,
+ content_type = "application/javascript")
+
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource/subresource.py b/testing/web-platform/tests/referrer-policy/generic/subresource/subresource.py
new file mode 100644
index 000000000..7571b32d0
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource/subresource.py
@@ -0,0 +1,94 @@
+import os, sys, json, urlparse, urllib
+
+def get_template(template_basename):
+ script_directory = os.path.dirname(os.path.abspath(__file__))
+ template_directory = os.path.abspath(os.path.join(script_directory,
+ "..",
+ "template"))
+ template_filename = os.path.join(template_directory, template_basename);
+
+ with open(template_filename, "r") as f:
+ return f.read()
+
+# TODO(kristijanburnik): subdomain_prefix is a hardcoded value aligned with
+# referrer-policy-test-case.js. The prefix should be configured in one place.
+def get_swapped_origin_netloc(netloc, subdomain_prefix = "www1."):
+ if netloc.startswith(subdomain_prefix):
+ return netloc[len(subdomain_prefix):]
+ else:
+ return subdomain_prefix + netloc
+
+def create_redirect_url(request, cross_origin = False):
+ parsed = urlparse.urlsplit(request.url)
+ destination_netloc = parsed.netloc
+ if cross_origin:
+ destination_netloc = get_swapped_origin_netloc(parsed.netloc)
+
+ destination_url = urlparse.urlunsplit(urlparse.SplitResult(
+ scheme = parsed.scheme,
+ netloc = destination_netloc,
+ path = parsed.path,
+ query = None,
+ fragment = None))
+
+ return destination_url
+
+
+def redirect(url, response):
+ response.add_required_headers = False
+ response.writer.write_status(301)
+ response.writer.write_header("access-control-allow-origin", "*")
+ response.writer.write_header("location", url)
+ response.writer.end_headers()
+ response.writer.write("")
+
+
+def preprocess_redirection(request, response):
+ if "redirection" not in request.GET:
+ return False
+
+ redirection = request.GET["redirection"]
+
+ if redirection == "no-redirect":
+ return False
+ elif redirection == "keep-origin-redirect":
+ redirect_url = create_redirect_url(request, cross_origin = False)
+ elif redirection == "swap-origin-redirect":
+ redirect_url = create_redirect_url(request, cross_origin = True)
+ else:
+ raise ValueError("Invalid redirection type '%s'" % redirection)
+
+ redirect(redirect_url, response)
+ return True
+
+
+def __noop(request, response):
+ return ""
+
+
+def respond(request,
+ response,
+ status_code = 200,
+ content_type = "text/html",
+ payload_generator = __noop,
+ cache_control = "no-cache; must-revalidate",
+ access_control_allow_origin = "*"):
+ if preprocess_redirection(request, response):
+ return
+
+ response.add_required_headers = False
+ response.writer.write_status(status_code)
+
+ if access_control_allow_origin != None:
+ response.writer.write_header("access-control-allow-origin",
+ access_control_allow_origin)
+ response.writer.write_header("content-type", content_type)
+ response.writer.write_header("cache-control", cache_control)
+ response.writer.end_headers()
+
+ server_data = {"headers": json.dumps(request.headers, indent = 4)}
+
+ payload = payload_generator(server_data)
+ response.writer.write(payload)
+
+
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource/worker.py b/testing/web-platform/tests/referrer-policy/generic/subresource/worker.py
new file mode 100644
index 000000000..895bc0d84
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource/worker.py
@@ -0,0 +1,12 @@
+import os, sys, json
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+import subresource
+
+def generate_payload(server_data):
+ return subresource.get_template("worker.js.template") % server_data
+
+def main(request, response):
+ subresource.respond(request,
+ response,
+ payload_generator = generate_payload,
+ content_type = "application/javascript")
diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource/xhr.py b/testing/web-platform/tests/referrer-policy/generic/subresource/xhr.py
new file mode 100755
index 000000000..45f38159c
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/subresource/xhr.py
@@ -0,0 +1,15 @@
+import os, sys, json
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+import subresource
+
+def generate_payload(server_data):
+ data = ('{"headers": %(headers)s}') % server_data
+ return data
+
+def main(request, response):
+ subresource.respond(request,
+ response,
+ payload_generator = generate_payload,
+ access_control_allow_origin = "*",
+ content_type = "application/json")
+
diff --git a/testing/web-platform/tests/referrer-policy/generic/template/disclaimer.template b/testing/web-platform/tests/referrer-policy/generic/template/disclaimer.template
new file mode 100644
index 000000000..66c43ed6f
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/template/disclaimer.template
@@ -0,0 +1 @@
+<!-- DO NOT EDIT! Generated by %(generating_script_filename)s using %(html_template_filename)s. -->
diff --git a/testing/web-platform/tests/referrer-policy/generic/template/document.html.template b/testing/web-platform/tests/referrer-policy/generic/template/document.html.template
new file mode 100644
index 000000000..141711c14
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/template/document.html.template
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>This page reports back it's request details to the parent frame</title>
+ </head>
+ <body>
+ <script>
+ var result = {
+ location: document.location.toString(),
+ referrer: document.referrer.length > 0 ? document.referrer : undefined,
+ headers: %(headers)s
+ };
+ parent.postMessage(result, "*");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/template/script.js.template b/testing/web-platform/tests/referrer-policy/generic/template/script.js.template
new file mode 100644
index 000000000..e2edf2181
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/template/script.js.template
@@ -0,0 +1,3 @@
+postMessage({
+ "headers": %(headers)s
+}, "*");
diff --git a/testing/web-platform/tests/referrer-policy/generic/template/spec_json.js.template b/testing/web-platform/tests/referrer-policy/generic/template/spec_json.js.template
new file mode 100644
index 000000000..e4cbd0342
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/template/spec_json.js.template
@@ -0,0 +1 @@
+var SPEC_JSON = %(spec_json)s;
diff --git a/testing/web-platform/tests/referrer-policy/generic/template/test.debug.html.template b/testing/web-platform/tests/referrer-policy/generic/template/test.debug.html.template
new file mode 100644
index 000000000..0faf63bdd
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/template/test.debug.html.template
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+%(generated_disclaimer)s
+<html>
+ <head>
+ <title>Referrer-Policy: %(spec_title)s</title>%(meta_delivery_method)s
+ <meta name="description" content="%(spec_description)s">
+ <meta name="assert" content="%(test_description)s">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Common global functions for referrer-policy tests. -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ <!-- The original specification JSON for validating the scenario. -->
+ <script src="/referrer-policy/spec_json.js"></script>
+ <!-- Internal checking of the tests -->
+ <script src="/referrer-policy/generic/sanity-checker.js"></script>
+ <!-- Simple wrapper API for all referrer-policy test cases. -->
+ <script src="/referrer-policy/generic/referrer-policy-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <h1>%(spec_title)s</h1>
+ <h2>%(spec_description)s</h2>
+
+ <p>
+ <script>
+ // Show the detailed assertion description of the test.
+ document.write(document.querySelector("meta[name=assert]").content);
+ </script>
+ </p>
+
+ <p>See <a href="%(spec_specification_url)s" target="_blank">specification</a>
+ details for this test.</p>
+
+ <h3>Scenario outline</h3>
+ <table>
+ <tbody>
+ <tr>
+ <th>Delivery method</th>
+ <td>%(delivery_method)s</td>
+ </tr>
+ <tr>
+ <th>Redirection</th>
+ <td>%(redirection)s</td>
+ </tr>
+ <tr>
+ <th>Origin transition</th>
+ <td>%(origin)s</td>
+ </tr>
+ <tr>
+ <th>Protocol transition</th>
+ <td>from %(source_protocol)s to %(target_protocol)s</td>
+ </tr>
+ <tr>
+ <th>Subresource type</th>
+ <td>%(subresource)s</td>
+ </tr>
+ <tr>
+ <td colspan="2"><hr></td>
+ </tr>
+ <tr>
+ <th>Expected result</th>
+ <td>Referrer URL should be <strong>%(referrer_url)s</strong></td>
+ </tr>
+ <tbody>
+ </table>
+
+ <script>%(test_js)s</script>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/template/test.js.template b/testing/web-platform/tests/referrer-policy/generic/template/test.js.template
new file mode 100644
index 000000000..4b01d4d11
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/template/test.js.template
@@ -0,0 +1,15 @@
+ReferrerPolicyTestCase(
+ {
+ "referrer_policy": %(referrer_policy_json)s,
+ "delivery_method": "%(delivery_method)s",
+ "redirection": "%(redirection)s",
+ "origin": "%(origin)s",
+ "source_protocol": "%(source_protocol)s",
+ "target_protocol": "%(target_protocol)s",
+ "subresource": "%(subresource)s",
+ "subresource_path": "%(subresource_path)s",
+ "referrer_url": "%(referrer_url)s"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+).start();
diff --git a/testing/web-platform/tests/referrer-policy/generic/template/test.release.html.template b/testing/web-platform/tests/referrer-policy/generic/template/test.release.html.template
new file mode 100644
index 000000000..0d63fd68a
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/template/test.release.html.template
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+%(generated_disclaimer)s
+<html>
+ <head>
+ <title>Referrer-Policy: %(spec_title)s</title>
+ <meta name="description" content="%(spec_description)s">%(meta_delivery_method)s
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="%(spec_specification_url)s">
+ <meta name="assert" content="%(test_description)s">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- TODO(kristijanburnik): Minify and merge both: -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ <script src="/referrer-policy/generic/referrer-policy-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>%(test_js)s</script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/referrer-policy/generic/template/test_description.template b/testing/web-platform/tests/referrer-policy/generic/template/test_description.template
new file mode 100644
index 000000000..fbc80bb25
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/template/test_description.template
@@ -0,0 +1,5 @@
+The referrer URL is %(referrer_url)s when a
+document served over %(source_protocol)s requires an %(target_protocol)s
+sub-resource via %(subresource)s using the %(delivery_method)s
+delivery method with %(redirection)s and when
+the target request is %(origin)s.
diff --git a/testing/web-platform/tests/referrer-policy/generic/template/worker.js.template b/testing/web-platform/tests/referrer-policy/generic/template/worker.js.template
new file mode 100644
index 000000000..817dd8c87
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/template/worker.js.template
@@ -0,0 +1,3 @@
+postMessage({
+ "headers": %(headers)s
+});
diff --git a/testing/web-platform/tests/referrer-policy/generic/tools/__init__.py b/testing/web-platform/tests/referrer-policy/generic/tools/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/tools/__init__.py
diff --git a/testing/web-platform/tests/referrer-policy/generic/tools/clean.py b/testing/web-platform/tests/referrer-policy/generic/tools/clean.py
new file mode 100755
index 000000000..715e1d6ae
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/tools/clean.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+import os, json
+from common_paths import *
+import spec_validator
+
+def rmtree(top):
+ top = os.path.abspath(top)
+ assert top != os.path.expanduser("~")
+ assert len(top) > len(os.path.expanduser("~"))
+ assert "web-platform-tests" in top
+ assert "referrer-policy" in top
+
+ for root, dirs, files in os.walk(top, topdown=False):
+ for name in files:
+ os.remove(os.path.join(root, name))
+ for name in dirs:
+ os.rmdir(os.path.join(root, name))
+
+ os.rmdir(top)
+
+def main():
+ spec_json = load_spec_json();
+ spec_validator.assert_valid_spec_json(spec_json)
+
+ for spec in spec_json['specification']:
+ generated_dir = os.path.join(spec_directory, spec["name"])
+ if (os.path.isdir(generated_dir)):
+ rmtree(generated_dir)
+
+ if (os.path.isfile(generated_spec_json_filename)):
+ os.remove(generated_spec_json_filename)
+
+if __name__ == '__main__':
+ main()
diff --git a/testing/web-platform/tests/referrer-policy/generic/tools/common_paths.py b/testing/web-platform/tests/referrer-policy/generic/tools/common_paths.py
new file mode 100644
index 000000000..dc303f3c1
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/tools/common_paths.py
@@ -0,0 +1,52 @@
+import os, sys, json, re
+
+script_directory = os.path.dirname(os.path.abspath(__file__))
+generic_directory = os.path.abspath(os.path.join(script_directory, '..'))
+
+template_directory = os.path.abspath(os.path.join(script_directory,
+ '..',
+ 'template'))
+spec_directory = os.path.abspath(os.path.join(script_directory, '..', '..'))
+test_root_directory = os.path.abspath(os.path.join(script_directory,
+ '..', '..', '..'))
+
+spec_filename = os.path.join(spec_directory, "spec.src.json")
+generated_spec_json_filename = os.path.join(spec_directory, "spec_json.js")
+
+selection_pattern = '%(delivery_method)s/' + \
+ '%(origin)s/' + \
+ '%(source_protocol)s-%(target_protocol)s/' + \
+ '%(subresource)s/'
+
+test_file_path_pattern = '%(spec_name)s/' + selection_pattern + \
+ '%(name)s.%(redirection)s.%(source_protocol)s.html'
+
+
+def get_template(basename):
+ with open(os.path.join(template_directory, basename), "r") as f:
+ return f.read()
+
+
+def read_nth_line(fp, line_number):
+ fp.seek(0)
+ for i, line in enumerate(fp):
+ if (i + 1) == line_number:
+ return line
+
+
+def load_spec_json():
+ re_error_location = re.compile('line ([0-9]+) column ([0-9]+)')
+ with open(spec_filename, "r") as f:
+ try:
+ spec_json = json.load(f)
+ except ValueError, ex:
+ print ex.message
+ match = re_error_location.search(ex.message)
+ if match:
+ line_number, column = int(match.group(1)), int(match.group(2))
+ print read_nth_line(f, line_number).rstrip()
+ print " " * (column - 1) + "^"
+
+ sys.exit(1)
+
+ return spec_json
diff --git a/testing/web-platform/tests/referrer-policy/generic/tools/generate.py b/testing/web-platform/tests/referrer-policy/generic/tools/generate.py
new file mode 100755
index 000000000..10fc11c4f
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/tools/generate.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+
+import os, sys, json
+from common_paths import *
+import spec_validator
+import argparse
+
+
+def expand_test_expansion_pattern(spec_test_expansion, test_expansion_schema):
+ expansion = {}
+ for artifact in spec_test_expansion:
+ artifact_value = spec_test_expansion[artifact]
+ if artifact_value == '*':
+ expansion[artifact] = test_expansion_schema[artifact]
+ elif isinstance(artifact_value, list):
+ expansion[artifact] = artifact_value
+ else:
+ expansion[artifact] = [artifact_value]
+
+ return expansion
+
+
+def permute_expansion(expansion, selection = {}, artifact_index = 0):
+ artifact_order = ['delivery_method', 'redirection', 'origin',
+ 'source_protocol', 'target_protocol', 'subresource',
+ 'referrer_url', 'name']
+
+ if artifact_index >= len(artifact_order):
+ yield selection
+ return
+
+ artifact_key = artifact_order[artifact_index]
+
+ for artifact_value in expansion[artifact_key]:
+ selection[artifact_key] = artifact_value
+ for next_selection in permute_expansion(expansion,
+ selection,
+ artifact_index + 1):
+ yield next_selection
+
+
+def generate_selection(selection, spec, subresource_path,
+ test_html_template_basename):
+ selection['spec_name'] = spec['name']
+ selection['spec_title'] = spec['title']
+ selection['spec_description'] = spec['description']
+ selection['spec_specification_url'] = spec['specification_url']
+ selection['subresource_path'] = subresource_path
+ # Oddball: it can be None, so in JS it's null.
+ selection['referrer_policy_json'] = json.dumps(spec['referrer_policy'])
+
+ test_filename = test_file_path_pattern % selection
+ test_directory = os.path.dirname(test_filename)
+ full_path = os.path.join(spec_directory, test_directory)
+
+ test_html_template = get_template(test_html_template_basename)
+ test_js_template = get_template("test.js.template")
+ disclaimer_template = get_template('disclaimer.template')
+ test_description_template = get_template("test_description.template")
+
+ html_template_filename = os.path.join(template_directory,
+ test_html_template_basename)
+ generated_disclaimer = disclaimer_template \
+ % {'generating_script_filename': os.path.relpath(__file__,
+ test_root_directory),
+ 'html_template_filename': os.path.relpath(html_template_filename,
+ test_root_directory)}
+
+ # Adjust the template for the test invoking JS. Indent it to look nice.
+ selection['generated_disclaimer'] = generated_disclaimer.rstrip()
+ test_description_template = \
+ test_description_template.rstrip().replace("\n", "\n" + " " * 33)
+ selection['test_description'] = test_description_template % selection
+
+ # Adjust the template for the test invoking JS. Indent it to look nice.
+ indent = "\n" + " " * 6;
+ test_js_template = indent + test_js_template.replace("\n", indent);
+ selection['test_js'] = test_js_template % selection
+
+ # Directory for the test files.
+ try:
+ os.makedirs(full_path)
+ except:
+ pass
+
+ selection['meta_delivery_method'] = ''
+
+ if spec['referrer_policy'] != None:
+ if selection['delivery_method'] == 'meta-referrer':
+ selection['meta_delivery_method'] = \
+ '<meta name="referrer" content="%(referrer_policy)s">' % spec
+ elif selection['delivery_method'] == 'http-rp':
+ selection['meta_delivery_method'] = \
+ "<!-- No meta: Referrer policy delivered via HTTP headers. -->"
+ test_headers_filename = test_filename + ".headers"
+ with open(test_headers_filename, "w") as f:
+ f.write('Referrer-Policy: ' + \
+ '%(referrer_policy)s\n' % spec)
+ # TODO(kristijanburnik): Limit to WPT origins.
+ f.write('Access-Control-Allow-Origin: *\n')
+ elif selection['delivery_method'] == 'attr-referrer':
+ # attr-referrer is supported by the JS test wrapper.
+ pass
+ elif selection['delivery_method'] == 'rel-noreferrer':
+ # rel=noreferrer is supported by the JS test wrapper.
+ pass
+ else:
+ raise ValueError('Not implemented delivery_method: ' \
+ + selection['delivery_method'])
+
+ # Obey the lint and pretty format.
+ if len(selection['meta_delivery_method']) > 0:
+ selection['meta_delivery_method'] = "\n " + \
+ selection['meta_delivery_method']
+
+ with open(test_filename, 'w') as f:
+ f.write(test_html_template % selection)
+
+
+def generate_test_source_files(spec_json, target):
+ test_expansion_schema = spec_json['test_expansion_schema']
+ specification = spec_json['specification']
+
+ spec_json_js_template = get_template('spec_json.js.template')
+ with open(generated_spec_json_filename, 'w') as f:
+ f.write(spec_json_js_template
+ % {'spec_json': json.dumps(spec_json)})
+
+ # Choose a debug/release template depending on the target.
+ html_template = "test.%s.html.template" % target
+
+ # Create list of excluded tests.
+ exclusion_dict = {}
+ for excluded_pattern in spec_json['excluded_tests']:
+ excluded_expansion = \
+ expand_test_expansion_pattern(excluded_pattern,
+ test_expansion_schema)
+ for excluded_selection in permute_expansion(excluded_expansion):
+ excluded_selection_path = selection_pattern % excluded_selection
+ exclusion_dict[excluded_selection_path] = True
+
+ for spec in specification:
+ for spec_test_expansion in spec['test_expansion']:
+ expansion = expand_test_expansion_pattern(spec_test_expansion,
+ test_expansion_schema)
+ for selection in permute_expansion(expansion):
+ selection_path = selection_pattern % selection
+ if not selection_path in exclusion_dict:
+ subresource_path = \
+ spec_json["subresource_path"][selection["subresource"]]
+ generate_selection(selection,
+ spec,
+ subresource_path,
+ html_template)
+ else:
+ print 'Excluding selection:', selection_path
+
+
+def main(target):
+ spec_json = load_spec_json();
+ spec_validator.assert_valid_spec_json(spec_json)
+ generate_test_source_files(spec_json, target)
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Test suite generator utility')
+ parser.add_argument('-t', '--target', type = str,
+ choices = ("release", "debug"), default = "release",
+ help = 'Sets the appropriate template for generating tests')
+ # TODO(kristijanburnik): Add option for the spec_json file.
+ args = parser.parse_args()
+ main(args.target)
diff --git a/testing/web-platform/tests/referrer-policy/generic/tools/regenerate b/testing/web-platform/tests/referrer-policy/generic/tools/regenerate
new file mode 100755
index 000000000..e6bd63519
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/tools/regenerate
@@ -0,0 +1,3 @@
+#!/bin/bash
+DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+python $DIR/clean.py && python $DIR/generate.py
diff --git a/testing/web-platform/tests/referrer-policy/generic/tools/spec_validator.py b/testing/web-platform/tests/referrer-policy/generic/tools/spec_validator.py
new file mode 100755
index 000000000..8641bbc1f
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/tools/spec_validator.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+
+import json, sys
+from common_paths import *
+
+def assert_non_empty_string(obj, field):
+ assert field in obj, 'Missing field "%s"' % field
+ assert isinstance(obj[field], basestring), \
+ 'Field "%s" must be a string' % field
+ assert len(obj[field]) > 0, 'Field "%s" must not be empty' % field
+
+def assert_non_empty_list(obj, field):
+ assert isinstance(obj[field], list), \
+ '%s must be a list' % field
+ assert len(obj[field]) > 0, \
+ '%s list must not be empty' % field
+
+def assert_non_empty_dict(obj, field):
+ assert isinstance(obj[field], dict), \
+ '%s must be a dict' % field
+ assert len(obj[field]) > 0, \
+ '%s dict must not be empty' % field
+
+def assert_contains(obj, field):
+ assert field in obj, 'Must contain field "%s"' % field
+
+def assert_value_from(obj, field, items):
+ assert obj[field] in items, \
+ 'Field "%s" must be from: %s' % (field, str(items))
+
+def assert_atom_or_list_items_from(obj, field, items):
+ if isinstance(obj[field], basestring) or isinstance(obj[field], int):
+ assert_value_from(obj, field, items)
+ return
+
+ assert_non_empty_list(obj, field)
+ for allowed_value in obj[field]:
+ assert allowed_value != '*', "Wildcard is not supported for lists!"
+ assert allowed_value in items, \
+ 'Field "%s" must be from: %s' % (field, str(items))
+
+def assert_contains_only_fields(obj, expected_fields):
+ for expected_field in expected_fields:
+ assert_contains(obj, expected_field)
+
+ for actual_field in obj:
+ assert actual_field in expected_fields, \
+ 'Unexpected field "%s".' % actual_field
+
+def assert_value_unique_in(value, used_values):
+ assert value not in used_values, 'Duplicate value "%s"!' % str(value)
+ used_values[value] = True
+
+
+def validate(spec_json, details):
+ """ Validates the json specification for generating tests. """
+
+ details['object'] = spec_json
+ assert_contains_only_fields(spec_json, ["specification",
+ "referrer_policy_schema",
+ "test_expansion_schema",
+ "subresource_path",
+ "excluded_tests"])
+ assert_non_empty_list(spec_json, "specification")
+ assert_non_empty_list(spec_json, "referrer_policy_schema")
+ assert_non_empty_dict(spec_json, "test_expansion_schema")
+ assert_non_empty_list(spec_json, "excluded_tests")
+
+ specification = spec_json['specification']
+ referrer_policy_schema = spec_json['referrer_policy_schema']
+ test_expansion_schema = spec_json['test_expansion_schema']
+ excluded_tests = spec_json['excluded_tests']
+ subresource_path = spec_json['subresource_path']
+
+ valid_test_expansion_fields = ['name'] + test_expansion_schema.keys()
+
+ # Validate each single spec.
+ for spec in specification:
+ details['object'] = spec
+
+ # Validate required fields for a single spec.
+ assert_contains_only_fields(spec, ['name',
+ 'title',
+ 'description',
+ 'referrer_policy',
+ 'specification_url',
+ 'test_expansion'])
+ assert_non_empty_string(spec, 'name')
+ assert_non_empty_string(spec, 'title')
+ assert_non_empty_string(spec, 'description')
+ assert_non_empty_string(spec, 'specification_url')
+ assert_value_from(spec, 'referrer_policy', referrer_policy_schema)
+ assert_non_empty_list(spec, 'test_expansion')
+
+ # Validate spec's test expansion.
+ used_spec_names = {}
+
+ for spec_exp in spec['test_expansion']:
+ details['object'] = spec_exp
+ assert_non_empty_string(spec_exp, 'name')
+ # The name is unique in same expansion group.
+ assert_value_unique_in((spec_exp['expansion'], spec_exp['name']),
+ used_spec_names)
+ assert_contains_only_fields(spec_exp, valid_test_expansion_fields)
+
+ for artifact in test_expansion_schema:
+ details['test_expansion_field'] = artifact
+ assert_atom_or_list_items_from(
+ spec_exp, artifact, ['*'] + test_expansion_schema[artifact])
+ del details['test_expansion_field']
+
+ # Validate the test_expansion schema members.
+ details['object'] = test_expansion_schema
+ assert_contains_only_fields(test_expansion_schema, ['expansion',
+ 'delivery_method',
+ 'redirection',
+ 'origin',
+ 'source_protocol',
+ 'target_protocol',
+ 'subresource',
+ 'referrer_url'])
+ # Validate excluded tests.
+ details['object'] = excluded_tests
+ for excluded_test_expansion in excluded_tests:
+ assert_contains_only_fields(excluded_test_expansion,
+ valid_test_expansion_fields)
+ details['object'] = excluded_test_expansion
+ for artifact in test_expansion_schema:
+ details['test_expansion_field'] = artifact
+ assert_atom_or_list_items_from(
+ excluded_test_expansion,
+ artifact,
+ ['*'] + test_expansion_schema[artifact])
+ del details['test_expansion_field']
+
+ # Validate subresource paths.
+ details['object'] = subresource_path
+ assert_contains_only_fields(subresource_path,
+ test_expansion_schema['subresource']);
+
+ for subresource in subresource_path:
+ local_rel_path = "." + subresource_path[subresource]
+ full_path = os.path.join(test_root_directory, local_rel_path)
+ assert os.path.isfile(full_path), "%s is not an existing file" % path
+
+ del details['object']
+
+
+def assert_valid_spec_json(spec_json):
+ error_details = {}
+ try:
+ validate(spec_json, error_details)
+ except AssertionError, err:
+ print 'ERROR:', err.message
+ print json.dumps(error_details, indent=4)
+ sys.exit(1)
+
+
+def main():
+ spec_json = load_spec_json();
+ assert_valid_spec_json(spec_json)
+ print "Spec JSON is valid."
+
+
+if __name__ == '__main__':
+ main()
diff --git a/testing/web-platform/tests/referrer-policy/generic/unsupported-csp-referrer-directive.html b/testing/web-platform/tests/referrer-policy/generic/unsupported-csp-referrer-directive.html
new file mode 100644
index 000000000..a40dded44
--- /dev/null
+++ b/testing/web-platform/tests/referrer-policy/generic/unsupported-csp-referrer-directive.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Referrer Policy: CSP 'referrer' directive should not be supported</title>
+ <meta http-equiv="Content-Security-Policy" content="referrer no-referrer">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Common global functions for referrer-policy tests. -->
+ <script src="/referrer-policy/generic/common.js"></script>
+ </head>
+ <body>
+ <h1>Referrer Policy: CSP 'referrer' directive should not be supported</h1>
+ <p>CSP used to have a 'referrer' directive to set a Referrer Policy. This directive has been removed and should not be supported.</p>
+
+ <pre id="received_message">Running...</pre>
+
+ <script>
+ var test = async_test("Image has a referrer despite CSP 'referrer' directive");
+ var urlPath = '/referrer-policy/generic/subresource/image.py';
+ var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+ urlPath;
+ queryImage(url, test.step_func(function(message) {
+ assert_equals(message.referrer, document.location.href);
+ test.done();
+ }));
+ </script>
+
+ <div id="log"></div>
+ </body>
+</html>