|
1 |
|
2 const Cc = Components.classes; |
|
3 const Ci = Components.interfaces; |
|
4 const Cu = Components.utils; |
|
5 const Cr = Components.results; |
|
6 |
|
7 Cu.import("resource://testing-common/httpd.js"); |
|
8 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
9 Cu.import("resource://gre/modules/Services.jsm"); |
|
10 |
|
11 do_get_profile(); |
|
12 |
|
13 // Dynamically generates a classID for our component, registers it to mask |
|
14 // the existing component, and stored the masked components classID to be |
|
15 // restored later, when we unregister. |
|
16 function registerTemporaryComponent(comp) |
|
17 { |
|
18 let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
|
19 if (!comp.prototype.classID) { |
|
20 let uuidgen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator); |
|
21 comp.prototype.classID = uuidgen.generateUUID(); |
|
22 } |
|
23 comp.prototype.maskedClassID = Components.ID(Cc[comp.prototype.contractID].number); |
|
24 if (!comp.prototype.factory) |
|
25 comp.prototype.factory = getFactory(comp); |
|
26 registrar.registerFactory(comp.prototype.classID, "", comp.prototype.contractID, comp.prototype.factory); |
|
27 } |
|
28 |
|
29 function unregisterTemporaryComponent(comp) |
|
30 { |
|
31 let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
|
32 registrar.unregisterFactory(comp.prototype.classID, comp.prototype.factory); |
|
33 registrar.registerFactory(comp.prototype.maskedClassID, "", comp.prototype.contractID, null); |
|
34 } |
|
35 |
|
36 let DownloadListener = { |
|
37 init: function () { |
|
38 let obs = Services.obs; |
|
39 obs.addObserver(this, "dl-done", true); |
|
40 }, |
|
41 |
|
42 observe: function (subject, topic, data) { |
|
43 this.onFinished(subject, topic, data); |
|
44 }, |
|
45 |
|
46 QueryInterface: function (iid) { |
|
47 if (iid.equals(Ci.nsIObserver) || |
|
48 iid.equals(Ci.nsISupportsWeakReference) || |
|
49 iid.equals(Ci.nsISupports)) |
|
50 return this; |
|
51 |
|
52 throw Cr.NS_ERROR_NO_INTERFACE; |
|
53 } |
|
54 } |
|
55 DownloadListener.init(); |
|
56 |
|
57 function HelperAppDlg() { } |
|
58 HelperAppDlg.prototype = { |
|
59 QueryInterface: XPCOMUtils.generateQI([Ci.nsIHelperAppLauncherDialog]), |
|
60 contractID: "@mozilla.org/helperapplauncherdialog;1", |
|
61 show: function (launcher, ctx, reason, usePrivateUI) { |
|
62 launcher.MIMEInfo.preferredAction = Ci.nsIMIMEInfo.saveToFile; |
|
63 launcher.launchWithApplication(null, false); |
|
64 }, |
|
65 |
|
66 promptForSaveToFile: function (launcher, ctx, defaultFile, suggestedExtension, forcePrompt) { } |
|
67 } |
|
68 |
|
69 // Stolen from XPCOMUtils, since this handy function is not public there |
|
70 function getFactory(comp) |
|
71 { |
|
72 return { |
|
73 createInstance: function (outer, iid) { |
|
74 if (outer) |
|
75 throw Cr.NS_ERROR_NO_AGGREGATION; |
|
76 return (new comp()).QueryInterface(iid); |
|
77 } |
|
78 } |
|
79 } |
|
80 |
|
81 // Override the download-manager-ui to prevent anyone from trying to open |
|
82 // a window. |
|
83 function DownloadMgrUI() { } |
|
84 DownloadMgrUI.prototype = { |
|
85 QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadManagerUI]), |
|
86 contractID: "@mozilla.org/download-manager-ui;1", |
|
87 show: function (ir, aID, reason) { }, |
|
88 |
|
89 visible: false, |
|
90 |
|
91 getAttention: function () { } |
|
92 } |
|
93 |
|
94 function AlertsSVC() { } |
|
95 AlertsSVC.prototype = { |
|
96 QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService]), |
|
97 contractID: "@mozilla.org/alerts-service;1", |
|
98 showAlertNotification: function (url, title, text, clickable, cookie, listener, name) { }, |
|
99 } |
|
100 |
|
101 registerTemporaryComponent(HelperAppDlg); |
|
102 registerTemporaryComponent(DownloadMgrUI); |
|
103 registerTemporaryComponent(AlertsSVC); |
|
104 |
|
105 function initChildTestEnv() |
|
106 { |
|
107 sendCommand(' \ |
|
108 const Cc = Components.classes; \ |
|
109 const Ci = Components.interfaces; \ |
|
110 const Cr = Components.results; \ |
|
111 function WindowContext() { } \ |
|
112 \ |
|
113 WindowContext.prototype = { \ |
|
114 getInterface: function (iid) { \ |
|
115 if (iid.equals(Ci.nsIInterfaceRequestor) || \ |
|
116 iid.equals(Ci.nsIURIContentListener) || \ |
|
117 iid.equals(Ci.nsILoadGroup) || \ |
|
118 iid.equals(Ci.nsIDocumentLoader) || \ |
|
119 iid.equals(Ci.nsIDOMWindow)) \ |
|
120 return this; \ |
|
121 \ |
|
122 throw Cr.NS_ERROR_NO_INTERFACE; \ |
|
123 }, \ |
|
124 \ |
|
125 /* nsIURIContentListener */ \ |
|
126 onStartURIOpen: function (uri) { }, \ |
|
127 isPreferred: function (type, desiredtype) { return false; }, \ |
|
128 \ |
|
129 /* nsILoadGroup */ \ |
|
130 addRequest: function (request, context) { }, \ |
|
131 removeRequest: function (request, context, status) { } \ |
|
132 }; \ |
|
133 \ |
|
134 var ioservice = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);\ |
|
135 var uriloader = Cc["@mozilla.org/uriloader;1"].getService(Ci.nsIURILoader);\ |
|
136 '); |
|
137 } |
|
138 |
|
139 function testFinisher(endFunc) { |
|
140 let ef = endFunc; |
|
141 return function (file) { |
|
142 ef(file); |
|
143 runNextTest(); |
|
144 } |
|
145 } |
|
146 |
|
147 function runChildTestSet(set) |
|
148 { |
|
149 DownloadListener.onFinished = testFinisher(set[2]); |
|
150 sendCommand('\ |
|
151 let uri = ioservice.newURI("http://localhost:4444' + set[0] + '", null, null);\ |
|
152 let channel = ioservice.newChannelFromURI(uri); \ |
|
153 uriloader.openURI(channel, Ci.nsIURILoader.IS_CONTENT_PREFERRED, new WindowContext()); \ |
|
154 '); |
|
155 } |
|
156 |
|
157 var httpserver = null; |
|
158 let currentTest = 0; |
|
159 function runNextTest() |
|
160 { |
|
161 if (currentTest == tests.length) { |
|
162 httpserver.stop(do_test_finished); |
|
163 return; |
|
164 } |
|
165 |
|
166 let set = tests[currentTest++]; |
|
167 runChildTestSet(set); |
|
168 } |
|
169 |
|
170 const responseBody = [0x1f, 0x8b, 0x08, 0x00, 0x16, 0x5a, 0x8a, 0x48, 0x02, |
|
171 0x03, 0x2b, 0x49, 0x2d, 0x2e, 0xe1, 0x02, 0x00, 0xc6, |
|
172 0x35, 0xb9, 0x3b, 0x05, 0x00, 0x00, 0x00]; |
|
173 |
|
174 /* |
|
175 * First test: a file with Content-Type application/x-gzip and Content-Encoding gzip |
|
176 * should not be decoded in a round-trip |
|
177 */ |
|
178 function testResponse1(metadata, response) { |
|
179 response.setHeader("Content-Type", "application/x-gzip", false); |
|
180 response.setHeader("Content-Encoding", "gzip", false); |
|
181 response.setHeader("Content-Disposition", "attachment", false); |
|
182 |
|
183 var bos = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream); |
|
184 bos.setOutputStream(response.bodyOutputStream); |
|
185 bos.writeByteArray(responseBody, responseBody.length); |
|
186 } |
|
187 |
|
188 function finishTest1(subject, topic, data) { |
|
189 let file = subject.QueryInterface(Ci.nsIDownload).targetFile; |
|
190 do_check_true(file.path.search("test1.gz") != 0); |
|
191 let fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); |
|
192 fis.init(file, -1, -1, 0); |
|
193 let bis = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream); |
|
194 bis.setInputStream(fis); |
|
195 let str = bis.readByteArray(bis.available()); |
|
196 do_check_true(str.length == responseBody.length); |
|
197 |
|
198 let cmp = 0; |
|
199 for (i = 0; i < str.length; i++) { |
|
200 cmp += str[i] - responseBody[i]; |
|
201 if (cmp != 0) break; |
|
202 } |
|
203 do_check_true(cmp == 0); |
|
204 } |
|
205 |
|
206 /* |
|
207 * Second test: a file with Content-Type text/html and Content-Encoding gzip |
|
208 * should not be decoded in a round-trip, if its filename ends in ".gz". |
|
209 * We specify a Content-disposition header to force it to be saved as a file. |
|
210 */ |
|
211 function testResponse2(metadata, response) { |
|
212 response.setHeader("Content-Type", "text/html", false); |
|
213 response.setHeader("Content-Encoding", "gzip", false); |
|
214 response.setHeader("Content-Disposition", "attachment", false); |
|
215 |
|
216 var bos = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream); |
|
217 bos.setOutputStream(response.bodyOutputStream); |
|
218 bos.writeByteArray(responseBody, responseBody.length); |
|
219 } |
|
220 |
|
221 function finishTest2(subject, topic, data) { |
|
222 let file = subject.QueryInterface(Ci.nsIDownload).targetFile; |
|
223 do_check_true(file.path.search("test2.gz") != 0); |
|
224 let fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); |
|
225 fis.init(file, -1, -1, 0); |
|
226 let bis = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream); |
|
227 bis.setInputStream(fis); |
|
228 let str = bis.readByteArray(bis.available()); |
|
229 do_check_true(str.length == responseBody.length); |
|
230 |
|
231 let cmp = 0; |
|
232 for (i = 0; i < str.length; i++) { |
|
233 cmp += str[i] - responseBody[i]; |
|
234 if (cmp != 0) break; |
|
235 } |
|
236 do_check_true(cmp == 0); |
|
237 } |
|
238 |
|
239 function testResponse3(metadata, response) { |
|
240 response.setHeader("Content-Type", "text/html", false); |
|
241 response.setHeader("Content-Encoding", "gzip", false); |
|
242 response.setHeader("Content-Disposition", "attachment", false); |
|
243 |
|
244 var bos = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream); |
|
245 bos.setOutputStream(response.bodyOutputStream); |
|
246 bos.writeByteArray(responseBody, responseBody.length); |
|
247 } |
|
248 |
|
249 function finishTest3(subject, topic, data) { |
|
250 let file = subject.QueryInterface(Ci.nsIDownload).targetFile; |
|
251 do_check_true(file.path.search("test3.txt") != 0); |
|
252 let fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); |
|
253 fis.init(file, -1, -1, 0); |
|
254 let bis = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream); |
|
255 bis.setInputStream(fis); |
|
256 let str = bis.readByteArray(bis.available()); |
|
257 let decodedBody = [ 116, 101, 115, 116, 10 ]; // 't','e','s','t','\n' |
|
258 do_check_true(str.length == decodedBody.length); |
|
259 |
|
260 let cmp = 0; |
|
261 for (i = 0; i < str.length; i++) { |
|
262 cmp += str[i] - decodedBody[i]; |
|
263 if (cmp != 0) break; |
|
264 } |
|
265 do_check_true(cmp == 0); |
|
266 } |
|
267 |
|
268 let tests = [ |
|
269 [ "/test1.gz", testResponse1, finishTest1 ], |
|
270 [ "/test2.gz", testResponse2, finishTest2 ], |
|
271 [ "/test3.txt", testResponse3, finishTest3 ], |
|
272 ]; |
|
273 |
|
274 function run_test() { |
|
275 // do_load_child_test_harness(); |
|
276 httpserver = new HttpServer(); |
|
277 httpserver.start(4444); |
|
278 do_test_pending(); |
|
279 |
|
280 initChildTestEnv(); |
|
281 |
|
282 for each (set in tests) |
|
283 httpserver.registerPathHandler(set[0], set[1]); |
|
284 |
|
285 runNextTest(); |
|
286 } |