michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: // This file tests Bug 593815 - specifically that after downloading two files michael@0: // with the same name, the download manager still points to the correct files michael@0: michael@0: Components.utils.import("resource://gre/modules/Services.jsm"); michael@0: Components.utils.import("resource://gre/modules/NetUtil.jsm"); michael@0: do_load_manifest("test_downloads.manifest"); michael@0: michael@0: let httpserver = null; michael@0: let currentTest = 0; michael@0: michael@0: function WindowContext() { } michael@0: WindowContext.prototype = { michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor]), michael@0: getInterface: XPCOMUtils.generateQI([Ci.nsIURIContentListener, michael@0: Ci.nsILoadGroup]), michael@0: michael@0: /* nsIURIContentListener */ michael@0: onStartURIOpen: function (uri) { }, michael@0: isPreferred: function (type, desiredtype) { return false; }, michael@0: michael@0: /* nsILoadGroup */ michael@0: addRequest: function (request, context) { }, michael@0: removeRequest: function (request, context, status) { } michael@0: }; michael@0: michael@0: let DownloadListener = { michael@0: set: null, michael@0: prevFiles : [], michael@0: michael@0: init: function () { michael@0: Services.obs.addObserver(this, "dl-start", true); michael@0: Services.obs.addObserver(this, "dl-done", true); michael@0: }, michael@0: michael@0: observe: function (aSubject, aTopic, aData) { michael@0: michael@0: if (aTopic == "dl-start") { michael@0: // pause the download if requested michael@0: if (this.set.doPause) { michael@0: let dl = aSubject.QueryInterface(Ci.nsIDownload); michael@0: // Don't pause immediately, otherwise the external helper app handler michael@0: // won't be able to assign a permanent file name. michael@0: do_execute_soon(function() { michael@0: downloadUtils.downloadManager.pauseDownload(dl.id); michael@0: do_timeout(1000, function() { michael@0: downloadUtils.downloadManager.resumeDownload(dl.id); michael@0: }); michael@0: }); michael@0: } michael@0: } else if (aTopic == "dl-done") { michael@0: // check that no two files have the same filename in the download manager michael@0: let file = aSubject.QueryInterface(Ci.nsIDownload).targetFile; michael@0: for each (let prevFile in this.prevFiles) { michael@0: do_check_neq(file.leafName, prevFile.leafName); michael@0: } michael@0: this.prevFiles.push(file); michael@0: michael@0: // get the contents of the file michael@0: let fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); michael@0: fis.init(file, -1, -1, 0); michael@0: var cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(Ci.nsIConverterInputStream); michael@0: cstream.init(fis, "UTF-8", 0, 0); michael@0: michael@0: let val = ""; michael@0: let (str = {}) { michael@0: let read = 0; michael@0: do { michael@0: read = cstream.readString(0xffffffff, str); michael@0: val += str.value; michael@0: } while (read != 0); michael@0: } michael@0: cstream.close(); michael@0: michael@0: // check if the file contents match the expected ones michael@0: if (this.set.doPause) { michael@0: do_check_eq(val, this.set.data + this.set.data); // files that have been paused have the same data twice michael@0: } else { michael@0: do_check_eq(val, this.set.data); michael@0: } michael@0: runNextTest(); // download the next file michael@0: } michael@0: }, michael@0: michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, michael@0: Ci.nsISupportsWeakReference]) michael@0: } michael@0: michael@0: /* michael@0: Each test will download a file from the server. michael@0: */ michael@0: function runNextTest() michael@0: { michael@0: if (currentTest == tests.length) { michael@0: for each (var file in DownloadListener.prevFiles) { michael@0: try { michael@0: file.remove(false); michael@0: } catch (ex) { michael@0: try { michael@0: do_report_unexpected_exception(ex, "while removing " + file.path); michael@0: } catch (ex if ex == Components.results.NS_ERROR_ABORT) { michael@0: /* swallow */ michael@0: } michael@0: } michael@0: } michael@0: httpserver.stop(do_test_finished); michael@0: return; michael@0: } michael@0: let set = DownloadListener.set = tests[currentTest]; michael@0: currentTest++; michael@0: michael@0: let channel = NetUtil.newChannel("http://localhost:" + michael@0: httpserver.identity.primaryPort + michael@0: set.serverURL); michael@0: let uriloader = Cc["@mozilla.org/uriloader;1"].getService(Ci.nsIURILoader); michael@0: uriloader.openURI(channel, Ci.nsIURILoader.IS_CONTENT_PREFERRED, michael@0: new WindowContext()); michael@0: } michael@0: michael@0: // sends the responses for the files. sends the same content twice if we resume michael@0: // the download michael@0: function getResponse(aSet) { michael@0: return function(aMetadata, aResponse) { michael@0: aResponse.setHeader("Content-Type", "text/plain", false); michael@0: if (aMetadata.hasHeader("Range")) { michael@0: var matches = aMetadata.getHeader("Range").match(/^\s*bytes=(\d+)?-(\d+)?\s*$/); michael@0: aResponse.setStatusLine(aMetadata.httpVersion, 206, "Partial Content"); michael@0: aResponse.bodyOutputStream.write(aSet.data, aSet.data.length); michael@0: return; michael@0: } michael@0: aResponse.setHeader("Accept-Ranges", "bytes", false); michael@0: aResponse.setHeader("Content-Disposition", "attachment; filename=test.txt;", false); michael@0: aResponse.bodyOutputStream.write(aSet.data, aSet.data.length); michael@0: } michael@0: } michael@0: michael@0: // files to be downloaded. All files will have the same suggested filename, but michael@0: // should contain different data. doPause will cause the download to pause and resume michael@0: // itself michael@0: let tests = [ michael@0: { serverURL: "/test1.html", data: "Test data 1", doPause: false }, michael@0: { serverURL: "/test2.html", data: "Test data 2", doPause: false }, michael@0: { serverURL: "/test3.html", data: "Test data 3", doPause: true } michael@0: ]; michael@0: michael@0: function run_test() { michael@0: if (oldDownloadManagerDisabled()) { michael@0: return; michael@0: } michael@0: michael@0: // setup a download listener to run tests after each download finished michael@0: DownloadListener.init(); michael@0: Services.prefs.setBoolPref("browser.download.manager.showWhenStarting", false); michael@0: michael@0: httpserver = new HttpServer(); michael@0: httpserver.start(-1); michael@0: do_test_pending(); michael@0: michael@0: // setup files to be download, each with the same suggested filename michael@0: // from the server, but with different contents michael@0: for(let i = 0; i < tests.length; i++) { michael@0: let set = tests[i]; michael@0: httpserver.registerPathHandler(set.serverURL, getResponse(set)); michael@0: } michael@0: michael@0: runNextTest(); // start downloading the first file michael@0: }