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