diff options
author | Matt A. Tobin <email@mattatobin.com> | 2020-02-25 15:07:00 -0500 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2020-02-25 15:07:00 -0500 |
commit | 0ddd00f1959c78ce37c14fef3c83401408fca3bf (patch) | |
tree | d408e02767c86cf8aac3acbb86722b03c77ede6f /toolkit/components/jsdownloads/test/unit/common_test_Download.js | |
parent | 20f0905b33cbb18d1caa80c55e2f552c2e18957b (diff) | |
download | UXP-0ddd00f1959c78ce37c14fef3c83401408fca3bf.tar UXP-0ddd00f1959c78ce37c14fef3c83401408fca3bf.tar.gz UXP-0ddd00f1959c78ce37c14fef3c83401408fca3bf.tar.lz UXP-0ddd00f1959c78ce37c14fef3c83401408fca3bf.tar.xz UXP-0ddd00f1959c78ce37c14fef3c83401408fca3bf.zip |
Issue #439 - Remove tests from toolkit/
Diffstat (limited to 'toolkit/components/jsdownloads/test/unit/common_test_Download.js')
-rw-r--r-- | toolkit/components/jsdownloads/test/unit/common_test_Download.js | 2432 |
1 files changed, 0 insertions, 2432 deletions
diff --git a/toolkit/components/jsdownloads/test/unit/common_test_Download.js b/toolkit/components/jsdownloads/test/unit/common_test_Download.js deleted file mode 100644 index 42d4c5682..000000000 --- a/toolkit/components/jsdownloads/test/unit/common_test_Download.js +++ /dev/null @@ -1,2432 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * This script is loaded by "test_DownloadCore.js" and "test_DownloadLegacy.js" - * with different values of the gUseLegacySaver variable, to apply tests to both - * the "copy" and "legacy" saver implementations. - */ - -"use strict"; - -// Globals - -const kDeleteTempFileOnExit = "browser.helperApps.deleteTempFileOnExit"; - -/** - * Creates and starts a new download, using either DownloadCopySaver or - * DownloadLegacySaver based on the current test run. - * - * @return {Promise} - * @resolves The newly created Download object. The download may be in progress - * or already finished. The promiseDownloadStopped function can be - * used to wait for completion. - * @rejects JavaScript exception. - */ -function promiseStartDownload(aSourceUrl) { - if (gUseLegacySaver) { - return promiseStartLegacyDownload(aSourceUrl); - } - - return promiseNewDownload(aSourceUrl).then(download => { - download.start().catch(() => {}); - return download; - }); -} - -/** - * Creates and starts a new download, configured to keep partial data, and - * returns only when the first part of "interruptible_resumable.txt" has been - * saved to disk. You must call "continueResponses" to allow the interruptible - * request to continue. - * - * This function uses either DownloadCopySaver or DownloadLegacySaver based on - * the current test run. - * - * @return {Promise} - * @resolves The newly created Download object, still in progress. - * @rejects JavaScript exception. - */ -function promiseStartDownload_tryToKeepPartialData() { - return Task.spawn(function* () { - mustInterruptResponses(); - - // Start a new download and configure it to keep partially downloaded data. - let download; - if (!gUseLegacySaver) { - let targetFilePath = getTempFile(TEST_TARGET_FILE_NAME).path; - download = yield Downloads.createDownload({ - source: httpUrl("interruptible_resumable.txt"), - target: { path: targetFilePath, - partFilePath: targetFilePath + ".part" }, - }); - download.tryToKeepPartialData = true; - download.start().catch(() => {}); - } else { - // Start a download using nsIExternalHelperAppService, that is configured - // to keep partially downloaded data by default. - download = yield promiseStartExternalHelperAppServiceDownload(); - } - - yield promiseDownloadMidway(download); - yield promisePartFileReady(download); - - return download; - }); -} - -/** - * This function should be called after the progress notification for a download - * is received, and waits for the worker thread of BackgroundFileSaver to - * receive the data to be written to the ".part" file on disk. - * - * @return {Promise} - * @resolves When the ".part" file has been written to disk. - * @rejects JavaScript exception. - */ -function promisePartFileReady(aDownload) { - return Task.spawn(function* () { - // We don't have control over the file output code in BackgroundFileSaver. - // After we receive the download progress notification, we may only check - // that the ".part" file has been created, while its size cannot be - // determined because the file is currently open. - try { - do { - yield promiseTimeout(50); - } while (!(yield OS.File.exists(aDownload.target.partFilePath))); - } catch (ex) { - if (!(ex instanceof OS.File.Error)) { - throw ex; - } - // This indicates that the file has been created and cannot be accessed. - // The specific error might vary with the platform. - do_print("Expected exception while checking existence: " + ex.toString()); - // Wait some more time to allow the write to complete. - yield promiseTimeout(100); - } - }); -} - -/** - * Checks that the actual data written to disk matches the expected data as well - * as the properties of the given DownloadTarget object. - * - * @param downloadTarget - * The DownloadTarget object whose details have to be verified. - * @param expectedContents - * String containing the octets that are expected in the file. - * - * @return {Promise} - * @resolves When the properties have been verified. - * @rejects JavaScript exception. - */ -var promiseVerifyTarget = Task.async(function* (downloadTarget, - expectedContents) { - yield promiseVerifyContents(downloadTarget.path, expectedContents); - do_check_true(downloadTarget.exists); - do_check_eq(downloadTarget.size, expectedContents.length); -}); - -/** - * Waits for an attempt to launch a file, and returns the nsIMIMEInfo used for - * the launch, or null if the file was launched with the default handler. - */ -function waitForFileLaunched() { - return new Promise(resolve => { - let waitFn = base => ({ - launchFile(file, mimeInfo) { - Integration.downloads.unregister(waitFn); - if (!mimeInfo || - mimeInfo.preferredAction == Ci.nsIMIMEInfo.useSystemDefault) { - resolve(null); - } else { - resolve(mimeInfo); - } - return Promise.resolve(); - }, - }); - Integration.downloads.register(waitFn); - }); -} - -/** - * Waits for an attempt to show the directory where a file is located, and - * returns the path of the file. - */ -function waitForDirectoryShown() { - return new Promise(resolve => { - let waitFn = base => ({ - showContainingDirectory(path) { - Integration.downloads.unregister(waitFn); - resolve(path); - return Promise.resolve(); - }, - }); - Integration.downloads.register(waitFn); - }); -} - -// Tests - -/** - * Executes a download and checks its basic properties after construction. - * The download is started by constructing the simplest Download object with - * the "copy" saver, or using the legacy nsITransfer interface. - */ -add_task(function* test_basic() -{ - let targetFile = getTempFile(TEST_TARGET_FILE_NAME); - - let download; - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we have control over the download, thus - // we can check its basic properties before it starts. - download = yield Downloads.createDownload({ - source: { url: httpUrl("source.txt") }, - target: { path: targetFile.path }, - saver: { type: "copy" }, - }); - - do_check_eq(download.source.url, httpUrl("source.txt")); - do_check_eq(download.target.path, targetFile.path); - - yield download.start(); - } else { - // When testing DownloadLegacySaver, the download is already started when it - // is created, thus we must check its basic properties while in progress. - download = yield promiseStartLegacyDownload(null, - { targetFile: targetFile }); - - do_check_eq(download.source.url, httpUrl("source.txt")); - do_check_eq(download.target.path, targetFile.path); - - yield promiseDownloadStopped(download); - } - - // Check additional properties on the finished download. - do_check_true(download.source.referrer === null); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT); -}); - -/** - * Executes a download with the tryToKeepPartialData property set, and ensures - * that the file is saved correctly. When testing DownloadLegacySaver, the - * download is executed using the nsIExternalHelperAppService component. - */ -add_task(function* test_basic_tryToKeepPartialData() -{ - let download = yield promiseStartDownload_tryToKeepPartialData(); - continueResponses(); - yield promiseDownloadStopped(download); - - // The target file should now have been created, and the ".part" file deleted. - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); - do_check_false(yield OS.File.exists(download.target.partFilePath)); - do_check_eq(32, download.saver.getSha256Hash().length); -}); - -/** - * Tests the permissions of the final target file once the download finished. - */ -add_task(function* test_unix_permissions() -{ - // This test is only executed on some Desktop systems. - if (Services.appinfo.OS != "Darwin" && Services.appinfo.OS != "Linux" && - Services.appinfo.OS != "WINNT") { - do_print("Skipping test."); - return; - } - - let launcherPath = getTempFile("app-launcher").path; - - for (let autoDelete of [false, true]) { - for (let isPrivate of [false, true]) { - for (let launchWhenSucceeded of [false, true]) { - do_print("Checking " + JSON.stringify({ autoDelete, - isPrivate, - launchWhenSucceeded })); - - Services.prefs.setBoolPref(kDeleteTempFileOnExit, autoDelete); - - let download; - if (!gUseLegacySaver) { - download = yield Downloads.createDownload({ - source: { url: httpUrl("source.txt"), isPrivate }, - target: getTempFile(TEST_TARGET_FILE_NAME).path, - launchWhenSucceeded, - launcherPath, - }); - yield download.start(); - } else { - download = yield promiseStartLegacyDownload(httpUrl("source.txt"), { - isPrivate, - launchWhenSucceeded, - launcherPath: launchWhenSucceeded && launcherPath, - }); - yield promiseDownloadStopped(download); - } - - let isTemporary = launchWhenSucceeded && (autoDelete || isPrivate); - let stat = yield OS.File.stat(download.target.path); - if (Services.appinfo.OS == "WINNT") { - // On Windows - // Temporary downloads should be read-only - do_check_eq(stat.winAttributes.readOnly, isTemporary ? true : false); - } else { - // On Linux, Mac - // Temporary downloads should be read-only and not accessible to other - // users, while permanently downloaded files should be readable and - // writable as specified by the system umask. - do_check_eq(stat.unixMode, - isTemporary ? 0o400 : (0o666 & ~OS.Constants.Sys.umask)); - } - } - } - } - - // Clean up the changes to the preference. - Services.prefs.clearUserPref(kDeleteTempFileOnExit); -}); - -/** - * Checks the referrer for downloads. - */ -add_task(function* test_referrer() -{ - let sourcePath = "/test_referrer.txt"; - let sourceUrl = httpUrl("test_referrer.txt"); - let targetPath = getTempFile(TEST_TARGET_FILE_NAME).path; - - function cleanup() { - gHttpServer.registerPathHandler(sourcePath, null); - } - do_register_cleanup(cleanup); - - gHttpServer.registerPathHandler(sourcePath, function (aRequest, aResponse) { - aResponse.setHeader("Content-Type", "text/plain", false); - - do_check_true(aRequest.hasHeader("Referer")); - do_check_eq(aRequest.getHeader("Referer"), TEST_REFERRER_URL); - }); - let download = yield Downloads.createDownload({ - source: { url: sourceUrl, referrer: TEST_REFERRER_URL }, - target: targetPath, - }); - do_check_eq(download.source.referrer, TEST_REFERRER_URL); - yield download.start(); - - download = yield Downloads.createDownload({ - source: { url: sourceUrl, referrer: TEST_REFERRER_URL, - isPrivate: true }, - target: targetPath, - }); - do_check_eq(download.source.referrer, TEST_REFERRER_URL); - yield download.start(); - - // Test the download still works for non-HTTP channel with referrer. - sourceUrl = "data:text/html,<html><body></body></html>"; - download = yield Downloads.createDownload({ - source: { url: sourceUrl, referrer: TEST_REFERRER_URL }, - target: targetPath, - }); - do_check_eq(download.source.referrer, TEST_REFERRER_URL); - yield download.start(); - - cleanup(); -}); - -/** - * Checks the adjustChannel callback for downloads. - */ -add_task(function* test_adjustChannel() -{ - const sourcePath = "/test_post.txt"; - const sourceUrl = httpUrl("test_post.txt"); - const targetPath = getTempFile(TEST_TARGET_FILE_NAME).path; - const customHeader = { name: "X-Answer", value: "42" }; - const postData = "Don't Panic"; - - function cleanup() { - gHttpServer.registerPathHandler(sourcePath, null); - } - do_register_cleanup(cleanup); - - gHttpServer.registerPathHandler(sourcePath, aRequest => { - do_check_eq(aRequest.method, "POST"); - - do_check_true(aRequest.hasHeader(customHeader.name)); - do_check_eq(aRequest.getHeader(customHeader.name), customHeader.value); - - const stream = aRequest.bodyInputStream; - const body = NetUtil.readInputStreamToString(stream, stream.available()); - do_check_eq(body, postData); - }); - - function adjustChannel(channel) { - channel.QueryInterface(Ci.nsIHttpChannel); - channel.setRequestHeader(customHeader.name, customHeader.value, false); - - const stream = Cc["@mozilla.org/io/string-input-stream;1"] - .createInstance(Ci.nsIStringInputStream); - stream.setData(postData, postData.length); - - channel.QueryInterface(Ci.nsIUploadChannel2); - channel.explicitSetUploadStream(stream, null, -1, "POST", false); - - return Promise.resolve(); - } - - const download = yield Downloads.createDownload({ - source: { url: sourceUrl, adjustChannel }, - target: targetPath, - }); - do_check_eq(download.source.adjustChannel, adjustChannel); - do_check_eq(download.toSerializable(), null); - yield download.start(); - - cleanup(); -}); - -/** - * Checks initial and final state and progress for a successful download. - */ -add_task(function* test_initial_final_state() -{ - let download; - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we have control over the download, thus - // we can check its state before it starts. - download = yield promiseNewDownload(); - - do_check_true(download.stopped); - do_check_false(download.succeeded); - do_check_false(download.canceled); - do_check_true(download.error === null); - do_check_eq(download.progress, 0); - do_check_true(download.startTime === null); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); - - yield download.start(); - } else { - // When testing DownloadLegacySaver, the download is already started when it - // is created, thus we cannot check its initial state. - download = yield promiseStartLegacyDownload(); - yield promiseDownloadStopped(download); - } - - do_check_true(download.stopped); - do_check_true(download.succeeded); - do_check_false(download.canceled); - do_check_true(download.error === null); - do_check_eq(download.progress, 100); - do_check_true(isValidDate(download.startTime)); - do_check_true(download.target.exists); - do_check_eq(download.target.size, TEST_DATA_SHORT.length); -}); - -/** - * Checks the notification of the final download state. - */ -add_task(function* test_final_state_notified() -{ - mustInterruptResponses(); - - let download = yield promiseStartDownload(httpUrl("interruptible.txt")); - - let onchangeNotified = false; - let lastNotifiedStopped; - let lastNotifiedProgress; - download.onchange = function () { - onchangeNotified = true; - lastNotifiedStopped = download.stopped; - lastNotifiedProgress = download.progress; - }; - - // Allow the download to complete. - let promiseAttempt = download.start(); - continueResponses(); - yield promiseAttempt; - - // The view should have been notified before the download completes. - do_check_true(onchangeNotified); - do_check_true(lastNotifiedStopped); - do_check_eq(lastNotifiedProgress, 100); -}); - -/** - * Checks intermediate progress for a successful download. - */ -add_task(function* test_intermediate_progress() -{ - mustInterruptResponses(); - - let download = yield promiseStartDownload(httpUrl("interruptible.txt")); - - yield promiseDownloadMidway(download); - - do_check_true(download.hasProgress); - do_check_eq(download.currentBytes, TEST_DATA_SHORT.length); - do_check_eq(download.totalBytes, TEST_DATA_SHORT.length * 2); - - // The final file size should not be computed for in-progress downloads. - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); - - // Continue after the first chunk of data is fully received. - continueResponses(); - yield promiseDownloadStopped(download); - - do_check_true(download.stopped); - do_check_eq(download.progress, 100); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); -}); - -/** - * Downloads a file with a "Content-Length" of 0 and checks the progress. - */ -add_task(function* test_empty_progress() -{ - let download = yield promiseStartDownload(httpUrl("empty.txt")); - yield promiseDownloadStopped(download); - - do_check_true(download.stopped); - do_check_true(download.hasProgress); - do_check_eq(download.progress, 100); - do_check_eq(download.currentBytes, 0); - do_check_eq(download.totalBytes, 0); - - // We should have received the content type even for an empty file. - do_check_eq(download.contentType, "text/plain"); - - do_check_eq((yield OS.File.stat(download.target.path)).size, 0); - do_check_true(download.target.exists); - do_check_eq(download.target.size, 0); -}); - -/** - * Downloads a file with a "Content-Length" of 0 with the tryToKeepPartialData - * property set, and ensures that the file is saved correctly. - */ -add_task(function* test_empty_progress_tryToKeepPartialData() -{ - // Start a new download and configure it to keep partially downloaded data. - let download; - if (!gUseLegacySaver) { - let targetFilePath = getTempFile(TEST_TARGET_FILE_NAME).path; - download = yield Downloads.createDownload({ - source: httpUrl("empty.txt"), - target: { path: targetFilePath, - partFilePath: targetFilePath + ".part" }, - }); - download.tryToKeepPartialData = true; - download.start().catch(() => {}); - } else { - // Start a download using nsIExternalHelperAppService, that is configured - // to keep partially downloaded data by default. - download = yield promiseStartExternalHelperAppServiceDownload( - httpUrl("empty.txt")); - } - yield promiseDownloadStopped(download); - - // The target file should now have been created, and the ".part" file deleted. - do_check_eq((yield OS.File.stat(download.target.path)).size, 0); - do_check_true(download.target.exists); - do_check_eq(download.target.size, 0); - - do_check_false(yield OS.File.exists(download.target.partFilePath)); - do_check_eq(32, download.saver.getSha256Hash().length); -}); - -/** - * Downloads an empty file with no "Content-Length" and checks the progress. - */ -add_task(function* test_empty_noprogress() -{ - let sourcePath = "/test_empty_noprogress.txt"; - let sourceUrl = httpUrl("test_empty_noprogress.txt"); - let deferRequestReceived = Promise.defer(); - - // Register an interruptible handler that notifies us when the request occurs. - function cleanup() { - gHttpServer.registerPathHandler(sourcePath, null); - } - do_register_cleanup(cleanup); - - registerInterruptibleHandler(sourcePath, - function firstPart(aRequest, aResponse) { - aResponse.setHeader("Content-Type", "text/plain", false); - deferRequestReceived.resolve(); - }, function secondPart(aRequest, aResponse) { }); - - // Start the download, without allowing the request to finish. - mustInterruptResponses(); - let download; - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we have control over the download, thus - // we can hook its onchange callback that will be notified when the - // download starts. - download = yield promiseNewDownload(sourceUrl); - - download.onchange = function () { - if (!download.stopped) { - do_check_false(download.hasProgress); - do_check_eq(download.currentBytes, 0); - do_check_eq(download.totalBytes, 0); - } - }; - - download.start().catch(() => {}); - } else { - // When testing DownloadLegacySaver, the download is already started when it - // is created, and it may have already made all needed property change - // notifications, thus there is no point in checking the onchange callback. - download = yield promiseStartLegacyDownload(sourceUrl); - } - - // Wait for the request to be received by the HTTP server, but don't allow the - // request to finish yet. Before checking the download state, wait for the - // events to be processed by the client. - yield deferRequestReceived.promise; - yield promiseExecuteSoon(); - - // Check that this download has no progress report. - do_check_false(download.stopped); - do_check_false(download.hasProgress); - do_check_eq(download.currentBytes, 0); - do_check_eq(download.totalBytes, 0); - - // Now allow the response to finish. - continueResponses(); - yield promiseDownloadStopped(download); - - // We should have received the content type even if no progress is reported. - do_check_eq(download.contentType, "text/plain"); - - // Verify the state of the completed download. - do_check_true(download.stopped); - do_check_false(download.hasProgress); - do_check_eq(download.progress, 100); - do_check_eq(download.currentBytes, 0); - do_check_eq(download.totalBytes, 0); - do_check_true(download.target.exists); - do_check_eq(download.target.size, 0); - - do_check_eq((yield OS.File.stat(download.target.path)).size, 0); -}); - -/** - * Calls the "start" method two times before the download is finished. - */ -add_task(function* test_start_twice() -{ - mustInterruptResponses(); - - let download; - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we have control over the download, thus - // we can start the download later during the test. - download = yield promiseNewDownload(httpUrl("interruptible.txt")); - } else { - // When testing DownloadLegacySaver, the download is already started when it - // is created. Effectively, we are starting the download three times. - download = yield promiseStartLegacyDownload(httpUrl("interruptible.txt")); - } - - // Call the start method two times. - let promiseAttempt1 = download.start(); - let promiseAttempt2 = download.start(); - - // Allow the download to finish. - continueResponses(); - - // Both promises should now be resolved. - yield promiseAttempt1; - yield promiseAttempt2; - - do_check_true(download.stopped); - do_check_true(download.succeeded); - do_check_false(download.canceled); - do_check_true(download.error === null); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); -}); - -/** - * Cancels a download and verifies that its state is reported correctly. - */ -add_task(function* test_cancel_midway() -{ - mustInterruptResponses(); - - // In this test case, we execute different checks that are only possible with - // DownloadCopySaver or DownloadLegacySaver respectively. - let download; - let options = {}; - if (!gUseLegacySaver) { - download = yield promiseNewDownload(httpUrl("interruptible.txt")); - } else { - download = yield promiseStartLegacyDownload(httpUrl("interruptible.txt"), - options); - } - - // Cancel the download after receiving the first part of the response. - let deferCancel = Promise.defer(); - let onchange = function () { - if (!download.stopped && !download.canceled && download.progress == 50) { - // Cancel the download immediately during the notification. - deferCancel.resolve(download.cancel()); - - // The state change happens immediately after calling "cancel", but - // temporary files or part files may still exist at this point. - do_check_true(download.canceled); - } - }; - - // Register for the notification, but also call the function directly in - // case the download already reached the expected progress. This may happen - // when using DownloadLegacySaver. - download.onchange = onchange; - onchange(); - - let promiseAttempt; - if (!gUseLegacySaver) { - promiseAttempt = download.start(); - } - - // Wait on the promise returned by the "cancel" method to ensure that the - // cancellation process finished and temporary files were removed. - yield deferCancel.promise; - - if (gUseLegacySaver) { - // The nsIWebBrowserPersist instance should have been canceled now. - do_check_eq(options.outPersist.result, Cr.NS_ERROR_ABORT); - } - - do_check_true(download.stopped); - do_check_true(download.canceled); - do_check_true(download.error === null); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); - - do_check_false(yield OS.File.exists(download.target.path)); - - // Progress properties are not reset by canceling. - do_check_eq(download.progress, 50); - do_check_eq(download.totalBytes, TEST_DATA_SHORT.length * 2); - do_check_eq(download.currentBytes, TEST_DATA_SHORT.length); - - if (!gUseLegacySaver) { - // The promise returned by "start" should have been rejected meanwhile. - try { - yield promiseAttempt; - do_throw("The download should have been canceled."); - } catch (ex) { - if (!(ex instanceof Downloads.Error)) { - throw ex; - } - do_check_false(ex.becauseSourceFailed); - do_check_false(ex.becauseTargetFailed); - } - } -}); - -/** - * Cancels a download while keeping partially downloaded data, and verifies that - * both the target file and the ".part" file are deleted. - */ -add_task(function* test_cancel_midway_tryToKeepPartialData() -{ - let download = yield promiseStartDownload_tryToKeepPartialData(); - - do_check_true(yield OS.File.exists(download.target.path)); - do_check_true(yield OS.File.exists(download.target.partFilePath)); - - yield download.cancel(); - yield download.removePartialData(); - - do_check_true(download.stopped); - do_check_true(download.canceled); - do_check_true(download.error === null); - - do_check_false(yield OS.File.exists(download.target.path)); - do_check_false(yield OS.File.exists(download.target.partFilePath)); -}); - -/** - * Cancels a download right after starting it. - */ -add_task(function* test_cancel_immediately() -{ - mustInterruptResponses(); - - let download = yield promiseStartDownload(httpUrl("interruptible.txt")); - - let promiseAttempt = download.start(); - do_check_false(download.stopped); - - let promiseCancel = download.cancel(); - do_check_true(download.canceled); - - // At this point, we don't know whether the download has already stopped or - // is still waiting for cancellation. We can wait on the promise returned - // by the "start" method to know for sure. - try { - yield promiseAttempt; - do_throw("The download should have been canceled."); - } catch (ex) { - if (!(ex instanceof Downloads.Error)) { - throw ex; - } - do_check_false(ex.becauseSourceFailed); - do_check_false(ex.becauseTargetFailed); - } - - do_check_true(download.stopped); - do_check_true(download.canceled); - do_check_true(download.error === null); - - do_check_false(yield OS.File.exists(download.target.path)); - - // Check that the promise returned by the "cancel" method has been resolved. - yield promiseCancel; -}); - -/** - * Cancels and restarts a download sequentially. - */ -add_task(function* test_cancel_midway_restart() -{ - mustInterruptResponses(); - - let download = yield promiseStartDownload(httpUrl("interruptible.txt")); - - // The first time, cancel the download midway. - yield promiseDownloadMidway(download); - yield download.cancel(); - - do_check_true(download.stopped); - - // The second time, we'll provide the entire interruptible response. - continueResponses(); - download.onchange = null; - let promiseAttempt = download.start(); - - // Download state should have already been reset. - do_check_false(download.stopped); - do_check_false(download.canceled); - do_check_true(download.error === null); - - // For the following test, we rely on the network layer reporting its progress - // asynchronously. Otherwise, there is nothing stopping the restarted - // download from reaching the same progress as the first request already. - do_check_eq(download.progress, 0); - do_check_eq(download.totalBytes, 0); - do_check_eq(download.currentBytes, 0); - - yield promiseAttempt; - - do_check_true(download.stopped); - do_check_true(download.succeeded); - do_check_false(download.canceled); - do_check_true(download.error === null); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); -}); - -/** - * Cancels a download and restarts it from where it stopped. - */ -add_task(function* test_cancel_midway_restart_tryToKeepPartialData() -{ - let download = yield promiseStartDownload_tryToKeepPartialData(); - yield download.cancel(); - - do_check_true(download.stopped); - do_check_true(download.hasPartialData); - - // The target file should not exist, but we should have kept the partial data. - do_check_false(yield OS.File.exists(download.target.path)); - yield promiseVerifyContents(download.target.partFilePath, TEST_DATA_SHORT); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); - - // Verify that the server sent the response from the start. - do_check_eq(gMostRecentFirstBytePos, 0); - - // The second time, we'll request and obtain the second part of the response, - // but we still stop when half of the remaining progress is reached. - let deferMidway = Promise.defer(); - download.onchange = function () { - if (!download.stopped && !download.canceled && - download.currentBytes == Math.floor(TEST_DATA_SHORT.length * 3 / 2)) { - download.onchange = null; - deferMidway.resolve(); - } - }; - - mustInterruptResponses(); - let promiseAttempt = download.start(); - - // Continue when the number of bytes we received is correct, then check that - // progress is at about 75 percent. The exact figure may vary because of - // rounding issues, since the total number of bytes in the response might not - // be a multiple of four. - yield deferMidway.promise; - do_check_true(download.progress > 72 && download.progress < 78); - - // Now we allow the download to finish. - continueResponses(); - yield promiseAttempt; - - // Check that the server now sent the second part only. - do_check_eq(gMostRecentFirstBytePos, TEST_DATA_SHORT.length); - - // The target file should now have been created, and the ".part" file deleted. - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); - do_check_false(yield OS.File.exists(download.target.partFilePath)); -}); - -/** - * Cancels a download while keeping partially downloaded data, then removes the - * data and restarts the download from the beginning. - */ -add_task(function* test_cancel_midway_restart_removePartialData() -{ - let download = yield promiseStartDownload_tryToKeepPartialData(); - yield download.cancel(); - - do_check_true(download.hasPartialData); - yield promiseVerifyContents(download.target.partFilePath, TEST_DATA_SHORT); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); - - yield download.removePartialData(); - - do_check_false(download.hasPartialData); - do_check_false(yield OS.File.exists(download.target.partFilePath)); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); - - // The second time, we'll request and obtain the entire response again. - continueResponses(); - yield download.start(); - - // Verify that the server sent the response from the start. - do_check_eq(gMostRecentFirstBytePos, 0); - - // The target file should now have been created, and the ".part" file deleted. - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); - do_check_false(yield OS.File.exists(download.target.partFilePath)); -}); - -/** - * Cancels a download while keeping partially downloaded data, then removes the - * data and restarts the download from the beginning without keeping the partial - * data anymore. - */ -add_task(function* test_cancel_midway_restart_tryToKeepPartialData_false() -{ - let download = yield promiseStartDownload_tryToKeepPartialData(); - yield download.cancel(); - - download.tryToKeepPartialData = false; - - // The above property change does not affect existing partial data. - do_check_true(download.hasPartialData); - yield promiseVerifyContents(download.target.partFilePath, TEST_DATA_SHORT); - - yield download.removePartialData(); - do_check_false(yield OS.File.exists(download.target.partFilePath)); - - // Restart the download from the beginning. - mustInterruptResponses(); - download.start().catch(() => {}); - - yield promiseDownloadMidway(download); - yield promisePartFileReady(download); - - // While the download is in progress, we should still have a ".part" file. - do_check_false(download.hasPartialData); - do_check_true(yield OS.File.exists(download.target.partFilePath)); - - // On Unix, verify that the file with the partially downloaded data is not - // accessible by other users on the system. - if (Services.appinfo.OS == "Darwin" || Services.appinfo.OS == "Linux") { - do_check_eq((yield OS.File.stat(download.target.partFilePath)).unixMode, - 0o600); - } - - yield download.cancel(); - - // The ".part" file should be deleted now that the download is canceled. - do_check_false(download.hasPartialData); - do_check_false(yield OS.File.exists(download.target.partFilePath)); - - // The third time, we'll request and obtain the entire response again. - continueResponses(); - yield download.start(); - - // Verify that the server sent the response from the start. - do_check_eq(gMostRecentFirstBytePos, 0); - - // The target file should now have been created, and the ".part" file deleted. - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); - do_check_false(yield OS.File.exists(download.target.partFilePath)); -}); - -/** - * Cancels a download right after starting it, then restarts it immediately. - */ -add_task(function* test_cancel_immediately_restart_immediately() -{ - mustInterruptResponses(); - - let download = yield promiseStartDownload(httpUrl("interruptible.txt")); - let promiseAttempt = download.start(); - - do_check_false(download.stopped); - - download.cancel(); - do_check_true(download.canceled); - - let promiseRestarted = download.start(); - do_check_false(download.stopped); - do_check_false(download.canceled); - do_check_true(download.error === null); - - // For the following test, we rely on the network layer reporting its progress - // asynchronously. Otherwise, there is nothing stopping the restarted - // download from reaching the same progress as the first request already. - do_check_eq(download.hasProgress, false); - do_check_eq(download.progress, 0); - do_check_eq(download.totalBytes, 0); - do_check_eq(download.currentBytes, 0); - - // Ensure the next request is now allowed to complete, regardless of whether - // the canceled request was received by the server or not. - continueResponses(); - try { - yield promiseAttempt; - // If we get here, it means that the first attempt actually succeeded. In - // fact, this could be a valid outcome, because the cancellation request may - // not have been processed in time before the download finished. - do_print("The download should have been canceled."); - } catch (ex) { - if (!(ex instanceof Downloads.Error)) { - throw ex; - } - do_check_false(ex.becauseSourceFailed); - do_check_false(ex.becauseTargetFailed); - } - - yield promiseRestarted; - - do_check_true(download.stopped); - do_check_true(download.succeeded); - do_check_false(download.canceled); - do_check_true(download.error === null); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); -}); - -/** - * Cancels a download midway, then restarts it immediately. - */ -add_task(function* test_cancel_midway_restart_immediately() -{ - mustInterruptResponses(); - - let download = yield promiseStartDownload(httpUrl("interruptible.txt")); - let promiseAttempt = download.start(); - - // The first time, cancel the download midway. - yield promiseDownloadMidway(download); - download.cancel(); - do_check_true(download.canceled); - - let promiseRestarted = download.start(); - do_check_false(download.stopped); - do_check_false(download.canceled); - do_check_true(download.error === null); - - // For the following test, we rely on the network layer reporting its progress - // asynchronously. Otherwise, there is nothing stopping the restarted - // download from reaching the same progress as the first request already. - do_check_eq(download.hasProgress, false); - do_check_eq(download.progress, 0); - do_check_eq(download.totalBytes, 0); - do_check_eq(download.currentBytes, 0); - - // The second request is allowed to complete. - continueResponses(); - try { - yield promiseAttempt; - do_throw("The download should have been canceled."); - } catch (ex) { - if (!(ex instanceof Downloads.Error)) { - throw ex; - } - do_check_false(ex.becauseSourceFailed); - do_check_false(ex.becauseTargetFailed); - } - - yield promiseRestarted; - - do_check_true(download.stopped); - do_check_true(download.succeeded); - do_check_false(download.canceled); - do_check_true(download.error === null); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); -}); - -/** - * Calls the "cancel" method on a successful download. - */ -add_task(function* test_cancel_successful() -{ - let download = yield promiseStartDownload(); - yield promiseDownloadStopped(download); - - // The cancel method should succeed with no effect. - yield download.cancel(); - - do_check_true(download.stopped); - do_check_true(download.succeeded); - do_check_false(download.canceled); - do_check_true(download.error === null); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT); -}); - -/** - * Calls the "cancel" method two times in a row. - */ -add_task(function* test_cancel_twice() -{ - mustInterruptResponses(); - - let download = yield promiseStartDownload(httpUrl("interruptible.txt")); - - let promiseAttempt = download.start(); - do_check_false(download.stopped); - - let promiseCancel1 = download.cancel(); - do_check_true(download.canceled); - let promiseCancel2 = download.cancel(); - - try { - yield promiseAttempt; - do_throw("The download should have been canceled."); - } catch (ex) { - if (!(ex instanceof Downloads.Error)) { - throw ex; - } - do_check_false(ex.becauseSourceFailed); - do_check_false(ex.becauseTargetFailed); - } - - // Both promises should now be resolved. - yield promiseCancel1; - yield promiseCancel2; - - do_check_true(download.stopped); - do_check_false(download.succeeded); - do_check_true(download.canceled); - do_check_true(download.error === null); - - do_check_false(yield OS.File.exists(download.target.path)); -}); - -/** - * Checks the "refresh" method for succeeded downloads. - */ -add_task(function* test_refresh_succeeded() -{ - let download = yield promiseStartDownload(); - yield promiseDownloadStopped(download); - - // The DownloadTarget properties should be the same after calling "refresh". - yield download.refresh(); - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT); - - // If the file is removed, only the "exists" property should change, and the - // "size" property should keep its previous value. - yield OS.File.move(download.target.path, download.target.path + ".old"); - yield download.refresh(); - do_check_false(download.target.exists); - do_check_eq(download.target.size, TEST_DATA_SHORT.length); - - // The DownloadTarget properties should be restored when the file is put back. - yield OS.File.move(download.target.path + ".old", download.target.path); - yield download.refresh(); - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT); -}); - -/** - * Checks that a download cannot be restarted after the "finalize" method. - */ -add_task(function* test_finalize() -{ - mustInterruptResponses(); - - let download = yield promiseStartDownload(httpUrl("interruptible.txt")); - - let promiseFinalized = download.finalize(); - - try { - yield download.start(); - do_throw("It should not be possible to restart after finalization."); - } catch (ex) { } - - yield promiseFinalized; - - do_check_true(download.stopped); - do_check_false(download.succeeded); - do_check_true(download.canceled); - do_check_true(download.error === null); - - do_check_false(yield OS.File.exists(download.target.path)); -}); - -/** - * Checks that the "finalize" method can remove partially downloaded data. - */ -add_task(function* test_finalize_tryToKeepPartialData() -{ - // Check finalization without removing partial data. - let download = yield promiseStartDownload_tryToKeepPartialData(); - yield download.finalize(); - - do_check_true(download.hasPartialData); - do_check_true(yield OS.File.exists(download.target.partFilePath)); - - // Clean up. - yield download.removePartialData(); - - // Check finalization while removing partial data. - download = yield promiseStartDownload_tryToKeepPartialData(); - yield download.finalize(true); - - do_check_false(download.hasPartialData); - do_check_false(yield OS.File.exists(download.target.partFilePath)); -}); - -/** - * Checks that whenSucceeded returns a promise that is resolved after a restart. - */ -add_task(function* test_whenSucceeded_after_restart() -{ - mustInterruptResponses(); - - let promiseSucceeded; - - let download; - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we have control over the download, thus - // we can verify getting a reference before the first download attempt. - download = yield promiseNewDownload(httpUrl("interruptible.txt")); - promiseSucceeded = download.whenSucceeded(); - download.start().catch(() => {}); - } else { - // When testing DownloadLegacySaver, the download is already started when it - // is created, thus we cannot get the reference before the first attempt. - download = yield promiseStartLegacyDownload(httpUrl("interruptible.txt")); - promiseSucceeded = download.whenSucceeded(); - } - - // Cancel the first download attempt. - yield download.cancel(); - - // The second request is allowed to complete. - continueResponses(); - download.start().catch(() => {}); - - // Wait for the download to finish by waiting on the whenSucceeded promise. - yield promiseSucceeded; - - do_check_true(download.stopped); - do_check_true(download.succeeded); - do_check_false(download.canceled); - do_check_true(download.error === null); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); -}); - -/** - * Ensures download error details are reported on network failures. - */ -add_task(function* test_error_source() -{ - let serverSocket = startFakeServer(); - try { - let sourceUrl = "http://localhost:" + serverSocket.port + "/source.txt"; - - let download; - try { - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we want to check that the promise - // returned by the "start" method is rejected. - download = yield promiseNewDownload(sourceUrl); - - do_check_true(download.error === null); - - yield download.start(); - } else { - // When testing DownloadLegacySaver, we cannot be sure whether we are - // testing the promise returned by the "start" method or we are testing - // the "error" property checked by promiseDownloadStopped. This happens - // because we don't have control over when the download is started. - download = yield promiseStartLegacyDownload(sourceUrl); - yield promiseDownloadStopped(download); - } - do_throw("The download should have failed."); - } catch (ex) { - if (!(ex instanceof Downloads.Error) || !ex.becauseSourceFailed) { - throw ex; - } - // A specific error object is thrown when reading from the source fails. - } - - // Check the properties now that the download stopped. - do_check_true(download.stopped); - do_check_false(download.canceled); - do_check_true(download.error !== null); - do_check_true(download.error.becauseSourceFailed); - do_check_false(download.error.becauseTargetFailed); - - do_check_false(yield OS.File.exists(download.target.path)); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); - } finally { - serverSocket.close(); - } -}); - -/** - * Ensures a download error is reported when receiving less bytes than what was - * specified in the Content-Length header. - */ -add_task(function* test_error_source_partial() -{ - let sourceUrl = httpUrl("shorter-than-content-length-http-1-1.txt"); - - let enforcePref = Services.prefs.getBoolPref("network.http.enforce-framing.http1"); - Services.prefs.setBoolPref("network.http.enforce-framing.http1", true); - - function cleanup() { - Services.prefs.setBoolPref("network.http.enforce-framing.http1", enforcePref); - } - do_register_cleanup(cleanup); - - let download; - try { - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we want to check that the promise - // returned by the "start" method is rejected. - download = yield promiseNewDownload(sourceUrl); - - do_check_true(download.error === null); - - yield download.start(); - } else { - // When testing DownloadLegacySaver, we cannot be sure whether we are - // testing the promise returned by the "start" method or we are testing - // the "error" property checked by promiseDownloadStopped. This happens - // because we don't have control over when the download is started. - download = yield promiseStartLegacyDownload(sourceUrl); - yield promiseDownloadStopped(download); - } - do_throw("The download should have failed."); - } catch (ex) { - if (!(ex instanceof Downloads.Error) || !ex.becauseSourceFailed) { - throw ex; - } - // A specific error object is thrown when reading from the source fails. - } - - // Check the properties now that the download stopped. - do_check_true(download.stopped); - do_check_false(download.canceled); - do_check_true(download.error !== null); - do_check_true(download.error.becauseSourceFailed); - do_check_false(download.error.becauseTargetFailed); - do_check_eq(download.error.result, Cr.NS_ERROR_NET_PARTIAL_TRANSFER); - - do_check_false(yield OS.File.exists(download.target.path)); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); -}); - -/** - * Ensures download error details are reported on local writing failures. - */ -add_task(function* test_error_target() -{ - // Create a file without write access permissions before downloading. - let targetFile = getTempFile(TEST_TARGET_FILE_NAME); - targetFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0); - try { - let download; - try { - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we want to check that the promise - // returned by the "start" method is rejected. - download = yield Downloads.createDownload({ - source: httpUrl("source.txt"), - target: targetFile, - }); - yield download.start(); - } else { - // When testing DownloadLegacySaver, we cannot be sure whether we are - // testing the promise returned by the "start" method or we are testing - // the "error" property checked by promiseDownloadStopped. This happens - // because we don't have control over when the download is started. - download = yield promiseStartLegacyDownload(null, - { targetFile: targetFile }); - yield promiseDownloadStopped(download); - } - do_throw("The download should have failed."); - } catch (ex) { - if (!(ex instanceof Downloads.Error) || !ex.becauseTargetFailed) { - throw ex; - } - // A specific error object is thrown when writing to the target fails. - } - - // Check the properties now that the download stopped. - do_check_true(download.stopped); - do_check_false(download.canceled); - do_check_true(download.error !== null); - do_check_true(download.error.becauseTargetFailed); - do_check_false(download.error.becauseSourceFailed); - } finally { - // Restore the default permissions to allow deleting the file on Windows. - if (targetFile.exists()) { - targetFile.permissions = FileUtils.PERMS_FILE; - targetFile.remove(false); - } - } -}); - -/** - * Restarts a failed download. - */ -add_task(function* test_error_restart() -{ - let download; - - // Create a file without write access permissions before downloading. - let targetFile = getTempFile(TEST_TARGET_FILE_NAME); - targetFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0); - try { - // Use DownloadCopySaver or DownloadLegacySaver based on the test run, - // specifying the target file we created. - if (!gUseLegacySaver) { - download = yield Downloads.createDownload({ - source: httpUrl("source.txt"), - target: targetFile, - }); - download.start().catch(() => {}); - } else { - download = yield promiseStartLegacyDownload(null, - { targetFile: targetFile }); - } - yield promiseDownloadStopped(download); - do_throw("The download should have failed."); - } catch (ex) { - if (!(ex instanceof Downloads.Error) || !ex.becauseTargetFailed) { - throw ex; - } - // A specific error object is thrown when writing to the target fails. - } finally { - // Restore the default permissions to allow deleting the file on Windows. - if (targetFile.exists()) { - targetFile.permissions = FileUtils.PERMS_FILE; - - // Also for Windows, rename the file before deleting. This makes the - // current file name available immediately for a new file, while deleting - // in place prevents creation of a file with the same name for some time. - targetFile.moveTo(null, targetFile.leafName + ".delete.tmp"); - targetFile.remove(false); - } - } - - // Restart the download and wait for completion. - yield download.start(); - - do_check_true(download.stopped); - do_check_true(download.succeeded); - do_check_false(download.canceled); - do_check_true(download.error === null); - do_check_eq(download.progress, 100); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT); -}); - -/** - * Executes download in both public and private modes. - */ -add_task(function* test_public_and_private() -{ - let sourcePath = "/test_public_and_private.txt"; - let sourceUrl = httpUrl("test_public_and_private.txt"); - let testCount = 0; - - // Apply pref to allow all cookies. - Services.prefs.setIntPref("network.cookie.cookieBehavior", 0); - - function cleanup() { - Services.prefs.clearUserPref("network.cookie.cookieBehavior"); - Services.cookies.removeAll(); - gHttpServer.registerPathHandler(sourcePath, null); - } - do_register_cleanup(cleanup); - - gHttpServer.registerPathHandler(sourcePath, function (aRequest, aResponse) { - aResponse.setHeader("Content-Type", "text/plain", false); - - if (testCount == 0) { - // No cookies should exist for first public download. - do_check_false(aRequest.hasHeader("Cookie")); - aResponse.setHeader("Set-Cookie", "foobar=1", false); - testCount++; - } else if (testCount == 1) { - // The cookie should exists for second public download. - do_check_true(aRequest.hasHeader("Cookie")); - do_check_eq(aRequest.getHeader("Cookie"), "foobar=1"); - testCount++; - } else if (testCount == 2) { - // No cookies should exist for first private download. - do_check_false(aRequest.hasHeader("Cookie")); - } - }); - - let targetFile = getTempFile(TEST_TARGET_FILE_NAME); - yield Downloads.fetch(sourceUrl, targetFile); - yield Downloads.fetch(sourceUrl, targetFile); - - if (!gUseLegacySaver) { - let download = yield Downloads.createDownload({ - source: { url: sourceUrl, isPrivate: true }, - target: targetFile, - }); - yield download.start(); - } else { - let download = yield promiseStartLegacyDownload(sourceUrl, - { isPrivate: true }); - yield promiseDownloadStopped(download); - } - - cleanup(); -}); - -/** - * Checks the startTime gets updated even after a restart. - */ -add_task(function* test_cancel_immediately_restart_and_check_startTime() -{ - let download = yield promiseStartDownload(); - - let startTime = download.startTime; - do_check_true(isValidDate(download.startTime)); - - yield download.cancel(); - do_check_eq(download.startTime.getTime(), startTime.getTime()); - - // Wait for a timeout. - yield promiseTimeout(10); - - yield download.start(); - do_check_true(download.startTime.getTime() > startTime.getTime()); -}); - -/** - * Executes download with content-encoding. - */ -add_task(function* test_with_content_encoding() -{ - let sourcePath = "/test_with_content_encoding.txt"; - let sourceUrl = httpUrl("test_with_content_encoding.txt"); - - function cleanup() { - gHttpServer.registerPathHandler(sourcePath, null); - } - do_register_cleanup(cleanup); - - gHttpServer.registerPathHandler(sourcePath, function (aRequest, aResponse) { - aResponse.setHeader("Content-Type", "text/plain", false); - aResponse.setHeader("Content-Encoding", "gzip", false); - aResponse.setHeader("Content-Length", - "" + TEST_DATA_SHORT_GZIP_ENCODED.length, false); - - let bos = new BinaryOutputStream(aResponse.bodyOutputStream); - bos.writeByteArray(TEST_DATA_SHORT_GZIP_ENCODED, - TEST_DATA_SHORT_GZIP_ENCODED.length); - }); - - let download = yield promiseStartDownload(sourceUrl); - yield promiseDownloadStopped(download); - - do_check_eq(download.progress, 100); - do_check_eq(download.totalBytes, TEST_DATA_SHORT_GZIP_ENCODED.length); - - // Ensure the content matches the decoded test data. - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT); - - cleanup(); -}); - -/** - * Checks that the file is not decoded if the extension matches the encoding. - */ -add_task(function* test_with_content_encoding_ignore_extension() -{ - let sourcePath = "/test_with_content_encoding_ignore_extension.gz"; - let sourceUrl = httpUrl("test_with_content_encoding_ignore_extension.gz"); - - function cleanup() { - gHttpServer.registerPathHandler(sourcePath, null); - } - do_register_cleanup(cleanup); - - gHttpServer.registerPathHandler(sourcePath, function (aRequest, aResponse) { - aResponse.setHeader("Content-Type", "text/plain", false); - aResponse.setHeader("Content-Encoding", "gzip", false); - aResponse.setHeader("Content-Length", - "" + TEST_DATA_SHORT_GZIP_ENCODED.length, false); - - let bos = new BinaryOutputStream(aResponse.bodyOutputStream); - bos.writeByteArray(TEST_DATA_SHORT_GZIP_ENCODED, - TEST_DATA_SHORT_GZIP_ENCODED.length); - }); - - let download = yield promiseStartDownload(sourceUrl); - yield promiseDownloadStopped(download); - - do_check_eq(download.progress, 100); - do_check_eq(download.totalBytes, TEST_DATA_SHORT_GZIP_ENCODED.length); - do_check_eq(download.target.size, TEST_DATA_SHORT_GZIP_ENCODED.length); - - // Ensure the content matches the encoded test data. We convert the data to a - // string before executing the content check. - yield promiseVerifyTarget(download.target, - String.fromCharCode.apply(String, TEST_DATA_SHORT_GZIP_ENCODED)); - - cleanup(); -}); - -/** - * Cancels and restarts a download sequentially with content-encoding. - */ -add_task(function* test_cancel_midway_restart_with_content_encoding() -{ - mustInterruptResponses(); - - let download = yield promiseStartDownload(httpUrl("interruptible_gzip.txt")); - - // The first time, cancel the download midway. - let deferCancel = Promise.defer(); - let onchange = function () { - if (!download.stopped && !download.canceled && - download.currentBytes == TEST_DATA_SHORT_GZIP_ENCODED_FIRST.length) { - deferCancel.resolve(download.cancel()); - } - }; - - // Register for the notification, but also call the function directly in - // case the download already reached the expected progress. - download.onchange = onchange; - onchange(); - - yield deferCancel.promise; - - do_check_true(download.stopped); - - // The second time, we'll provide the entire interruptible response. - continueResponses(); - download.onchange = null; - yield download.start(); - - do_check_eq(download.progress, 100); - do_check_eq(download.totalBytes, TEST_DATA_SHORT_GZIP_ENCODED.length); - - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT); -}); - -/** - * Download with parental controls enabled. - */ -add_task(function* test_blocked_parental_controls() -{ - let blockFn = base => ({ - shouldBlockForParentalControls: () => Promise.resolve(true), - }); - - Integration.downloads.register(blockFn); - function cleanup() { - Integration.downloads.unregister(blockFn); - } - do_register_cleanup(cleanup); - - let download; - try { - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we want to check that the promise - // returned by the "start" method is rejected. - download = yield promiseNewDownload(); - yield download.start(); - } else { - // When testing DownloadLegacySaver, we cannot be sure whether we are - // testing the promise returned by the "start" method or we are testing - // the "error" property checked by promiseDownloadStopped. This happens - // because we don't have control over when the download is started. - download = yield promiseStartLegacyDownload(); - yield promiseDownloadStopped(download); - } - do_throw("The download should have blocked."); - } catch (ex) { - if (!(ex instanceof Downloads.Error) || !ex.becauseBlocked) { - throw ex; - } - do_check_true(ex.becauseBlockedByParentalControls); - do_check_true(download.error.becauseBlockedByParentalControls); - } - - // Now that the download stopped, the target file should not exist. - do_check_false(yield OS.File.exists(download.target.path)); - - cleanup(); -}); - -/** - * Test a download that will be blocked by Windows parental controls by - * resulting in an HTTP status code of 450. - */ -add_task(function* test_blocked_parental_controls_httpstatus450() -{ - let download; - try { - if (!gUseLegacySaver) { - download = yield promiseNewDownload(httpUrl("parentalblocked.zip")); - yield download.start(); - } - else { - download = yield promiseStartLegacyDownload(httpUrl("parentalblocked.zip")); - yield promiseDownloadStopped(download); - } - do_throw("The download should have blocked."); - } catch (ex) { - if (!(ex instanceof Downloads.Error) || !ex.becauseBlocked) { - throw ex; - } - do_check_true(ex.becauseBlockedByParentalControls); - do_check_true(download.error.becauseBlockedByParentalControls); - do_check_true(download.stopped); - } - - do_check_false(yield OS.File.exists(download.target.path)); -}); - -/** - * Download with runtime permissions - */ -add_task(function* test_blocked_runtime_permissions() -{ - let blockFn = base => ({ - shouldBlockForRuntimePermissions: () => Promise.resolve(true), - }); - - Integration.downloads.register(blockFn); - function cleanup() { - Integration.downloads.unregister(blockFn); - } - do_register_cleanup(cleanup); - - let download; - try { - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we want to check that the promise - // returned by the "start" method is rejected. - download = yield promiseNewDownload(); - yield download.start(); - } else { - // When testing DownloadLegacySaver, we cannot be sure whether we are - // testing the promise returned by the "start" method or we are testing - // the "error" property checked by promiseDownloadStopped. This happens - // because we don't have control over when the download is started. - download = yield promiseStartLegacyDownload(); - yield promiseDownloadStopped(download); - } - do_throw("The download should have blocked."); - } catch (ex) { - if (!(ex instanceof Downloads.Error) || !ex.becauseBlocked) { - throw ex; - } - do_check_true(ex.becauseBlockedByRuntimePermissions); - do_check_true(download.error.becauseBlockedByRuntimePermissions); - } - - // Now that the download stopped, the target file should not exist. - do_check_false(yield OS.File.exists(download.target.path)); - - cleanup(); -}); - -/** - * Check that DownloadCopySaver can always retrieve the hash. - * DownloadLegacySaver can only retrieve the hash when - * nsIExternalHelperAppService is invoked. - */ -add_task(function* test_getSha256Hash() -{ - if (!gUseLegacySaver) { - let download = yield promiseStartDownload(httpUrl("source.txt")); - yield promiseDownloadStopped(download); - do_check_true(download.stopped); - do_check_eq(32, download.saver.getSha256Hash().length); - } -}); - -/** - * Create a download which will be reputation blocked. - * - * @param options - * { - * keepPartialData: bool, - * keepBlockedData: bool, - * } - * @return {Promise} - * @resolves The reputation blocked download. - * @rejects JavaScript exception. - */ -var promiseBlockedDownload = Task.async(function* (options) { - let blockFn = base => ({ - shouldBlockForReputationCheck: () => Promise.resolve({ - shouldBlock: true, - verdict: Downloads.Error.BLOCK_VERDICT_UNCOMMON, - }), - shouldKeepBlockedData: () => Promise.resolve(options.keepBlockedData), - }); - - Integration.downloads.register(blockFn); - function cleanup() { - Integration.downloads.unregister(blockFn); - } - do_register_cleanup(cleanup); - - let download; - - try { - if (options.keepPartialData) { - download = yield promiseStartDownload_tryToKeepPartialData(); - continueResponses(); - } else if (gUseLegacySaver) { - download = yield promiseStartLegacyDownload(); - } else { - download = yield promiseNewDownload(); - yield download.start(); - do_throw("The download should have blocked."); - } - - yield promiseDownloadStopped(download); - do_throw("The download should have blocked."); - } catch (ex) { - if (!(ex instanceof Downloads.Error) || !ex.becauseBlocked) { - throw ex; - } - do_check_true(ex.becauseBlockedByReputationCheck); - do_check_eq(ex.reputationCheckVerdict, - Downloads.Error.BLOCK_VERDICT_UNCOMMON); - do_check_true(download.error.becauseBlockedByReputationCheck); - do_check_eq(download.error.reputationCheckVerdict, - Downloads.Error.BLOCK_VERDICT_UNCOMMON); - } - - do_check_true(download.stopped); - do_check_false(download.succeeded); - do_check_false(yield OS.File.exists(download.target.path)); - - cleanup(); - return download; -}); - -/** - * Checks that application reputation blocks the download and the target file - * does not exist. - */ -add_task(function* test_blocked_applicationReputation() -{ - let download = yield promiseBlockedDownload({ - keepPartialData: false, - keepBlockedData: false, - }); - - // Now that the download is blocked, the target file should not exist. - do_check_false(yield OS.File.exists(download.target.path)); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); - - // There should also be no blocked data in this case - do_check_false(download.hasBlockedData); -}); - -/** - * Checks that if a download restarts while processing an application reputation - * request, the status is handled correctly. - */ -add_task(function* test_blocked_applicationReputation_race() -{ - let isFirstShouldBlockCall = true; - - let blockFn = base => ({ - shouldBlockForReputationCheck(download) { - if (isFirstShouldBlockCall) { - isFirstShouldBlockCall = false; - - // 2. Cancel and restart the download before the first attempt has a - // chance to finish. - download.cancel(); - download.removePartialData(); - download.start(); - - // 3. Allow the first attempt to finish with a blocked response. - return Promise.resolve({ - shouldBlock: true, - verdict: Downloads.Error.BLOCK_VERDICT_UNCOMMON, - }); - } - - // 4/5. Don't block the download the second time. The race condition would - // occur with the first attempt regardless of whether the second one - // is blocked, but not blocking here makes the test simpler. - return Promise.resolve({ - shouldBlock: false, - verdict: "", - }); - }, - shouldKeepBlockedData: () => Promise.resolve(true), - }); - - Integration.downloads.register(blockFn); - function cleanup() { - Integration.downloads.unregister(blockFn); - } - do_register_cleanup(cleanup); - - let download; - - try { - // 1. Start the download and get a reference to the promise asociated with - // the first attempt, before allowing the response to continue. - download = yield promiseStartDownload_tryToKeepPartialData(); - let firstAttempt = promiseDownloadStopped(download); - continueResponses(); - - // 4/5. Wait for the first attempt to be completed. The result of this - // should appear as a cancellation. - yield firstAttempt; - - do_throw("The first attempt should have been canceled."); - } catch (ex) { - // The "becauseBlocked" property should be false. - if (!(ex instanceof Downloads.Error) || ex.becauseBlocked) { - throw ex; - } - } - - // 6. Wait for the second attempt to be completed. - yield promiseDownloadStopped(download); - - // 7. At this point, "hasBlockedData" should be false. - do_check_false(download.hasBlockedData); - - cleanup(); -}); - -/** - * Checks that application reputation blocks the download but maintains the - * blocked data, which will be deleted when the block is confirmed. - */ -add_task(function* test_blocked_applicationReputation_confirmBlock() -{ - let download = yield promiseBlockedDownload({ - keepPartialData: true, - keepBlockedData: true, - }); - - do_check_true(download.hasBlockedData); - do_check_true(yield OS.File.exists(download.target.partFilePath)); - - yield download.confirmBlock(); - - // After confirming the block the download should be in a failed state and - // have no downloaded data left on disk. - do_check_true(download.stopped); - do_check_false(download.succeeded); - do_check_false(download.hasBlockedData); - do_check_false(yield OS.File.exists(download.target.partFilePath)); - do_check_false(yield OS.File.exists(download.target.path)); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); -}); - -/** - * Checks that application reputation blocks the download but maintains the - * blocked data, which will be used to complete the download when unblocking. - */ -add_task(function* test_blocked_applicationReputation_unblock() -{ - let download = yield promiseBlockedDownload({ - keepPartialData: true, - keepBlockedData: true, - }); - - do_check_true(download.hasBlockedData); - do_check_true(yield OS.File.exists(download.target.partFilePath)); - - yield download.unblock(); - - // After unblocking the download should have succeeded and be - // present at the final path. - do_check_true(download.stopped); - do_check_true(download.succeeded); - do_check_false(download.hasBlockedData); - do_check_false(yield OS.File.exists(download.target.partFilePath)); - yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT); - - // The only indication the download was previously blocked is the - // existence of the error, so we make sure it's still set. - do_check_true(download.error instanceof Downloads.Error); - do_check_true(download.error.becauseBlocked); - do_check_true(download.error.becauseBlockedByReputationCheck); -}); - -/** - * Check that calling cancel on a blocked download will not cause errors - */ -add_task(function* test_blocked_applicationReputation_cancel() -{ - let download = yield promiseBlockedDownload({ - keepPartialData: true, - keepBlockedData: true, - }); - - // This call should succeed on a blocked download. - yield download.cancel(); - - // Calling cancel should not have changed the current state, the download - // should still be blocked. - do_check_true(download.error.becauseBlockedByReputationCheck); - do_check_true(download.stopped); - do_check_false(download.succeeded); - do_check_true(download.hasBlockedData); -}); - -/** - * Checks that unblock and confirmBlock cannot race on a blocked download - */ -add_task(function* test_blocked_applicationReputation_decisionRace() -{ - let download = yield promiseBlockedDownload({ - keepPartialData: true, - keepBlockedData: true, - }); - - let unblockPromise = download.unblock(); - let confirmBlockPromise = download.confirmBlock(); - - yield confirmBlockPromise.then(() => { - do_throw("confirmBlock should have failed."); - }, () => {}); - - yield unblockPromise; - - // After unblocking the download should have succeeded and be - // present at the final path. - do_check_true(download.stopped); - do_check_true(download.succeeded); - do_check_false(download.hasBlockedData); - do_check_false(yield OS.File.exists(download.target.partFilePath)); - do_check_true(yield OS.File.exists(download.target.path)); - - download = yield promiseBlockedDownload({ - keepPartialData: true, - keepBlockedData: true, - }); - - confirmBlockPromise = download.confirmBlock(); - unblockPromise = download.unblock(); - - yield unblockPromise.then(() => { - do_throw("unblock should have failed."); - }, () => {}); - - yield confirmBlockPromise; - - // After confirming the block the download should be in a failed state and - // have no downloaded data left on disk. - do_check_true(download.stopped); - do_check_false(download.succeeded); - do_check_false(download.hasBlockedData); - do_check_false(yield OS.File.exists(download.target.partFilePath)); - do_check_false(yield OS.File.exists(download.target.path)); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); -}); - -/** - * Checks that unblocking a blocked download fails if the blocked data has been - * removed. - */ -add_task(function* test_blocked_applicationReputation_unblock() -{ - let download = yield promiseBlockedDownload({ - keepPartialData: true, - keepBlockedData: true, - }); - - do_check_true(download.hasBlockedData); - do_check_true(yield OS.File.exists(download.target.partFilePath)); - - // Remove the blocked data without telling the download. - yield OS.File.remove(download.target.partFilePath); - - let unblockPromise = download.unblock(); - yield unblockPromise.then(() => { - do_throw("unblock should have failed."); - }, () => {}); - - // Even though unblocking failed the download state should have been updated - // to reflect the lack of blocked data. - do_check_false(download.hasBlockedData); - do_check_true(download.stopped); - do_check_false(download.succeeded); - do_check_false(download.target.exists); - do_check_eq(download.target.size, 0); -}); - -/** - * download.showContainingDirectory() action - */ -add_task(function* test_showContainingDirectory() { - let targetPath = getTempFile(TEST_TARGET_FILE_NAME).path; - - let download = yield Downloads.createDownload({ - source: { url: httpUrl("source.txt") }, - target: "" - }); - - let promiseDirectoryShown = waitForDirectoryShown(); - yield download.showContainingDirectory(); - let path = yield promiseDirectoryShown; - try { - new FileUtils.File(path); - do_throw("Should have failed because of an invalid path."); - } catch (ex) { - if (!(ex instanceof Components.Exception)) { - throw ex; - } - // Invalid paths on Windows are reported with NS_ERROR_FAILURE, - // but with NS_ERROR_FILE_UNRECOGNIZED_PATH on Mac/Linux - let validResult = ex.result == Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH || - ex.result == Cr.NS_ERROR_FAILURE; - do_check_true(validResult); - } - - download = yield Downloads.createDownload({ - source: { url: httpUrl("source.txt") }, - target: targetPath - }); - - promiseDirectoryShown = waitForDirectoryShown(); - download.showContainingDirectory(); - yield promiseDirectoryShown; -}); - -/** - * download.launch() action - */ -add_task(function* test_launch() { - let customLauncher = getTempFile("app-launcher"); - - // Test both with and without setting a custom application. - for (let launcherPath of [null, customLauncher.path]) { - let download; - if (!gUseLegacySaver) { - // When testing DownloadCopySaver, we have control over the download, thus - // we can test that file is not launched if download.succeeded is not set. - download = yield Downloads.createDownload({ - source: httpUrl("source.txt"), - target: getTempFile(TEST_TARGET_FILE_NAME).path, - launcherPath: launcherPath, - launchWhenSucceeded: true - }); - - try { - yield download.launch(); - do_throw("Can't launch download file as it has not completed yet"); - } catch (ex) { - do_check_eq(ex.message, - "launch can only be called if the download succeeded"); - } - - yield download.start(); - } else { - // When testing DownloadLegacySaver, the download is already started when - // it is created, thus we don't test calling "launch" before starting. - download = yield promiseStartLegacyDownload( - httpUrl("source.txt"), - { launcherPath: launcherPath, - launchWhenSucceeded: true }); - yield promiseDownloadStopped(download); - } - - do_check_true(download.launchWhenSucceeded); - - let promiseFileLaunched = waitForFileLaunched(); - download.launch(); - let result = yield promiseFileLaunched; - - // Verify that the results match the test case. - if (!launcherPath) { - // This indicates that the default handler has been chosen. - do_check_true(result === null); - } else { - // Check the nsIMIMEInfo instance that would have been used for launching. - do_check_eq(result.preferredAction, Ci.nsIMIMEInfo.useHelperApp); - do_check_true(result.preferredApplicationHandler - .QueryInterface(Ci.nsILocalHandlerApp) - .executable.equals(customLauncher)); - } - } -}); - -/** - * Test passing an invalid path as the launcherPath property. - */ -add_task(function* test_launcherPath_invalid() { - let download = yield Downloads.createDownload({ - source: { url: httpUrl("source.txt") }, - target: { path: getTempFile(TEST_TARGET_FILE_NAME).path }, - launcherPath: " " - }); - - let promiseDownloadLaunched = new Promise(resolve => { - let waitFn = base => ({ - __proto__: base, - launchDownload() { - Integration.downloads.unregister(waitFn); - let superPromise = super.launchDownload(...arguments); - resolve(superPromise); - return superPromise; - }, - }); - Integration.downloads.register(waitFn); - }); - - yield download.start(); - try { - download.launch(); - yield promiseDownloadLaunched; - do_throw("Can't launch file with invalid custom launcher") - } catch (ex) { - if (!(ex instanceof Components.Exception)) { - throw ex; - } - // Invalid paths on Windows are reported with NS_ERROR_FAILURE, - // but with NS_ERROR_FILE_UNRECOGNIZED_PATH on Mac/Linux - let validResult = ex.result == Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH || - ex.result == Cr.NS_ERROR_FAILURE; - do_check_true(validResult); - } -}); - -/** - * Tests that download.launch() is automatically called after - * the download finishes if download.launchWhenSucceeded = true - */ -add_task(function* test_launchWhenSucceeded() { - let customLauncher = getTempFile("app-launcher"); - - // Test both with and without setting a custom application. - for (let launcherPath of [null, customLauncher.path]) { - let promiseFileLaunched = waitForFileLaunched(); - - if (!gUseLegacySaver) { - let download = yield Downloads.createDownload({ - source: httpUrl("source.txt"), - target: getTempFile(TEST_TARGET_FILE_NAME).path, - launchWhenSucceeded: true, - launcherPath: launcherPath, - }); - yield download.start(); - } else { - let download = yield promiseStartLegacyDownload( - httpUrl("source.txt"), - { launcherPath: launcherPath, - launchWhenSucceeded: true }); - yield promiseDownloadStopped(download); - } - - let result = yield promiseFileLaunched; - - // Verify that the results match the test case. - if (!launcherPath) { - // This indicates that the default handler has been chosen. - do_check_true(result === null); - } else { - // Check the nsIMIMEInfo instance that would have been used for launching. - do_check_eq(result.preferredAction, Ci.nsIMIMEInfo.useHelperApp); - do_check_true(result.preferredApplicationHandler - .QueryInterface(Ci.nsILocalHandlerApp) - .executable.equals(customLauncher)); - } - } -}); - -/** - * Tests that the proper content type is set for a normal download. - */ -add_task(function* test_contentType() { - let download = yield promiseStartDownload(httpUrl("source.txt")); - yield promiseDownloadStopped(download); - - do_check_eq("text/plain", download.contentType); -}); - -/** - * Tests that the serialization/deserialization of the startTime Date - * object works correctly. - */ -add_task(function* test_toSerializable_startTime() -{ - let download1 = yield promiseStartDownload(httpUrl("source.txt")); - yield promiseDownloadStopped(download1); - - let serializable = download1.toSerializable(); - let reserialized = JSON.parse(JSON.stringify(serializable)); - - let download2 = yield Downloads.createDownload(reserialized); - - do_check_eq(download1.startTime.constructor.name, "Date"); - do_check_eq(download2.startTime.constructor.name, "Date"); - do_check_eq(download1.startTime.toJSON(), download2.startTime.toJSON()); -}); - -/** - * Checks that downloads are added to browsing history when they start. - */ -add_task(function* test_history() -{ - mustInterruptResponses(); - - // We will wait for the visit to be notified during the download. - yield PlacesTestUtils.clearHistory(); - let promiseVisit = promiseWaitForVisit(httpUrl("interruptible.txt")); - - // Start a download that is not allowed to finish yet. - let download = yield promiseStartDownload(httpUrl("interruptible.txt")); - - // The history notifications should be received before the download completes. - let [time, transitionType] = yield promiseVisit; - do_check_eq(time, download.startTime.getTime() * 1000); - do_check_eq(transitionType, Ci.nsINavHistoryService.TRANSITION_DOWNLOAD); - - // Restart and complete the download after clearing history. - yield PlacesTestUtils.clearHistory(); - download.cancel(); - continueResponses(); - yield download.start(); - - // The restart should not have added a new history visit. - do_check_false(yield promiseIsURIVisited(httpUrl("interruptible.txt"))); -}); - -/** - * Checks that downloads started by nsIHelperAppService are added to the - * browsing history when they start. - */ -add_task(function* test_history_tryToKeepPartialData() -{ - // We will wait for the visit to be notified during the download. - yield PlacesTestUtils.clearHistory(); - let promiseVisit = - promiseWaitForVisit(httpUrl("interruptible_resumable.txt")); - - // Start a download that is not allowed to finish yet. - let beforeStartTimeMs = Date.now(); - let download = yield promiseStartDownload_tryToKeepPartialData(); - - // The history notifications should be received before the download completes. - let [time, transitionType] = yield promiseVisit; - do_check_eq(transitionType, Ci.nsINavHistoryService.TRANSITION_DOWNLOAD); - - // The time set by nsIHelperAppService may be different than the start time in - // the download object, thus we only check that it is a meaningful time. Note - // that we subtract one second from the earliest time to account for rounding. - do_check_true(time >= beforeStartTimeMs * 1000 - 1000000); - - // Complete the download before finishing the test. - continueResponses(); - yield promiseDownloadStopped(download); -}); - -/** - * Tests that the temp download files are removed on exit and exiting private - * mode after they have been launched. - */ -add_task(function* test_launchWhenSucceeded_deleteTempFileOnExit() { - let customLauncherPath = getTempFile("app-launcher").path; - let autoDeleteTargetPathOne = getTempFile(TEST_TARGET_FILE_NAME).path; - let autoDeleteTargetPathTwo = getTempFile(TEST_TARGET_FILE_NAME).path; - let noAutoDeleteTargetPath = getTempFile(TEST_TARGET_FILE_NAME).path; - - let autoDeleteDownloadOne = yield Downloads.createDownload({ - source: { url: httpUrl("source.txt"), isPrivate: true }, - target: autoDeleteTargetPathOne, - launchWhenSucceeded: true, - launcherPath: customLauncherPath, - }); - yield autoDeleteDownloadOne.start(); - - Services.prefs.setBoolPref(kDeleteTempFileOnExit, true); - let autoDeleteDownloadTwo = yield Downloads.createDownload({ - source: httpUrl("source.txt"), - target: autoDeleteTargetPathTwo, - launchWhenSucceeded: true, - launcherPath: customLauncherPath, - }); - yield autoDeleteDownloadTwo.start(); - - Services.prefs.setBoolPref(kDeleteTempFileOnExit, false); - let noAutoDeleteDownload = yield Downloads.createDownload({ - source: httpUrl("source.txt"), - target: noAutoDeleteTargetPath, - launchWhenSucceeded: true, - launcherPath: customLauncherPath, - }); - yield noAutoDeleteDownload.start(); - - Services.prefs.clearUserPref(kDeleteTempFileOnExit); - - do_check_true(yield OS.File.exists(autoDeleteTargetPathOne)); - do_check_true(yield OS.File.exists(autoDeleteTargetPathTwo)); - do_check_true(yield OS.File.exists(noAutoDeleteTargetPath)); - - // Simulate leaving private browsing mode - Services.obs.notifyObservers(null, "last-pb-context-exited", null); - do_check_false(yield OS.File.exists(autoDeleteTargetPathOne)); - - // Simulate browser shutdown - let expire = Cc["@mozilla.org/uriloader/external-helper-app-service;1"] - .getService(Ci.nsIObserver); - expire.observe(null, "profile-before-change", null); - do_check_false(yield OS.File.exists(autoDeleteTargetPathTwo)); - do_check_true(yield OS.File.exists(noAutoDeleteTargetPath)); -}); |