/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; const { HandlerServiceTestUtils } = ChromeUtils.importESModule( "resource://testing-common/HandlerServiceTestUtils.sys.mjs" ); const TEST_PATH = getRootDirectory(gTestPath).replace( "chrome://mochitests/content", "https://example.com" ); async function selectPdfCategoryItem() { await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true }); info("Preferences page opened on the general pane."); await gBrowser.selectedBrowser.contentWindow.promiseLoadHandlersList; info("Apps list loaded."); let win = gBrowser.selectedBrowser.contentWindow; let container = win.document.getElementById("handlersView"); let pdfCategory = container.querySelector( "richlistitem[type='application/pdf']" ); pdfCategory.closest("richlistbox").selectItem(pdfCategory); Assert.ok(pdfCategory.selected, "Should be able to select our item."); return pdfCategory; } async function selectItemInPopup(item, list) { let popup = list.menupopup; let popupShown = BrowserTestUtils.waitForEvent(popup, "popupshown"); // Synthesizing the mouse on the .actionsMenu menulist somehow just selects // the top row. Probably something to do with the multiple layers of anon // content - workaround by using the `.open` setter instead. list.open = true; await popupShown; let popupHidden = BrowserTestUtils.waitForEvent(popup, "popuphidden"); item.click(); popup.hidePopup(); await popupHidden; return item; } function downloadHadFinished(publicList) { return new Promise(resolve => { publicList.addView({ onDownloadChanged(download) { if (download.succeeded || download.error) { publicList.removeView(this); resolve(download); } }, }); }); } async function removeTheFile(download) { Assert.ok( await IOUtils.exists(download.target.path), "The file should have been downloaded." ); try { info("removing " + download.target.path); if (Services.appinfo.OS === "WINNT") { // We need to make the file writable to delete it on Windows. await IOUtils.setPermissions(download.target.path, 0o600); } await IOUtils.remove(download.target.path); } catch (ex) { info("The file " + download.target.path + " is not removed, " + ex); } } add_task(async function alwaysAskPreferenceWorks() { await SpecialPowers.pushPrefEnv({ set: [ ["browser.download.always_ask_before_handling_new_types", false], ["browser.download.useDownloadDir", true], ], }); let pdfCategory = await selectPdfCategoryItem(); let list = pdfCategory.querySelector(".actionsMenu"); let alwaysAskItem = list.querySelector( `menuitem[action='${Ci.nsIHandlerInfo.alwaysAsk}']` ); await selectItemInPopup(alwaysAskItem, list); Assert.equal( list.selectedItem, alwaysAskItem, "Should have selected 'always ask' for pdf" ); let alwaysAskBeforeHandling = HandlerServiceTestUtils.getHandlerInfo( pdfCategory.getAttribute("type") ).alwaysAskBeforeHandling; Assert.ok( alwaysAskBeforeHandling, "Should have turned on 'always asking before handling'" ); let domWindowPromise = BrowserTestUtils.domWindowOpenedAndLoaded(); let loadingTab = await BrowserTestUtils.openNewForegroundTab({ gBrowser, opening: TEST_PATH + "empty_pdf_file.pdf", waitForLoad: false, waitForStateStop: true, }); let domWindow = await domWindowPromise; let dialog = domWindow.document.querySelector("#unknownContentType"); let button = dialog.getButton("cancel"); await TestUtils.waitForCondition( () => !button.disabled, "Wait for Cancel button to get enabled" ); Assert.ok(dialog, "Dialog should be shown"); dialog.cancelDialog(); BrowserTestUtils.removeTab(loadingTab); gBrowser.removeCurrentTab(); }); add_task(async function handleInternallyPreferenceWorks() { await SpecialPowers.pushPrefEnv({ set: [ ["browser.download.always_ask_before_handling_new_types", false], ["browser.download.useDownloadDir", true], ], }); let pdfCategory = await selectPdfCategoryItem(); let list = pdfCategory.querySelector(".actionsMenu"); let handleInternallyItem = list.querySelector( `menuitem[action='${Ci.nsIHandlerInfo.handleInternally}']` ); await selectItemInPopup(handleInternallyItem, list); Assert.equal( list.selectedItem, handleInternallyItem, "Should have selected 'handle internally' for pdf" ); let loadingTab = await BrowserTestUtils.openNewForegroundTab({ gBrowser, opening: TEST_PATH + "empty_pdf_file.pdf", waitForLoad: false, waitForStateStop: true, }); await ContentTask.spawn(loadingTab.linkedBrowser, null, async () => { await ContentTaskUtils.waitForCondition( () => content.document.readyState == "complete" ); Assert.ok( content.document.querySelector("div#viewer"), "document content has viewer UI" ); }); BrowserTestUtils.removeTab(loadingTab); gBrowser.removeCurrentTab(); }); add_task(async function saveToDiskPreferenceWorks() { await SpecialPowers.pushPrefEnv({ set: [ ["browser.download.always_ask_before_handling_new_types", false], ["browser.download.useDownloadDir", true], ], }); let pdfCategory = await selectPdfCategoryItem(); let list = pdfCategory.querySelector(".actionsMenu"); let saveToDiskItem = list.querySelector( `menuitem[action='${Ci.nsIHandlerInfo.saveToDisk}']` ); await selectItemInPopup(saveToDiskItem, list); Assert.equal( list.selectedItem, saveToDiskItem, "Should have selected 'save to disk' for pdf" ); let publicList = await Downloads.getList(Downloads.PUBLIC); registerCleanupFunction(async () => { await publicList.removeFinished(); }); let downloadFinishedPromise = downloadHadFinished(publicList); let loadingTab = await BrowserTestUtils.openNewForegroundTab({ gBrowser, opening: TEST_PATH + "empty_pdf_file.pdf", waitForLoad: false, waitForStateStop: true, }); let download = await downloadFinishedPromise; BrowserTestUtils.removeTab(loadingTab); await removeTheFile(download); gBrowser.removeCurrentTab(); }); add_task(async function useSystemDefaultPreferenceWorks() { await SpecialPowers.pushPrefEnv({ set: [ ["browser.download.always_ask_before_handling_new_types", false], ["browser.download.useDownloadDir", true], ], }); let pdfCategory = await selectPdfCategoryItem(); let list = pdfCategory.querySelector(".actionsMenu"); let useSystemDefaultItem = list.querySelector( `menuitem[action='${Ci.nsIHandlerInfo.useSystemDefault}']` ); // Whether there's a "use default" item depends on the OS, there might not be a system default viewer. if (!useSystemDefaultItem) { info( "No 'Use default' item, so no testing for setting 'use system default' preference" ); gBrowser.removeCurrentTab(); return; } await selectItemInPopup(useSystemDefaultItem, list); Assert.equal( list.selectedItem, useSystemDefaultItem, "Should have selected 'use system default' for pdf" ); let oldLaunchFile = DownloadIntegration.launchFile; let waitForLaunchFileCalled = new Promise(resolve => { DownloadIntegration.launchFile = () => { ok(true, "The file should be launched with an external application"); resolve(); }; }); let publicList = await Downloads.getList(Downloads.PUBLIC); registerCleanupFunction(async () => { await publicList.removeFinished(); }); let downloadFinishedPromise = downloadHadFinished(publicList); let loadingTab = await BrowserTestUtils.openNewForegroundTab({ gBrowser, opening: TEST_PATH + "empty_pdf_file.pdf", waitForLoad: false, waitForStateStop: true, }); info("Downloading had finished"); let download = await downloadFinishedPromise; info("Waiting until DownloadIntegration.launchFile is called"); await waitForLaunchFileCalled; DownloadIntegration.launchFile = oldLaunchFile; await removeTheFile(download); BrowserTestUtils.removeTab(loadingTab); gBrowser.removeCurrentTab(); });