1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/**
* Test for the "alternative data stream" stored withing a cache entry.
*
* - we load a URL with preference for an alt data (check what we get is the raw data,
* since there was nothing previously cached)
* - we write a big chunk of alt-data to the output stream
* - we load the URL again, expecting to get alt-data
* - we check that the alt-data is streamed. We should get the first chunk, then
* the rest of the alt-data is written, and we check that it is received in
* the proper order.
*
*/
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "URL", function() {
return "http://localhost:" + httpServer.identity.primaryPort + "/content";
});
var httpServer = null;
function make_channel(url, callback, ctx) {
return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
}
const responseContent = "response body";
// We need a large content in order to make sure that the IPDL stream is cut
// into several different chunks.
// We fill each chunk with a different character for easy debugging.
const altContent = "a".repeat(128*1024) +
"b".repeat(128*1024) +
"c".repeat(128*1024) +
"d".repeat(128*1024) +
"e".repeat(128*1024) +
"f".repeat(128*1024) +
"g".repeat(128*1024) +
"h".repeat(128*1024) +
"i".repeat(13); // Just so the chunk size doesn't match exactly.
const firstChunkSize = Math.floor(altContent.length / 4);
const altContentType = "text/binary";
function contentHandler(metadata, response)
{
response.setHeader("Content-Type", "text/plain");
response.setHeader("Cache-Control", "max-age=86400");
response.bodyOutputStream.write(responseContent, responseContent.length);
}
function run_test()
{
do_get_profile();
httpServer = new HttpServer();
httpServer.registerPathHandler("/content", contentHandler);
httpServer.start(-1);
var chan = make_channel(URL);
var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
cc.preferAlternativeDataType(altContentType);
chan.asyncOpen2(new ChannelListener(readServerContent, null));
do_test_pending();
}
// Output stream used to write alt-data to the cache entry.
var os;
function readServerContent(request, buffer)
{
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
do_check_eq(buffer, responseContent);
do_check_eq(cc.alternativeDataType, "");
do_execute_soon(() => {
os = cc.openAlternativeOutputStream(altContentType);
// Write a quarter of the alt data content
os.write(altContent, firstChunkSize);
do_execute_soon(openAltChannel);
});
}
function openAltChannel()
{
var chan = make_channel(URL);
var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
cc.preferAlternativeDataType(altContentType);
chan.asyncOpen2(listener);
}
var listener = {
buffer: "",
onStartRequest: function(request, context) { },
onDataAvailable: function(request, context, stream, offset, count) {
let string = NetUtil.readInputStreamToString(stream, count);
this.buffer += string;
// XXX: this condition might be a bit volatile. If this test times out,
// it probably means that for some reason, the listener didn't get all the
// data in the first chunk.
if (this.buffer.length == firstChunkSize) {
// write the rest of the content
os.write(altContent.substring(firstChunkSize, altContent.length), altContent.length - firstChunkSize);
os.close();
}
},
onStopRequest: function(request, context, status) {
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
do_check_eq(cc.alternativeDataType, altContentType);
do_check_eq(this.buffer.length, altContent.length);
do_check_eq(this.buffer, altContent);
httpServer.stop(do_test_finished);
},
};
|