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";
function cookiesToMime(cookies) {
return `dummy/${encodeURIComponent(cookies)}`.toLowerCase();
}
function mimeToCookies(mime) {
return decodeURIComponent(mime.replace("dummy/", ""));
}
const server = createHttpServer({ hosts: ["example.net"] });
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", cookiesToMime(cookies));
// Response of length 7.
response.write("1234567");
});
const DOWNLOAD_URL = "http://example.net/download";
async function setUpCookies() {
Services.cookies.removeAll();
let extension = ExtensionTestUtils.loadExtension({
incognitoOverride: "spanning",
manifest: {
permissions: ["cookies", "http://example.net/download"],
},
async background() {
// Add default cookie
await browser.cookies.set({
url,
name: "cookie_normal",
value: "1",
});
// Add private cookie
await browser.cookies.set({
url,
storeId: "firefox-private",
name: "cookie_private",
value: "1",
});
// Add container cookie
await browser.cookies.set({
url,
storeId: "firefox-container-1",
name: "cookie_container",
value: "1",
});
browser.test.sendMessage("cookies set");
},
});
await extension.startup();
await extension.awaitMessage("cookies set");
await extension.unload();
}
function createDownloadTestExtension(extraPermissions = [], incognito = false) {
let extensionOptions = {
manifest: {
permissions: ["downloads", ...extraPermissions],
},
background() {
browser.test.onMessage.addListener(async (method, data) => {
async function getDownload(data) {
let donePromise = new Promise(resolve => {
browser.downloads.onChanged.addListener(async delta => {
if (delta.state?.current === "complete") {
resolve(delta.id);
}
});
});
let downloadId = await browser.downloads.download(data);
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");
return download;
}
function checkDownloadError(data) {
return browser.test.assertRejects(
browser.downloads.download(data.downloadData),
data.exceptionRe
);
}
function search(data) {
return browser.downloads.search(data);
}
function erase(data) {
return browser.downloads.erase(data);
}
switch (method) {
case "getDownload":
return browser.test.sendMessage(method, await getDownload(data));
case "checkDownloadError":
return browser.test.sendMessage(
method,
await checkDownloadError(data)
);
case "search":
return browser.test.sendMessage(method, await search(data));
case "erase":
return browser.test.sendMessage(method, await erase(data));
}
});
},
};
if (incognito) {
extensionOptions.incognitoOverride = "spanning";
}
return ExtensionTestUtils.loadExtension(extensionOptions);
}
function getResult(extension, method, data) {
extension.sendMessage(method, data);
return extension.awaitMessage(method);
}
async function getCookies(extension, data) {
let download = await getResult(extension, "getDownload", data);
// The "/download" endpoint mirrors received cookies via Content-Type.
let cookies = mimeToCookies(download.mime);
return cookies;
}
async function runTests(extension, containerDownloadAllowed, privateAllowed) {
let forcedIncognitoException = null;
if (!privateAllowed) {
forcedIncognitoException = /private browsing access not allowed/;
} else if (!containerDownloadAllowed) {
forcedIncognitoException = /No permission for cookieStoreId/;
}
// Test default container download
if (containerDownloadAllowed) {
equal(
await getCookies(extension, {
url: DOWNLOAD_URL,
cookieStoreId: "firefox-default",
}),
"cookie_normal=1",
"Default container cookies for downloads.download"
);
} else {
await getResult(extension, "checkDownloadError", {
exceptionRe: /No permission for cookieStoreId/,
downloadData: {
url: DOWNLOAD_URL,
cookieStoreId: "firefox-default",
},
});
}
// Test private container download
if (privateAllowed && containerDownloadAllowed) {
equal(
await getCookies(extension, {
url: DOWNLOAD_URL,
cookieStoreId: "firefox-private",
incognito: true,
}),
"cookie_private=1",
"Private container cookies for downloads.download"
);
} else {
await getResult(extension, "checkDownloadError", {
exceptionRe: forcedIncognitoException,
downloadData: {
url: DOWNLOAD_URL,
cookieStoreId: "firefox-private",
incognito: true,
},
});
}
// Test firefox-container-1 download
if (containerDownloadAllowed) {
equal(
await getCookies(extension, {
url: DOWNLOAD_URL,
cookieStoreId: "firefox-container-1",
}),
"cookie_container=1",
"firefox-container-1 cookies for downloads.download"
);
} else {
await getResult(extension, "checkDownloadError", {
exceptionRe: /No permission for cookieStoreId/,
downloadData: {
url: DOWNLOAD_URL,
cookieStoreId: "firefox-container-1",
},
});
}
// Test mismatched incognito and cookieStoreId download
await getResult(extension, "checkDownloadError", {
exceptionRe: forcedIncognitoException
? forcedIncognitoException
: /Illegal to set non-private cookieStoreId in a private window/,
downloadData: {
url: DOWNLOAD_URL,
incognito: true,
cookieStoreId: "firefox-container-1",
},
});
await getResult(extension, "checkDownloadError", {
exceptionRe: containerDownloadAllowed
? /Illegal to set private cookieStoreId in a non-private window/
: /No permission for cookieStoreId/,
downloadData: {
url: DOWNLOAD_URL,
incognito: false,
cookieStoreId: "firefox-private",
},
});
// Test invalid cookieStoreId download
await getResult(extension, "checkDownloadError", {
exceptionRe: containerDownloadAllowed
? /Illegal cookieStoreId/
: /No permission for cookieStoreId/,
downloadData: {
url: DOWNLOAD_URL,
cookieStoreId: "invalid-invalid-invalid",
},
});
let searchRes, searchResDownload;
// Test default container search
searchRes = await getResult(extension, "search", {
cookieStoreId: "firefox-default",
});
equal(
searchRes.length,
1,
"Default container results length for downloads.search"
);
[searchResDownload] = searchRes;
equal(
mimeToCookies(searchResDownload.mime),
"cookie_normal=1",
"Default container cookies for downloads.search"
);
// Test default container search with mismatched container
searchRes = await getResult(extension, "search", {
mime: cookiesToMime("cookie_normal=1"),
cookieStoreId: "firefox-container-1",
});
equal(
searchRes.length,
0,
"Default container results length for downloads.search when container mismatched"
);
// Test private container search
searchRes = await getResult(extension, "search", {
cookieStoreId: "firefox-private",
});
if (privateAllowed) {
equal(
searchRes.length,
1,
"Private container results length for downloads.search"
);
[searchResDownload] = searchRes;
equal(
mimeToCookies(searchResDownload.mime),
"cookie_private=1",
"Private container cookies for downloads.search"
);
// Test private container search with mismatched container
searchRes = await getResult(extension, "search", {
mime: cookiesToMime("cookie_private=1"),
cookieStoreId: "firefox-container-1",
});
equal(
searchRes.length,
0,
"Private container results length for downloads.search when container mismatched"
);
} else {
equal(
searchRes.length,
0,
"Private container results length for downloads.search when private disallowed"
);
}
// Test firefox-container-1 search
searchRes = await getResult(extension, "search", {
cookieStoreId: "firefox-container-1",
});
equal(
searchRes.length,
1,
"firefox-container-1 results length for downloads.search"
);
[searchResDownload] = searchRes;
equal(
mimeToCookies(searchResDownload.mime),
"cookie_container=1",
"firefox-container-1 cookies for downloads.search"
);
// Test firefox-container-1 search with mismatched container
searchRes = await getResult(extension, "search", {
mime: cookiesToMime("cookie_container=1"),
cookieStoreId: "firefox-default",
});
equal(
searchRes.length,
0,
"firefox-container-1 container results length for downloads.search when container mismatched"
);
// Test default container erase with mismatched container
await getResult(extension, "erase", {
mime: cookiesToMime("cookie_normal=1"),
cookieStoreId: "firefox-container-1",
});
searchRes = await getResult(extension, "search", {
mime: cookiesToMime("cookie_normal=1"),
});
equal(
searchRes.length,
1,
"Default container results length for downloads.search after erase with mismatched container"
);
// Test private container erase with mismatched container
await getResult(extension, "erase", {
mime: cookiesToMime("cookie_private=1"),
cookieStoreId: "firefox-container-1",
});
searchRes = await getResult(extension, "search", {
mime: cookiesToMime("cookie_private=1"),
});
equal(
searchRes.length,
privateAllowed ? 1 : 0,
"Private container results length for downloads.search after erase with mismatched container"
);
// Test firefox-container-1 erase with mismatched container
await getResult(extension, "erase", {
mime: cookiesToMime("cookie_container=1"),
cookieStoreId: "firefox-default",
});
searchRes = await getResult(extension, "search", {
mime: cookiesToMime("cookie_container=1"),
});
equal(
searchRes.length,
1,
"firefox-container-1 results length for downloads.search after erase with mismatched container"
);
// Test default container erase
await getResult(extension, "erase", {
cookieStoreId: "firefox-default",
});
searchRes = await getResult(extension, "search", {
mime: cookiesToMime("cookie_normal=1"),
});
equal(
searchRes.length,
0,
"Default container results length for downloads.search after erase"
);
// Test private container erase
await getResult(extension, "erase", {
cookieStoreId: "firefox-private",
});
searchRes = await getResult(extension, "search", {
mime: cookiesToMime("cookie_private=1"),
});
// The following will also pass when incognito disabled
equal(
searchRes.length,
0,
"Private container results length for downloads.search after erase"
);
// Test firefox-container-1 erase
await getResult(extension, "erase", {
cookieStoreId: "firefox-container-1",
});
searchRes = await getResult(extension, "search", {
mime: cookiesToMime("cookie_container=1"),
});
equal(
searchRes.length,
0,
"firefox-container-1 results length for downloads.search after erase"
);
}
async function populateDownloads(extension) {
await getResult(extension, "erase", {});
await getResult(extension, "getDownload", {
url: DOWNLOAD_URL,
});
await getResult(extension, "getDownload", {
url: DOWNLOAD_URL,
incognito: true,
});
await getResult(extension, "getDownload", {
url: DOWNLOAD_URL,
cookieStoreId: "firefox-container-1",
});
}
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);
Services.prefs.setBoolPref("privacy.userContext.enabled", true);
await setUpCookies();
registerCleanupFunction(() => {
Services.cookies.removeAll();
Services.prefs.clearUserPref("browser.download.folderList");
Services.prefs.clearUserPref("browser.download.dir");
downloadDir.remove(false);
});
});
add_task(async function download_cookieStoreId() {
// Test extension with cookies permission and incognito enabled
let extension = createDownloadTestExtension(["cookies"], true);
await extension.startup();
await runTests(extension, true, true);
// Test extension with incognito enabled and no cookies permission
await populateDownloads(extension);
let noCookiesExtension = createDownloadTestExtension([], true);
await noCookiesExtension.startup();
await runTests(noCookiesExtension, false, true);
await noCookiesExtension.unload();
// Test extension with incognito disabled and no cookies permission
await populateDownloads(extension);
let noCookiesAndPrivateExtension = createDownloadTestExtension([], false);
await noCookiesAndPrivateExtension.startup();
await runTests(noCookiesAndPrivateExtension, false, false);
await noCookiesAndPrivateExtension.unload();
// Verify that incognito disabled test did not delete private download
let searchRes = await getResult(extension, "search", {
mime: cookiesToMime("cookie_private=1"),
});
ok(searchRes.length, "Incognito disabled does not delete private download");
await extension.unload();
});