toolkit/components/downloads/test/unit/test_offline_support.js

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 /**
michael@0 6 * Test bug 437415 by making sure the download manager responds to offline and
michael@0 7 * online notifications by pausing and resuming downloads.
michael@0 8 */
michael@0 9
michael@0 10 /**
michael@0 11 * Used to indicate if we should error out or not. See bug 431745 for more
michael@0 12 * details.
michael@0 13 */
michael@0 14 let doNotError = false;
michael@0 15
michael@0 16 const nsIF = Ci.nsIFile;
michael@0 17 const nsIDM = Ci.nsIDownloadManager;
michael@0 18 const nsIWBP = Ci.nsIWebBrowserPersist;
michael@0 19 const nsIWPL = Ci.nsIWebProgressListener;
michael@0 20 const dm = Cc["@mozilla.org/download-manager;1"].getService(nsIDM);
michael@0 21 if (!oldDownloadManagerDisabled()) {
michael@0 22 dm.cleanUp();
michael@0 23 }
michael@0 24
michael@0 25 function setOnlineState(aOnline)
michael@0 26 {
michael@0 27 // We do not actually set the offline state because that introduces some neat
michael@0 28 // conditions when being called within a listener. We do dispatch the right
michael@0 29 // observer topics though, so this tests just the download manager.
michael@0 30 let topic = aOnline ?
michael@0 31 "network:offline-status-changed" :
michael@0 32 "network:offline-about-to-go-offline";
michael@0 33 let state = aOnline ? "online" : "offline";
michael@0 34 Cc["@mozilla.org/observer-service;1"].
michael@0 35 getService(Ci.nsIObserverService).
michael@0 36 notifyObservers(null, topic, state);
michael@0 37 }
michael@0 38
michael@0 39 function run_test()
michael@0 40 {
michael@0 41 if (oldDownloadManagerDisabled()) {
michael@0 42 return;
michael@0 43 }
michael@0 44
michael@0 45 /**
michael@0 46 * 1. Create data for http server to send
michael@0 47 */
michael@0 48 // data starts at 10 bytes
michael@0 49 let data = "1234567890";
michael@0 50 // data * 10^4 = 100,000 bytes (actually 101,111 bytes with newline)
michael@0 51 for (let i = 0; i < 4; i++)
michael@0 52 data = [data,data,data,data,data,data,data,data,data,data,"\n"].join("");
michael@0 53
michael@0 54 /**
michael@0 55 * 2. Start the http server that can handle resume
michael@0 56 */
michael@0 57 let httpserv = new HttpServer();
michael@0 58 let didResumeServer = false;
michael@0 59 httpserv.registerPathHandler("/resume", function(meta, resp) {
michael@0 60 let body = data;
michael@0 61 resp.setHeader("Content-Type", "text/html", false);
michael@0 62 if (meta.hasHeader("Range")) {
michael@0 63 // track that we resumed for testing
michael@0 64 didResumeServer = true;
michael@0 65 // Syntax: bytes=[from]-[to] (we don't support multiple ranges)
michael@0 66 let matches = meta.getHeader("Range").match(/^\s*bytes=(\d+)?-(\d+)?\s*$/);
michael@0 67 let from = (matches[1] === undefined) ? 0 : matches[1];
michael@0 68 let to = (matches[2] === undefined) ? data.length - 1 : matches[2];
michael@0 69 if (from >= data.length) {
michael@0 70 resp.setStatusLine(meta.httpVersion, 416, "Start pos too high");
michael@0 71 resp.setHeader("Content-Range", "*/" + data.length);
michael@0 72 dump("Returning early - from >= data.length. Not an error (bug 431745)\n");
michael@0 73 doNotError = true;
michael@0 74 return;
michael@0 75 }
michael@0 76 body = body.substring(from, to + 1);
michael@0 77 // always respond to successful range requests with 206
michael@0 78 resp.setStatusLine(meta.httpVersion, 206, "Partial Content");
michael@0 79 resp.setHeader("Content-Range", from + "-" + to + "/" + data.length);
michael@0 80 }
michael@0 81 resp.bodyOutputStream.write(body, body.length);
michael@0 82 });
michael@0 83 httpserv.start(-1);
michael@0 84
michael@0 85 /**
michael@0 86 * 3. Perform various actions for certain download states
michael@0 87 */
michael@0 88 let didPause = false;
michael@0 89 let didResumeDownload = false;
michael@0 90 dm.addListener({
michael@0 91 onDownloadStateChange: function(a, aDl) {
michael@0 92 if (aDl.state == nsIDM.DOWNLOAD_DOWNLOADING && !didPause) {
michael@0 93 /**
michael@0 94 * (1) queued -> downloading = pause the download by going offline
michael@0 95 */
michael@0 96 setOnlineState(false);
michael@0 97 } else if (aDl.state == nsIDM.DOWNLOAD_PAUSED) {
michael@0 98 /**
michael@0 99 * (2) downloading -> paused
michael@0 100 */
michael@0 101 didPause = true;
michael@0 102 } else if (aDl.state == nsIDM.DOWNLOAD_FINISHED) {
michael@0 103 /**
michael@0 104 * (4) downloading (resumed) -> finished = check tests
michael@0 105 */
michael@0 106 // did we pause at all?
michael@0 107 do_check_true(didPause);
michael@0 108 // did we real-resume and not fake-resume?
michael@0 109 do_check_true(didResumeDownload);
michael@0 110 // extra real-resume check for the server
michael@0 111 do_check_true(didResumeServer);
michael@0 112
michael@0 113 httpserv.stop(do_test_finished);
michael@0 114 aDl.targetFile.remove(false);
michael@0 115 }
michael@0 116 else if (aDl.state == nsIDM.DOWNLOAD_FAILED) {
michael@0 117 // this is only ok if we are not supposed to fail
michael@0 118 do_check_true(doNotError);
michael@0 119 httpserv.stop(do_test_finished);
michael@0 120 }
michael@0 121 },
michael@0 122 onStateChange: function(a, b, aState, d, aDl) {
michael@0 123 if ((aState & nsIWPL.STATE_STOP) && didPause && !didResumeServer &&
michael@0 124 !didResumeDownload) {
michael@0 125 /**
michael@0 126 * (3) paused -> stopped = resume the download by coming online
michael@0 127 */
michael@0 128 setOnlineState(true);
michael@0 129 didResumeDownload = true;
michael@0 130 }
michael@0 131 },
michael@0 132 onProgressChange: function(a, b, c, d, e, f, g) { },
michael@0 133 onSecurityChange: function(a, b, c, d) { }
michael@0 134 });
michael@0 135 dm.addListener(getDownloadListener());
michael@0 136
michael@0 137 /**
michael@0 138 * 4. Start the download
michael@0 139 */
michael@0 140 let destFile = dirSvc.get("ProfD", nsIF);
michael@0 141 destFile.append("offline_online");
michael@0 142 if (destFile.exists())
michael@0 143 destFile.remove(false);
michael@0 144 let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].
michael@0 145 createInstance(nsIWBP);
michael@0 146 persist.persistFlags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
michael@0 147 nsIWBP.PERSIST_FLAGS_BYPASS_CACHE |
michael@0 148 nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
michael@0 149 let dl = dm.addDownload(nsIDM.DOWNLOAD_TYPE_DOWNLOAD,
michael@0 150 createURI("http://localhost:" +
michael@0 151 httpserv.identity.primaryPort + "/resume"),
michael@0 152 createURI(destFile), null, null,
michael@0 153 Math.round(Date.now() * 1000), null, persist, false);
michael@0 154 persist.progressListener = dl.QueryInterface(nsIWPL);
michael@0 155 persist.saveURI(dl.source, null, null, null, null, dl.targetFile, null);
michael@0 156
michael@0 157 // Mark as pending, so clear this when we actually finish the download
michael@0 158 do_test_pending();
michael@0 159 }

mercurial