2 * Test for the "alternative data stream" stored withing a cache entry.
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 the alt data along the channel (to the cache entry)
7 * - we flush the HTTP cache
8 * - we reload the same URL using a new channel, again prefering the alt data be loaded
9 * - this time the alt data must arive
14 const { HttpServer } = ChromeUtils.importESModule(
15 "resource://testing-common/httpd.sys.mjs"
18 ChromeUtils.defineLazyGetter(this, "URL", function () {
19 return "http://localhost:" + httpServer.identity.primaryPort + "/content";
22 var httpServer = null;
24 function make_channel(url) {
25 return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
28 function inChildProcess() {
29 return Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
32 const responseContent = "response body";
33 const responseContent2 = "response body 2";
34 const altContent = "!@#$%^&*()";
35 const altContentType = "text/binary";
37 var servedNotModified = false;
38 var shouldPassRevalidation = true;
40 var cache_storage = null;
42 function contentHandler(metadata, response) {
43 response.setHeader("Content-Type", "text/plain");
44 response.setHeader("Cache-Control", "no-cache");
45 response.setHeader("ETag", "test-etag1");
49 etag = metadata.getHeader("If-None-Match");
54 if (etag == "test-etag1" && shouldPassRevalidation) {
55 response.setStatusLine(metadata.httpVersion, 304, "Not Modified");
56 servedNotModified = true;
58 var content = shouldPassRevalidation ? responseContent : responseContent2;
59 response.bodyOutputStream.write(content, content.length);
63 function check_has_alt_data_in_index(aHasAltData, callback) {
64 if (inChildProcess()) {
69 syncWithCacheIOThread(() => {
71 cache_storage.getCacheIndexEntryAttrs(createURI(URL), "", hasAltData, {});
72 Assert.equal(hasAltData.value, aHasAltData);
77 // This file is loaded as part of test_alt-data_cross_process_wrap.js.
78 // eslint-disable-next-line no-unused-vars
80 httpServer = new HttpServer();
81 httpServer.registerPathHandler("/content", contentHandler);
88 function asyncOpen() {
89 var chan = make_channel(URL);
91 var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
92 cc.preferAlternativeDataType(
95 Ci.nsICacheInfoChannel.ASYNC
98 chan.asyncOpen(new ChannelListener(readServerContent, null));
101 function readServerContent(request, buffer) {
102 var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
104 Assert.equal(buffer, responseContent);
105 Assert.equal(cc.alternativeDataType, "");
106 check_has_alt_data_in_index(false, () => {
108 var os = cc.openAlternativeOutputStream(
112 os.write(altContent, altContent.length);
115 executeSoon(flushAndOpenAltChannel);
120 function flushAndOpenAltChannel() {
121 // We need to do a GC pass to ensure the cache entry has been freed.
123 do_send_remote_message("flush");
124 do_await_remote_message("flushed").then(() => {
129 function openAltChannel() {
130 var chan = make_channel(URL);
131 var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
132 cc.preferAlternativeDataType(
135 Ci.nsICacheInfoChannel.ASYNC
138 chan.asyncOpen(new ChannelListener(readAltContent, null));
141 function readAltContent(request, buffer) {
142 var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
144 Assert.equal(servedNotModified, true);
145 Assert.equal(cc.alternativeDataType, altContentType);
146 Assert.equal(buffer, altContent);
149 do_send_remote_message("done");
150 do_await_remote_message("finish").then(() => {
151 httpServer.stop(do_test_finished);