test_file_protocol.js (7358B)
1 /* run some tests on the file:// protocol handler */ 2 3 "use strict"; 4 5 const PR_RDONLY = 0x1; // see prio.h 6 7 const special_type = "application/x-our-special-type"; 8 9 [ 10 test_read_file, 11 test_read_dir_1, 12 test_read_dir_2, 13 test_upload_file, 14 test_load_shelllink, 15 do_test_finished, 16 ].forEach(f => add_test(f)); 17 18 function new_file_input_stream(file, buffered) { 19 var stream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance( 20 Ci.nsIFileInputStream 21 ); 22 stream.init(file, PR_RDONLY, 0, 0); 23 if (!buffered) { 24 return stream; 25 } 26 27 var buffer = Cc[ 28 "@mozilla.org/network/buffered-input-stream;1" 29 ].createInstance(Ci.nsIBufferedInputStream); 30 buffer.init(stream, 4096); 31 return buffer; 32 } 33 34 function new_file_channel(file) { 35 let uri = Services.io.newFileURI(file); 36 return NetUtil.newChannel({ 37 uri, 38 loadingPrincipal: Services.scriptSecurityManager.createContentPrincipal( 39 uri, 40 {} 41 ), 42 securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT, 43 contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT, 44 }); 45 } 46 47 /* 48 * stream listener 49 * this listener has some additional file-specific tests, so we can't just use 50 * ChannelListener here. 51 */ 52 function FileStreamListener(closure) { 53 this._closure = closure; 54 } 55 FileStreamListener.prototype = { 56 _closure: null, 57 _buffer: "", 58 _got_onstartrequest: false, 59 _got_onstoprequest: false, 60 _contentLen: -1, 61 62 _isDir(request) { 63 request.QueryInterface(Ci.nsIFileChannel); 64 return request.file.isDirectory(); 65 }, 66 67 QueryInterface: ChromeUtils.generateQI([ 68 "nsIStreamListener", 69 "nsIRequestObserver", 70 ]), 71 72 onStartRequest(request) { 73 if (this._got_onstartrequest) { 74 do_throw("Got second onStartRequest event!"); 75 } 76 this._got_onstartrequest = true; 77 78 if (!this._isDir(request)) { 79 request.QueryInterface(Ci.nsIChannel); 80 this._contentLen = request.contentLength; 81 if (this._contentLen == -1) { 82 do_throw("Content length is unknown in onStartRequest!"); 83 } 84 } 85 }, 86 87 onDataAvailable(request, stream, offset, count) { 88 if (!this._got_onstartrequest) { 89 do_throw("onDataAvailable without onStartRequest event!"); 90 } 91 if (this._got_onstoprequest) { 92 do_throw("onDataAvailable after onStopRequest event!"); 93 } 94 if (!request.isPending()) { 95 do_throw("request reports itself as not pending from onStartRequest!"); 96 } 97 98 this._buffer = this._buffer.concat(read_stream(stream, count)); 99 }, 100 101 onStopRequest(request, status) { 102 if (!this._got_onstartrequest) { 103 do_throw("onStopRequest without onStartRequest event!"); 104 } 105 if (this._got_onstoprequest) { 106 do_throw("Got second onStopRequest event!"); 107 } 108 this._got_onstoprequest = true; 109 if (!Components.isSuccessCode(status)) { 110 do_throw("Failed to load file: " + status.toString(16)); 111 } 112 if (status != request.status) { 113 do_throw("request.status does not match status arg to onStopRequest!"); 114 } 115 if (request.isPending()) { 116 do_throw("request reports itself as pending from onStopRequest!"); 117 } 118 if (this._contentLen != -1 && this._buffer.length != this._contentLen) { 119 do_throw("did not read nsIChannel.contentLength number of bytes!"); 120 } 121 122 this._closure(this._buffer); 123 }, 124 }; 125 126 function test_read_file() { 127 dump("*** test_read_file\n"); 128 129 var file = do_get_file("../unit/data/test_readline6.txt"); 130 var chan = new_file_channel(file); 131 132 function on_read_complete(data) { 133 dump("*** test_read_file.on_read_complete\n"); 134 135 // bug 326693 136 if (chan.contentType != special_type) { 137 do_throw( 138 "Type mismatch! Is <" + 139 chan.contentType + 140 ">, should be <" + 141 special_type + 142 ">" 143 ); 144 } 145 146 /* read completed successfully. now read data directly from file, 147 and compare the result. */ 148 var stream = new_file_input_stream(file, false); 149 var result = read_stream(stream, stream.available()); 150 if (result != data) { 151 do_throw("Stream contents do not match with direct read!"); 152 } 153 run_next_test(); 154 } 155 156 chan.contentType = special_type; 157 chan.asyncOpen(new FileStreamListener(on_read_complete)); 158 } 159 160 function do_test_read_dir(set_type, expected_type) { 161 dump("*** test_read_dir(" + set_type + ", " + expected_type + ")\n"); 162 163 var file = do_get_tempdir(); 164 var chan = new_file_channel(file); 165 166 function on_read_complete() { 167 dump( 168 "*** test_read_dir.on_read_complete(" + 169 set_type + 170 ", " + 171 expected_type + 172 ")\n" 173 ); 174 175 // bug 326693 176 if (chan.contentType != expected_type) { 177 do_throw( 178 "Type mismatch! Is <" + 179 chan.contentType + 180 ">, should be <" + 181 expected_type + 182 ">" 183 ); 184 } 185 186 run_next_test(); 187 } 188 189 if (set_type) { 190 chan.contentType = expected_type; 191 } 192 chan.asyncOpen(new FileStreamListener(on_read_complete)); 193 } 194 195 function test_read_dir_1() { 196 return do_test_read_dir(false, "application/http-index-format"); 197 } 198 199 function test_read_dir_2() { 200 return do_test_read_dir(true, special_type); 201 } 202 203 function test_upload_file() { 204 dump("*** test_upload_file\n"); 205 206 var file = do_get_file("../unit/data/test_readline6.txt"); // file to upload 207 var dest = do_get_tempdir(); // file upload destination 208 dest.append("junk.dat"); 209 dest.createUnique(dest.NORMAL_FILE_TYPE, 0o600); 210 211 var uploadstream = new_file_input_stream(file, true); 212 213 var chan = new_file_channel(dest); 214 chan.QueryInterface(Ci.nsIUploadChannel); 215 chan.setUploadStream(uploadstream, "", file.fileSize); 216 217 function on_upload_complete(data) { 218 dump("*** test_upload_file.on_upload_complete\n"); 219 220 // bug 326693 221 if (chan.contentType != special_type) { 222 do_throw( 223 "Type mismatch! Is <" + 224 chan.contentType + 225 ">, should be <" + 226 special_type + 227 ">" 228 ); 229 } 230 231 /* upload of file completed successfully. */ 232 if (data.length) { 233 do_throw("Upload resulted in data!"); 234 } 235 236 var oldstream = new_file_input_stream(file, false); 237 var newstream = new_file_input_stream(dest, false); 238 var olddata = read_stream(oldstream, oldstream.available()); 239 var newdata = read_stream(newstream, newstream.available()); 240 if (olddata != newdata) { 241 do_throw("Stream contents do not match after file copy!"); 242 } 243 oldstream.close(); 244 newstream.close(); 245 246 /* cleanup... also ensures that the destination file is not in 247 use when OnStopRequest is called. */ 248 try { 249 dest.remove(false); 250 } catch (e) { 251 dump(e + "\n"); 252 do_throw("Unable to remove uploaded file!\n"); 253 } 254 255 run_next_test(); 256 } 257 258 chan.contentType = special_type; 259 chan.asyncOpen(new FileStreamListener(on_upload_complete)); 260 } 261 262 function test_load_shelllink() { 263 // lnk files should not resolve to their targets 264 dump("*** test_load_shelllink\n"); 265 let file = do_get_file("data/system_root.lnk", false); 266 var chan = new_file_channel(file); 267 268 // The original URI path should be the same as the URI path 269 Assert.equal(chan.URI.pathQueryRef, chan.originalURI.pathQueryRef); 270 271 // The original URI path should be the same as the lnk file path 272 Assert.equal( 273 chan.originalURI.pathQueryRef, 274 Services.io.newFileURI(file).pathQueryRef 275 ); 276 run_next_test(); 277 }