Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
"use strict";
const TEST_PATH = getRootDirectory(gTestPath).replace(
);
let gPathsToRemove = [];
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [["browser.download.useDownloadDir", true]],
});
registerCleanupFunction(async () => {
for (let path of gPathsToRemove) {
// IOUtils.remove ignores non-existing files out of the box.
await IOUtils.remove(path);
}
let publicList = await Downloads.getList(Downloads.PUBLIC);
await publicList.removeFinished();
});
});
async function testLinkWithoutExtension(type, shouldHaveExtension) {
info("Checking " + type);
let task = function () {
return SpecialPowers.spawn(gBrowser.selectedBrowser, [type], mimetype => {
let link = content.document.createElement("a");
link.textContent = "Click me";
link.href = "data:" + mimetype + ",hello";
link.download = "somefile";
content.document.body.appendChild(link);
link.click();
});
};
await checkDownloadWithExtensionState(task, {
type,
shouldHaveExtension,
alwaysViewPDFInline: false,
});
if (type == "application/pdf") {
// For PDF, try again with the always open inline preference set
await SpecialPowers.pushPrefEnv({
set: [["browser.download.open_pdf_attachments_inline", true]],
});
await checkDownloadWithExtensionState(task, {
type,
shouldHaveExtension,
alwaysViewPDFInline: true,
});
await SpecialPowers.popPrefEnv();
}
}
async function checkDownloadWithExtensionState(
task,
{ type, shouldHaveExtension, expectedName = null, alwaysViewPDFInline }
) {
const shouldExpectDialog = Services.prefs.getBoolPref(
"browser.download.always_ask_before_handling_new_types",
false
);
let winPromise;
if (shouldExpectDialog) {
winPromise = BrowserTestUtils.domWindowOpenedAndLoaded();
}
let publicList = await Downloads.getList(Downloads.PUBLIC);
let shouldCheckFilename = shouldHaveExtension || !shouldExpectDialog;
let downloadFinishedPromise = shouldCheckFilename
? promiseDownloadFinished(publicList)
: null;
// PDF should load using the internal viewer without downloading it.
let waitForLoad;
if (
(!shouldExpectDialog || alwaysViewPDFInline) &&
type == "application/pdf"
) {
waitForLoad = BrowserTestUtils.waitForNewTab(gBrowser);
}
await task();
await waitForLoad;
let win;
if (shouldExpectDialog) {
info("Waiting for dialog.");
win = await winPromise;
}
expectedName ??= shouldHaveExtension
? "somefile." + getMIMEInfoForType(type).primaryExtension
: "somefile";
let closedPromise = true;
if (shouldExpectDialog) {
let actualName = win.document.getElementById("location").value;
closedPromise = BrowserTestUtils.windowClosed(win);
if (shouldHaveExtension) {
is(actualName, expectedName, `${type} should get an extension`);
} else {
is(actualName, expectedName, `${type} should not get an extension`);
}
}
if (shouldExpectDialog && shouldHaveExtension) {
// Then pick "save" in the dialog, if we have a dialog.
let dialog = win.document.getElementById("unknownContentType");
win.document.getElementById("save").click();
let button = dialog.getButton("accept");
button.disabled = false;
dialog.acceptDialog();
}
if (!shouldExpectDialog && type == "application/pdf") {
if (alwaysViewPDFInline) {
is(
gURLBar.inputField.value,
"data:application/pdf,hello",
"url is correct for " + type
);
} else {
ok(
gURLBar.inputField.value.startsWith("file://") &&
gURLBar.inputField.value.endsWith("somefile.pdf"),
"url is correct for " + type
);
}
BrowserTestUtils.removeTab(gBrowser.selectedTab);
}
if (shouldExpectDialog || !alwaysViewPDFInline || type != "application/pdf") {
// Wait for the download if it exists (may produce null).
let download = await downloadFinishedPromise;
if (download) {
// Check the download's extension is correct.
is(
PathUtils.filename(download.target.path),
expectedName,
`Downloaded file should match ${expectedName}`
);
gPathsToRemove.push(download.target.path);
let pathToRemove = download.target.path;
// Avoid one file interfering with subsequent files.
await publicList.removeFinished();
await IOUtils.remove(pathToRemove);
} else if (win) {
// We just cancel out for files that would end up without a path, as we'd
// prompt for a filename.
win.close();
}
}
return closedPromise;
}
/**
* Check that for document types, images, videos and audio files,
* we enforce a useful extension.
*/
add_task(async function test_enforce_useful_extension() {
await BrowserTestUtils.withNewTab("data:text/html,", async () => {
await testLinkWithoutExtension("image/png", true);
await testLinkWithoutExtension("audio/ogg", true);
await testLinkWithoutExtension("video/webm", true);
await testLinkWithoutExtension("application/pdf", true);
await testLinkWithoutExtension("application/x-nonsense", false);
await testLinkWithoutExtension("application/octet-stream", false);
await testLinkWithoutExtension("binary/octet-stream", false);
await testLinkWithoutExtension("application/x-msdownload", false);
});
});
/**
* Check that we still use URL extension info when we don't have anything else,
* despite bogus local info.
*/
add_task(async function test_broken_saved_handlerinfo_and_useless_mimetypes() {
let bogusType = getMIMEInfoForType("binary/octet-stream");
registerCleanupFunction(() => {
handlerSvc.remove(bogusType);
});
bogusType.setFileExtensions(["jpg"]);
let handlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].getService(
Ci.nsIHandlerService
);
handlerSvc.store(bogusType);
let tabToClean = null;
let task = function () {
return BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: TEST_PATH + "file_as.exe?foo=bar",
waitForLoad: false,
waitForStateStop: true,
}).then(tab => {
return (tabToClean = tab);
});
};
await checkDownloadWithExtensionState(task, {
type: "binary/octet-stream",
shouldHaveExtension: true,
expectedName: "file_as.exe",
});
// Downloads should really close their tabs...
if (tabToClean?.isConnected) {
BrowserTestUtils.removeTab(tabToClean);
}
});