1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/test/unit/test_plaintext_sniff.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,194 @@ 1.4 +// Test the plaintext-or-binary sniffer 1.5 + 1.6 +Cu.import("resource://testing-common/httpd.js"); 1.7 + 1.8 +// List of Content-Type headers to test. For each header we have an array. 1.9 +// The first element in the array is the Content-Type header string. The 1.10 +// second element in the array is a boolean indicating whether we allow 1.11 +// sniffing for that type. 1.12 +var contentTypeHeaderList = 1.13 +[ 1.14 + [ "text/plain", true ], 1.15 + [ "text/plain; charset=ISO-8859-1", true ], 1.16 + [ "text/plain; charset=iso-8859-1", true ], 1.17 + [ "text/plain; charset=UTF-8", true ], 1.18 + [ "text/plain; charset=unknown", false ], 1.19 + [ "text/plain; param", false ], 1.20 + [ "text/plain; charset=ISO-8859-1; param", false ], 1.21 + [ "text/plain; charset=iso-8859-1; param", false ], 1.22 + [ "text/plain; charset=UTF-8; param", false ], 1.23 + [ "text/plain; charset=utf-8", false ], 1.24 + [ "text/plain; charset=utf8", false ], 1.25 + [ "text/plain; charset=UTF8", false ], 1.26 + [ "text/plain; charset=iSo-8859-1", false ] 1.27 +]; 1.28 + 1.29 +// List of response bodies to test. For each response we have an array. The 1.30 +// first element in the array is the body string. The second element in the 1.31 +// array is a boolean indicating whether that string should sniff as binary. 1.32 +var bodyList = 1.33 +[ 1.34 + [ "Plaintext", false ] 1.35 +]; 1.36 + 1.37 +// List of possible BOMs 1.38 +var BOMList = 1.39 +[ 1.40 + "\xFE\xFF", // UTF-16BE 1.41 + "\xFF\xFE", // UTF-16LE 1.42 + "\xEF\xBB\xBF", // UTF-8 1.43 + "\x00\x00\xFE\xFF", // UCS-4BE 1.44 + "\x00\x00\xFF\xFE" // UCS-4LE 1.45 +]; 1.46 + 1.47 +// Build up bodyList. The things we treat as binary are ASCII codes 0-8, 1.48 +// 14-26, 28-31. That is, the control char range, except for tab, newline, 1.49 +// vertical tab, form feed, carriage return, and ESC (this last being used by 1.50 +// Shift_JIS, apparently). 1.51 +function isBinaryChar(ch) { 1.52 + return (0 <= ch && ch <= 8) || (14 <= ch && ch <= 26) || 1.53 + (28 <= ch && ch <= 31); 1.54 +} 1.55 + 1.56 +// Test chars on their own 1.57 +var i; 1.58 +for (i = 0; i <= 127; ++i) { 1.59 + bodyList.push([ String.fromCharCode(i), isBinaryChar(i) ]); 1.60 +} 1.61 + 1.62 +// Test that having a BOM prevents plaintext sniffing 1.63 +var j; 1.64 +for (i = 0; i <= 127; ++i) { 1.65 + for (j = 0; j < BOMList.length; ++j) { 1.66 + bodyList.push([ BOMList[j] + String.fromCharCode(i, i), false ]); 1.67 + } 1.68 +} 1.69 + 1.70 +// Test that having a BOM requires at least 4 chars to kick in 1.71 +for (i = 0; i <= 127; ++i) { 1.72 + for (j = 0; j < BOMList.length; ++j) { 1.73 + bodyList.push([ BOMList[j] + String.fromCharCode(i), 1.74 + BOMList[j].length == 2 && isBinaryChar(i) ]); 1.75 + } 1.76 +} 1.77 + 1.78 +function makeChan(headerIdx, bodyIdx) { 1.79 + var ios = Components.classes["@mozilla.org/network/io-service;1"] 1.80 + .getService(Components.interfaces.nsIIOService); 1.81 + var chan = 1.82 + ios.newChannel("http://localhost:" + httpserv.identity.primaryPort + 1.83 + "/" + headerIdx + "/" + bodyIdx, null, null) 1.84 + .QueryInterface(Components.interfaces.nsIHttpChannel); 1.85 + 1.86 + chan.loadFlags |= 1.87 + Components.interfaces.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS; 1.88 + 1.89 + return chan; 1.90 +} 1.91 + 1.92 +function makeListener(headerIdx, bodyIdx) { 1.93 + var listener = { 1.94 + onStartRequest : function test_onStartR(request, ctx) { 1.95 + try { 1.96 + var chan = request.QueryInterface(Components.interfaces.nsIChannel); 1.97 + 1.98 + do_check_eq(chan.status, Components.results.NS_OK); 1.99 + 1.100 + var type = chan.contentType; 1.101 + 1.102 + var expectedType = 1.103 + contentTypeHeaderList[headerIdx][1] && bodyList[bodyIdx][1] ? 1.104 + "application/x-vnd.mozilla.guess-from-ext" : "text/plain"; 1.105 + if (expectedType != type) { 1.106 + do_throw("Unexpected sniffed type '" + type + "'. " + 1.107 + "Should be '" + expectedType + "'. " + 1.108 + "Header is ['" + 1.109 + contentTypeHeaderList[headerIdx][0] + "', " + 1.110 + contentTypeHeaderList[headerIdx][1] + "]. " + 1.111 + "Body is ['" + 1.112 + bodyList[bodyIdx][0].toSource() + "', " + 1.113 + bodyList[bodyIdx][1] + 1.114 + "]."); 1.115 + } 1.116 + do_check_eq(expectedType, type); 1.117 + } catch (e) { 1.118 + do_throw("Unexpected exception: " + e); 1.119 + } 1.120 + 1.121 + throw Components.results.NS_ERROR_ABORT; 1.122 + }, 1.123 + 1.124 + onDataAvailable: function test_ODA() { 1.125 + do_throw("Should not get any data!"); 1.126 + }, 1.127 + 1.128 + onStopRequest: function test_onStopR(request, ctx, status) { 1.129 + // Advance to next test 1.130 + ++headerIdx; 1.131 + if (headerIdx == contentTypeHeaderList.length) { 1.132 + headerIdx = 0; 1.133 + ++bodyIdx; 1.134 + } 1.135 + 1.136 + if (bodyIdx == bodyList.length) { 1.137 + do_test_pending(); 1.138 + httpserv.stop(do_test_finished); 1.139 + } else { 1.140 + doTest(headerIdx, bodyIdx); 1.141 + } 1.142 + 1.143 + do_test_finished(); 1.144 + } 1.145 + }; 1.146 + 1.147 + return listener; 1.148 +} 1.149 + 1.150 +function doTest(headerIdx, bodyIdx) { 1.151 + var chan = makeChan(headerIdx, bodyIdx); 1.152 + 1.153 + var listener = makeListener(headerIdx, bodyIdx); 1.154 + 1.155 + chan.asyncOpen(listener, null); 1.156 + 1.157 + do_test_pending(); 1.158 +} 1.159 + 1.160 +function createResponse(headerIdx, bodyIdx, metadata, response) { 1.161 + response.setHeader("Content-Type", contentTypeHeaderList[headerIdx][0], false); 1.162 + response.bodyOutputStream.write(bodyList[bodyIdx][0], 1.163 + bodyList[bodyIdx][0].length); 1.164 +} 1.165 + 1.166 +function makeHandler(headerIdx, bodyIdx) { 1.167 + var f = 1.168 + function handlerClosure(metadata, response) { 1.169 + return createResponse(headerIdx, bodyIdx, metadata, response); 1.170 + }; 1.171 + return f; 1.172 +} 1.173 + 1.174 +var httpserv; 1.175 +function run_test() { 1.176 + // disable again for everything for now (causes sporatic oranges) 1.177 + return; 1.178 + 1.179 + // disable on Windows for now, because it seems to leak sockets and die. 1.180 + // Silly operating system! 1.181 + // This is a really nasty way to detect Windows. I wish we could do better. 1.182 + if ("@mozilla.org/windows-registry-key;1" in Cc) { 1.183 + return; 1.184 + } 1.185 + 1.186 + httpserv = new HttpServer(); 1.187 + 1.188 + for (i = 0; i < contentTypeHeaderList.length; ++i) { 1.189 + for (j = 0; j < bodyList.length; ++j) { 1.190 + httpserv.registerPathHandler("/" + i + "/" + j, makeHandler(i, j)); 1.191 + } 1.192 + } 1.193 + 1.194 + httpserv.start(-1); 1.195 + 1.196 + doTest(0, 0); 1.197 +}