Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const { UrlClassifierTestUtils } = ChromeUtils.importESModule(
);
// Value for network.cookie.cookieBehavior to reject all third-party cookies.
const { BEHAVIOR_REJECT_FOREIGN } = Ci.nsICookieService;
const server = createHttpServer({ hosts: ["example.net", "itisatracker.org"] });
server.registerPathHandler("/setcookies", (request, response) => {
response.setHeader("Content-Type", "text/html; charset=utf-8", false);
response.setHeader("Set-Cookie", "c_none=1; sameSite=none", true);
response.setHeader("Set-Cookie", "c_lax=1; sameSite=lax", true);
response.setHeader("Set-Cookie", "c_strict=1; sameSite=strict", true);
});
server.registerPathHandler("/download", (request, response) => {
response.setStatusLine(request.httpVersion, 200, "OK");
let cookies = request.hasHeader("Cookie") ? request.getHeader("Cookie") : "";
// Assign the result through the MIME-type, to make it easier to read the
// result via the downloads API.
response.setHeader("Content-Type", `dummy/${encodeURIComponent(cookies)}`);
// Response of length 7.
response.write("1234567");
});
server.registerPathHandler("/redirect", (request, response) => {
response.setStatusLine(request.httpVersion, 302, "Found");
response.setHeader("Location", "/download");
});
function createDownloadTestExtension(extraPermissions = []) {
return ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["downloads", ...extraPermissions],
},
incognitoOverride: "spanning",
background() {
async function getCookiesForDownload(url) {
let donePromise = new Promise(resolve => {
browser.downloads.onChanged.addListener(async delta => {
if (delta.state?.current === "complete") {
resolve(delta.id);
}
});
});
// TODO bug 1653636: Remove this when the correct browsing mode is used.
const incognito = browser.extension.inIncognitoContext;
let downloadId = await browser.downloads.download({ url, incognito });
browser.test.assertEq(await donePromise, downloadId, "got download");
let [download] = await browser.downloads.search({ id: downloadId });
browser.test.log(`Download results: ${JSON.stringify(download)}`);
// Delete the file since we aren't interested in it.
// TODO bug 1654819: On Windows the file may be recreated.
await browser.downloads.removeFile(download.id);
// Sanity check to verify that we got the result from /download.
browser.test.assertEq(7, download.fileSize, "download succeeded");
// The "/download" endpoint mirrors received cookies via Content-Type.
let cookies = decodeURIComponent(download.mime.replace("dummy/", ""));
return cookies;
}
browser.test.onMessage.addListener(async url => {
browser.test.sendMessage("result", await getCookiesForDownload(url));
});
},
});
}
async function downloadAndGetCookies(extension, url) {
extension.sendMessage(url);
return extension.awaitMessage("result");
}
add_task(async function setup() {
const nsIFile = Ci.nsIFile;
const downloadDir = FileUtils.getDir("TmpD", ["downloads"]);
downloadDir.createUnique(nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
Services.prefs.setIntPref("browser.download.folderList", 2);
Services.prefs.setComplexValue("browser.download.dir", nsIFile, downloadDir);
// Support sameSite=none despite the server using http instead of https.
Services.prefs.setBoolPref(
"network.cookie.sameSite.noneRequiresSecure",
false
);
async function loadAndClose(url) {
let contentPage = await ExtensionTestUtils.loadContentPage(url);
await contentPage.close();
}
// Generate cookies for use in this test.
await loadAndClose("http://example.net/setcookies");
await loadAndClose("http://itisatracker.org/setcookies");
await UrlClassifierTestUtils.addTestTrackers();
registerCleanupFunction(() => {
UrlClassifierTestUtils.cleanupTestTrackers();
Services.cookies.removeAll();
Services.prefs.clearUserPref("browser.download.folderList");
Services.prefs.clearUserPref("browser.download.dir");
downloadDir.remove(false);
});
});
// Checks that (sameSite) cookies are included in download requests.
add_task(async function download_cookies_basic() {
let extension = createDownloadTestExtension(["*://example.net/*"]);
await extension.startup();
equal(
await downloadAndGetCookies(extension, "http://example.net/download"),
"c_none=1; c_lax=1; c_strict=1",
"Cookies for downloads.download with sameSite cookies"
);
equal(
await downloadAndGetCookies(extension, "http://example.net/redirect"),
"c_none=1; c_lax=1; c_strict=1",
"Cookies for downloads.download with redirect"
);
await runWithPrefs(
[["network.cookie.cookieBehavior", BEHAVIOR_REJECT_FOREIGN]],
async () => {
equal(
await downloadAndGetCookies(extension, "http://example.net/download"),
"c_none=1; c_lax=1; c_strict=1",
"Cookies for downloads.download with all third-party cookies disabled"
);
}
);
await extension.unload();
});
// Checks that (sameSite) cookies are included even when tracking protection
// would block cookies from third-party requests.
add_task(async function download_cookies_from_tracker_url() {
let extension = createDownloadTestExtension(["*://itisatracker.org/*"]);
await extension.startup();
equal(
await downloadAndGetCookies(extension, "http://itisatracker.org/download"),
"c_none=1; c_lax=1; c_strict=1",
"Cookies for downloads.download of itisatracker.org"
);
await extension.unload();
});
// Checks that (sameSite) cookies are included even without host permissions.
add_task(async function download_cookies_without_host_permissions() {
let extension = createDownloadTestExtension();
await extension.startup();
equal(
await downloadAndGetCookies(extension, "http://example.net/download"),
"c_none=1; c_lax=1; c_strict=1",
"Cookies for downloads.download without host permissions"
);
equal(
await downloadAndGetCookies(extension, "http://itisatracker.org/download"),
"c_none=1; c_lax=1; c_strict=1",
"Cookies for downloads.download of itisatracker.org"
);
await runWithPrefs(
[["network.cookie.cookieBehavior", BEHAVIOR_REJECT_FOREIGN]],
async () => {
equal(
await downloadAndGetCookies(extension, "http://example.net/download"),
"c_none=1; c_lax=1; c_strict=1",
"Cookies for downloads.download with all third-party cookies disabled"
);
}
);
await extension.unload();
});
// Checks that (sameSite) cookies from private browsing are included.
add_task(async function download_cookies_in_perma_private_browsing() {
Services.prefs.setBoolPref("browser.privatebrowsing.autostart", true);
Services.prefs.setBoolPref("dom.security.https_first_pbm", false);
let extension = createDownloadTestExtension(["*://example.net/*"]);
await extension.startup();
equal(
await downloadAndGetCookies(extension, "http://example.net/download"),
"",
"Initially no cookies in permanent private browsing mode"
);
let contentPage = await ExtensionTestUtils.loadContentPage(
{ privateBrowsing: true }
);
equal(
await downloadAndGetCookies(extension, "http://example.net/download"),
"c_none=1; c_lax=1; c_strict=1",
"Cookies for downloads.download in perma-private-browsing mode"
);
await extension.unload();
await contentPage.close();
Services.prefs.clearUserPref("browser.privatebrowsing.autostart");
Services.prefs.clearUserPref("dom.security.https_first_pbm");
});