Bug 1606300 - escape filenames in tab titles, save as... dialog and as used by webbrowserpersist, r=valentin

The getDefaultFileName helper function does its own filename parsing using header info
it has previously 'manually' retrieved, so it needs to manually unescape its input.

Meanwhile, NS_GetFilenameFromDisposition is used by webbrowserpersist and for
the title of documents, and so updating that helps ensure better UI as well as
correct filename suggestions when saving from the context menu.

Differential Revision: https://phabricator.services.mozilla.com/D61734

--HG--
rename : accessible/tests/mochitest/moz.png => uriloader/exthandler/tests/mochitest/file_with@@funny_name.png
rename : toolkit/components/mediasniffer/test/unit/data/file.webm => uriloader/exthandler/tests/mochitest/file_with[funny_name.webm
extra : moz-landing-system : lando
This commit is contained in:
Gijs Kruitbosch 2020-02-06 18:23:45 +00:00
parent 04ffe0753a
commit 9632554164
8 changed files with 102 additions and 1 deletions

View File

@ -63,6 +63,7 @@
#include "nsIIncrementalStreamLoader.h"
#include "nsStringStream.h"
#include "nsSyncStreamListener.h"
#include "nsITextToSubURI.h"
#include "nsIURIWithSpecialOrigin.h"
#include "nsIViewSourceChannel.h"
#include "nsInterfaceRequestorAgg.h"
@ -2674,6 +2675,19 @@ nsresult NS_GetFilenameFromDisposition(nsAString& aFilename,
if (aFilename.IsEmpty()) return NS_ERROR_NOT_AVAILABLE;
// Filename may still be percent-encoded. Fix:
if (aFilename.FindChar('%') != -1) {
nsCOMPtr<nsITextToSubURI> textToSubURI =
do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
nsAutoString unescaped;
textToSubURI->UnEscapeURIForUI(NS_LITERAL_CSTRING("UTF-8"),
NS_ConvertUTF16toUTF8(aFilename),
unescaped);
aFilename.Assign(unescaped);
}
}
return NS_OK;
}

View File

@ -1197,7 +1197,9 @@ function getDefaultFileName(
} catch (e) {}
}
if (fileName) {
return validateFileName(fileName);
return validateFileName(
Services.textToSubURI.unEscapeURIForUI("UTF-8", fileName)
);
}
}

View File

@ -11,6 +11,12 @@ support-files =
download.sjs
[browser_download_always_ask_preferred_app.js]
[browser_download_privatebrowsing.js]
[browser_download_urlescape.js]
support-files =
file_with@@funny_name.png
file_with@@funny_name.png^headers^
file_with[funny_name.webm
file_with[funny_name.webm^headers^
[browser_protocolhandler_loop.js]
skip-if = fission # Bug 1597154
[browser_remember_download_option.js]

View File

@ -0,0 +1,75 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_PATH = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"https://example.com"
);
var MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init(window);
registerCleanupFunction(() => MockFilePicker.cleanup());
/**
* Check downloading files URL-escapes content-disposition
* information when necessary.
*/
add_task(async function test_check_filename_urlescape() {
let pendingPromise;
let pendingTest = "";
let expectedFileName = "";
MockFilePicker.showCallback = function(fp) {
info(`${pendingTest} - Filepicker shown, checking filename`);
is(
fp.defaultString,
expectedFileName,
`${pendingTest} - Should have escaped filename`
);
ok(
pendingPromise,
`${pendingTest} - Should have expected this picker open.`
);
if (pendingPromise) {
pendingPromise.resolve();
}
return Ci.nsIFilePicker.returnCancel;
};
function runTestFor(fileName, selector) {
return BrowserTestUtils.withNewTab(TEST_PATH + fileName, async browser => {
expectedFileName = fileName;
let tabLabel = gBrowser.getTabForBrowser(browser).getAttribute("label");
ok(
tabLabel.startsWith(fileName),
`"${tabLabel}" should have been escaped.`
);
pendingTest = "save browser";
pendingPromise = PromiseUtils.defer();
// First try to save the browser
saveBrowser(browser);
await pendingPromise.promise;
// Next, try the context menu:
pendingTest = "save from context menu";
pendingPromise = PromiseUtils.defer();
let menu = document.getElementById("contentAreaContextMenu");
let menuShown = BrowserTestUtils.waitForEvent(menu, "popupshown");
BrowserTestUtils.synthesizeMouse(
selector,
5,
5,
{ type: "contextmenu", button: 2 },
browser
);
await menuShown;
gContextMenu.saveMedia();
menu.hidePopup();
await pendingPromise.promise;
pendingPromise = null;
});
}
await runTestFor("file_with@@funny_name.png", "img");
await runTestFor("file_with[funny_name.webm", "video");
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,2 @@
Content-Disposition: inline; filename=file_with%40%40funny_name.png
Content-Type: image/png

View File

@ -0,0 +1,2 @@
Content-Disposition: inline; filename=file_with%5Bfunny_name.webm
Content-Type: video/webm