2 * Test for the "alternative data stream" - closing the stream with an error.
4 * - we load a URL with preference for an alt data (check what we get is the raw data,
5 * since there was nothing previously cached)
6 * - we store something in alt data (using the asyncWait method)
7 * - then we abort the operation calling closeWithStatus()
8 * - we flush the HTTP cache
9 * - we reload the same URL using a new channel, again prefering the alt data be loaded
10 * - again we receive the data from the server.
15 const { HttpServer } = ChromeUtils.importESModule(
16 "resource://testing-common/httpd.sys.mjs"
19 ChromeUtils.defineLazyGetter(this, "URL", function () {
20 return "http://localhost:" + httpServer.identity.primaryPort + "/content";
23 var httpServer = null;
26 var cacheFlushObserver = (cacheFlushObserver = {
28 cacheFlushObserver = null;
29 readServerContentAgain();
33 var currentThread = null;
35 function make_channel(url) {
36 return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
39 function inChildProcess() {
40 return Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
43 const responseContent = "response body";
44 const responseContent2 = "response body 2";
45 const altContent = "!@#$%^&*()";
46 const altContentType = "text/binary";
48 var shouldPassRevalidation = true;
50 var cache_storage = null;
52 function contentHandler(metadata, response) {
53 response.setHeader("Content-Type", "text/plain");
54 response.setHeader("Cache-Control", "no-cache");
55 response.setHeader("ETag", "test-etag1");
59 etag = metadata.getHeader("If-None-Match");
64 if (etag == "test-etag1" && shouldPassRevalidation) {
65 response.setStatusLine(metadata.httpVersion, 304, "Not Modified");
67 var content = shouldPassRevalidation ? responseContent : responseContent2;
68 response.bodyOutputStream.write(content, content.length);
72 function check_has_alt_data_in_index(aHasAltData, callback) {
73 if (inChildProcess()) {
78 syncWithCacheIOThread(() => {
80 cache_storage.getCacheIndexEntryAttrs(createURI(URL), "", hasAltData, {});
81 Assert.equal(hasAltData.value, aHasAltData);
88 httpServer = new HttpServer();
89 httpServer.registerPathHandler("/content", contentHandler);
93 if (!inChildProcess()) {
94 cache_storage = getCacheStorage("disk");
95 wait_for_cache_index(asyncOpen);
101 function asyncOpen() {
102 var chan = make_channel(URL);
104 var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
105 cc.preferAlternativeDataType(
108 Ci.nsICacheInfoChannel.ASYNC
111 chan.asyncOpen(new ChannelListener(readServerContent, null));
114 function readServerContent(request, buffer) {
115 var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
117 Assert.equal(buffer, responseContent);
118 Assert.equal(cc.alternativeDataType, "");
119 check_has_alt_data_in_index(false, () => {
120 if (!inChildProcess()) {
121 currentThread = Services.tm.currentThread;
125 var os = cc.openAlternativeOutputStream(
130 var aos = os.QueryInterface(Ci.nsIAsyncOutputStream);
133 os.write(altContent, altContent.length);
134 aos.closeWithStatus(Cr.NS_ERROR_FAILURE);
135 executeSoon(flushAndReadServerContentAgain);
145 function flushAndReadServerContentAgain() {
146 // We need to do a GC pass to ensure the cache entry has been freed.
148 if (!inChildProcess()) {
150 .QueryInterface(Ci.nsICacheTesting)
151 .flush(cacheFlushObserver);
153 do_send_remote_message("flush");
154 do_await_remote_message("flushed").then(() => {
155 readServerContentAgain();
160 function readServerContentAgain() {
161 var chan = make_channel(URL);
162 var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
163 cc.preferAlternativeDataType(
166 Ci.nsICacheInfoChannel.ASYNC
168 cc.preferAlternativeDataType(
171 Ci.nsICacheInfoChannel.ASYNC
173 cc.preferAlternativeDataType("dummy2", "", Ci.nsICacheInfoChannel.ASYNC);
175 chan.asyncOpen(new ChannelListener(readServerContentAgainCB, null));
178 function readServerContentAgainCB(request, buffer) {
179 var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
181 Assert.equal(buffer, responseContent);
182 Assert.equal(cc.alternativeDataType, "");
183 check_has_alt_data_in_index(false, () => httpServer.stop(do_test_finished));