summaryrefslogtreecommitdiffstats
path: root/dom/security/test/referrer-policy
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /dom/security/test/referrer-policy
parentInitial commit. (diff)
downloadfirefox-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/security/test/referrer-policy')
-rw-r--r--dom/security/test/referrer-policy/browser.toml9
-rw-r--r--dom/security/test/referrer-policy/browser_fragment_navigation.js42
-rw-r--r--dom/security/test/referrer-policy/browser_referrer_disallow_cross_site_relaxing.js458
-rw-r--r--dom/security/test/referrer-policy/browser_referrer_telemetry.js126
-rw-r--r--dom/security/test/referrer-policy/file_fragment_navigation.sjs21
-rw-r--r--dom/security/test/referrer-policy/img_referrer_testserver.sjs337
-rw-r--r--dom/security/test/referrer-policy/mochitest.toml28
-rw-r--r--dom/security/test/referrer-policy/referrer_header.sjs6
-rw-r--r--dom/security/test/referrer-policy/referrer_header_current_document_iframe.html12
-rw-r--r--dom/security/test/referrer-policy/referrer_helper.js129
-rw-r--r--dom/security/test/referrer-policy/referrer_page.sjs39
-rw-r--r--dom/security/test/referrer-policy/referrer_testserver.sjs704
-rw-r--r--dom/security/test/referrer-policy/test_img_referrer.html190
-rw-r--r--dom/security/test/referrer-policy/test_referrer_header_current_document.html35
-rw-r--r--dom/security/test/referrer-policy/test_referrer_redirect.html171
15 files changed, 2307 insertions, 0 deletions
diff --git a/dom/security/test/referrer-policy/browser.toml b/dom/security/test/referrer-policy/browser.toml
new file mode 100644
index 0000000000..325b6a3f49
--- /dev/null
+++ b/dom/security/test/referrer-policy/browser.toml
@@ -0,0 +1,9 @@
+[DEFAULT]
+support-files = ["referrer_page.sjs"]
+
+["browser_fragment_navigation.js"]
+support-files = ["file_fragment_navigation.sjs"]
+
+["browser_referrer_disallow_cross_site_relaxing.js"]
+
+["browser_referrer_telemetry.js"]
diff --git a/dom/security/test/referrer-policy/browser_fragment_navigation.js b/dom/security/test/referrer-policy/browser_fragment_navigation.js
new file mode 100644
index 0000000000..c3d5e62854
--- /dev/null
+++ b/dom/security/test/referrer-policy/browser_fragment_navigation.js
@@ -0,0 +1,42 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_FILE =
+ "https://example.com/browser/dom/security/test/referrer-policy/file_fragment_navigation.sjs";
+
+add_task(async function test_browser_navigation() {
+ await BrowserTestUtils.withNewTab(TEST_FILE, async browser => {
+ let loadPromise = BrowserTestUtils.browserLoaded(browser);
+ await SpecialPowers.spawn(browser, [], () => {
+ ok(content.document.getElementById("ok"), "Initial page should load");
+
+ info("Clicking on link to check referrer");
+ content.document.getElementById("check_referrer").click();
+ });
+ await loadPromise;
+
+ await SpecialPowers.spawn(browser, [], () => {
+ ok(
+ content.document.getElementById("ok"),
+ "Page should load when checking referrer"
+ );
+
+ info("Clicking on fragment link");
+ content.document.getElementById("fragment").click();
+ });
+
+ info("Reloading tab");
+ loadPromise = BrowserTestUtils.browserLoaded(browser);
+ await BrowserTestUtils.reloadTab(gBrowser.selectedTab);
+ await loadPromise;
+
+ await SpecialPowers.spawn(browser, [], () => {
+ ok(
+ content.document.getElementById("ok"),
+ "Page should load when checking referrer after fragment navigation and reload"
+ );
+ });
+ });
+});
diff --git a/dom/security/test/referrer-policy/browser_referrer_disallow_cross_site_relaxing.js b/dom/security/test/referrer-policy/browser_referrer_disallow_cross_site_relaxing.js
new file mode 100644
index 0000000000..7f8df7b34b
--- /dev/null
+++ b/dom/security/test/referrer-policy/browser_referrer_disallow_cross_site_relaxing.js
@@ -0,0 +1,458 @@
+/**
+ * Bug 1720294 - Testing disallow relaxing default referrer policy for
+ * cross-site requests.
+ */
+
+"use strict";
+
+requestLongerTimeout(6);
+
+const TEST_DOMAIN = "https://example.com/";
+const TEST_SAME_SITE_DOMAIN = "https://test1.example.com/";
+const TEST_SAME_SITE_DOMAIN_HTTP = "http://test1.example.com/";
+const TEST_CROSS_SITE_DOMAIN = "https://test1.example.org/";
+const TEST_CROSS_SITE_DOMAIN_HTTP = "http://test1.example.org/";
+
+const TEST_PATH = "browser/dom/security/test/referrer-policy/";
+
+const TEST_PAGE = `${TEST_DOMAIN}${TEST_PATH}referrer_page.sjs`;
+const TEST_SAME_SITE_PAGE = `${TEST_SAME_SITE_DOMAIN}${TEST_PATH}referrer_page.sjs`;
+const TEST_SAME_SITE_PAGE_HTTP = `${TEST_SAME_SITE_DOMAIN_HTTP}${TEST_PATH}referrer_page.sjs`;
+const TEST_CROSS_SITE_PAGE = `${TEST_CROSS_SITE_DOMAIN}${TEST_PATH}referrer_page.sjs`;
+const TEST_CROSS_SITE_PAGE_HTTP = `${TEST_CROSS_SITE_DOMAIN_HTTP}${TEST_PATH}referrer_page.sjs`;
+
+const REFERRER_FULL = 0;
+const REFERRER_ORIGIN = 1;
+const REFERRER_NONE = 2;
+
+function getExpectedReferrer(referrer, type) {
+ let res;
+
+ switch (type) {
+ case REFERRER_FULL:
+ res = referrer;
+ break;
+ case REFERRER_ORIGIN:
+ let url = new URL(referrer);
+ res = `${url.origin}/`;
+ break;
+ case REFERRER_NONE:
+ res = "";
+ break;
+ default:
+ ok(false, "unknown type");
+ }
+
+ return res;
+}
+
+async function verifyResultInPage(browser, expected) {
+ await SpecialPowers.spawn(browser, [expected], value => {
+ is(content.document.referrer, value, "The document.referrer is correct.");
+
+ let result = content.document.getElementById("result");
+ is(result.textContent, value, "The referer header is correct");
+ });
+}
+
+function getExpectedConsoleMessage(expected, isPrefOn, url) {
+ let msg;
+
+ if (isPrefOn) {
+ msg =
+ "Referrer Policy: Ignoring the less restricted referrer policy “" +
+ expected +
+ "” for the cross-site request: " +
+ url;
+ } else {
+ msg =
+ "Referrer Policy: Less restricted policies, including " +
+ "‘no-referrer-when-downgrade’, ‘origin-when-cross-origin’ and " +
+ "‘unsafe-url’, will be ignored soon for the cross-site request: " +
+ url;
+ }
+
+ return msg;
+}
+
+function createConsoleMessageVerificationPromise(expected, isPrefOn, url) {
+ if (!expected) {
+ return Promise.resolve();
+ }
+
+ return new Promise(resolve => {
+ let listener = {
+ observe(msg) {
+ let message = msg.QueryInterface(Ci.nsIScriptError);
+
+ if (message.category.startsWith("Security")) {
+ is(
+ message.errorMessage,
+ getExpectedConsoleMessage(expected, isPrefOn, url),
+ "The console message is correct."
+ );
+ Services.console.unregisterListener(listener);
+ resolve();
+ }
+ },
+ };
+
+ Services.console.registerListener(listener);
+ });
+}
+
+function verifyNoConsoleMessage() {
+ // Verify that there is no referrer policy console message.
+ let allMessages = Services.console.getMessageArray();
+
+ for (let msg of allMessages) {
+ let message = msg.QueryInterface(Ci.nsIScriptError);
+ if (
+ message.category.startsWith("Security") &&
+ message.errorMessage.startsWith("Referrer Policy:")
+ ) {
+ ok(false, "There should be no console message for referrer policy.");
+ }
+ }
+}
+
+const TEST_CASES = [
+ // Testing that the referrer policy can be overridden with less restricted
+ // policy in the same-origin scenario.
+ {
+ policy: "unsafe-url",
+ referrer: TEST_PAGE,
+ test_url: TEST_PAGE,
+ expect: REFERRER_FULL,
+ original: REFERRER_FULL,
+ },
+ // Testing that the referrer policy can be overridden with less restricted
+ // policy in the same-site scenario.
+ {
+ policy: "unsafe-url",
+ referrer: TEST_PAGE,
+ test_url: TEST_SAME_SITE_PAGE,
+ expect: REFERRER_FULL,
+ original: REFERRER_FULL,
+ },
+ {
+ policy: "no-referrer-when-downgrade",
+ referrer: TEST_PAGE,
+ test_url: TEST_SAME_SITE_PAGE,
+ expect: REFERRER_FULL,
+ original: REFERRER_FULL,
+ },
+ {
+ policy: "origin-when-cross-origin",
+ referrer: TEST_PAGE,
+ test_url: TEST_SAME_SITE_PAGE_HTTP,
+ expect: REFERRER_ORIGIN,
+ original: REFERRER_ORIGIN,
+ },
+ // Testing that the referrer policy cannot be overridden with less restricted
+ // policy in the cross-site scenario.
+ {
+ policy: "unsafe-url",
+ referrer: TEST_PAGE,
+ test_url: TEST_CROSS_SITE_PAGE,
+ expect: REFERRER_ORIGIN,
+ expect_console: "unsafe-url",
+ original: REFERRER_FULL,
+ },
+ {
+ policy: "no-referrer-when-downgrade",
+ referrer: TEST_PAGE,
+ test_url: TEST_CROSS_SITE_PAGE,
+ expect: REFERRER_ORIGIN,
+ expect_console: "no-referrer-when-downgrade",
+ original: REFERRER_FULL,
+ },
+ {
+ policy: "origin-when-cross-origin",
+ referrer: TEST_PAGE,
+ test_url: TEST_CROSS_SITE_PAGE_HTTP,
+ expect: REFERRER_NONE,
+ expect_console: "origin-when-cross-origin",
+ original: REFERRER_ORIGIN,
+ },
+ // Testing that the referrer policy can still be overridden with more
+ // restricted policy in the cross-site scenario.
+ {
+ policy: "no-referrer",
+ referrer: TEST_PAGE,
+ test_url: TEST_CROSS_SITE_PAGE,
+ expect: REFERRER_NONE,
+ original: REFERRER_NONE,
+ },
+];
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ // Disable mixed content blocking to be able to test downgrade scenario.
+ ["security.mixed_content.block_active_content", false],
+ ],
+ });
+});
+
+async function runTestIniFrame(gBrowser, enabled, expectNoConsole) {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async browser => {
+ for (let type of ["meta", "header"]) {
+ for (let test of TEST_CASES) {
+ info(`Test iframe: ${test.toSource()}`);
+ let referrerURL = `${test.referrer}?${type}=${test.policy}`;
+ let expected = enabled
+ ? getExpectedReferrer(referrerURL, test.expect)
+ : getExpectedReferrer(referrerURL, test.original);
+
+ let expected_console = expectNoConsole
+ ? undefined
+ : test.expect_console;
+
+ Services.console.reset();
+
+ BrowserTestUtils.startLoadingURIString(browser, referrerURL);
+ await BrowserTestUtils.browserLoaded(browser, false, referrerURL);
+
+ let iframeURL = test.test_url + "?show";
+
+ let consolePromise = createConsoleMessageVerificationPromise(
+ expected_console,
+ enabled,
+ iframeURL
+ );
+ // Create an iframe and load the url.
+ let bc = await SpecialPowers.spawn(
+ browser,
+ [iframeURL],
+ async url => {
+ let iframe = content.document.createElement("iframe");
+ let loadPromise = ContentTaskUtils.waitForEvent(iframe, "load");
+ iframe.src = url;
+ content.document.body.appendChild(iframe);
+
+ await loadPromise;
+
+ return iframe.browsingContext;
+ }
+ );
+
+ await verifyResultInPage(bc, expected);
+ await consolePromise;
+ if (!expected_console) {
+ verifyNoConsoleMessage();
+ }
+ }
+ }
+ }
+ );
+}
+
+async function runTestForLinkClick(gBrowser, enabled, expectNoConsole) {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async browser => {
+ for (let type of ["meta", "header"]) {
+ for (let test of TEST_CASES) {
+ info(`Test link click: ${test.toSource()}`);
+ let referrerURL = `${test.referrer}?${type}=${test.policy}`;
+ let expected = enabled
+ ? getExpectedReferrer(referrerURL, test.expect)
+ : getExpectedReferrer(referrerURL, test.original);
+
+ let expected_console = expectNoConsole
+ ? undefined
+ : test.expect_console;
+
+ Services.console.reset();
+
+ BrowserTestUtils.startLoadingURIString(browser, referrerURL);
+ await BrowserTestUtils.browserLoaded(browser, false, referrerURL);
+
+ let linkURL = test.test_url + "?show";
+
+ let consolePromise = createConsoleMessageVerificationPromise(
+ expected_console,
+ enabled,
+ linkURL
+ );
+
+ // Create the promise to wait for the navigation finishes.
+ let loadedPromise = BrowserTestUtils.browserLoaded(
+ browser,
+ false,
+ linkURL
+ );
+
+ // Generate the link and click it to navigate.
+ await SpecialPowers.spawn(browser, [linkURL], async url => {
+ let link = content.document.createElement("a");
+ link.textContent = "Link";
+ link.setAttribute("href", url);
+
+ content.document.body.appendChild(link);
+ link.click();
+ });
+
+ await loadedPromise;
+
+ await verifyResultInPage(browser, expected);
+ await consolePromise;
+ if (!expected_console) {
+ verifyNoConsoleMessage();
+ }
+ }
+ }
+ }
+ );
+}
+
+async function toggleETPForPage(gBrowser, url, toggle) {
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+
+ // First, Toggle ETP off for the test page.
+ let browserLoadedPromise = BrowserTestUtils.browserLoaded(
+ tab.linkedBrowser,
+ false,
+ url
+ );
+
+ if (toggle) {
+ gProtectionsHandler.enableForCurrentPage();
+ } else {
+ gProtectionsHandler.disableForCurrentPage();
+ }
+
+ await browserLoadedPromise;
+ BrowserTestUtils.removeTab(tab);
+}
+
+add_task(async function test_iframe() {
+ for (let enabled of [true, false]) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["network.http.referer.disallowCrossSiteRelaxingDefault", enabled]],
+ });
+
+ await runTestIniFrame(gBrowser, enabled);
+ }
+});
+
+add_task(async function test_iframe_pbmode() {
+ let win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
+
+ for (let enabled of [true, false]) {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [
+ "network.http.referer.disallowCrossSiteRelaxingDefault.pbmode",
+ enabled,
+ ],
+ ],
+ });
+
+ await runTestIniFrame(win.gBrowser, enabled);
+ }
+
+ await BrowserTestUtils.closeWindow(win);
+});
+
+add_task(async function test_link_click() {
+ for (let enabled of [true, false]) {
+ for (let enabled_top of [true, false]) {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["network.http.referer.disallowCrossSiteRelaxingDefault", enabled],
+ [
+ "network.http.referer.disallowCrossSiteRelaxingDefault.top_navigation",
+ enabled_top,
+ ],
+ ],
+ });
+
+ // We won't show the console message if the strict rule is disabled for
+ // the top navigation.
+ await runTestForLinkClick(gBrowser, enabled && enabled_top, !enabled_top);
+ }
+ }
+});
+
+add_task(async function test_link_click_pbmode() {
+ let win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
+
+ for (let enabled of [true, false]) {
+ for (let enabled_top of [true, false]) {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [
+ "network.http.referer.disallowCrossSiteRelaxingDefault.pbmode",
+ enabled,
+ ],
+ [
+ "network.http.referer.disallowCrossSiteRelaxingDefault.pbmode.top_navigation",
+ enabled_top,
+ ],
+ // Disable https first mode for private browsing mode to test downgrade
+ // cases.
+ ["dom.security.https_first_pbm", false],
+ ],
+ });
+
+ // We won't show the console message if the strict rule is disabled for
+ // the top navigation in the private browsing window.
+ await runTestForLinkClick(
+ win.gBrowser,
+ enabled && enabled_top,
+ !enabled_top
+ );
+ }
+ }
+
+ await BrowserTestUtils.closeWindow(win);
+});
+
+add_task(async function test_iframe_etp_toggle_off() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["network.http.referer.disallowCrossSiteRelaxingDefault", true]],
+ });
+
+ // Open a new tab for the test page and toggle ETP off.
+ await toggleETPForPage(gBrowser, TEST_PAGE, false);
+
+ // Run the test to see if the protection is disabled. We won't send console
+ // message if the protection was disabled by the ETP toggle.
+ await runTestIniFrame(gBrowser, false, true);
+
+ // toggle ETP on again.
+ await toggleETPForPage(gBrowser, TEST_PAGE, true);
+
+ // Run the test again to see if the protection is enabled.
+ await runTestIniFrame(gBrowser, true);
+});
+
+add_task(async function test_link_click_etp_toggle_off() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["network.http.referer.disallowCrossSiteRelaxingDefault", true],
+ [
+ "network.http.referer.disallowCrossSiteRelaxingDefault.top_navigation",
+ true,
+ ],
+ ],
+ });
+
+ // Toggle ETP off for the cross site. Note that the cross site is the place
+ // where we test against the ETP permission for top navigation.
+ await toggleETPForPage(gBrowser, TEST_CROSS_SITE_PAGE, false);
+
+ // Run the test to see if the protection is disabled. We won't send console
+ // message if the protection was disabled by the ETP toggle.
+ await runTestForLinkClick(gBrowser, false, true);
+
+ // toggle ETP on again.
+ await toggleETPForPage(gBrowser, TEST_CROSS_SITE_PAGE, true);
+
+ // Run the test again to see if the protection is enabled.
+ await runTestForLinkClick(gBrowser, true);
+});
diff --git a/dom/security/test/referrer-policy/browser_referrer_telemetry.js b/dom/security/test/referrer-policy/browser_referrer_telemetry.js
new file mode 100644
index 0000000000..7542dd9338
--- /dev/null
+++ b/dom/security/test/referrer-policy/browser_referrer_telemetry.js
@@ -0,0 +1,126 @@
+/**
+ * Bug 1720869 - Testing the referrer policy telemetry.
+ */
+
+"use strict";
+
+const TEST_DOMAIN = "https://example.com/";
+const TEST_CROSS_SITE_DOMAIN = "https://test1.example.org/";
+
+const TEST_PATH = "browser/dom/security/test/referrer-policy/";
+
+const TEST_PAGE = `${TEST_DOMAIN}${TEST_PATH}referrer_page.sjs`;
+const TEST_CROSS_SITE_PAGE = `${TEST_CROSS_SITE_DOMAIN}${TEST_PATH}referrer_page.sjs`;
+
+// This matches to the order in ReferrerPolicy.webidl
+const REFERRER_POLICY_INDEX = {
+ empty: 0,
+ "no-referrer": 1,
+ "no-referrer-when-downgrade": 2,
+ origin: 3,
+ "origin-when-cross-origin": 4,
+ "unsafe-url": 5,
+ "same-origin": 6,
+ "strict-origin": 7,
+ "strict-origin-when-cross-origin": 8,
+};
+
+const TEST_CASES = [
+ {
+ policy: "",
+ expected: REFERRER_POLICY_INDEX.empty,
+ },
+ {
+ policy: "no-referrer",
+ expected: REFERRER_POLICY_INDEX["no-referrer"],
+ },
+ {
+ policy: "no-referrer-when-downgrade",
+ expected: REFERRER_POLICY_INDEX["no-referrer-when-downgrade"],
+ },
+ {
+ policy: "origin",
+ expected: REFERRER_POLICY_INDEX.origin,
+ },
+ {
+ policy: "origin-when-cross-origin",
+ expected: REFERRER_POLICY_INDEX["origin-when-cross-origin"],
+ },
+ {
+ policy: "same-origin",
+ expected: REFERRER_POLICY_INDEX["same-origin"],
+ },
+ {
+ policy: "strict-origin",
+ expected: REFERRER_POLICY_INDEX["strict-origin"],
+ },
+ {
+ policy: "strict-origin-when-cross-origin",
+ expected: REFERRER_POLICY_INDEX["strict-origin-when-cross-origin"],
+ },
+ {
+ policy: "unsafe-url",
+ expected: REFERRER_POLICY_INDEX["unsafe-url"],
+ },
+];
+
+function clearTelemetry() {
+ Services.telemetry.getSnapshotForHistograms("main", true /* clear */);
+ Services.telemetry.getHistogramById("REFERRER_POLICY_COUNT").clear();
+}
+
+add_setup(async function () {
+ // Clear Telemetry probes before testing.
+ clearTelemetry();
+});
+
+function verifyTelemetry(expected, isSameSite) {
+ // The record of cross-site loads is placed in the second half of the
+ // telemetry.
+ const offset = isSameSite ? 0 : Object.keys(REFERRER_POLICY_INDEX).length;
+
+ let histograms = Services.telemetry.getSnapshotForHistograms(
+ "main",
+ false /* clear */
+ ).parent;
+
+ let referrerPolicyCountProbe = histograms.REFERRER_POLICY_COUNT;
+
+ ok(referrerPolicyCountProbe, "The telemetry probe has been recorded.");
+ is(
+ referrerPolicyCountProbe.values[expected + offset],
+ 1,
+ "The telemetry is added correctly."
+ );
+}
+
+add_task(async function run_tests() {
+ for (let test of TEST_CASES) {
+ for (let sameSite of [true, false]) {
+ clearTelemetry();
+ let referrerURL = `${TEST_PAGE}?header=${test.policy}`;
+
+ await BrowserTestUtils.withNewTab(referrerURL, async browser => {
+ let iframeURL = sameSite
+ ? TEST_PAGE + "?show"
+ : TEST_CROSS_SITE_PAGE + "?show";
+
+ // Create an iframe and load the url.
+ await SpecialPowers.spawn(browser, [iframeURL], async url => {
+ let iframe = content.document.createElement("iframe");
+ iframe.src = url;
+
+ await new content.Promise(resolve => {
+ iframe.onload = () => {
+ resolve();
+ };
+
+ content.document.body.appendChild(iframe);
+ });
+ });
+
+ verifyTelemetry(test.expected, sameSite);
+ });
+ }
+ }
+});
diff --git a/dom/security/test/referrer-policy/file_fragment_navigation.sjs b/dom/security/test/referrer-policy/file_fragment_navigation.sjs
new file mode 100644
index 0000000000..5fb6f0d826
--- /dev/null
+++ b/dom/security/test/referrer-policy/file_fragment_navigation.sjs
@@ -0,0 +1,21 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function handleRequest(request, response) {
+ if (
+ request.queryString === "check_referrer" &&
+ (!request.hasHeader("referer") ||
+ request.getHeader("referer") !==
+ "https://example.com/browser/dom/security/test/referrer-policy/file_fragment_navigation.sjs")
+ ) {
+ response.setStatusLine(request.httpVersion, 400, "Bad Request");
+ response.write("Did not receive referrer");
+ } else {
+ response.setHeader("Content-Type", "text/html");
+ response.write(
+ `<span id="ok">OK</span>
+<a id="check_referrer" href="?check_referrer">check_referrer</a>
+<a id="fragment" href="#fragment">fragment</a>`
+ );
+ }
+}
diff --git a/dom/security/test/referrer-policy/img_referrer_testserver.sjs b/dom/security/test/referrer-policy/img_referrer_testserver.sjs
new file mode 100644
index 0000000000..7fcc8d4914
--- /dev/null
+++ b/dom/security/test/referrer-policy/img_referrer_testserver.sjs
@@ -0,0 +1,337 @@
+var BASE_URL =
+ "example.com/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs";
+const IMG_BYTES = atob(
+ "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
+ "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
+);
+
+function createTestUrl(aPolicy, aAction, aName, aContent) {
+ var content = aContent || "text";
+ return (
+ "http://" +
+ BASE_URL +
+ "?" +
+ "action=" +
+ aAction +
+ "&" +
+ "policy=" +
+ aPolicy +
+ "&" +
+ "name=" +
+ aName +
+ "&" +
+ "content=" +
+ content
+ );
+}
+
+function createTestPage(aHead, aImgPolicy, aName) {
+ var _createTestUrl = createTestUrl.bind(null, aImgPolicy, "test", aName);
+
+ return (
+ "<!DOCTYPE HTML>\n\
+ <html>" +
+ aHead +
+ '<body>\n\
+ <img src="' +
+ _createTestUrl("img") +
+ '" referrerpolicy="' +
+ aImgPolicy +
+ '" id="image"></img>\n\
+ <script>' +
+ // LOAD EVENT (of the test)
+ // fires when the img resource for the page is loaded
+ 'window.addEventListener("load", function() {\n\
+ parent.postMessage("childLoadComplete", "http://mochi.test:8888");\n\
+ }.bind(window), false);' +
+ "</script>\n\
+ </body>\n\
+ </html>"
+ );
+}
+
+// Creates the following test cases for the specified referrer
+// policy combination:
+// <img> with referrer
+function createTest(aPolicy, aImgPolicy, aName) {
+ var headString = "<head>";
+ if (aPolicy) {
+ headString += '<meta name="referrer" content="' + aPolicy + '">';
+ }
+
+ headString += "<script></script>";
+
+ return createTestPage(headString, aImgPolicy, aName);
+}
+
+// testing regular load img with referrer policy
+// speculative parser should not kick in here
+function createTest2(aImgPolicy, name) {
+ return createTestPage("", aImgPolicy, name);
+}
+
+function createTest3(aImgPolicy1, aImgPolicy2, aImgPolicy3, aName) {
+ return (
+ '<!DOCTYPE HTML>\n\
+ <html>\n\
+ <body>\n\
+ <img src="' +
+ createTestUrl(aImgPolicy1, "test", aName + aImgPolicy1) +
+ '" referrerpolicy="' +
+ aImgPolicy1 +
+ '" id="image"></img>\n\
+ <img src="' +
+ createTestUrl(aImgPolicy2, "test", aName + aImgPolicy2) +
+ '" referrerpolicy="' +
+ aImgPolicy2 +
+ '" id="image"></img>\n\
+ <img src="' +
+ createTestUrl(aImgPolicy3, "test", aName + aImgPolicy3) +
+ '" referrerpolicy="' +
+ aImgPolicy3 +
+ '" id="image"></img>\n\
+ <script>\n\
+ var _numLoads = 0;' +
+ // LOAD EVENT (of the test)
+ // fires when the img resource for the page is loaded
+ 'window.addEventListener("load", function() {\n\
+ parent.postMessage("childLoadComplete", "http://mochi.test:8888");\n\
+ }.bind(window), false);' +
+ "</script>\n\
+ </body>\n\
+ </html>"
+ );
+}
+
+function createTestPage2(aHead, aPolicy, aName) {
+ return (
+ "<!DOCTYPE HTML>\n\
+ <html>" +
+ aHead +
+ '<body>\n\
+ <img src="' +
+ createTestUrl(aPolicy, "test", aName) +
+ '" id="image"></img>\n\
+ <script>' +
+ // LOAD EVENT (of the test)
+ // fires when the img resource for the page is loaded
+ 'window.addEventListener("load", function() {\n\
+ parent.postMessage("childLoadComplete", "http://mochi.test:8888");\n\
+ }.bind(window), false);' +
+ "</script>\n\
+ </body>\n\
+ </html>"
+ );
+}
+
+function createTestPage3(aHead, aPolicy, aName) {
+ return (
+ "<!DOCTYPE HTML>\n\
+ <html>" +
+ aHead +
+ "<body>\n\
+ <script>" +
+ 'var image = new Image();\n\
+ image.src = "' +
+ createTestUrl(aPolicy, "test", aName, "image") +
+ '";\n\
+ image.referrerPolicy = "' +
+ aPolicy +
+ '";\n\
+ image.onload = function() {\n\
+ window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");\n\
+ }\n\
+ document.body.appendChild(image);' +
+ "</script>\n\
+ </body>\n\
+ </html>"
+ );
+}
+
+function createTestPage4(aHead, aPolicy, aName) {
+ return (
+ "<!DOCTYPE HTML>\n\
+ <html>" +
+ aHead +
+ "<body>\n\
+ <script>" +
+ 'var image = new Image();\n\
+ image.referrerPolicy = "' +
+ aPolicy +
+ '";\n\
+ image.src = "' +
+ createTestUrl(aPolicy, "test", aName, "image") +
+ '";\n\
+ image.onload = function() {\n\
+ window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");\n\
+ }\n\
+ document.body.appendChild(image);' +
+ "</script>\n\
+ </body>\n\
+ </html>"
+ );
+}
+
+function createSetAttributeTest1(aPolicy, aImgPolicy, aName) {
+ var headString = "<head>";
+ headString += '<meta name="referrer" content="' + aPolicy + '">';
+ headString += "<script></script>";
+
+ return createTestPage3(headString, aImgPolicy, aName);
+}
+
+function createSetAttributeTest2(aPolicy, aImgPolicy, aName) {
+ var headString = "<head>";
+ headString += '<meta name="referrer" content="' + aPolicy + '">';
+ headString += "<script></script>";
+
+ return createTestPage4(headString, aImgPolicy, aName);
+}
+
+function createTest4(aPolicy, aName) {
+ var headString = "<head>";
+ headString += '<meta name="referrer" content="' + aPolicy + '">';
+ headString += "<script></script>";
+
+ return createTestPage2(headString, aPolicy, aName);
+}
+
+function createTest5(aPolicy, aName) {
+ var headString = "<head>";
+ headString += '<meta name="referrer" content="' + aPolicy + '">';
+
+ return createTestPage2(headString, aPolicy, aName);
+}
+
+function handleRequest(request, response) {
+ var sharedKey = "img_referrer_testserver.sjs";
+ var params = request.queryString.split("&");
+ var action = params[0].split("=")[1];
+
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/html; charset=utf-8", false);
+
+ if (action === "resetState") {
+ let state = getSharedState(sharedKey);
+ state = {};
+ setSharedState(sharedKey, JSON.stringify(state));
+ response.write("");
+ return;
+ }
+ if (action === "test") {
+ // ?action=test&policy=origin&name=name&content=content
+ let policy = params[1].split("=")[1];
+ let name = params[2].split("=")[1];
+ let content = params[3].split("=")[1];
+ let result = getSharedState(sharedKey);
+
+ if (result === "") {
+ result = {};
+ } else {
+ result = JSON.parse(result);
+ }
+
+ if (!result.tests) {
+ result.tests = {};
+ }
+
+ var referrerLevel = "none";
+ var test = {};
+ if (request.hasHeader("Referer")) {
+ let referrer = request.getHeader("Referer");
+ if (referrer.indexOf("img_referrer_testserver") > 0) {
+ referrerLevel = "full";
+ } else if (referrer == "http://mochi.test:8888/") {
+ referrerLevel = "origin";
+ }
+ test.referrer = request.getHeader("Referer");
+ } else {
+ test.referrer = "";
+ }
+ test.policy = referrerLevel;
+ test.expected = policy;
+
+ result.tests[name] = test;
+
+ setSharedState(sharedKey, JSON.stringify(result));
+
+ if (content === "image") {
+ response.setHeader("Content-Type", "image/png");
+ response.write(IMG_BYTES);
+ }
+ return;
+ }
+ if (action === "get-test-results") {
+ // ?action=get-result
+ response.write(getSharedState(sharedKey));
+ return;
+ }
+ if (action === "generate-img-policy-test") {
+ // ?action=generate-img-policy-test&imgPolicy=b64-encoded-string&name=name&policy=b64-encoded-string
+ let imgPolicy = unescape(params[1].split("=")[1]);
+ let name = unescape(params[2].split("=")[1]);
+ let metaPolicy = "";
+ if (params[3]) {
+ metaPolicy = params[3].split("=")[1];
+ }
+
+ response.write(createTest(metaPolicy, imgPolicy, name));
+ return;
+ }
+ if (action === "generate-img-policy-test2") {
+ // ?action=generate-img-policy-test2&imgPolicy=b64-encoded-string&name=name
+ let imgPolicy = unescape(params[1].split("=")[1]);
+ let name = unescape(params[2].split("=")[1]);
+
+ response.write(createTest2(imgPolicy, name));
+ return;
+ }
+ if (action === "generate-img-policy-test3") {
+ // ?action=generate-img-policy-test3&imgPolicy1=b64-encoded-string&imgPolicy2=b64-encoded-string&imgPolicy3=b64-encoded-string&name=name
+ let imgPolicy1 = unescape(params[1].split("=")[1]);
+ let imgPolicy2 = unescape(params[2].split("=")[1]);
+ let imgPolicy3 = unescape(params[3].split("=")[1]);
+ let name = unescape(params[4].split("=")[1]);
+
+ response.write(createTest3(imgPolicy1, imgPolicy2, imgPolicy3, name));
+ return;
+ }
+ if (action === "generate-img-policy-test4") {
+ // ?action=generate-img-policy-test4&imgPolicy=b64-encoded-string&name=name
+ let policy = unescape(params[1].split("=")[1]);
+ let name = unescape(params[2].split("=")[1]);
+
+ response.write(createTest4(policy, name));
+ return;
+ }
+ if (action === "generate-img-policy-test5") {
+ // ?action=generate-img-policy-test5&policy=b64-encoded-string&name=name
+ let policy = unescape(params[1].split("=")[1]);
+ let name = unescape(params[2].split("=")[1]);
+
+ response.write(createTest5(policy, name));
+ return;
+ }
+
+ if (action === "generate-setAttribute-test1") {
+ // ?action=generate-setAttribute-test1&policy=b64-encoded-string&name=name
+ let imgPolicy = unescape(params[1].split("=")[1]);
+ let policy = unescape(params[2].split("=")[1]);
+ let name = unescape(params[3].split("=")[1]);
+
+ response.write(createSetAttributeTest1(policy, imgPolicy, name));
+ return;
+ }
+
+ if (action === "generate-setAttribute-test2") {
+ // ?action=generate-setAttribute-test2&policy=b64-encoded-string&name=name
+ let imgPolicy = unescape(params[1].split("=")[1]);
+ let policy = unescape(params[2].split("=")[1]);
+ let name = unescape(params[3].split("=")[1]);
+
+ response.write(createSetAttributeTest2(policy, imgPolicy, name));
+ return;
+ }
+
+ response.write("I don't know action " + action);
+}
diff --git a/dom/security/test/referrer-policy/mochitest.toml b/dom/security/test/referrer-policy/mochitest.toml
new file mode 100644
index 0000000000..89a54ad554
--- /dev/null
+++ b/dom/security/test/referrer-policy/mochitest.toml
@@ -0,0 +1,28 @@
+[DEFAULT]
+support-files = [
+ "img_referrer_testserver.sjs",
+ "referrer_header.sjs",
+ "referrer_header_current_document_iframe.html",
+ "referrer_helper.js",
+ "referrer_testserver.sjs",
+]
+
+["test_img_referrer.html"]
+skip-if = [
+ "http3",
+ "http2",
+]
+
+["test_referrer_header_current_document.html"]
+skip-if = [
+ "http3",
+ "http2",
+]
+
+["test_referrer_redirect.html"]
+# Please keep alphabetical order.
+skip-if = [
+ "http3",
+ "http2",
+]
+
diff --git a/dom/security/test/referrer-policy/referrer_header.sjs b/dom/security/test/referrer-policy/referrer_header.sjs
new file mode 100644
index 0000000000..29c324b8f6
--- /dev/null
+++ b/dom/security/test/referrer-policy/referrer_header.sjs
@@ -0,0 +1,6 @@
+function handleRequest(request, response) {
+ response.setHeader("Referrer-Policy", "same-origin");
+ response.write(
+ '<!DOCTYPE HTML><html><body>Loaded</body><script>parent.postMessage(document.referrer, "*");</script></html>'
+ );
+}
diff --git a/dom/security/test/referrer-policy/referrer_header_current_document_iframe.html b/dom/security/test/referrer-policy/referrer_header_current_document_iframe.html
new file mode 100644
index 0000000000..5996c8ba8a
--- /dev/null
+++ b/dom/security/test/referrer-policy/referrer_header_current_document_iframe.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <script>
+ window.addEventListener("load", function() {
+ document.getElementById("link").click();
+ });
+ </script>
+</head>
+<body>
+ <a id="link" href="http://example.org/tests/dom/security/test/referrer-policy/referrer_header.sjs">Navigate</a>
+</body>
diff --git a/dom/security/test/referrer-policy/referrer_helper.js b/dom/security/test/referrer-policy/referrer_helper.js
new file mode 100644
index 0000000000..b892017eef
--- /dev/null
+++ b/dom/security/test/referrer-policy/referrer_helper.js
@@ -0,0 +1,129 @@
+// This helper expects these globals to be defined.
+/* global PARAMS, SJS, testCases */
+
+/*
+ * common functionality for iframe, anchor, and area referrer attribute tests
+ */
+const GET_RESULT = SJS + "ACTION=get-test-results";
+const RESET_STATE = SJS + "ACTION=resetState";
+
+SimpleTest.waitForExplicitFinish();
+var advance = function () {
+ tests.next();
+};
+
+/**
+ * Listen for notifications from the child.
+ * These are sent in case of error, or when the loads we await have completed.
+ */
+window.addEventListener("message", function (event) {
+ if (event.data == "childLoadComplete") {
+ // all loads happen, continue the test.
+ advance();
+ }
+});
+
+/**
+ * helper to perform an XHR
+ * to do checkIndividualResults and resetState
+ */
+function doXHR(aUrl, onSuccess, onFail) {
+ // The server is at http[s]://example.com so we need cross-origin XHR.
+ var xhr = new XMLHttpRequest({ mozSystem: true });
+ xhr.responseType = "json";
+ xhr.onload = function () {
+ onSuccess(xhr);
+ };
+ xhr.onerror = function () {
+ onFail(xhr);
+ };
+ xhr.open("GET", "http" + aUrl, true);
+ xhr.send(null);
+}
+
+/**
+ * Grabs the results via XHR and passes to checker.
+ */
+function checkIndividualResults(aTestname, aExpectedReferrer, aName) {
+ var onload = xhr => {
+ var results = xhr.response;
+ info(JSON.stringify(xhr.response));
+ ok(aName in results, aName + " tests have to be performed.");
+ is(
+ results[aName].policy,
+ aExpectedReferrer,
+ aTestname +
+ " --- " +
+ results[aName].policy +
+ " (" +
+ results[aName].referrer +
+ ")"
+ );
+ advance();
+ };
+ var onerror = xhr => {
+ ok(false, "Can't get results from the counter server.");
+ SimpleTest.finish();
+ };
+ doXHR(GET_RESULT, onload, onerror);
+}
+
+function resetState() {
+ doXHR(RESET_STATE, advance, function (xhr) {
+ ok(false, "error in reset state");
+ SimpleTest.finish();
+ });
+}
+
+/**
+ * testing if referrer header is sent correctly
+ */
+var tests = (function* () {
+ yield SpecialPowers.pushPrefEnv(
+ { set: [["security.mixed_content.block_active_content", false]] },
+ advance
+ );
+ yield SpecialPowers.pushPrefEnv(
+ { set: [["network.http.referer.disallowCrossSiteRelaxingDefault", false]] },
+ advance
+ );
+ yield SpecialPowers.pushPermissions(
+ [{ type: "systemXHR", allow: true, context: document }],
+ advance
+ );
+
+ var iframe = document.getElementById("testframe");
+
+ for (var j = 0; j < testCases.length; j++) {
+ if (testCases[j].PREFS) {
+ yield SpecialPowers.pushPrefEnv({ set: testCases[j].PREFS }, advance);
+ }
+
+ var actions = testCases[j].ACTION;
+ var subTests = testCases[j].TESTS;
+ for (var k = 0; k < actions.length; k++) {
+ var actionString = actions[k];
+ for (var i = 0; i < subTests.length; i++) {
+ yield resetState();
+ var searchParams = new URLSearchParams();
+ searchParams.append("ACTION", actionString);
+ searchParams.append("NAME", subTests[i].NAME);
+ for (var l of PARAMS) {
+ if (subTests[i][l]) {
+ searchParams.append(l, subTests[i][l]);
+ }
+ }
+ var schemeFrom = subTests[i].SCHEME_FROM || "http";
+ yield (iframe.src = schemeFrom + SJS + searchParams.toString());
+ yield checkIndividualResults(
+ subTests[i].DESC,
+ subTests[i].RESULT,
+ subTests[i].NAME
+ );
+ }
+ }
+ }
+
+ // complete.
+ SimpleTest.finish();
+})();
diff --git a/dom/security/test/referrer-policy/referrer_page.sjs b/dom/security/test/referrer-policy/referrer_page.sjs
new file mode 100644
index 0000000000..2cfae0d398
--- /dev/null
+++ b/dom/security/test/referrer-policy/referrer_page.sjs
@@ -0,0 +1,39 @@
+function handleRequest(request, response) {
+ let params = new URLSearchParams(request.queryString);
+ let referrerPolicyHeader = params.get("header") || "";
+ let metaReferrerPolicy = params.get("meta") || "";
+ let showReferrer = params.has("show");
+
+ if (referrerPolicyHeader) {
+ response.setHeader("Referrer-Policy", referrerPolicyHeader, false);
+ }
+
+ let metaString = "";
+ let resultString = "";
+
+ if (metaReferrerPolicy) {
+ metaString = `<meta name="referrer" content="${metaReferrerPolicy}">`;
+ }
+
+ if (showReferrer) {
+ if (request.hasHeader("Referer")) {
+ resultString = `Referer Header: <a id="result">${request.getHeader(
+ "Referer"
+ )}</a>`;
+ } else {
+ resultString = `Referer Header: <a id="result"></a>`;
+ }
+ }
+
+ response.write(
+ `<!DOCTYPE HTML>
+ <html>
+ <head>
+ ${metaString}
+ </head>
+ <body>
+ ${resultString}
+ </body>
+ </html>`
+ );
+}
diff --git a/dom/security/test/referrer-policy/referrer_testserver.sjs b/dom/security/test/referrer-policy/referrer_testserver.sjs
new file mode 100644
index 0000000000..9f112e88dc
--- /dev/null
+++ b/dom/security/test/referrer-policy/referrer_testserver.sjs
@@ -0,0 +1,704 @@
+/*
+ * Test server for iframe, anchor, and area referrer attributes.
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=1175736
+ * Also server for further referrer tests such as redirecting tests
+ * bug 1174913, bug 1175736, bug 1184781
+ */
+
+const SJS = "referrer_testserver.sjs?";
+const SJS_PATH = "/tests/dom/security/test/referrer-policy/";
+const BASE_ORIGIN = "example.com";
+const BASE_URL = BASE_ORIGIN + SJS_PATH + SJS;
+const SHARED_KEY = SJS;
+const SAME_ORIGIN = "mochi.test:8888" + SJS_PATH + SJS;
+const CROSS_ORIGIN_URL = "test1.example.com" + SJS_PATH + SJS;
+const HSTS_URL = "includesubdomains.preloaded.test" + SJS_PATH + SJS;
+
+const IMG_BYTES = atob(
+ "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
+ "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
+);
+
+function createTestUrl(
+ aPolicy,
+ aAction,
+ aName,
+ aType,
+ aSchemeFrom,
+ aSchemeTo,
+ crossOrigin,
+ referrerPolicyHeader
+) {
+ var schemeTo = aSchemeTo || "http";
+ var schemeFrom = aSchemeFrom || "http";
+ var rpHeader = referrerPolicyHeader || "";
+ var url = schemeTo + "://";
+ url += crossOrigin ? CROSS_ORIGIN_URL : BASE_URL;
+ url +=
+ "ACTION=" +
+ aAction +
+ "&" +
+ "policy=" +
+ aPolicy +
+ "&" +
+ "NAME=" +
+ aName +
+ "&" +
+ "type=" +
+ aType +
+ "&" +
+ "RP_HEADER=" +
+ rpHeader +
+ "&" +
+ "SCHEME_FROM=" +
+ schemeFrom;
+ return url;
+}
+
+// test page using iframe referrer attribute
+// if aParams are set this creates a test where the iframe url is a redirect
+function createIframeTestPageUsingRefferer(
+ aMetaPolicy,
+ aAttributePolicy,
+ aNewAttributePolicy,
+ aName,
+ aParams,
+ aSchemeFrom,
+ aSchemeTo,
+ aChangingMethod
+) {
+ var metaString = "";
+ if (aMetaPolicy) {
+ metaString = `<meta name="referrer" content="${aMetaPolicy}">`;
+ }
+ var changeString = "";
+ if (aChangingMethod === "setAttribute") {
+ changeString = `document.getElementById("myframe").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`;
+ } else if (aChangingMethod === "property") {
+ changeString = `document.getElementById("myframe").referrerPolicy = "${aNewAttributePolicy}"`;
+ }
+ var iFrameString = `<iframe src="" id="myframe" ${
+ aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : ""
+ }>iframe</iframe>`;
+ var iframeUrl = "";
+ if (aParams) {
+ aParams.delete("ACTION");
+ aParams.append("ACTION", "redirectIframe");
+ iframeUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString();
+ } else {
+ iframeUrl = createTestUrl(
+ aAttributePolicy,
+ "test",
+ aName,
+ "iframe",
+ aSchemeFrom,
+ aSchemeTo
+ );
+ }
+
+ return `<!DOCTYPE HTML>
+ <html>
+ <head>
+ ${metaString}
+ </head>
+ <body>
+ ${iFrameString}
+ <script>
+ window.addEventListener("load", function() {
+ ${changeString}
+ document.getElementById("myframe").onload = function(){
+ parent.postMessage("childLoadComplete", "http://mochi.test:8888");
+ };
+ document.getElementById("myframe").src = "${iframeUrl}";
+ }.bind(window), false);
+ </script>
+ </body>
+ </html>`;
+}
+
+function buildAnchorString(
+ aMetaPolicy,
+ aReferrerPolicy,
+ aName,
+ aRelString,
+ aSchemeFrom,
+ aSchemeTo
+) {
+ if (aReferrerPolicy) {
+ return `<a href="${createTestUrl(
+ aReferrerPolicy,
+ "test",
+ aName,
+ "link",
+ aSchemeFrom,
+ aSchemeTo
+ )}" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>${aReferrerPolicy}</a>`;
+ }
+ return `<a href="${createTestUrl(
+ aMetaPolicy,
+ "test",
+ aName,
+ "link",
+ aSchemeFrom,
+ aSchemeTo
+ )}" id="link" ${aRelString}>link</a>`;
+}
+
+function buildAreaString(
+ aMetaPolicy,
+ aReferrerPolicy,
+ aName,
+ aRelString,
+ aSchemeFrom,
+ aSchemeTo
+) {
+ var result = `<img src="file_mozfiledataurl_img.jpg" alt="image" usemap="#imageMap">`;
+ result += `<map name="imageMap">`;
+ if (aReferrerPolicy) {
+ result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(
+ aReferrerPolicy,
+ "test",
+ aName,
+ "link",
+ aSchemeFrom,
+ aSchemeTo
+ )}" alt="theArea" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>`;
+ } else {
+ result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(
+ aMetaPolicy,
+ "test",
+ aName,
+ "link",
+ aSchemeFrom,
+ aSchemeTo
+ )}" alt="theArea" id="link" ${aRelString}>`;
+ }
+ result += `</map>`;
+
+ return result;
+}
+
+// test page using anchor or area referrer attribute
+function createAETestPageUsingRefferer(
+ aMetaPolicy,
+ aAttributePolicy,
+ aNewAttributePolicy,
+ aName,
+ aRel,
+ aStringBuilder,
+ aSchemeFrom,
+ aSchemeTo,
+ aChangingMethod
+) {
+ var metaString = "";
+ if (aMetaPolicy) {
+ metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`;
+ }
+ var changeString = "";
+ if (aChangingMethod === "setAttribute") {
+ changeString = `document.getElementById("link").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`;
+ } else if (aChangingMethod === "property") {
+ changeString = `document.getElementById("link").referrerPolicy = "${aNewAttributePolicy}"`;
+ }
+ var relString = "";
+ if (aRel) {
+ relString = `rel="noreferrer"`;
+ }
+ var elementString = aStringBuilder(
+ aMetaPolicy,
+ aAttributePolicy,
+ aName,
+ relString,
+ aSchemeFrom,
+ aSchemeTo
+ );
+
+ return `<!DOCTYPE HTML>
+ <html>
+ ${metaString}
+ <body>
+ ${elementString}
+ <script>
+ window.addEventListener("load", function() {
+ ${changeString}
+ document.getElementById("link").click();
+ }.bind(window), false);
+ </script>
+ </body>
+ </html>`;
+}
+
+// test page using anchor target=_blank rel=noopener
+function createTargetBlankRefferer(
+ aMetaPolicy,
+ aName,
+ aSchemeFrom,
+ aSchemeTo,
+ aRpHeader
+) {
+ var metaString = "";
+ if (aMetaPolicy) {
+ metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`;
+ }
+ var elementString = `<a href="${createTestUrl(
+ aMetaPolicy,
+ "test",
+ aName,
+ "link",
+ aSchemeFrom,
+ aSchemeTo,
+ aRpHeader
+ )}" target=_blank rel="noopener" id="link">link</a>`;
+
+ return `<!DOCTYPE HTML>
+ <html>
+ ${metaString}
+ <body>
+ ${elementString}
+ <script>
+ window.addEventListener("load", function() {
+ let link = document.getElementById("link");
+ SpecialPowers.wrap(window).parent.postMessage("childLoadReady", "*");
+ link.click();
+ }.bind(window), false);
+ </script>
+ </body>
+ </html>`;
+}
+
+// creates test page with img that is a redirect
+function createImgTestCase(aParams, aAttributePolicy, aRedirect) {
+ var metaString = "";
+ if (aParams.has("META_POLICY")) {
+ metaString = `<meta name="referrer" content="${aParams.get(
+ "META_POLICY"
+ )}">`;
+ }
+ aParams.delete("ACTION");
+ if (aRedirect) {
+ aParams.append("ACTION", "redirectImg");
+ } else {
+ aParams.append("ACTION", "test");
+ aParams.append("type", "img");
+ }
+ var imgUrl =
+ "http://" +
+ (aParams.get("HSTS") ? HSTS_URL : CROSS_ORIGIN_URL) +
+ aParams.toString();
+
+ return `<!DOCTYPE HTML>
+ <html>
+ <head>
+ <meta charset="utf-8">
+ ${metaString}
+ <title>Test referrer policies on redirect (img)</title>
+ </head>
+ <body>
+ <img id="testImg" src="${imgUrl}" ${
+ aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : ""
+ }>
+ <script>
+ window.addEventListener("load", function() {
+ parent.postMessage("childLoadComplete", "http://mochi.test:8888");
+ }.bind(window), false);
+ </script>
+ </body>
+ </html>`;
+}
+
+// test page using link referrer attribute
+function createLinkPageUsingRefferer(
+ aMetaPolicy,
+ aAttributePolicy,
+ aNewAttributePolicy,
+ aName,
+ aRel,
+ aStringBuilder,
+ aSchemeFrom,
+ aSchemeTo,
+ aTestType
+) {
+ var metaString = "";
+ if (aMetaPolicy) {
+ metaString = `<meta name="referrer" content="${aMetaPolicy}">`;
+ }
+
+ var changeString = "";
+ var policy = aAttributePolicy ? aAttributePolicy : aMetaPolicy;
+ var elementString = aStringBuilder(
+ policy,
+ aName,
+ aRel,
+ aSchemeFrom,
+ aSchemeTo,
+ aTestType
+ );
+
+ if (aTestType === "setAttribute") {
+ changeString = `var link = document.getElementById("test_link");
+ link.setAttribute("referrerpolicy", "${aNewAttributePolicy}");
+ link.href = "${createTestUrl(
+ policy,
+ "test",
+ aName,
+ "link_element_" + aRel,
+ aSchemeFrom,
+ aSchemeTo
+ )}";`;
+ } else if (aTestType === "property") {
+ changeString = `var link = document.getElementById("test_link");
+ link.referrerPolicy = "${aNewAttributePolicy}";
+ link.href = "${createTestUrl(
+ policy,
+ "test",
+ aName,
+ "link_element_" + aRel,
+ aSchemeFrom,
+ aSchemeTo
+ )}";`;
+ }
+
+ return `<!DOCTYPE HTML>
+ <html>
+ <head>
+ ${metaString}
+ </head>
+ <body>
+ ${elementString}
+ <script>
+ ${changeString}
+ </script>
+ </body>
+ </html>`;
+}
+
+function createFetchUserControlRPTestCase(
+ aName,
+ aSchemeFrom,
+ aSchemeTo,
+ crossOrigin
+) {
+ var srcUrl = createTestUrl(
+ "",
+ "test",
+ aName,
+ "fetch",
+ aSchemeFrom,
+ aSchemeTo,
+ crossOrigin
+ );
+
+ return `<!DOCTYPE HTML>
+ <html>
+ <head>
+ <meta charset="utf-8">
+ <title>Test user control referrer policies</title>
+ </head>
+ <body>
+ <script>
+ fetch("${srcUrl}", {referrerPolicy: ""}).then(function (response) {
+ window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");
+ });
+ </script>
+ </body>
+ </html>`;
+}
+
+function buildLinkString(
+ aPolicy,
+ aName,
+ aRel,
+ aSchemeFrom,
+ aSchemeTo,
+ aTestType
+) {
+ var href = "";
+ var onChildComplete = `window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");`;
+ var policy = "";
+ var asString = "";
+ var relString = "";
+
+ if (aRel) {
+ relString = `rel="${aRel}"`;
+ }
+
+ if (aPolicy) {
+ policy = `referrerpolicy=${aPolicy}`;
+ }
+
+ if (aRel == "preload") {
+ asString = 'as="image"';
+ }
+
+ if (!aTestType) {
+ href = `href=${createTestUrl(
+ aPolicy,
+ "test",
+ aName,
+ "link_element_" + aRel,
+ aSchemeFrom,
+ aSchemeTo
+ )}`;
+ }
+
+ return `<link ${relString} ${href} ${policy} ${asString} id="test_link" onload='${onChildComplete}' onerror='${onChildComplete}'>`;
+}
+// eslint-disable-next-line complexity
+function handleRequest(request, response) {
+ var params = new URLSearchParams(request.queryString);
+ var action = params.get("ACTION");
+ var schemeFrom = params.get("SCHEME_FROM") || "http";
+ var schemeTo = params.get("SCHEME_TO") || "http";
+ var crossOrigin = params.get("CROSS_ORIGIN") || false;
+ var referrerPolicyHeader = params.get("RP_HEADER") || "";
+
+ response.setHeader("Access-Control-Allow-Origin", "*", false);
+ if (referrerPolicyHeader) {
+ response.setHeader("Referrer-Policy", referrerPolicyHeader, false);
+ }
+
+ if (action === "resetState") {
+ setSharedState(SHARED_KEY, "{}");
+ response.write("");
+ return;
+ }
+ if (action === "get-test-results") {
+ // ?action=get-result
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write(getSharedState(SHARED_KEY));
+ return;
+ }
+ if (action === "redirect") {
+ response.write(
+ '<script>parent.postMessage("childLoadComplete", "http://mochi.test:8888");</script>'
+ );
+ return;
+ }
+ if (action === "redirectImg") {
+ params.delete("ACTION");
+ params.append("ACTION", "test");
+ params.append("type", "img");
+ // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect
+ response.setStatusLine("1.1", 302, "found");
+ response.setHeader(
+ "Location",
+ "http://" + CROSS_ORIGIN_URL + params.toString(),
+ false
+ );
+ return;
+ }
+ if (action === "redirectIframe") {
+ params.delete("ACTION");
+ params.append("ACTION", "test");
+ params.append("type", "iframe");
+ // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect
+ response.setStatusLine("1.1", 302, "found");
+ response.setHeader(
+ "Location",
+ "http://" + CROSS_ORIGIN_URL + params.toString(),
+ false
+ );
+ return;
+ }
+ if (action === "test") {
+ // ?action=test&policy=origin&name=name
+ let policy = params.get("policy");
+ let name = params.get("NAME");
+ let type = params.get("type");
+ let result = getSharedState(SHARED_KEY);
+
+ result = result ? JSON.parse(result) : {};
+
+ var referrerLevel = "none";
+ var test = {};
+ if (request.hasHeader("Referer")) {
+ var referrer = request.getHeader("Referer");
+ if (referrer.indexOf("referrer_testserver") > 0) {
+ referrerLevel = "full";
+ } else if (referrer.indexOf(schemeFrom + "://example.com") == 0) {
+ referrerLevel = "origin";
+ } else {
+ // this is never supposed to happen
+ referrerLevel = "other-origin";
+ }
+ test.referrer = referrer;
+ } else {
+ test.referrer = "";
+ }
+ test.policy = referrerLevel;
+ test.expected = policy;
+
+ result[name] = test;
+
+ setSharedState(SHARED_KEY, JSON.stringify(result));
+
+ if (type === "img" || type == "link_element_preload") {
+ // return image
+ response.setHeader("Content-Type", "image/png");
+ response.write(IMG_BYTES);
+ return;
+ }
+ if (type === "iframe") {
+ // return iframe page
+ response.write("<html><body>I am the iframe</body></html>");
+ return;
+ }
+ if (type === "link") {
+ // forward link click to redirect URL to finish test
+ var loc = "http://" + BASE_URL + "ACTION=redirect";
+ response.setStatusLine("1.1", 302, "Found");
+ response.setHeader("Location", loc, false);
+ }
+ return;
+ }
+
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/html; charset=utf-8", false);
+
+ // parse test arguments and start test
+ var attributePolicy = params.get("ATTRIBUTE_POLICY") || "";
+ var newAttributePolicy = params.get("NEW_ATTRIBUTE_POLICY") || "";
+ var metaPolicy = params.get("META_POLICY") || "";
+ var rel = params.get("REL") || "";
+ var name = params.get("NAME");
+
+ // anchor & area
+ var _getPage = createAETestPageUsingRefferer.bind(
+ null,
+ metaPolicy,
+ attributePolicy,
+ newAttributePolicy,
+ name,
+ rel
+ );
+ var _getAnchorPage = _getPage.bind(
+ null,
+ buildAnchorString,
+ schemeFrom,
+ schemeTo
+ );
+ var _getAreaPage = _getPage.bind(null, buildAreaString, schemeFrom, schemeTo);
+
+ // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod, aStringBuilder
+ if (action === "generate-anchor-policy-test") {
+ response.write(_getAnchorPage());
+ return;
+ }
+ if (action === "generate-anchor-changing-policy-test-set-attribute") {
+ response.write(_getAnchorPage("setAttribute"));
+ return;
+ }
+ if (action === "generate-anchor-changing-policy-test-property") {
+ response.write(_getAnchorPage("property"));
+ return;
+ }
+ if (action === "generate-area-policy-test") {
+ response.write(_getAreaPage());
+ return;
+ }
+ if (action === "generate-area-changing-policy-test-set-attribute") {
+ response.write(_getAreaPage("setAttribute"));
+ return;
+ }
+ if (action === "generate-area-changing-policy-test-property") {
+ response.write(_getAreaPage("property"));
+ return;
+ }
+ if (action === "generate-anchor-target-blank-policy-test") {
+ response.write(
+ createTargetBlankRefferer(
+ metaPolicy,
+ name,
+ schemeFrom,
+ schemeTo,
+ referrerPolicyHeader
+ )
+ );
+ return;
+ }
+
+ // iframe
+ _getPage = createIframeTestPageUsingRefferer.bind(
+ null,
+ metaPolicy,
+ attributePolicy,
+ newAttributePolicy,
+ name,
+ "",
+ schemeFrom,
+ schemeTo
+ );
+
+ // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod
+ if (action === "generate-iframe-policy-test") {
+ response.write(_getPage());
+ return;
+ }
+ if (action === "generate-iframe-changing-policy-test-set-attribute") {
+ response.write(_getPage("setAttribute"));
+ return;
+ }
+ if (action === "generate-iframe-changing-policy-test-property") {
+ response.write(_getPage("property"));
+ return;
+ }
+
+ // redirect tests with img and iframe
+ if (action === "generate-img-redirect-policy-test") {
+ response.write(createImgTestCase(params, attributePolicy, true));
+ return;
+ }
+ if (action === "generate-iframe-redirect-policy-test") {
+ response.write(
+ createIframeTestPageUsingRefferer(
+ metaPolicy,
+ attributePolicy,
+ newAttributePolicy,
+ name,
+ params,
+ schemeFrom,
+ schemeTo
+ )
+ );
+ return;
+ }
+
+ if (action === "generate-img-policy-test") {
+ response.write(createImgTestCase(params, attributePolicy, false));
+ return;
+ }
+
+ _getPage = createLinkPageUsingRefferer.bind(
+ null,
+ metaPolicy,
+ attributePolicy,
+ newAttributePolicy,
+ name,
+ rel
+ );
+ var _getLinkPage = _getPage.bind(null, buildLinkString, schemeFrom, schemeTo);
+
+ // link
+ if (action === "generate-link-policy-test") {
+ response.write(_getLinkPage());
+ return;
+ }
+ if (action === "generate-link-policy-test-set-attribute") {
+ response.write(_getLinkPage("setAttribute"));
+ return;
+ }
+ if (action === "generate-link-policy-test-property") {
+ response.write(_getLinkPage("property"));
+ return;
+ }
+
+ if (action === "generate-fetch-user-control-policy-test") {
+ response.write(
+ createFetchUserControlRPTestCase(name, schemeFrom, schemeTo, crossOrigin)
+ );
+ return;
+ }
+
+ response.write("I don't know action " + action);
+}
diff --git a/dom/security/test/referrer-policy/test_img_referrer.html b/dom/security/test/referrer-policy/test_img_referrer.html
new file mode 100644
index 0000000000..fcc80929d2
--- /dev/null
+++ b/dom/security/test/referrer-policy/test_img_referrer.html
@@ -0,0 +1,190 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test img policy attribute for Bug 1166910</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+<!--
+Testing that img referrer attribute is honoured correctly
+* Speculative parser loads (generate-img-policy-test)
+* regular loads (generate-img-policy-test2)
+* loading a single image multiple times with different policies (generate-img-policy-test3)
+* testing setAttribute and .referrer (generate-setAttribute-test)
+* regression tests that meta referrer is still working even if attribute referrers are enabled
+https://bugzilla.mozilla.org/show_bug.cgi?id=1166910
+-->
+
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+var advance = function() { tests.next(); };
+
+/**
+ * Listen for notifications from the child.
+ * These are sent in case of error, or when the loads we await have completed.
+ */
+window.addEventListener("message", function(event) {
+ if (event.data == "childLoadComplete" ||
+ event.data.contains("childLoadComplete")) {
+ advance();
+ }
+});
+
+/**
+ * helper to perform an XHR.
+ */
+function doXHR(aUrl, onSuccess, onFail) {
+ var xhr = new XMLHttpRequest();
+ xhr.responseType = "json";
+ xhr.onload = function () {
+ onSuccess(xhr);
+ };
+ xhr.onerror = function () {
+ onFail(xhr);
+ };
+ xhr.open('GET', aUrl, true);
+ xhr.send(null);
+}
+
+/**
+ * Grabs the results via XHR and passes to checker.
+ */
+function checkIndividualResults(aTestname, aExpectedImg, aName) {
+ doXHR('/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=get-test-results',
+ function(xhr) {
+ var results = xhr.response;
+ info(JSON.stringify(xhr.response));
+
+ for (let i in aName) {
+ ok(aName[i] in results.tests, aName[i] + " tests have to be performed.");
+ is(results.tests[aName[i]].policy, aExpectedImg[i], aTestname + ' --- ' + results.tests[aName[i]].policy + ' (' + results.tests[aName[i]].referrer + ')');
+ }
+
+ advance();
+ },
+ function(xhr) {
+ ok(false, "Can't get results from the counter server.");
+ SimpleTest.finish();
+ });
+}
+
+function resetState() {
+ doXHR('/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=resetState',
+ advance,
+ function(xhr) {
+ ok(false, "error in reset state");
+ SimpleTest.finish();
+ });
+}
+
+/**
+ * testing if img referrer attribute is honoured (1165501)
+ */
+var tests = (function*() {
+
+ yield SpecialPowers.pushPrefEnv(
+ { set: [["network.http.referer.disallowCrossSiteRelaxingDefault", false]] },
+ advance
+ );
+
+ var iframe = document.getElementById("testframe");
+ var sjs = "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-img-policy-test";
+
+ // setting img unsafe-url and meta origin - unsafe-url shall prevail (should use speculative load)
+ yield resetState();
+ var name = 'unsaf-url-with-meta-in-origin';
+ yield iframe.src = sjs + "&imgPolicy=" + escape('unsafe-url') + "&name=" + name + "&policy=" + escape('origin');
+ yield checkIndividualResults("unsafe-url (img) with origin in meta", ["full"], [name]);
+
+ // setting img no-referrer and meta default - no-referrer shall prevail (should use speculative load)
+ yield resetState();
+ name = 'no-referrer-with-meta-in-origin';
+ yield iframe.src = sjs + "&imgPolicy=" + escape('no-referrer')+ "&name=" + name + "&policy=" + escape('origin');
+ yield checkIndividualResults("no-referrer (img) with default in meta", ["none"], [name]);
+
+ // test referrer policy in regular load
+ yield resetState();
+ sjs = "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-img-policy-test2";
+ name = 'regular-load-unsafe-url';
+ yield iframe.src = sjs + "&imgPolicy=" + escape('unsafe-url') + "&name=" + name;
+ yield checkIndividualResults("unsafe-url in img", ["full"], [name]);
+
+ // test referrer policy in regular load with multiple images
+ var policies = ['unsafe-url', 'origin', 'no-referrer'];
+ var expected = ["full", "origin", "none"];
+ yield resetState();
+ sjs = "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-img-policy-test3";
+ name = 'multiple-images-'+policies[0]+'-'+policies[1]+'-'+policies[2];
+ yield iframe.src = sjs + "&imgPolicy1=" + escape(policies[0]) + "&imgPolicy2=" + escape(policies[1]) + "&imgPolicy3=" + escape(policies[2]) + "&name=" + name;
+ yield checkIndividualResults(policies[0]+", "+policies[1]+" and "+policies[2]+" in img", expected, [name+policies[0], name+policies[1], name+policies[2]]);
+
+ policies = ['origin', 'no-referrer', 'unsafe-url'];
+ expected = ["origin", "none", "full"];
+ yield resetState();
+ sjs = "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-img-policy-test3";
+ name = 'multiple-images-'+policies[0]+'-'+policies[1]+'-'+policies[2];
+ yield iframe.src = sjs + "&imgPolicy1=" + escape(policies[0]) + "&imgPolicy2=" + escape(policies[1]) + "&imgPolicy3=" + escape(policies[2]) + "&name=" + name;
+ yield checkIndividualResults(policies[0]+", "+policies[1]+" and "+policies[2]+" in img", expected, [name+policies[0], name+policies[1], name+policies[2]]);
+
+ policies = ['no-referrer', 'origin', 'unsafe-url'];
+ expected = ["none", "origin", "full"];
+ yield resetState();
+ sjs = "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-img-policy-test3";
+ name = 'multiple-images-'+policies[0]+'-'+policies[1]+'-'+policies[2];
+ yield iframe.src = sjs + "&imgPolicy1=" + escape(policies[0]) + "&imgPolicy2=" + escape(policies[1]) + "&imgPolicy3=" + escape(policies[2]) + "&name=" + name;
+ yield checkIndividualResults(policies[0]+", "+policies[1]+" and "+policies[2]+" in img", expected, [name+policies[0], name+policies[1], name+policies[2]]);
+
+ // regression tests that meta referrer is still working even if attribute referrers are enabled
+ yield resetState();
+ sjs = "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-img-policy-test4";
+ name = 'regular-load-no-referrer-meta';
+ yield iframe.src = sjs + "&policy=" + escape('no-referrer') + "&name=" + name;
+ yield checkIndividualResults("no-referrer in meta (no img referrer policy), speculative load", ["none"], [name]);
+
+ yield resetState();
+ sjs = "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-img-policy-test5";
+ name = 'regular-load-no-referrer-meta';
+ yield iframe.src = sjs + "&policy=" + escape('no-referrer') + "&name=" + name;
+ yield checkIndividualResults("no-referrer in meta (no img referrer policy), regular load", ["none"], [name]);
+
+ //test setAttribute
+ yield resetState();
+ sjs = "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-setAttribute-test1";
+ name = 'set-referrer-policy-attribute-before-src';
+ yield iframe.src = sjs + "&imgPolicy=" + escape('no-referrer') + "&policy=" + escape('unsafe-url') + "&name=" + name;
+ yield checkIndividualResults("no-referrer in img", ["none"], [name]);
+
+ yield resetState();
+ sjs = "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-setAttribute-test2";
+ name = 'set-referrer-policy-attribute-after-src';
+ yield iframe.src = sjs + "&imgPolicy=" + escape('no-referrer') + "&policy=" + escape('unsafe-url') + "&name=" + name;
+ yield checkIndividualResults("no-referrer in img", ["none"], [name]);
+
+ yield resetState();
+ sjs =
+ "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-setAttribute-test2";
+ name = 'set-invalid-referrer-policy-attribute-before-src-invalid';
+ yield iframe.src = sjs + "&imgPolicy=" + escape('invalid') + "&policy=" + escape('unsafe-url') + "&name=" + name;
+ yield checkIndividualResults("unsafe-url in meta, invalid in img", ["full"], [name]);
+
+ yield resetState();
+ sjs =
+ "/tests/dom/security/test/referrer-policy/img_referrer_testserver.sjs?action=generate-setAttribute-test2";
+ name = 'set-invalid-referrer-policy-attribute-before-src-invalid';
+ yield iframe.src = sjs + "&imgPolicy=" + escape('default') + "&policy=" + escape('unsafe-url') + "&name=" + name;
+ yield checkIndividualResults("unsafe-url in meta, default in img", ["full"], [name]);
+
+ // complete.
+ SimpleTest.finish();
+})();
+
+</script>
+</head>
+
+<body onload="tests.next();">
+ <iframe id="testframe"></iframe>
+
+</body>
+</html>
diff --git a/dom/security/test/referrer-policy/test_referrer_header_current_document.html b/dom/security/test/referrer-policy/test_referrer_header_current_document.html
new file mode 100644
index 0000000000..27dc54a21f
--- /dev/null
+++ b/dom/security/test/referrer-policy/test_referrer_header_current_document.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test referrer header not affecting document.referrer for current document for Bug 1601743</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!--
+ Testing that navigating to a document with Referrer-Policy:same-origin doesn't affect
+ the value of document.referrer for that document.
+ https://bugzilla.mozilla.org/show_bug.cgi?id=1601743
+ -->
+
+ <script type="application/javascript">
+ function getExpectedReferrer(referrer) {
+ let defaultPolicy = SpecialPowers.getIntPref("network.http.referer.defaultPolicy");
+ SimpleTest.ok([2, 3].indexOf(defaultPolicy) > -1, "default referrer policy should be either strict-origin-when-cross-origin(2) or no-referrer-when-downgrade(3)");
+ if (defaultPolicy == 2) {
+ return referrer.match(/https?:\/\/[^\/]+\/?/i)[0];
+ }
+ return referrer;
+ }
+ const IFRAME_URL = `${location.origin}/tests/dom/security/test/referrer-policy/referrer_header_current_document_iframe.html`;
+
+ SimpleTest.waitForExplicitFinish();
+ window.addEventListener("message", (event) => {
+ SimpleTest.is(event.data, getExpectedReferrer(IFRAME_URL), "Must have the original iframe as the referrer!");
+ SimpleTest.finish();
+ }, { once: true });
+ </script>
+</head>
+
+<body>
+<iframe src="referrer_header_current_document_iframe.html"></iframe>
+</body>
diff --git a/dom/security/test/referrer-policy/test_referrer_redirect.html b/dom/security/test/referrer-policy/test_referrer_redirect.html
new file mode 100644
index 0000000000..df7a75a19c
--- /dev/null
+++ b/dom/security/test/referrer-policy/test_referrer_redirect.html
@@ -0,0 +1,171 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test anchor and area policy attribute for Bug 1184781</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+ <!--
+ Testing referrer headers after redirects.
+ https://bugzilla.mozilla.org/show_bug.cgi?id=1184781
+ -->
+
+ <script type="application/javascript">
+
+ const SJS = "://example.com/tests/dom/security/test/referrer-policy/referrer_testserver.sjs?";
+ const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY", "RP_HEADER", "HSTS"];
+
+ const testCases = [
+ {ACTION: ["generate-img-redirect-policy-test", "generate-iframe-redirect-policy-test"],
+ TESTS: [
+ {
+ ATTRIBUTE_POLICY: "no-referrer",
+ NAME: "no-referrer-with-no-meta",
+ DESC: "no-referrer (img/iframe) with no meta",
+ RESULT: "none"
+ },
+ {
+ ATTRIBUTE_POLICY: "origin",
+ NAME: "origin-with-no-meta",
+ DESC: "origin (img/iframe) with no meta",
+ RESULT: "origin"
+ },
+ {
+ ATTRIBUTE_POLICY: "unsafe-url",
+ NAME: "unsafe-url-with-no-meta",
+ DESC: "unsafe-url (img/iframe) with no meta",
+ RESULT: "full"
+ },
+ {
+ META_POLICY: "unsafe-url",
+ NAME: "unsafe-url-in-meta",
+ DESC: "unsafe-url in meta",
+ RESULT: "full"
+ },
+ {
+ META_POLICY: "origin",
+ NAME: "origin-in-meta",
+ DESC: "origin in meta",
+ RESULT: "origin"
+ },
+ {
+ META_POLICY: "no-referrer",
+ NAME: "no-referrer-in-meta",
+ DESC: "no-referrer in meta",
+ RESULT: "none"
+ },
+ {
+ META_POLICY: "origin-when-cross-origin",
+ NAME: "origin-when-cross-origin-in-meta",
+ DESC: "origin-when-cross-origin in meta",
+ RESULT: "origin"
+ },
+ {
+ ATTRIBUTE_POLICY: "no-referrer",
+ RP_HEADER: "origin",
+ NAME: "no-referrer-with-no-meta-origin-RP-header",
+ DESC: "no-referrer (img/iframe) with no meta, origin Referrer-Policy redirect header",
+ RESULT: "none"
+ },
+ {
+ ATTRIBUTE_POLICY: "origin",
+ RP_HEADER: "no-referrer",
+ NAME: "origin-with-no-meta-no-referrer-RP-header",
+ DESC: "origin (img/iframe) with no meta, no-referrer Referrer-Policy redirect header",
+ RESULT: "none"
+ },
+ {
+ ATTRIBUTE_POLICY: "unsafe-url",
+ RP_HEADER: "origin",
+ NAME: "unsafe-url-with-no-meta-origin-RP-header",
+ DESC: "unsafe-url (img/iframe) with no meta, origin Referrer-Policy redirect header",
+ RESULT: "origin"
+ },
+ {
+ META_POLICY: "unsafe-url",
+ RP_HEADER: "origin",
+ NAME: "unsafe-url-in-meta-origin-RP-header",
+ DESC: "unsafe-url in meta, origin Referrer-Policy redirect header",
+ RESULT: "origin"
+ },
+ {
+ META_POLICY: "origin",
+ RP_HEADER: "no-referrer",
+ NAME: "origin-in-meta-no-referrer-RP-header",
+ DESC: "origin in meta, no-referrer Referrer-Policy redirect header",
+ RESULT: "none"
+ },
+ {
+ META_POLICY: "no-referrer",
+ RP_HEADER: "origin",
+ NAME: "no-referrer-in-meta-origin-RP-header",
+ DESC: "no-referrer in meta, origin Referrer-Policy redirect header",
+ RESULT: "none"
+ },
+ {
+ META_POLICY: "origin-when-cross-origin",
+ RP_HEADER: "unsafe-url",
+ NAME: "origin-when-cross-origin-in-meta-unsafe-url-RP-header",
+ DESC: "origin-when-cross-origin in meta, unsafe-url Referrer-Policy redirect header",
+ RESULT: "origin"
+ }
+ ]
+ },
+ // Check that "internal" redirects for mixed content upgrading
+ // are invisible, but not for HSTS upgrades (Bug 1857894).
+ {
+ ACTION: ["generate-img-policy-test"],
+ PREFS: [
+ ["security.mixed_content.upgrade_display_content", true],
+ ["security.mixed_content.upgrade_display_content.image", true],
+ ],
+ TESTS: [
+ {
+ META_POLICY: "strict-origin",
+ NAME: "img-strict-origin-mixed-content-upgrade",
+ DESC: "img-strict-origin-mixed-content-upgrade",
+ SCHEME_FROM: "https",
+ RESULT: "other-origin",
+ },
+ ]
+ },
+ {
+ ACTION: ["generate-img-policy-test"],
+ PREFS: [["security.mixed_content.upgrade_display_content", false]],
+ TESTS: [
+ {
+ META_POLICY: "strict-origin",
+ NAME: "img-strict-origin-mixed-content-no-upgrade",
+ DESC: "img-strict-origin-mixed-content-no-upgrade",
+ SCHEME_FROM: "https",
+ RESULT: "none",
+ },
+ ]
+ },
+ {
+ ACTION: ["generate-img-policy-test"],
+ PREFS: [
+ ["security.mixed_content.upgrade_display_content", false],
+ ["network.stricttransportsecurity.preloadlist", true],
+ ],
+ TESTS: [
+ {
+ META_POLICY: "strict-origin",
+ NAME: "img-strict-origin-hsts-upgrade",
+ DESC: "img-strict-origin-hsts-upgrade",
+ SCHEME_FROM: "https",
+ RESULT: "none",
+ HSTS: true,
+ },
+ ]
+ }
+ ];
+ </script>
+ <script type="application/javascript" src="/tests/dom/security/test/referrer-policy/referrer_helper.js"></script>
+</head>
+<body onload="tests.next();">
+ <iframe id="testframe"></iframe>
+</body>
+</html>
+