michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // This file tests the download manager backend michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: const Cr = Components.results; michael@0: michael@0: do_get_profile(); michael@0: michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import("resource://testing-common/httpd.js"); michael@0: Cu.import("resource://gre/modules/PlacesUtils.jsm"); michael@0: XPCOMUtils.defineLazyModuleGetter(this, "Promise", michael@0: "resource://gre/modules/Promise.jsm"); michael@0: michael@0: var downloadUtils = { }; michael@0: XPCOMUtils.defineLazyServiceGetter(downloadUtils, michael@0: "downloadManager", michael@0: "@mozilla.org/download-manager;1", michael@0: Ci.nsIDownloadManager); michael@0: michael@0: function createURI(aObj) michael@0: { michael@0: var ios = Cc["@mozilla.org/network/io-service;1"]. michael@0: getService(Ci.nsIIOService); michael@0: return (aObj instanceof Ci.nsIFile) ? ios.newFileURI(aObj) : michael@0: ios.newURI(aObj, null, null); michael@0: } michael@0: michael@0: var dirSvc = Cc["@mozilla.org/file/directory_service;1"]. michael@0: getService(Ci.nsIProperties); michael@0: michael@0: var provider = { michael@0: getFile: function(prop, persistent) { michael@0: persistent.value = true; michael@0: if (prop == "DLoads") { michael@0: var file = dirSvc.get("ProfD", Ci.nsILocalFile); michael@0: file.append("downloads.rdf"); michael@0: return file; michael@0: } michael@0: print("*** Throwing trying to get " + prop); michael@0: throw Cr.NS_ERROR_FAILURE; michael@0: }, michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Ci.nsIDirectoryServiceProvider) || michael@0: iid.equals(Ci.nsISupports)) { michael@0: return this; michael@0: } michael@0: throw Cr.NS_ERROR_NO_INTERFACE; michael@0: } michael@0: }; michael@0: dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); michael@0: michael@0: var gDownloadCount = 0; michael@0: /** michael@0: * Adds a download to the DM, and starts it. michael@0: * @param server: a HttpServer used to serve the sourceURI michael@0: * @param aParams (optional): an optional object which contains the function michael@0: * parameters: michael@0: * resultFileName: leaf node for the target file michael@0: * targetFile: nsIFile for the target (overrides resultFileName) michael@0: * sourceURI: the download source URI michael@0: * downloadName: the display name of the download michael@0: * runBeforeStart: a function to run before starting the download michael@0: * isPrivate: whether the download is private or not michael@0: */ michael@0: function addDownload(server, aParams) michael@0: { michael@0: if (!server) michael@0: do_throw("Must provide a valid server."); michael@0: const PORT = server.identity.primaryPort; michael@0: if (!aParams) michael@0: aParams = {}; michael@0: if (!("resultFileName" in aParams)) michael@0: aParams.resultFileName = "download.result"; michael@0: if (!("targetFile" in aParams)) { michael@0: aParams.targetFile = dirSvc.get("ProfD", Ci.nsIFile); michael@0: aParams.targetFile.append(aParams.resultFileName); michael@0: } michael@0: if (!("sourceURI" in aParams)) michael@0: aParams.sourceURI = "http://localhost:" + PORT + "/head_download_manager.js"; michael@0: if (!("downloadName" in aParams)) michael@0: aParams.downloadName = null; michael@0: if (!("runBeforeStart" in aParams)) michael@0: aParams.runBeforeStart = function () {}; michael@0: michael@0: const nsIWBP = Ci.nsIWebBrowserPersist; michael@0: var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"] michael@0: .createInstance(Ci.nsIWebBrowserPersist); michael@0: persist.persistFlags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES | michael@0: nsIWBP.PERSIST_FLAGS_BYPASS_CACHE | michael@0: nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION; michael@0: michael@0: // it is part of the active downloads the moment addDownload is called michael@0: gDownloadCount++; michael@0: michael@0: let dm = downloadUtils.downloadManager; michael@0: var dl = dm.addDownload(Ci.nsIDownloadManager.DOWNLOAD_TYPE_DOWNLOAD, michael@0: createURI(aParams.sourceURI), michael@0: createURI(aParams.targetFile), aParams.downloadName, null, michael@0: Math.round(Date.now() * 1000), null, persist, aParams.isPrivate); michael@0: michael@0: // This will throw if it isn't found, and that would mean test failure, so no michael@0: // try catch block michael@0: if (!aParams.isPrivate) michael@0: var test = dm.getDownload(dl.id); michael@0: michael@0: aParams.runBeforeStart.call(undefined, dl); michael@0: michael@0: persist.progressListener = dl.QueryInterface(Ci.nsIWebProgressListener); michael@0: persist.savePrivacyAwareURI(dl.source, null, null, null, null, dl.targetFile, michael@0: aParams.isPrivate); michael@0: michael@0: return dl; michael@0: } michael@0: michael@0: function getDownloadListener() michael@0: { michael@0: return { michael@0: onDownloadStateChange: function(aState, aDownload) michael@0: { michael@0: if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_QUEUED) michael@0: do_test_pending(); michael@0: michael@0: if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_FINISHED || michael@0: aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_CANCELED || michael@0: aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_FAILED) { michael@0: gDownloadCount--; michael@0: do_test_finished(); michael@0: } michael@0: michael@0: if (gDownloadCount == 0 && typeof httpserv != "undefined" && httpserv) michael@0: { michael@0: do_test_pending(); michael@0: httpserv.stop(do_test_finished); michael@0: } michael@0: }, michael@0: onStateChange: function(a, b, c, d, e) { }, michael@0: onProgressChange: function(a, b, c, d, e, f, g) { }, michael@0: onSecurityChange: function(a, b, c, d) { } michael@0: }; michael@0: } michael@0: michael@0: /** michael@0: * Asynchronously adds visits to a page. michael@0: * michael@0: * @param aPlaceInfo michael@0: * Can be an nsIURI, in such a case a single LINK visit will be added. michael@0: * Otherwise can be an object describing the visit to add, or an array michael@0: * of these objects: michael@0: * { uri: nsIURI of the page, michael@0: * transition: one of the TRANSITION_* from nsINavHistoryService, michael@0: * [optional] title: title of the page, michael@0: * [optional] visitDate: visit date in microseconds from the epoch michael@0: * [optional] referrer: nsIURI of the referrer for this visit michael@0: * } michael@0: * michael@0: * @return {Promise} michael@0: * @resolves When all visits have been added successfully. michael@0: * @rejects JavaScript exception. michael@0: */ michael@0: function promiseAddVisits(aPlaceInfo) michael@0: { michael@0: let deferred = Promise.defer(); michael@0: let places = []; michael@0: if (aPlaceInfo instanceof Ci.nsIURI) { michael@0: places.push({ uri: aPlaceInfo }); michael@0: } michael@0: else if (Array.isArray(aPlaceInfo)) { michael@0: places = places.concat(aPlaceInfo); michael@0: } else { michael@0: places.push(aPlaceInfo) michael@0: } michael@0: michael@0: // Create mozIVisitInfo for each entry. michael@0: let now = Date.now(); michael@0: for (let i = 0; i < places.length; i++) { michael@0: if (!places[i].title) { michael@0: places[i].title = "test visit for " + places[i].uri.spec; michael@0: } michael@0: places[i].visits = [{ michael@0: transitionType: places[i].transition === undefined ? Ci.nsINavHistoryService.TRANSITION_LINK michael@0: : places[i].transition, michael@0: visitDate: places[i].visitDate || (now++) * 1000, michael@0: referrerURI: places[i].referrer michael@0: }]; michael@0: } michael@0: michael@0: PlacesUtils.asyncHistory.updatePlaces( michael@0: places, michael@0: { michael@0: handleError: function handleError(aResultCode, aPlaceInfo) { michael@0: let ex = new Components.Exception("Unexpected error in adding visits.", michael@0: aResultCode); michael@0: deferred.reject(ex); michael@0: }, michael@0: handleResult: function () {}, michael@0: handleCompletion: function handleCompletion() { michael@0: deferred.resolve(); michael@0: } michael@0: } michael@0: ); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: michael@0: XPCOMUtils.defineLazyGetter(this, "Services", function() { michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: return Services; michael@0: }); michael@0: michael@0: // Disable alert service notifications michael@0: Services.prefs.setBoolPref("browser.download.manager.showAlertOnComplete", false); michael@0: michael@0: do_register_cleanup(function() { michael@0: Services.obs.notifyObservers(null, "quit-application", null); michael@0: }); michael@0: michael@0: function oldDownloadManagerDisabled() { michael@0: try { michael@0: // This method throws an exception if the old Download Manager is disabled. michael@0: Services.downloads.activeDownloadCount; michael@0: } catch (ex) { michael@0: return true; michael@0: } michael@0: return false; michael@0: }