Thu, 15 Jan 2015 15:55:04 +0100
Back out 97036ab72558 which inappropriately compared turds to third parties.
1 // Test the plaintext-or-binary sniffer
3 Cu.import("resource://testing-common/httpd.js");
5 // List of Content-Type headers to test. For each header we have an array.
6 // The first element in the array is the Content-Type header string. The
7 // second element in the array is a boolean indicating whether we allow
8 // sniffing for that type.
9 var contentTypeHeaderList =
10 [
11 [ "text/plain", true ],
12 [ "text/plain; charset=ISO-8859-1", true ],
13 [ "text/plain; charset=iso-8859-1", true ],
14 [ "text/plain; charset=UTF-8", true ],
15 [ "text/plain; charset=unknown", false ],
16 [ "text/plain; param", false ],
17 [ "text/plain; charset=ISO-8859-1; param", false ],
18 [ "text/plain; charset=iso-8859-1; param", false ],
19 [ "text/plain; charset=UTF-8; param", false ],
20 [ "text/plain; charset=utf-8", false ],
21 [ "text/plain; charset=utf8", false ],
22 [ "text/plain; charset=UTF8", false ],
23 [ "text/plain; charset=iSo-8859-1", false ]
24 ];
26 // List of response bodies to test. For each response we have an array. The
27 // first element in the array is the body string. The second element in the
28 // array is a boolean indicating whether that string should sniff as binary.
29 var bodyList =
30 [
31 [ "Plaintext", false ]
32 ];
34 // List of possible BOMs
35 var BOMList =
36 [
37 "\xFE\xFF", // UTF-16BE
38 "\xFF\xFE", // UTF-16LE
39 "\xEF\xBB\xBF", // UTF-8
40 "\x00\x00\xFE\xFF", // UCS-4BE
41 "\x00\x00\xFF\xFE" // UCS-4LE
42 ];
44 // Build up bodyList. The things we treat as binary are ASCII codes 0-8,
45 // 14-26, 28-31. That is, the control char range, except for tab, newline,
46 // vertical tab, form feed, carriage return, and ESC (this last being used by
47 // Shift_JIS, apparently).
48 function isBinaryChar(ch) {
49 return (0 <= ch && ch <= 8) || (14 <= ch && ch <= 26) ||
50 (28 <= ch && ch <= 31);
51 }
53 // Test chars on their own
54 var i;
55 for (i = 0; i <= 127; ++i) {
56 bodyList.push([ String.fromCharCode(i), isBinaryChar(i) ]);
57 }
59 // Test that having a BOM prevents plaintext sniffing
60 var j;
61 for (i = 0; i <= 127; ++i) {
62 for (j = 0; j < BOMList.length; ++j) {
63 bodyList.push([ BOMList[j] + String.fromCharCode(i, i), false ]);
64 }
65 }
67 // Test that having a BOM requires at least 4 chars to kick in
68 for (i = 0; i <= 127; ++i) {
69 for (j = 0; j < BOMList.length; ++j) {
70 bodyList.push([ BOMList[j] + String.fromCharCode(i),
71 BOMList[j].length == 2 && isBinaryChar(i) ]);
72 }
73 }
75 function makeChan(headerIdx, bodyIdx) {
76 var ios = Components.classes["@mozilla.org/network/io-service;1"]
77 .getService(Components.interfaces.nsIIOService);
78 var chan =
79 ios.newChannel("http://localhost:" + httpserv.identity.primaryPort +
80 "/" + headerIdx + "/" + bodyIdx, null, null)
81 .QueryInterface(Components.interfaces.nsIHttpChannel);
83 chan.loadFlags |=
84 Components.interfaces.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;
86 return chan;
87 }
89 function makeListener(headerIdx, bodyIdx) {
90 var listener = {
91 onStartRequest : function test_onStartR(request, ctx) {
92 try {
93 var chan = request.QueryInterface(Components.interfaces.nsIChannel);
95 do_check_eq(chan.status, Components.results.NS_OK);
97 var type = chan.contentType;
99 var expectedType =
100 contentTypeHeaderList[headerIdx][1] && bodyList[bodyIdx][1] ?
101 "application/x-vnd.mozilla.guess-from-ext" : "text/plain";
102 if (expectedType != type) {
103 do_throw("Unexpected sniffed type '" + type + "'. " +
104 "Should be '" + expectedType + "'. " +
105 "Header is ['" +
106 contentTypeHeaderList[headerIdx][0] + "', " +
107 contentTypeHeaderList[headerIdx][1] + "]. " +
108 "Body is ['" +
109 bodyList[bodyIdx][0].toSource() + "', " +
110 bodyList[bodyIdx][1] +
111 "].");
112 }
113 do_check_eq(expectedType, type);
114 } catch (e) {
115 do_throw("Unexpected exception: " + e);
116 }
118 throw Components.results.NS_ERROR_ABORT;
119 },
121 onDataAvailable: function test_ODA() {
122 do_throw("Should not get any data!");
123 },
125 onStopRequest: function test_onStopR(request, ctx, status) {
126 // Advance to next test
127 ++headerIdx;
128 if (headerIdx == contentTypeHeaderList.length) {
129 headerIdx = 0;
130 ++bodyIdx;
131 }
133 if (bodyIdx == bodyList.length) {
134 do_test_pending();
135 httpserv.stop(do_test_finished);
136 } else {
137 doTest(headerIdx, bodyIdx);
138 }
140 do_test_finished();
141 }
142 };
144 return listener;
145 }
147 function doTest(headerIdx, bodyIdx) {
148 var chan = makeChan(headerIdx, bodyIdx);
150 var listener = makeListener(headerIdx, bodyIdx);
152 chan.asyncOpen(listener, null);
154 do_test_pending();
155 }
157 function createResponse(headerIdx, bodyIdx, metadata, response) {
158 response.setHeader("Content-Type", contentTypeHeaderList[headerIdx][0], false);
159 response.bodyOutputStream.write(bodyList[bodyIdx][0],
160 bodyList[bodyIdx][0].length);
161 }
163 function makeHandler(headerIdx, bodyIdx) {
164 var f =
165 function handlerClosure(metadata, response) {
166 return createResponse(headerIdx, bodyIdx, metadata, response);
167 };
168 return f;
169 }
171 var httpserv;
172 function run_test() {
173 // disable again for everything for now (causes sporatic oranges)
174 return;
176 // disable on Windows for now, because it seems to leak sockets and die.
177 // Silly operating system!
178 // This is a really nasty way to detect Windows. I wish we could do better.
179 if ("@mozilla.org/windows-registry-key;1" in Cc) {
180 return;
181 }
183 httpserv = new HttpServer();
185 for (i = 0; i < contentTypeHeaderList.length; ++i) {
186 for (j = 0; j < bodyList.length; ++j) {
187 httpserv.registerPathHandler("/" + i + "/" + j, makeHandler(i, j));
188 }
189 }
191 httpserv.start(-1);
193 doTest(0, 0);
194 }