1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/downloads/test/unit/test_offline_support.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,159 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/** 1.9 + * Test bug 437415 by making sure the download manager responds to offline and 1.10 + * online notifications by pausing and resuming downloads. 1.11 + */ 1.12 + 1.13 +/** 1.14 + * Used to indicate if we should error out or not. See bug 431745 for more 1.15 + * details. 1.16 + */ 1.17 +let doNotError = false; 1.18 + 1.19 +const nsIF = Ci.nsIFile; 1.20 +const nsIDM = Ci.nsIDownloadManager; 1.21 +const nsIWBP = Ci.nsIWebBrowserPersist; 1.22 +const nsIWPL = Ci.nsIWebProgressListener; 1.23 +const dm = Cc["@mozilla.org/download-manager;1"].getService(nsIDM); 1.24 +if (!oldDownloadManagerDisabled()) { 1.25 + dm.cleanUp(); 1.26 +} 1.27 + 1.28 +function setOnlineState(aOnline) 1.29 +{ 1.30 + // We do not actually set the offline state because that introduces some neat 1.31 + // conditions when being called within a listener. We do dispatch the right 1.32 + // observer topics though, so this tests just the download manager. 1.33 + let topic = aOnline ? 1.34 + "network:offline-status-changed" : 1.35 + "network:offline-about-to-go-offline"; 1.36 + let state = aOnline ? "online" : "offline"; 1.37 + Cc["@mozilla.org/observer-service;1"]. 1.38 + getService(Ci.nsIObserverService). 1.39 + notifyObservers(null, topic, state); 1.40 +} 1.41 + 1.42 +function run_test() 1.43 +{ 1.44 + if (oldDownloadManagerDisabled()) { 1.45 + return; 1.46 + } 1.47 + 1.48 + /** 1.49 + * 1. Create data for http server to send 1.50 + */ 1.51 + // data starts at 10 bytes 1.52 + let data = "1234567890"; 1.53 + // data * 10^4 = 100,000 bytes (actually 101,111 bytes with newline) 1.54 + for (let i = 0; i < 4; i++) 1.55 + data = [data,data,data,data,data,data,data,data,data,data,"\n"].join(""); 1.56 + 1.57 + /** 1.58 + * 2. Start the http server that can handle resume 1.59 + */ 1.60 + let httpserv = new HttpServer(); 1.61 + let didResumeServer = false; 1.62 + httpserv.registerPathHandler("/resume", function(meta, resp) { 1.63 + let body = data; 1.64 + resp.setHeader("Content-Type", "text/html", false); 1.65 + if (meta.hasHeader("Range")) { 1.66 + // track that we resumed for testing 1.67 + didResumeServer = true; 1.68 + // Syntax: bytes=[from]-[to] (we don't support multiple ranges) 1.69 + let matches = meta.getHeader("Range").match(/^\s*bytes=(\d+)?-(\d+)?\s*$/); 1.70 + let from = (matches[1] === undefined) ? 0 : matches[1]; 1.71 + let to = (matches[2] === undefined) ? data.length - 1 : matches[2]; 1.72 + if (from >= data.length) { 1.73 + resp.setStatusLine(meta.httpVersion, 416, "Start pos too high"); 1.74 + resp.setHeader("Content-Range", "*/" + data.length); 1.75 + dump("Returning early - from >= data.length. Not an error (bug 431745)\n"); 1.76 + doNotError = true; 1.77 + return; 1.78 + } 1.79 + body = body.substring(from, to + 1); 1.80 + // always respond to successful range requests with 206 1.81 + resp.setStatusLine(meta.httpVersion, 206, "Partial Content"); 1.82 + resp.setHeader("Content-Range", from + "-" + to + "/" + data.length); 1.83 + } 1.84 + resp.bodyOutputStream.write(body, body.length); 1.85 + }); 1.86 + httpserv.start(-1); 1.87 + 1.88 + /** 1.89 + * 3. Perform various actions for certain download states 1.90 + */ 1.91 + let didPause = false; 1.92 + let didResumeDownload = false; 1.93 + dm.addListener({ 1.94 + onDownloadStateChange: function(a, aDl) { 1.95 + if (aDl.state == nsIDM.DOWNLOAD_DOWNLOADING && !didPause) { 1.96 + /** 1.97 + * (1) queued -> downloading = pause the download by going offline 1.98 + */ 1.99 + setOnlineState(false); 1.100 + } else if (aDl.state == nsIDM.DOWNLOAD_PAUSED) { 1.101 + /** 1.102 + * (2) downloading -> paused 1.103 + */ 1.104 + didPause = true; 1.105 + } else if (aDl.state == nsIDM.DOWNLOAD_FINISHED) { 1.106 + /** 1.107 + * (4) downloading (resumed) -> finished = check tests 1.108 + */ 1.109 + // did we pause at all? 1.110 + do_check_true(didPause); 1.111 + // did we real-resume and not fake-resume? 1.112 + do_check_true(didResumeDownload); 1.113 + // extra real-resume check for the server 1.114 + do_check_true(didResumeServer); 1.115 + 1.116 + httpserv.stop(do_test_finished); 1.117 + aDl.targetFile.remove(false); 1.118 + } 1.119 + else if (aDl.state == nsIDM.DOWNLOAD_FAILED) { 1.120 + // this is only ok if we are not supposed to fail 1.121 + do_check_true(doNotError); 1.122 + httpserv.stop(do_test_finished); 1.123 + } 1.124 + }, 1.125 + onStateChange: function(a, b, aState, d, aDl) { 1.126 + if ((aState & nsIWPL.STATE_STOP) && didPause && !didResumeServer && 1.127 + !didResumeDownload) { 1.128 + /** 1.129 + * (3) paused -> stopped = resume the download by coming online 1.130 + */ 1.131 + setOnlineState(true); 1.132 + didResumeDownload = true; 1.133 + } 1.134 + }, 1.135 + onProgressChange: function(a, b, c, d, e, f, g) { }, 1.136 + onSecurityChange: function(a, b, c, d) { } 1.137 + }); 1.138 + dm.addListener(getDownloadListener()); 1.139 + 1.140 + /** 1.141 + * 4. Start the download 1.142 + */ 1.143 + let destFile = dirSvc.get("ProfD", nsIF); 1.144 + destFile.append("offline_online"); 1.145 + if (destFile.exists()) 1.146 + destFile.remove(false); 1.147 + let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]. 1.148 + createInstance(nsIWBP); 1.149 + persist.persistFlags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES | 1.150 + nsIWBP.PERSIST_FLAGS_BYPASS_CACHE | 1.151 + nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION; 1.152 + let dl = dm.addDownload(nsIDM.DOWNLOAD_TYPE_DOWNLOAD, 1.153 + createURI("http://localhost:" + 1.154 + httpserv.identity.primaryPort + "/resume"), 1.155 + createURI(destFile), null, null, 1.156 + Math.round(Date.now() * 1000), null, persist, false); 1.157 + persist.progressListener = dl.QueryInterface(nsIWPL); 1.158 + persist.saveURI(dl.source, null, null, null, null, dl.targetFile, null); 1.159 + 1.160 + // Mark as pending, so clear this when we actually finish the download 1.161 + do_test_pending(); 1.162 +}