content: sync load service: don't die when channels have unknown size (b=894586 r=jst r=jduell)
☠☠ backed out by 009130768e09 ☠ ☠
authorMook <marky+mozhg@activestate.com>
Fri, 26 Jul 2013 15:25:27 -0700
changeset 140246 f570fc641c5f087fc00e87708ecda8053495c3ad
parent 140245 2ee2dc1d2bcc0d8210fcf1dfe61e66284cec4026
child 140247 2287b266756501af9cedfe42082b3525969be655
push id1951
push userryanvm@gmail.com
push dateSun, 28 Jul 2013 01:55:51 +0000
treeherderfx-team@73b69c146ca6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst, jduell
bugs894586
milestone25.0a1
content: sync load service: don't die when channels have unknown size (b=894586 r=jst r=jduell)
content/base/src/nsSyncLoadService.cpp
netwerk/test/unit/test_bug894586.js
netwerk/test/unit/xpcshell.ini
--- a/content/base/src/nsSyncLoadService.cpp
+++ b/content/base/src/nsSyncLoadService.cpp
@@ -335,17 +335,17 @@ nsSyncLoadService::PushSyncStreamToListe
                                             nsIChannel* aChannel)
 {
     // Set up buffering stream
     nsresult rv;
     nsCOMPtr<nsIInputStream> bufferedStream;
     if (!NS_InputStreamIsBuffered(aIn)) {
         int64_t chunkSize;
         rv = aChannel->GetContentLength(&chunkSize);
-        if (NS_FAILED(rv)) {
+        if (NS_FAILED(rv) || chunkSize < 1) {
             chunkSize = 4096;
         }
         chunkSize = std::min(int64_t(UINT16_MAX), chunkSize);
 
         rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aIn,
                                        chunkSize);
         NS_ENSURE_SUCCESS(rv, rv);
 
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_bug894586.js
@@ -0,0 +1,115 @@
+/*
+ * Tests for bug 894586: nsSyncLoadService::PushSyncStreamToListener
+ * should not fail for channels of unknown size
+ */
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+function ProtocolHandler() {
+  this.uri = Cc["@mozilla.org/network/simple-uri;1"].
+               createInstance(Ci.nsIURI);
+  this.uri.spec = this.scheme + ":dummy";
+  this.uri.QueryInterface(Ci.nsIMutable).mutable = false;
+}
+
+ProtocolHandler.prototype = {
+  /** nsIProtocolHandler */
+  get scheme() "x-bug894586",
+  get defaultPort() -1,
+  get protocolFlags() Ci.nsIProtocolHandler.URI_NORELATIVE |
+                      Ci.nsIProtocolHandler.URI_NOAUTH |
+                      Ci.nsIProtocolHandler.URI_IS_UI_RESOURCE |
+                      Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE |
+                      Ci.nsIProtocolHandler.URI_NON_PERSISTABLE |
+                      Ci.nsIProtocolHandler.URI_SYNC_LOAD_IS_OK,
+  newURI: function(aSpec, aOriginCharset, aBaseURI) this.uri,
+  newChannel: function(aURI) this,
+  allowPort: function(port, scheme) port != -1,
+
+  /** nsIChannel */
+  get originalURI() this.uri,
+  get URI() this.uri,
+  owner: null,
+  notificationCallbacks: null,
+  get securityInfo() null,
+  get contentType() "text/css",
+  set contentType(val) void(0),
+  contentCharset: "UTF-8",
+  get contentLength() -1,
+  set contentLength(val) {
+    throw Components.Exception("Setting content length", NS_ERROR_NOT_IMPLEMENTED);
+  },
+  open: function() {
+    var url = Services.io.newURI("resource://app/chrome.manifest", null, null);
+    do_check_true(url.QueryInterface(Ci.nsIFileURL).file.exists());
+    return Services.io.newChannelFromURI(url).open();
+  },
+  asyncOpen: function(aListener, aContext) {
+    throw Components.Exception("Not implemented",
+                               Cr.NS_ERROR_NOT_IMPLEMENTED);
+  },
+  contentDisposition: Ci.nsIChannel.DISPOSITION_INLINE,
+  get contentDispositionFilename() {
+    throw Components.Exception("No file name",
+                               Cr.NS_ERROR_NOT_AVAILABLE);
+  },
+  get contentDispositionHeader() {
+    throw Components.Exception("No header",
+                               Cr.NS_ERROR_NOT_AVAILABLE);
+  },
+
+  /** nsIRequest */
+  get name() this.uri.spec,
+  isPending: function() false,
+  get status() Cr.NS_OK,
+  cancel: function(status) {},
+  loadGroup: null,
+  loadFlags: Ci.nsIRequest.LOAD_NORMAL |
+             Ci.nsIRequest.INHIBIT_CACHING |
+             Ci.nsIRequest.LOAD_BYPASS_CACHE,
+
+  /** nsIFactory */
+  createInstance: function(aOuter, aIID) {
+    if (aOuter) {
+      throw Components.Exception("createInstance no aggregation",
+                                 Cr.NS_ERROR_NO_AGGREGATION);
+    }
+    return this.QueryInterface(aIID);
+  },
+  lockFactory: function() {},
+
+  /** nsISupports */
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler,
+                                         Ci.nsIRequest,
+                                         Ci.nsIChannel,
+                                         Ci.nsIFactory]),
+  classID: Components.ID("{16d594bc-d9d8-47ae-a139-ea714dc0c35c}")
+};
+
+/**
+ * Attempt a sync load; we use the stylesheet service to do this for us,
+ * based on the knowledge that it forces a sync load under the hood.
+ */
+function run_test()
+{
+  var handler = new ProtocolHandler();
+  var registrar = Components.manager.
+                             QueryInterface(Ci.nsIComponentRegistrar);
+  registrar.registerFactory(handler.classID, "",
+                            "@mozilla.org/network/protocol;1?name=" + handler.scheme,
+                            handler);
+  try {
+    var ss = Cc["@mozilla.org/content/style-sheet-service;1"].
+               getService(Ci.nsIStyleSheetService);
+    ss.loadAndRegisterSheet(handler.uri, Ci.nsIStyleSheetService.AGENT_SHEET);
+    do_check_true(ss.sheetRegistered(handler.uri, Ci.nsIStyleSheetService.AGENT_SHEET));
+  } finally {
+    registrar.unregisterFactory(handler.classID, handler);
+  }
+}
+
+// vim: set et ts=2 :
+
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -74,16 +74,19 @@ tail =
 [test_bug659569.js]
 [test_bug660066.js]
 [test_bug667907.js]
 [test_bug667818.js]
 [test_bug669001.js]
 [test_bug712914_secinfo_validation.js]
 [test_bug722299.js]
 [test_bug770243.js]
+[test_bug894586.js]
+# Allocating 4GB might actually succeed on 64 bit machines
+skip-if = bits != 32
 [test_doomentry.js]
 [test_cacheflags.js]
 [test_cache_jar.js]
 [test_channel_close.js]
 [test_compareURIs.js]
 [test_compressappend.js]
 [test_content_encoding_gzip.js]
 [test_content_sniffer.js]