summaryrefslogtreecommitdiffstats
path: root/dom/security/test/referrer-policy/browser_referrer_disallow_cross_site_relaxing.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/security/test/referrer-policy/browser_referrer_disallow_cross_site_relaxing.js')
-rw-r--r--dom/security/test/referrer-policy/browser_referrer_disallow_cross_site_relaxing.js458
1 files changed, 458 insertions, 0 deletions
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);
+});