/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; const UCT_URI = "chrome://mozapps/content/downloads/unknownContentType.xhtml"; async function promiseDownloadFinished(list) { return new Promise(resolve => { list.addView({ onDownloadChanged(download) { info("Download changed!"); if (download.succeeded || download.error) { info("Download succeeded or errored"); list.removeView(this); resolve(download); } }, }); }); } /** * Check that both in the download "what do you want to do with this file" * dialog and in the about:downloads download list, we represent blob URL * download sources using the principal (origin) that generated the blob. */ add_task(async function test_check_blob_origin_representation() { forcePromptForFiles("text/plain", "txt"); await check_blob_origin( "https://example.org/1", "example.org", "example.org" ); await check_blob_origin( "data:text/html,Some Text
", "(data)", "blob" ); }); async function check_blob_origin(pageURL, expectedSource, expectedListOrigin) { await BrowserTestUtils.withNewTab(pageURL, async browser => { // Ensure we wait for the download to finish: let downloadList = await Downloads.getList(Downloads.PUBLIC); let downloadPromise = promiseDownloadFinished(downloadList); // Wait for the download prompting dialog let dialogPromise = BrowserTestUtils.domWindowOpenedAndLoaded( null, win => win.document.documentURI == UCT_URI ); // create and click an link to a txt file. await SpecialPowers.spawn(browser, [], () => { // Use `eval` to get a blob URL scoped to content, so that content is // actually allowed to open it and so we can check the origin is correct. let url = content.eval(` window.foo = new Blob(["Hello"], {type: "text/plain"}); URL.createObjectURL(window.foo)`); let link = content.document.createElement("a"); link.href = url; link.textContent = "Click me, click me, me me me"; link.download = "my-file.txt"; content.document.body.append(link); link.click(); }); // Check what we display in the dialog let dialogWin = await dialogPromise; let source = dialogWin.document.getElementById("source"); is( source.value, expectedSource, "Should list origin as source if available." ); // Close the dialog let closedPromise = BrowserTestUtils.windowClosed(dialogWin); // Ensure we're definitely saving (otherwise this depends on mime service // defaults): dialogWin.document.getElementById("save").click(); let dialogNode = dialogWin.document.querySelector("dialog"); dialogNode.getButton("accept").disabled = false; dialogNode.acceptDialog(); await closedPromise; // Wait for the download to finish and ensure it is cleared up. let download = await downloadPromise; registerCleanupFunction(async () => { let target = download.target.path; await download.finalize(); await IOUtils.remove(target); }); // Check that the same download is displayed correctly in about:downloads. await BrowserTestUtils.withNewTab("about:downloads", async dlBrowser => { let doc = dlBrowser.contentDocument; let listNode = doc.getElementById("downloadsListBox"); await BrowserTestUtils.waitForMutationCondition( listNode, { childList: true, subtree: true, attributeFilter: ["value"] }, () => listNode.firstElementChild ?.querySelector(".downloadDetailsNormal") ?.getAttribute("value") ); let download = listNode.firstElementChild; let detailString = download.querySelector(".downloadDetailsNormal").value; Assert.stringContains( detailString, expectedListOrigin, "Should list origin in download list if available." ); }); }); }