1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/test/cancellable_request.sjs Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,154 @@ 1.4 +function parseQuery(request, key) { 1.5 + var params = request.queryString.split('&'); 1.6 + for (var j = 0; j < params.length; ++j) { 1.7 + var p = params[j]; 1.8 + if (p == key) 1.9 + return true; 1.10 + if (p.indexOf(key + "=") == 0) 1.11 + return p.substring(key.length + 1); 1.12 + if (p.indexOf("=") < 0 && key == "") 1.13 + return p; 1.14 + } 1.15 + return false; 1.16 +} 1.17 + 1.18 +function push32BE(array, input) { 1.19 + array.push(String.fromCharCode((input >> 24) & 0xff)); 1.20 + array.push(String.fromCharCode((input >> 16) & 0xff)); 1.21 + array.push(String.fromCharCode((input >> 8) & 0xff)); 1.22 + array.push(String.fromCharCode((input) & 0xff)); 1.23 +} 1.24 + 1.25 +function push32LE(array, input) { 1.26 + array.push(String.fromCharCode((input) & 0xff)); 1.27 + array.push(String.fromCharCode((input >> 8) & 0xff)); 1.28 + array.push(String.fromCharCode((input >> 16) & 0xff)); 1.29 + array.push(String.fromCharCode((input >> 24) & 0xff)); 1.30 +} 1.31 + 1.32 +function push16LE(array, input) { 1.33 + array.push(String.fromCharCode((input) & 0xff)); 1.34 + array.push(String.fromCharCode((input >> 8) & 0xff)); 1.35 +} 1.36 + 1.37 +function buildWave(samples, sample_rate) { 1.38 + const RIFF_MAGIC = 0x52494646; 1.39 + const WAVE_MAGIC = 0x57415645; 1.40 + const FRMT_MAGIC = 0x666d7420; 1.41 + const DATA_MAGIC = 0x64617461; 1.42 + const RIFF_SIZE = 44; 1.43 + 1.44 + var header = []; 1.45 + push32BE(header, RIFF_MAGIC); 1.46 + push32LE(header, RIFF_SIZE + samples.length * 2); 1.47 + push32BE(header, WAVE_MAGIC); 1.48 + push32BE(header, FRMT_MAGIC); 1.49 + push32LE(header, 16); 1.50 + push16LE(header, 1); 1.51 + push16LE(header, 1); 1.52 + push32LE(header, sample_rate); 1.53 + push32LE(header, sample_rate); 1.54 + push16LE(header, 2); 1.55 + push16LE(header, 16); 1.56 + push32BE(header, DATA_MAGIC); 1.57 + push32LE(header, samples.length * 2); 1.58 + for (var i = 0; i < samples.length; ++i) { 1.59 + push16LE(header, samples[i], 2); 1.60 + } 1.61 + return header; 1.62 +} 1.63 + 1.64 +const Ci = Components.interfaces; 1.65 +const CC = Components.Constructor; 1.66 +const Timer = CC("@mozilla.org/timer;1", "nsITimer", "initWithCallback"); 1.67 +const BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1", 1.68 + "nsIBinaryOutputStream", 1.69 + "setOutputStream"); 1.70 + 1.71 +function poll(f) { 1.72 + if (f()) { 1.73 + return; 1.74 + } 1.75 + new Timer(function() { poll(f); }, 100, Ci.nsITimer.TYPE_ONE_SHOT); 1.76 +} 1.77 + 1.78 +function handleRequest(request, response) 1.79 +{ 1.80 + var cancel = parseQuery(request, "cancelkey"); 1.81 + if (cancel) { 1.82 + setState(cancel[1], "cancelled"); 1.83 + response.setStatusLine(request.httpVersion, 200, "OK"); 1.84 + response.write("Cancel approved!"); 1.85 + return; 1.86 + } 1.87 + 1.88 + var samples = []; 1.89 + for (var i = 0; i < 1000000; ++i) { 1.90 + samples.push(0); 1.91 + } 1.92 + var bytes = buildWave(samples, 44100).join(""); 1.93 + 1.94 + var key = parseQuery(request, "key"); 1.95 + response.setHeader("Content-Type", "audio/x-wav"); 1.96 + response.setHeader("Content-Length", ""+bytes.length, false); 1.97 + 1.98 + var out = new BinaryOutputStream(response.bodyOutputStream); 1.99 + 1.100 + var start = 0, end = bytes.length - 1; 1.101 + if (request.hasHeader("Range")) 1.102 + { 1.103 + var rangeMatch = request.getHeader("Range").match(/^bytes=(\d+)?-(\d+)?$/); 1.104 + 1.105 + if (rangeMatch[1] !== undefined) 1.106 + start = parseInt(rangeMatch[1], 10); 1.107 + 1.108 + if (rangeMatch[2] !== undefined) 1.109 + end = parseInt(rangeMatch[2], 10); 1.110 + 1.111 + // No start given, so the end is really the count of bytes from the 1.112 + // end of the file. 1.113 + if (start === undefined) 1.114 + { 1.115 + start = Math.max(0, bytes.length - end); 1.116 + end = bytes.length - 1; 1.117 + } 1.118 + 1.119 + // start and end are inclusive 1.120 + if (end === undefined || end >= bytes.length) 1.121 + end = bytes.length - 1; 1.122 + 1.123 + if (end < start) 1.124 + { 1.125 + response.setStatusLine(request.httpVersion, 200, "OK"); 1.126 + start = 0; 1.127 + end = bytes.length - 1; 1.128 + } 1.129 + else 1.130 + { 1.131 + response.setStatusLine(request.httpVersion, 206, "Partial Content"); 1.132 + var contentRange = "bytes " + start + "-" + end + "/" + bytes.length; 1.133 + response.setHeader("Content-Range", contentRange); 1.134 + } 1.135 + } 1.136 + 1.137 + if (start > 0) { 1.138 + // Send all requested data 1.139 + out.write(bytes.slice(start, end + 1), end + 1 - start); 1.140 + return; 1.141 + } 1.142 + 1.143 + // Write the first 1.2M of the Wave file. We know the cache size is set to 1.144 + // 100K so this will fill the cache and and cause a "suspend" event on 1.145 + // the loading element. 1.146 + out.write(bytes, 1200000); 1.147 + 1.148 + response.processAsync(); 1.149 + // Now wait for the message to cancel this response 1.150 + poll(function() { 1.151 + if (getState(key[1]) != "cancelled") { 1.152 + return false; 1.153 + } 1.154 + response.finish(); 1.155 + return true; 1.156 + }); 1.157 +}