diff options
Diffstat (limited to 'toolkit/components/jsdownloads/test/unit/head.js')
-rw-r--r-- | toolkit/components/jsdownloads/test/unit/head.js | 843 |
1 files changed, 0 insertions, 843 deletions
diff --git a/toolkit/components/jsdownloads/test/unit/head.js b/toolkit/components/jsdownloads/test/unit/head.js deleted file mode 100644 index f322244c4..000000000 --- a/toolkit/components/jsdownloads/test/unit/head.js +++ /dev/null @@ -1,843 +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/ */ - -/** - * Provides infrastructure for automated download components tests. - */ - -"use strict"; - -// Globals - -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; -var Cr = Components.results; - -Cu.import("resource://gre/modules/Integration.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "DownloadPaths", - "resource://gre/modules/DownloadPaths.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Downloads", - "resource://gre/modules/Downloads.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", - "resource://gre/modules/FileUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "HttpServer", - "resource://testing-common/httpd.js"); -XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", - "resource://gre/modules/NetUtil.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils", - "resource://testing-common/PlacesTestUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", - "resource://gre/modules/PlacesUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Promise", - "resource://gre/modules/Promise.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Services", - "resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "OS", - "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "MockRegistrar", - "resource://testing-common/MockRegistrar.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "gExternalHelperAppService", - "@mozilla.org/uriloader/external-helper-app-service;1", - Ci.nsIExternalHelperAppService); - -Integration.downloads.defineModuleGetter(this, "DownloadIntegration", - "resource://gre/modules/DownloadIntegration.jsm"); - -const ServerSocket = Components.Constructor( - "@mozilla.org/network/server-socket;1", - "nsIServerSocket", - "init"); -const BinaryOutputStream = Components.Constructor( - "@mozilla.org/binaryoutputstream;1", - "nsIBinaryOutputStream", - "setOutputStream") - -XPCOMUtils.defineLazyServiceGetter(this, "gMIMEService", - "@mozilla.org/mime;1", - "nsIMIMEService"); - -const TEST_TARGET_FILE_NAME = "test-download.txt"; -const TEST_STORE_FILE_NAME = "test-downloads.json"; - -const TEST_REFERRER_URL = "http://www.example.com/referrer.html"; - -const TEST_DATA_SHORT = "This test string is downloaded."; -// Generate using gzipCompressString in TelemetryController.jsm. -const TEST_DATA_SHORT_GZIP_ENCODED_FIRST = [ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 3, 11, 201, 200, 44, 86, 40, 73, 45, 46, 81, 40, 46, 41, 202, 204 -]; -const TEST_DATA_SHORT_GZIP_ENCODED_SECOND = [ - 75, 87, 0, 114, 83, 242, 203, 243, 114, 242, 19, 83, 82, 83, 244, 0, 151, 222, 109, 43, 31, 0, 0, 0 -]; -const TEST_DATA_SHORT_GZIP_ENCODED = - TEST_DATA_SHORT_GZIP_ENCODED_FIRST.concat(TEST_DATA_SHORT_GZIP_ENCODED_SECOND); - -/** - * All the tests are implemented with add_task, this starts them automatically. - */ -function run_test() -{ - do_get_profile(); - run_next_test(); -} - -// Support functions - -/** - * HttpServer object initialized before tests start. - */ -var gHttpServer; - -/** - * Given a file name, returns a string containing an URI that points to the file - * on the currently running instance of the test HTTP server. - */ -function httpUrl(aFileName) { - return "http://localhost:" + gHttpServer.identity.primaryPort + "/" + - aFileName; -} - -// While the previous test file should have deleted all the temporary files it -// used, on Windows these might still be pending deletion on the physical file -// system. Thus, start from a new base number every time, to make a collision -// with a file that is still pending deletion highly unlikely. -var gFileCounter = Math.floor(Math.random() * 1000000); - -/** - * Returns a reference to a temporary file, that is guaranteed not to exist, and - * to have never been created before. - * - * @param aLeafName - * Suggested leaf name for the file to be created. - * - * @return nsIFile pointing to a non-existent file in a temporary directory. - * - * @note It is not enough to delete the file if it exists, or to delete the file - * after calling nsIFile.createUnique, because on Windows the delete - * operation in the file system may still be pending, preventing a new - * file with the same name to be created. - */ -function getTempFile(aLeafName) -{ - // Prepend a serial number to the extension in the suggested leaf name. - let [base, ext] = DownloadPaths.splitBaseNameAndExtension(aLeafName); - let leafName = base + "-" + gFileCounter + ext; - gFileCounter++; - - // Get a file reference under the temporary directory for this test file. - let file = FileUtils.getFile("TmpD", [leafName]); - do_check_false(file.exists()); - - do_register_cleanup(function () { - try { - file.remove(false) - } catch (e) { - if (!(e instanceof Components.Exception && - (e.result == Cr.NS_ERROR_FILE_ACCESS_DENIED || - e.result == Cr.NS_ERROR_FILE_TARGET_DOES_NOT_EXIST || - e.result == Cr.NS_ERROR_FILE_NOT_FOUND))) { - throw e; - } - // On Windows, we may get an access denied error if the file existed before, - // and was recently deleted. - // Don't bother checking file.exists() as that may also cause an access - // denied error. - } - }); - - return file; -} - -/** - * Waits for pending events to be processed. - * - * @return {Promise} - * @resolves When pending events have been processed. - * @rejects Never. - */ -function promiseExecuteSoon() -{ - let deferred = Promise.defer(); - do_execute_soon(deferred.resolve); - return deferred.promise; -} - -/** - * Waits for a pending events to be processed after a timeout. - * - * @return {Promise} - * @resolves When pending events have been processed. - * @rejects Never. - */ -function promiseTimeout(aTime) -{ - let deferred = Promise.defer(); - do_timeout(aTime, deferred.resolve); - return deferred.promise; -} - -/** - * Waits for a new history visit to be notified for the specified URI. - * - * @param aUrl - * String containing the URI that will be visited. - * - * @return {Promise} - * @resolves Array [aTime, aTransitionType] from nsINavHistoryObserver.onVisit. - * @rejects Never. - */ -function promiseWaitForVisit(aUrl) -{ - let deferred = Promise.defer(); - - let uri = NetUtil.newURI(aUrl); - - PlacesUtils.history.addObserver({ - QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver]), - onBeginUpdateBatch: function () {}, - onEndUpdateBatch: function () {}, - onVisit: function (aURI, aVisitID, aTime, aSessionID, aReferringID, - aTransitionType, aGUID, aHidden) { - if (aURI.equals(uri)) { - PlacesUtils.history.removeObserver(this); - deferred.resolve([aTime, aTransitionType]); - } - }, - onTitleChanged: function () {}, - onDeleteURI: function () {}, - onClearHistory: function () {}, - onPageChanged: function () {}, - onDeleteVisits: function () {}, - }, false); - - return deferred.promise; -} - -/** - * Check browsing history to see whether the given URI has been visited. - * - * @param aUrl - * String containing the URI that will be visited. - * - * @return {Promise} - * @resolves Boolean indicating whether the URI has been visited. - * @rejects JavaScript exception. - */ -function promiseIsURIVisited(aUrl) { - let deferred = Promise.defer(); - - PlacesUtils.asyncHistory.isURIVisited(NetUtil.newURI(aUrl), - function (aURI, aIsVisited) { - deferred.resolve(aIsVisited); - }); - - return deferred.promise; -} - -/** - * Creates a new Download object, setting a temporary file as the target. - * - * @param aSourceUrl - * String containing the URI for the download source, or null to use - * httpUrl("source.txt"). - * - * @return {Promise} - * @resolves The newly created Download object. - * @rejects JavaScript exception. - */ -function promiseNewDownload(aSourceUrl) { - return Downloads.createDownload({ - source: aSourceUrl || httpUrl("source.txt"), - target: getTempFile(TEST_TARGET_FILE_NAME), - }); -} - -/** - * Starts a new download using the nsIWebBrowserPersist interface, and controls - * it using the legacy nsITransfer interface. - * - * @param aSourceUrl - * String containing the URI for the download source, or null to use - * httpUrl("source.txt"). - * @param aOptions - * An optional object used to control the behavior of this function. - * You may pass an object with a subset of the following fields: - * { - * isPrivate: Boolean indicating whether the download originated from a - * private window. - * targetFile: nsIFile for the target, or null to use a temporary file. - * outPersist: Receives a reference to the created nsIWebBrowserPersist - * instance. - * launchWhenSucceeded: Boolean indicating whether the target should - * be launched when it has completed successfully. - * launcherPath: String containing the path of the custom executable to - * use to launch the target of the download. - * } - * - * @return {Promise} - * @resolves The Download object created as a consequence of controlling the - * download through the legacy nsITransfer interface. - * @rejects Never. The current test fails in case of exceptions. - */ -function promiseStartLegacyDownload(aSourceUrl, aOptions) { - let sourceURI = NetUtil.newURI(aSourceUrl || httpUrl("source.txt")); - let targetFile = (aOptions && aOptions.targetFile) - || getTempFile(TEST_TARGET_FILE_NAME); - - let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"] - .createInstance(Ci.nsIWebBrowserPersist); - if (aOptions) { - aOptions.outPersist = persist; - } - - let fileExtension = null, mimeInfo = null; - let match = sourceURI.path.match(/\.([^.\/]+)$/); - if (match) { - fileExtension = match[1]; - } - - if (fileExtension) { - try { - mimeInfo = gMIMEService.getFromTypeAndExtension(null, fileExtension); - mimeInfo.preferredAction = Ci.nsIMIMEInfo.saveToDisk; - } catch (ex) { } - } - - if (aOptions && aOptions.launcherPath) { - do_check_true(mimeInfo != null); - - let localHandlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"] - .createInstance(Ci.nsILocalHandlerApp); - localHandlerApp.executable = new FileUtils.File(aOptions.launcherPath); - - mimeInfo.preferredApplicationHandler = localHandlerApp; - mimeInfo.preferredAction = Ci.nsIMIMEInfo.useHelperApp; - } - - if (aOptions && aOptions.launchWhenSucceeded) { - do_check_true(mimeInfo != null); - - mimeInfo.preferredAction = Ci.nsIMIMEInfo.useHelperApp; - } - - // Apply decoding if required by the "Content-Encoding" header. - persist.persistFlags &= ~Ci.nsIWebBrowserPersist.PERSIST_FLAGS_NO_CONVERSION; - persist.persistFlags |= - Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION; - - let transfer = Cc["@mozilla.org/transfer;1"].createInstance(Ci.nsITransfer); - - let deferred = Promise.defer(); - - Downloads.getList(Downloads.ALL).then(function (aList) { - // Temporarily register a view that will get notified when the download we - // are controlling becomes visible in the list of downloads. - aList.addView({ - onDownloadAdded: function (aDownload) { - aList.removeView(this).then(null, do_report_unexpected_exception); - - // Remove the download to keep the list empty for the next test. This - // also allows the caller to register the "onchange" event directly. - let promise = aList.remove(aDownload); - - // When the download object is ready, make it available to the caller. - promise.then(() => deferred.resolve(aDownload), - do_report_unexpected_exception); - }, - }).then(null, do_report_unexpected_exception); - - let isPrivate = aOptions && aOptions.isPrivate; - - // Initialize the components so they reference each other. This will cause - // the Download object to be created and added to the public downloads. - transfer.init(sourceURI, NetUtil.newURI(targetFile), null, mimeInfo, null, - null, persist, isPrivate); - persist.progressListener = transfer; - - // Start the actual download process. - persist.savePrivacyAwareURI(sourceURI, null, null, 0, null, null, targetFile, - isPrivate); - }.bind(this)).then(null, do_report_unexpected_exception); - - return deferred.promise; -} - -/** - * Starts a new download using the nsIHelperAppService interface, and controls - * it using the legacy nsITransfer interface. The source of the download will - * be "interruptible_resumable.txt" and partially downloaded data will be kept. - * - * @param aSourceUrl - * String containing the URI for the download source, or null to use - * httpUrl("interruptible_resumable.txt"). - * - * @return {Promise} - * @resolves The Download object created as a consequence of controlling the - * download through the legacy nsITransfer interface. - * @rejects Never. The current test fails in case of exceptions. - */ -function promiseStartExternalHelperAppServiceDownload(aSourceUrl) { - let sourceURI = NetUtil.newURI(aSourceUrl || - httpUrl("interruptible_resumable.txt")); - - let deferred = Promise.defer(); - - Downloads.getList(Downloads.PUBLIC).then(function (aList) { - // Temporarily register a view that will get notified when the download we - // are controlling becomes visible in the list of downloads. - aList.addView({ - onDownloadAdded: function (aDownload) { - aList.removeView(this).then(null, do_report_unexpected_exception); - - // Remove the download to keep the list empty for the next test. This - // also allows the caller to register the "onchange" event directly. - let promise = aList.remove(aDownload); - - // When the download object is ready, make it available to the caller. - promise.then(() => deferred.resolve(aDownload), - do_report_unexpected_exception); - }, - }).then(null, do_report_unexpected_exception); - - let channel = NetUtil.newChannel({ - uri: sourceURI, - loadUsingSystemPrincipal: true - }); - - // Start the actual download process. - channel.asyncOpen2({ - contentListener: null, - - onStartRequest: function (aRequest, aContext) - { - let requestChannel = aRequest.QueryInterface(Ci.nsIChannel); - this.contentListener = gExternalHelperAppService.doContent( - requestChannel.contentType, aRequest, null, true); - this.contentListener.onStartRequest(aRequest, aContext); - }, - - onStopRequest: function (aRequest, aContext, aStatusCode) - { - this.contentListener.onStopRequest(aRequest, aContext, aStatusCode); - }, - - onDataAvailable: function (aRequest, aContext, aInputStream, aOffset, - aCount) - { - this.contentListener.onDataAvailable(aRequest, aContext, aInputStream, - aOffset, aCount); - }, - }); - }.bind(this)).then(null, do_report_unexpected_exception); - - return deferred.promise; -} - -/** - * Waits for a download to reach half of its progress, in case it has not - * reached the expected progress already. - * - * @param aDownload - * The Download object to wait upon. - * - * @return {Promise} - * @resolves When the download has reached half of its progress. - * @rejects Never. - */ -function promiseDownloadMidway(aDownload) { - let deferred = Promise.defer(); - - // Wait for the download to reach half of its progress. - let onchange = function () { - if (!aDownload.stopped && !aDownload.canceled && aDownload.progress == 50) { - aDownload.onchange = null; - deferred.resolve(); - } - }; - - // Register for the notification, but also call the function directly in - // case the download already reached the expected progress. - aDownload.onchange = onchange; - onchange(); - - return deferred.promise; -} - -/** - * Waits for a download to finish, in case it has not finished already. - * - * @param aDownload - * The Download object to wait upon. - * - * @return {Promise} - * @resolves When the download has finished successfully. - * @rejects JavaScript exception if the download failed. - */ -function promiseDownloadStopped(aDownload) { - if (!aDownload.stopped) { - // The download is in progress, wait for the current attempt to finish and - // report any errors that may occur. - return aDownload.start(); - } - - if (aDownload.succeeded) { - return Promise.resolve(); - } - - // The download failed or was canceled. - return Promise.reject(aDownload.error || new Error("Download canceled.")); -} - -/** - * Returns a new public or private DownloadList object. - * - * @param aIsPrivate - * True for the private list, false or undefined for the public list. - * - * @return {Promise} - * @resolves The newly created DownloadList object. - * @rejects JavaScript exception. - */ -function promiseNewList(aIsPrivate) -{ - // We need to clear all the internal state for the list and summary objects, - // since all the objects are interdependent internally. - Downloads._promiseListsInitialized = null; - Downloads._lists = {}; - Downloads._summaries = {}; - - return Downloads.getList(aIsPrivate ? Downloads.PRIVATE : Downloads.PUBLIC); -} - -/** - * Ensures that the given file contents are equal to the given string. - * - * @param aPath - * String containing the path of the file whose contents should be - * verified. - * @param aExpectedContents - * String containing the octets that are expected in the file. - * - * @return {Promise} - * @resolves When the operation completes. - * @rejects Never. - */ -function promiseVerifyContents(aPath, aExpectedContents) -{ - return Task.spawn(function* () { - let file = new FileUtils.File(aPath); - - if (!(yield OS.File.exists(aPath))) { - do_throw("File does not exist: " + aPath); - } - - if ((yield OS.File.stat(aPath)).size == 0) { - do_throw("File is empty: " + aPath); - } - - let deferred = Promise.defer(); - NetUtil.asyncFetch( - { uri: NetUtil.newURI(file), loadUsingSystemPrincipal: true }, - function(aInputStream, aStatus) { - do_check_true(Components.isSuccessCode(aStatus)); - let contents = NetUtil.readInputStreamToString(aInputStream, - aInputStream.available()); - if (contents.length > TEST_DATA_SHORT.length * 2 || - /[^\x20-\x7E]/.test(contents)) { - // Do not print the entire content string to the test log. - do_check_eq(contents.length, aExpectedContents.length); - do_check_true(contents == aExpectedContents); - } else { - // Print the string if it is short and made of printable characters. - do_check_eq(contents, aExpectedContents); - } - deferred.resolve(); - }); - - yield deferred.promise; - }); -} - -/** - * Starts a socket listener that closes each incoming connection. - * - * @returns nsIServerSocket that listens for connections. Call its "close" - * method to stop listening and free the server port. - */ -function startFakeServer() -{ - let serverSocket = new ServerSocket(-1, true, -1); - serverSocket.asyncListen({ - onSocketAccepted: function (aServ, aTransport) { - aTransport.close(Cr.NS_BINDING_ABORTED); - }, - onStopListening: function () { }, - }); - return serverSocket; -} - -/** - * This is an internal reference that should not be used directly by tests. - */ -var _gDeferResponses = Promise.defer(); - -/** - * Ensures that all the interruptible requests started after this function is - * called won't complete until the continueResponses function is called. - * - * Normally, the internal HTTP server returns all the available data as soon as - * a request is received. In order for some requests to be served one part at a - * time, special interruptible handlers are registered on the HTTP server. This - * allows testing events or actions that need to happen in the middle of a - * download. - * - * For example, the handler accessible at the httpUri("interruptible.txt") - * address returns the TEST_DATA_SHORT text, then it may block until the - * continueResponses method is called. At this point, the handler sends the - * TEST_DATA_SHORT text again to complete the response. - * - * If an interruptible request is started before the function is called, it may - * or may not be blocked depending on the actual sequence of events. - */ -function mustInterruptResponses() -{ - // If there are pending blocked requests, allow them to complete. This is - // done to prevent requests from being blocked forever, but should not affect - // the test logic, since previously started requests should not be monitored - // on the client side anymore. - _gDeferResponses.resolve(); - - do_print("Interruptible responses will be blocked midway."); - _gDeferResponses = Promise.defer(); -} - -/** - * Allows all the current and future interruptible requests to complete. - */ -function continueResponses() -{ - do_print("Interruptible responses are now allowed to continue."); - _gDeferResponses.resolve(); -} - -/** - * Registers an interruptible response handler. - * - * @param aPath - * Path passed to nsIHttpServer.registerPathHandler. - * @param aFirstPartFn - * This function is called when the response is received, with the - * aRequest and aResponse arguments of the server. - * @param aSecondPartFn - * This function is called with the aRequest and aResponse arguments of - * the server, when the continueResponses function is called. - */ -function registerInterruptibleHandler(aPath, aFirstPartFn, aSecondPartFn) -{ - gHttpServer.registerPathHandler(aPath, function (aRequest, aResponse) { - do_print("Interruptible request started."); - - // Process the first part of the response. - aResponse.processAsync(); - aFirstPartFn(aRequest, aResponse); - - // Wait on the current deferred object, then finish the request. - _gDeferResponses.promise.then(function RIH_onSuccess() { - aSecondPartFn(aRequest, aResponse); - aResponse.finish(); - do_print("Interruptible request finished."); - }).then(null, Cu.reportError); - }); -} - -/** - * Ensure the given date object is valid. - * - * @param aDate - * The date object to be checked. This value can be null. - */ -function isValidDate(aDate) { - return aDate && aDate.getTime && !isNaN(aDate.getTime()); -} - -/** - * Position of the first byte served by the "interruptible_resumable.txt" - * handler during the most recent response. - */ -var gMostRecentFirstBytePos; - -// Initialization functions common to all tests - -add_task(function test_common_initialize() -{ - // Start the HTTP server. - gHttpServer = new HttpServer(); - gHttpServer.registerDirectory("/", do_get_file("../data")); - gHttpServer.start(-1); - do_register_cleanup(() => { - return new Promise(resolve => { - // Ensure all the pending HTTP requests have a chance to finish. - continueResponses(); - // Stop the HTTP server, calling resolve when it's done. - gHttpServer.stop(resolve); - }); - }); - - // Cache locks might prevent concurrent requests to the same resource, and - // this may block tests that use the interruptible handlers. - Services.prefs.setBoolPref("browser.cache.disk.enable", false); - Services.prefs.setBoolPref("browser.cache.memory.enable", false); - do_register_cleanup(function () { - Services.prefs.clearUserPref("browser.cache.disk.enable"); - Services.prefs.clearUserPref("browser.cache.memory.enable"); - }); - - registerInterruptibleHandler("/interruptible.txt", - function firstPart(aRequest, aResponse) { - aResponse.setHeader("Content-Type", "text/plain", false); - aResponse.setHeader("Content-Length", "" + (TEST_DATA_SHORT.length * 2), - false); - aResponse.write(TEST_DATA_SHORT); - }, function secondPart(aRequest, aResponse) { - aResponse.write(TEST_DATA_SHORT); - }); - - registerInterruptibleHandler("/interruptible_resumable.txt", - function firstPart(aRequest, aResponse) { - aResponse.setHeader("Content-Type", "text/plain", false); - - // Determine if only part of the data should be sent. - let data = TEST_DATA_SHORT + TEST_DATA_SHORT; - if (aRequest.hasHeader("Range")) { - var matches = aRequest.getHeader("Range") - .match(/^\s*bytes=(\d+)?-(\d+)?\s*$/); - var firstBytePos = (matches[1] === undefined) ? 0 : matches[1]; - var lastBytePos = (matches[2] === undefined) ? data.length - 1 - : matches[2]; - if (firstBytePos >= data.length) { - aResponse.setStatusLine(aRequest.httpVersion, 416, - "Requested Range Not Satisfiable"); - aResponse.setHeader("Content-Range", "*/" + data.length, false); - aResponse.finish(); - return; - } - - aResponse.setStatusLine(aRequest.httpVersion, 206, "Partial Content"); - aResponse.setHeader("Content-Range", firstBytePos + "-" + - lastBytePos + "/" + - data.length, false); - - data = data.substring(firstBytePos, lastBytePos + 1); - - gMostRecentFirstBytePos = firstBytePos; - } else { - gMostRecentFirstBytePos = 0; - } - - aResponse.setHeader("Content-Length", "" + data.length, false); - - aResponse.write(data.substring(0, data.length / 2)); - - // Store the second part of the data on the response object, so that it - // can be used by the secondPart function. - aResponse.secondPartData = data.substring(data.length / 2); - }, function secondPart(aRequest, aResponse) { - aResponse.write(aResponse.secondPartData); - }); - - registerInterruptibleHandler("/interruptible_gzip.txt", - function firstPart(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); - - let bos = new BinaryOutputStream(aResponse.bodyOutputStream); - bos.writeByteArray(TEST_DATA_SHORT_GZIP_ENCODED_FIRST, - TEST_DATA_SHORT_GZIP_ENCODED_FIRST.length); - }, function secondPart(aRequest, aResponse) { - let bos = new BinaryOutputStream(aResponse.bodyOutputStream); - bos.writeByteArray(TEST_DATA_SHORT_GZIP_ENCODED_SECOND, - TEST_DATA_SHORT_GZIP_ENCODED_SECOND.length); - }); - - gHttpServer.registerPathHandler("/shorter-than-content-length-http-1-1.txt", - function (aRequest, aResponse) { - aResponse.processAsync(); - aResponse.setStatusLine("1.1", 200, "OK"); - aResponse.setHeader("Content-Type", "text/plain", false); - aResponse.setHeader("Content-Length", "" + (TEST_DATA_SHORT.length * 2), - false); - aResponse.write(TEST_DATA_SHORT); - aResponse.finish(); - }); - - // This URL will emulate being blocked by Windows Parental controls - gHttpServer.registerPathHandler("/parentalblocked.zip", - function (aRequest, aResponse) { - aResponse.setStatusLine(aRequest.httpVersion, 450, - "Blocked by Windows Parental Controls"); - }); - - // During unit tests, most of the functions that require profile access or - // operating system features will be disabled. Individual tests may override - // them again to check for specific behaviors. - Integration.downloads.register(base => ({ - __proto__: base, - loadPublicDownloadListFromStore: () => Promise.resolve(), - shouldKeepBlockedData: () => Promise.resolve(false), - shouldBlockForParentalControls: () => Promise.resolve(false), - shouldBlockForRuntimePermissions: () => Promise.resolve(false), - shouldBlockForReputationCheck: () => Promise.resolve({ - shouldBlock: false, - verdict: "", - }), - confirmLaunchExecutable: () => Promise.resolve(), - launchFile: () => Promise.resolve(), - showContainingDirectory: () => Promise.resolve(), - // This flag allows re-enabling the default observers during their tests. - allowObservers: false, - addListObservers() { - return this.allowObservers ? super.addListObservers(...arguments) - : Promise.resolve(); - }, - // This flag allows re-enabling the download directory logic for its tests. - _allowDirectories: false, - set allowDirectories(value) { - this._allowDirectories = value; - // We have to invalidate the previously computed directory path. - this._downloadsDirectory = null; - }, - _getDirectory(name) { - return super._getDirectory(this._allowDirectories ? name : "TmpD"); - }, - })); - - // Make sure that downloads started using nsIExternalHelperAppService are - // saved to disk without asking for a destination interactively. - let mock = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIHelperAppLauncherDialog]), - promptForSaveToFileAsync(aLauncher, - aWindowContext, - aDefaultFileName, - aSuggestedFileExtension, - aForcePrompt) { - // The dialog should create the empty placeholder file. - let file = getTempFile(TEST_TARGET_FILE_NAME); - file.create(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - aLauncher.saveDestinationAvailable(file); - }, - }; - - let cid = MockRegistrar.register("@mozilla.org/helperapplauncherdialog;1", mock); - do_register_cleanup(() => { - MockRegistrar.unregister(cid); - }); -}); |