Bug 1527293 - Loading a large script transferred with Content-Range from cache returns empty file, r=mayhemer
authorMichal Novotny <michal.novotny@gmail.com>
Fri, 01 Mar 2019 13:04:36 +0000
changeset 520113 c33c24d2142024dfb632fd4a50621fb2cf22e393
parent 520112 e54a2708003712ae706d1a6b59e232966d395824
child 520114 59c8fffe9e41a68f37f5f98f762425b4c4fac9a0
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer
bugs1527293
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1527293 - Loading a large script transferred with Content-Range from cache returns empty file, r=mayhemer Differential Revision: https://phabricator.services.mozilla.com/D21403
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/test/unit/test_bug1527293.js
netwerk/test/unit/xpcshell.ini
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -5539,16 +5539,17 @@ nsresult nsHttpChannel::InstallCacheList
     // Entry is already doomed.
     // This may happen when expiration time is set to past and the entry
     // has been removed by the background eviction logic.
     return NS_OK;
   }
   if (rv == NS_ERROR_FILE_TOO_BIG) {
     LOG(("  entry would exceed max allowed size, not writing it [channel=%p]",
          this));
+    mCacheEntry->AsyncDoom(nullptr);
     return NS_OK;
   }
   if (NS_FAILED(rv)) return rv;
 
   if (mCacheOnlyMetadata) {
     LOG(("Not storing content, cacheOnlyMetadata set"));
     // We must open and then close the output stream of the cache entry.
     // This way we indicate the content has been written (despite with zero
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_bug1527293.js
@@ -0,0 +1,92 @@
+// Test bug 1527293
+//
+// Summary:
+// The purpose of this test is to check that a cache entry is doomed and not
+// reused when we don't write the content due to max entry size limit.
+//
+// Test step:
+// 1. Create http request for an entry whose size is bigger than we allow to
+//    cache. The response must contain Content-Range header so the content size
+//    is known in advance, but it must not contain Content-Length header because
+//    the bug isn't reproducible with it.
+// 2. After receiving and checking the content do the same request again.
+// 3. Check that the request isn't conditional, i.e. the entry from previous
+//    load was doomed.
+
+
+const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
+const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
+
+
+XPCOMUtils.defineLazyGetter(this, "URL", function() {
+  return "http://localhost:" + httpServer.identity.primaryPort;
+});
+
+var httpServer = null;
+
+function make_channel(url, callback, ctx) {
+  return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
+}
+
+// need something bigger than 1024 bytes
+const responseBody =
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +
+  "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
+
+function contentHandler(metadata, response)
+{
+  response.setHeader("Content-Type", "text/plain");
+  response.setHeader("ETag", "Just testing");
+  response.setHeader("Cache-Control", "max-age=99999");
+
+  Assert.throws(() => { var etag = metadata.getHeader("If-None-Match"); },
+                /NS_ERROR_NOT_AVAILABLE/, "conditional request not expected");
+
+  response.setHeader("Accept-Ranges", "bytes");
+  let len = responseBody.length;
+  response.setHeader("Content-Range", "0-" + (len - 1) + "/" + len);
+  response.bodyOutputStream.write(responseBody, responseBody.length);
+}
+
+function run_test()
+{
+  // Static check
+  Assert.ok(responseBody.length > 1024);
+
+  do_get_profile();
+
+  Services.prefs.setIntPref("browser.cache.disk.max_entry_size", 1);
+  Services.prefs.setBoolPref("network.http.rcwn.enabled", false);
+
+  httpServer = new HttpServer();
+  httpServer.registerPathHandler("/content", contentHandler);
+  httpServer.start(-1);
+
+  var chan = make_channel(URL + "/content");
+  chan.asyncOpen(new ChannelListener(firstTimeThrough, null));
+
+  do_test_pending();
+}
+
+function firstTimeThrough(request, buffer)
+{
+  Assert.equal(buffer, responseBody);
+
+  var chan = make_channel(URL + "/content");
+  chan.asyncOpen(new ChannelListener(secondTimeThrough, null));
+}
+
+function secondTimeThrough(request, buffer)
+{
+  Assert.equal(buffer, responseBody);
+  httpServer.stop(do_test_finished);
+}
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -425,8 +425,9 @@ run-sequentially = node server exception
 [test_esni_dns_fetch.js]
 # http2-using tests require node available
 skip-if = os == "android"
 [test_network_connectivity_service.js]
 skip-if = os == "android" # DNSv6 issues on android
 [test_suspend_channel_on_authRetry.js]
 [test_suspend_channel_on_examine_merged_response.js]
 [test_crossOriginOpenerPolicy.js]
+[test_bug1527293.js]