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: /** michael@0: * Test bug 335418 by making sure the download manager responds to sleep and michael@0: * wake notifications by pausing and resuming downloads. michael@0: */ michael@0: michael@0: /** michael@0: * Used to indicate if we should error out or not. See bug 431745 for more michael@0: * details. michael@0: */ michael@0: let doNotError = false; michael@0: michael@0: const nsIF = Ci.nsIFile; michael@0: const nsIDM = Ci.nsIDownloadManager; michael@0: const nsIWBP = Ci.nsIWebBrowserPersist; michael@0: const nsIWPL = Ci.nsIWebProgressListener; michael@0: const dm = Cc["@mozilla.org/download-manager;1"].getService(nsIDM); michael@0: if (!oldDownloadManagerDisabled()) { michael@0: dm.cleanUp(); michael@0: } michael@0: michael@0: function notify(aTopic) michael@0: { michael@0: Cc["@mozilla.org/observer-service;1"]. michael@0: getService(Ci.nsIObserverService). michael@0: notifyObservers(null, aTopic, null); michael@0: } michael@0: michael@0: function run_test() michael@0: { michael@0: if (oldDownloadManagerDisabled()) { michael@0: return; michael@0: } michael@0: michael@0: /** michael@0: * 0. Speed up the resume on wake delay from 10 seconds michael@0: */ michael@0: Cc["@mozilla.org/preferences-service;1"]. michael@0: getService(Ci.nsIPrefBranch). michael@0: setIntPref("browser.download.manager.resumeOnWakeDelay", 1000); michael@0: michael@0: /** michael@0: * 1. Create data for http server to send michael@0: */ michael@0: // data starts at 10 bytes michael@0: let data = "1234567890"; michael@0: // data * 10^4 = 100,000 bytes (actually 101,111 bytes with newline) michael@0: for (let i = 0; i < 4; i++) michael@0: data = [data,data,data,data,data,data,data,data,data,data,"\n"].join(""); michael@0: michael@0: /** michael@0: * 2. Start the http server that can handle resume michael@0: */ michael@0: let httpserv = new HttpServer(); michael@0: let didResumeServer = false; michael@0: httpserv.registerPathHandler("/resume", function(meta, resp) { michael@0: let body = data; michael@0: resp.setHeader("Content-Type", "text/html", false); michael@0: if (meta.hasHeader("Range")) { michael@0: // track that we resumed for testing michael@0: didResumeServer = true; michael@0: // Syntax: bytes=[from]-[to] (we don't support multiple ranges) michael@0: let matches = meta.getHeader("Range").match(/^\s*bytes=(\d+)?-(\d+)?\s*$/); michael@0: let from = (matches[1] === undefined) ? 0 : matches[1]; michael@0: let to = (matches[2] === undefined) ? data.length - 1 : matches[2]; michael@0: if (from >= data.length) { michael@0: resp.setStatusLine(meta.httpVersion, 416, "Start pos too high"); michael@0: resp.setHeader("Content-Range", "*/" + data.length); michael@0: dump("Returning early - from >= data.length. Not an error (bug 431745)\n"); michael@0: doNotError = true; michael@0: return; michael@0: } michael@0: body = body.substring(from, to + 1); michael@0: // always respond to successful range requests with 206 michael@0: resp.setStatusLine(meta.httpVersion, 206, "Partial Content"); michael@0: resp.setHeader("Content-Range", from + "-" + to + "/" + data.length); michael@0: } michael@0: resp.bodyOutputStream.write(body, body.length); michael@0: }); michael@0: httpserv.start(-1); michael@0: michael@0: /** michael@0: * 3. Perform various actions for certain download states michael@0: */ michael@0: let didPause = false; michael@0: let didResumeDownload = false; michael@0: dm.addListener({ michael@0: onDownloadStateChange: function(a, aDl) { michael@0: if (aDl.state == nsIDM.DOWNLOAD_DOWNLOADING && !didPause) { michael@0: /** michael@0: * (1) queued -> downloading = pause the download with sleep michael@0: */ michael@0: notify("sleep_notification"); michael@0: } else if (aDl.state == nsIDM.DOWNLOAD_PAUSED) { michael@0: /** michael@0: * (2) downloading -> paused michael@0: */ michael@0: didPause = true; michael@0: } else if (aDl.state == nsIDM.DOWNLOAD_FINISHED) { michael@0: /** michael@0: * (4) downloading (resumed) -> finished = check tests michael@0: */ michael@0: // did we pause at all? michael@0: do_check_true(didPause); michael@0: // did we real-resume and not fake-resume? michael@0: do_check_true(didResumeDownload); michael@0: // extra real-resume check for the server michael@0: do_check_true(didResumeServer); michael@0: michael@0: aDl.targetFile.remove(false); michael@0: httpserv.stop(do_test_finished); michael@0: } michael@0: else if (aDl.state == nsIDM.DOWNLOAD_FAILED) { michael@0: // this is only ok if we are not supposed to fail michael@0: do_check_true(doNotError); michael@0: httpserv.stop(do_test_finished); michael@0: } michael@0: }, michael@0: onStateChange: function(a, b, aState, d, aDl) { michael@0: if ((aState & nsIWPL.STATE_STOP) && didPause && !didResumeServer && michael@0: !didResumeDownload) { michael@0: /** michael@0: * (3) paused -> stopped = resume the download by waking michael@0: */ michael@0: notify("wake_notification"); michael@0: didResumeDownload = true; michael@0: } michael@0: }, michael@0: onProgressChange: function(a, b, c, d, e, f, g) { }, michael@0: onSecurityChange: function(a, b, c, d) { } michael@0: }); michael@0: dm.addListener(getDownloadListener()); michael@0: michael@0: /** michael@0: * 4. Start the download michael@0: */ michael@0: let destFile = dirSvc.get("ProfD", nsIF); michael@0: destFile.append("sleep_wake"); michael@0: if (destFile.exists()) michael@0: destFile.remove(false); michael@0: let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]. michael@0: createInstance(nsIWBP); 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: let dl = dm.addDownload(nsIDM.DOWNLOAD_TYPE_DOWNLOAD, michael@0: createURI("http://localhost:" + michael@0: httpserv.identity.primaryPort + "/resume"), michael@0: createURI(destFile), null, null, michael@0: Math.round(Date.now() * 1000), null, persist, false); michael@0: persist.progressListener = dl.QueryInterface(nsIWPL); michael@0: persist.saveURI(dl.source, null, null, null, null, dl.targetFile, null); michael@0: michael@0: // Mark as pending, so clear this when we actually finish the download michael@0: do_test_pending(); michael@0: }