Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'win' && socketprocess_networking && fission OR os == 'mac' && socketprocess_networking && fission OR os == 'mac' && debug OR os == 'linux' && socketprocess_networking OR os == 'android'
- Manifest: toolkit/components/extensions/test/xpcshell/xpcshell-remote.toml includes toolkit/components/extensions/test/xpcshell/xpcshell-common.toml
- Manifest: toolkit/components/extensions/test/xpcshell/xpcshell.toml includes toolkit/components/extensions/test/xpcshell/xpcshell-common.toml
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const { Downloads } = ChromeUtils.importESModule(
"resource://gre/modules/Downloads.sys.mjs"
);
const server = createHttpServer();
server.registerDirectory("/data/", do_get_file("data"));
const TEST_FILE = "file_download.txt";
const TEST_URL = BASE + "/" + TEST_FILE;
// We use different cookieBehaviors so that we can verify if we use the correct
// cookieBehavior if option.incognito is set. Note that we need to set a
// non-default value to the private cookieBehavior because the private
// cookieBehavior will mirror the regular cookieBehavior if the private pref is
// default value and the regular pref is non-default value. To avoid affecting
// the test by mirroring, we set the private cookieBehavior to a non-default
// value.
const TEST_REGULAR_COOKIE_BEHAVIOR =
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER;
const TEST_PRIVATE_COOKIE_BEHAVIOR = Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN;
let downloadDir;
function observeDownloadChannel(uri, partitionKey, isPrivate) {
return new Promise(resolve => {
let observer = {
observe(subject, topic) {
if (topic === "http-on-modify-request") {
let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
if (httpChannel.URI.spec != uri) {
return;
}
let reqLoadInfo = httpChannel.loadInfo;
let cookieJarSettings = reqLoadInfo.cookieJarSettings;
// Check the partitionKey of the cookieJarSettings.
equal(
cookieJarSettings.partitionKey,
partitionKey,
"The loadInfo has the correct paritionKey"
);
// Check the cookieBehavior of the cookieJarSettings.
equal(
cookieJarSettings.cookieBehavior,
isPrivate
? TEST_PRIVATE_COOKIE_BEHAVIOR
: TEST_REGULAR_COOKIE_BEHAVIOR,
"The loadInfo has the correct cookieBehavior"
);
Services.obs.removeObserver(observer, "http-on-modify-request");
resolve();
}
},
};
Services.obs.addObserver(observer, "http-on-modify-request");
});
}
async function waitForDownloads() {
let list = await Downloads.getList(Downloads.ALL);
let downloads = await list.getAll();
let inprogress = downloads.filter(dl => !dl.stopped);
return Promise.all(inprogress.map(dl => dl.whenSucceeded()));
}
function backgroundScript() {
browser.test.onMessage.addListener(async (msg, ...args) => {
if (msg == "download.request") {
let options = args[0];
try {
let id = await browser.downloads.download(options);
browser.test.sendMessage("download.done", { status: "success", id });
} catch (error) {
browser.test.sendMessage("download.done", {
status: "error",
errmsg: error.message,
});
}
}
});
browser.test.sendMessage("ready");
}
// Remove a file in the downloads directory.
function remove(filename, recursive = false) {
let file = downloadDir.clone();
file.append(filename);
file.remove(recursive);
}
add_task(function setup() {
downloadDir = FileUtils.getDir("TmpD", ["downloads"]);
downloadDir.createUnique(
Ci.nsIFile.DIRECTORY_TYPE,
FileUtils.PERMS_DIRECTORY
);
info(`Using download directory ${downloadDir.path}`);
Services.prefs.setIntPref("browser.download.folderList", 2);
Services.prefs.setComplexValue(
"browser.download.dir",
Ci.nsIFile,
downloadDir
);
Services.prefs.setBoolPref("privacy.partition.network_state", true);
Services.prefs.setIntPref(
"network.cookie.cookieBehavior",
TEST_REGULAR_COOKIE_BEHAVIOR
);
Services.prefs.setIntPref(
"network.cookie.cookieBehavior.pbmode",
TEST_PRIVATE_COOKIE_BEHAVIOR
);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.download.folderList");
Services.prefs.clearUserPref("browser.download.dir");
Services.prefs.clearUserPref("privacy.partition.network_state");
Services.prefs.clearUserPref("network.cookie.cookieBehavior");
Services.prefs.clearUserPref("network.cookie.cookieBehavior.pbmode");
let entries = downloadDir.directoryEntries;
while (entries.hasMoreElements()) {
let entry = entries.nextFile;
info(`Leftover file ${entry.path} in download directory`);
ok(false, `Leftover file ${entry.path} in download directory`);
entry.remove(false);
}
downloadDir.remove(false);
});
});
add_task(async function test() {
let extension = ExtensionTestUtils.loadExtension({
background: `(${backgroundScript})()`,
manifest: {
permissions: ["downloads"],
},
incognitoOverride: "spanning",
});
function download(options) {
extension.sendMessage("download.request", options);
return extension.awaitMessage("download.done");
}
async function testDownload(url, partitionKey, isPrivate) {
let options = { url, incognito: isPrivate };
let promiseObserveDownloadChannel = observeDownloadChannel(
url,
partitionKey,
isPrivate
);
let msg = await download(options);
equal(msg.status, "success", `downloads.download() works`);
await promiseObserveDownloadChannel;
await waitForDownloads();
}
await extension.startup();
await extension.awaitMessage("ready");
info("extension started");
// Call download() to check partitionKey of the download channel for the
// regular browsing mode.
await testDownload(
TEST_URL,
`(http,localhost,${server.identity.primaryPort})`,
false
);
remove(TEST_FILE);
// Call download again for the private browsing mode.
await testDownload(
TEST_URL,
`(http,localhost,${server.identity.primaryPort})`,
true
);
remove(TEST_FILE);
await extension.unload();
});