Bug 1218029 - Adds IncrementalStreamLoader interface stubs. r=djvj
authorYury Delendik <ydelendik@mozilla.com>
Mon, 30 Nov 2015 08:54:11 -0600
changeset 309236 73cfba395b86e5c2520a0828a5ce4413dffb1c5c
parent 309235 9e68f234636f55415f9803a06e83096e24d7884d
child 309237 6fb6aac48d4d90fbb38e752e9e38bb86a4653f59
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdjvj
bugs1218029
milestone45.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 1218029 - Adds IncrementalStreamLoader interface stubs. r=djvj
dom/base/nsScriptLoader.cpp
dom/base/nsScriptLoader.h
dom/security/SRICheck.cpp
dom/security/SRICheck.h
dom/xul/XULDocument.h
js/xpconnect/loader/mozJSSubScriptLoader.cpp
netwerk/base/moz.build
netwerk/base/nsIIncrementalStreamLoader.idl
netwerk/base/nsIncrementalStreamLoader.cpp
netwerk/base/nsIncrementalStreamLoader.h
netwerk/base/nsNetUtil.cpp
netwerk/base/nsNetUtil.h
netwerk/base/nsNetUtil.inl
netwerk/build/nsNetCID.h
netwerk/build/nsNetModule.cpp
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -152,20 +152,20 @@ nsScriptLoader::~nsScriptLoader()
       req = req->getNext()) {
     req->FireScriptAvailable(NS_ERROR_ABORT);
   }
 
   // Unblock the kids, in case any of them moved to a different document
   // subtree in the meantime and therefore aren't actually going away.
   for (uint32_t j = 0; j < mPendingChildLoaders.Length(); ++j) {
     mPendingChildLoaders[j]->RemoveExecuteBlocker();
-  }  
+  }
 }
 
-NS_IMPL_ISUPPORTS(nsScriptLoader, nsIStreamLoaderObserver)
+NS_IMPL_ISUPPORTS(nsScriptLoader, nsIIncrementalStreamLoaderObserver)
 
 // Helper method for checking if the script element is an event-handler
 // This means that it has both a for-attribute and a event-attribute.
 // Also, if the for-attribute has a value that matches "\s*window\s*",
 // and the event-attribute matches "\s*onload([ \(].*)?" then it isn't an
 // eventhandler. (both matches are case insensitive).
 // This is how IE seems to filter out a window's onload handler from a
 // <script for=... event=...> element.
@@ -264,36 +264,36 @@ nsScriptLoader::ShouldLoadScript(nsIDocu
   rv = CheckContentPolicy(aDocument, aContext, aURI, aType, aIsPreLoad);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   return NS_OK;
 }
 
-class ContextMediator : public nsIStreamLoaderObserver
+class ContextMediator : public nsIIncrementalStreamLoaderObserver
 {
 public:
   explicit ContextMediator(nsScriptLoader *aScriptLoader, nsISupports *aContext)
   : mScriptLoader(aScriptLoader)
   , mContext(aContext) {}
 
   NS_DECL_ISUPPORTS
-  NS_DECL_NSISTREAMLOADEROBSERVER
+  NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
 
 private:
   virtual ~ContextMediator() {}
   RefPtr<nsScriptLoader> mScriptLoader;
   nsCOMPtr<nsISupports>  mContext;
 };
 
-NS_IMPL_ISUPPORTS(ContextMediator, nsIStreamLoaderObserver)
+NS_IMPL_ISUPPORTS(ContextMediator, nsIIncrementalStreamLoaderObserver)
 
 NS_IMETHODIMP
-ContextMediator::OnStreamComplete(nsIStreamLoader* aLoader,
+ContextMediator::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
                                   nsISupports* aContext,
                                   nsresult aStatus,
                                   uint32_t aStringLen,
                                   const uint8_t* aString)
 {
   // pass arguments through except for the aContext,
   // we have to mediate and use mContext instead.
   return mScriptLoader->OnStreamComplete(aLoader, mContext, aStatus,
@@ -380,18 +380,18 @@ nsScriptLoader::StartLoad(nsScriptLoadRe
   // Set the initiator type
   nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChannel));
   if (timedChannel) {
     timedChannel->SetInitiatorType(NS_LITERAL_STRING("script"));
   }
 
   RefPtr<ContextMediator> mediator = new ContextMediator(this, aRequest);
 
-  nsCOMPtr<nsIStreamLoader> loader;
-  rv = NS_NewStreamLoader(getter_AddRefs(loader), mediator);
+  nsCOMPtr<nsIIncrementalStreamLoader> loader;
+  rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), mediator);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return channel->AsyncOpen2(loader);
 }
 
 bool
 nsScriptLoader::PreloadURIComparator::Equals(const PreloadInfo &aPi,
                                              nsIURI * const &aURI) const
@@ -1434,17 +1434,17 @@ nsScriptLoader::ConvertToUTF16(nsIChanne
     js_free(aBufOut);
     aBufOut = nullptr;
     aLengthOut = 0;
   }
   return rv;
 }
 
 NS_IMETHODIMP
-nsScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
+nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
                                  nsISupports* aContext,
                                  nsresult aStatus,
                                  uint32_t aStringLen,
                                  const uint8_t* aString)
 {
   nsScriptLoadRequest* request = static_cast<nsScriptLoadRequest*>(aContext);
   NS_ASSERTION(request, "null request in stream complete handler");
   NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
@@ -1530,17 +1530,17 @@ nsScriptLoader::NumberOfProcessors()
   int32_t numProcs = PR_GetNumberOfProcessors();
   if (numProcs > 0)
     mNumberOfProcessors = numProcs;
   return mNumberOfProcessors;
 }
 
 nsresult
 nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
-                                     nsIStreamLoader* aLoader,
+                                     nsIIncrementalStreamLoader* aLoader,
                                      nsresult aStatus,
                                      uint32_t aStringLen,
                                      const uint8_t* aString)
 {
   if (NS_FAILED(aStatus)) {
     return aStatus;
   }
 
--- a/dom/base/nsScriptLoader.h
+++ b/dom/base/nsScriptLoader.h
@@ -12,17 +12,17 @@
 #define __nsScriptLoader_h__
 
 #include "nsCOMPtr.h"
 #include "nsIScriptElement.h"
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "nsIDocument.h"
-#include "nsIStreamLoader.h"
+#include "nsIIncrementalStreamLoader.h"
 #include "mozilla/CORSMode.h"
 #include "mozilla/dom/SRIMetadata.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
 class nsScriptLoadRequestList;
 class nsIURI;
 
@@ -190,17 +190,17 @@ public:
     return Steal(getFirst());
   }
 };
 
 //////////////////////////////////////////////////////////////
 // Script loader implementation
 //////////////////////////////////////////////////////////////
 
-class nsScriptLoader final : public nsIStreamLoaderObserver
+class nsScriptLoader final : public nsIIncrementalStreamLoaderObserver
 {
   class MOZ_STACK_CLASS AutoCurrentScriptUpdater
   {
   public:
     AutoCurrentScriptUpdater(nsScriptLoader* aScriptLoader,
                              nsIScriptElement* aCurrentScript)
       : mOldScript(aScriptLoader->mCurrentScript)
       , mScriptLoader(aScriptLoader)
@@ -218,17 +218,17 @@ class nsScriptLoader final : public nsIS
 
   friend class nsScriptRequestProcessor;
   friend class AutoCurrentScriptUpdater;
 
 public:
   explicit nsScriptLoader(nsIDocument* aDocument);
 
   NS_DECL_ISUPPORTS
-  NS_DECL_NSISTREAMLOADEROBSERVER
+  NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
 
   /**
    * The loader maintains a weak reference to the document with
    * which it is initialized. This call forces the reference to
    * be dropped.
    */
   void DropDocumentReference()
   {
@@ -484,17 +484,17 @@ private:
   already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();
   void FillCompileOptionsForRequest(const mozilla::dom::AutoJSAPI &jsapi,
                                     nsScriptLoadRequest *aRequest,
                                     JS::Handle<JSObject *> aScopeChain,
                                     JS::CompileOptions *aOptions);
 
   uint32_t NumberOfProcessors();
   nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
-                                nsIStreamLoader* aLoader,
+                                nsIIncrementalStreamLoader* aLoader,
                                 nsresult aStatus,
                                 uint32_t aStringLen,
                                 const uint8_t* aString);
 
   void AddDeferRequest(nsScriptLoadRequest* aRequest);
   bool MaybeRemovedDeferRequests();
 
   nsIDocument* mDocument;                   // [WEAK]
--- a/dom/security/SRICheck.cpp
+++ b/dom/security/SRICheck.cpp
@@ -11,17 +11,17 @@
 #include "mozilla/Preferences.h"
 #include "nsContentUtils.h"
 #include "nsIChannel.h"
 #include "nsICryptoHash.h"
 #include "nsIDocument.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
-#include "nsIStreamLoader.h"
+#include "nsIIncrementalStreamLoader.h"
 #include "nsIUnicharStreamLoader.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsWhitespaceTokenizer.h"
 
 static mozilla::LogModule*
 GetSriLog()
 {
@@ -312,17 +312,17 @@ SRICheck::VerifyIntegrity(const SRIMetad
 
   return VerifyIntegrityInternal(aMetadata, channel, aCORSMode,
                                  utf8Hash.Length(), (uint8_t*)utf8Hash.get(),
                                  aDocument);
 }
 
 /* static */ nsresult
 SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
-                          nsIStreamLoader* aLoader,
+                          nsIIncrementalStreamLoader* aLoader,
                           const CORSMode aCORSMode,
                           uint32_t aStringLen,
                           const uint8_t* aString,
                           const nsIDocument* aDocument)
 {
   NS_ENSURE_ARG_POINTER(aLoader);
 
   nsCOMPtr<nsIRequest> request;
--- a/dom/security/SRICheck.h
+++ b/dom/security/SRICheck.h
@@ -7,17 +7,17 @@
 #ifndef mozilla_dom_SRICheck_h
 #define mozilla_dom_SRICheck_h
 
 #include "mozilla/CORSMode.h"
 #include "nsCOMPtr.h"
 #include "SRIMetadata.h"
 
 class nsIDocument;
-class nsIStreamLoader;
+class nsIIncrementalStreamLoader;
 class nsIUnicharStreamLoader;
 
 namespace mozilla {
 namespace dom {
 
 class SRICheck final
 {
 public:
@@ -42,17 +42,17 @@ public:
                                   const nsAString& aString,
                                   const nsIDocument* aDocument);
 
   /**
    * Process the integrity attribute of the element.  A result of false
    * must prevent the resource from loading.
    */
   static nsresult VerifyIntegrity(const SRIMetadata& aMetadata,
-                                  nsIStreamLoader* aLoader,
+                                  nsIIncrementalStreamLoader* aLoader,
                                   const CORSMode aCORSMode,
                                   uint32_t aStringLen,
                                   const uint8_t* aString,
                                   const nsIDocument* aDocument);
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -16,16 +16,17 @@
 #include "nsIContent.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIDOMXULDocument.h"
 #include "nsCOMArray.h"
 #include "nsIURI.h"
 #include "nsIXULDocument.h"
 #include "nsScriptLoader.h"
 #include "nsIStreamListener.h"
+#include "nsIStreamLoader.h"
 #include "nsICSSLoaderObserver.h"
 #include "nsIXULStore.h"
 
 #include "mozilla/Attributes.h"
 
 #include "js/TracingAPI.h"
 #include "js/TypeDecls.h"
 
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -234,21 +234,21 @@ EvalScript(JSContext* cx,
 
     if (cache && ok && !!script) {
         WriteCachedScript(StartupCache::GetSingleton(),
                           cachePath, cx, principal, script);
     }
     return NS_OK;
 }
 
-class AsyncScriptLoader : public nsIStreamLoaderObserver
+class AsyncScriptLoader : public nsIIncrementalStreamLoaderObserver
 {
 public:
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-    NS_DECL_NSISTREAMLOADEROBSERVER
+    NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
 
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AsyncScriptLoader)
 
     AsyncScriptLoader(nsIChannel* aChannel, bool aReuseGlobal,
                       JSObject* aTargetObj, const nsAString& aCharset,
                       bool aCache, Promise* aPromise)
         : mChannel(aChannel)
         , mTargetObj(aTargetObj)
@@ -272,17 +272,17 @@ private:
     nsString                  mCharset;
     bool                      mReuseGlobal;
     bool                      mCache;
 };
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(AsyncScriptLoader)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AsyncScriptLoader)
-  NS_INTERFACE_MAP_ENTRY(nsIStreamLoaderObserver)
+  NS_INTERFACE_MAP_ENTRY(nsIIncrementalStreamLoaderObserver)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AsyncScriptLoader)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
   tmp->mTargetObj = nullptr;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AsyncScriptLoader)
@@ -321,17 +321,17 @@ class MOZ_STACK_CLASS AutoRejectPromise
 
   private:
     JSContext*                mCx;
     RefPtr<Promise>         mPromise;
     nsCOMPtr<nsIGlobalObject> mGlobalObject;
 };
 
 NS_IMETHODIMP
-AsyncScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
+AsyncScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
                                     nsISupports* aContext,
                                     nsresult aStatus,
                                     uint32_t aLength,
                                     const uint8_t* aBuf)
 {
     nsCOMPtr<nsIURI> uri;
     mChannel->GetURI(getter_AddRefs(uri));
 
@@ -426,18 +426,18 @@ mozJSSubScriptLoader::ReadScriptAsync(ns
     RefPtr<AsyncScriptLoader> loadObserver =
         new AsyncScriptLoader(channel,
                               reuseGlobal,
                               target_obj,
                               charset,
                               cache,
                               promise);
 
-    nsCOMPtr<nsIStreamLoader> loader;
-    rv = NS_NewStreamLoader(getter_AddRefs(loader), loadObserver);
+    nsCOMPtr<nsIIncrementalStreamLoader> loader;
+    rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), loadObserver);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIStreamListener> listener = loader.get();
     return channel->AsyncOpen2(listener);
 }
 
 nsresult
 mozJSSubScriptLoader::ReadScript(nsIURI* uri, JSContext* cx, JSObject* targetObjArg,
@@ -668,21 +668,21 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
 
     return EvalScript(cx, targetObj, retval, uri, !!cache, script, function);
 }
 
 /**
   * Let us compile scripts from a URI off the main thread.
   */
 
-class ScriptPrecompiler : public nsIStreamLoaderObserver
+class ScriptPrecompiler : public nsIIncrementalStreamLoaderObserver
 {
 public:
     NS_DECL_ISUPPORTS
-    NS_DECL_NSISTREAMLOADEROBSERVER
+    NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
 
     ScriptPrecompiler(nsIObserver* aObserver,
                       nsIPrincipal* aPrincipal,
                       nsIChannel* aChannel)
         : mObserver(aObserver)
         , mPrincipal(aPrincipal)
         , mChannel(aChannel)
         , mScriptBuf(nullptr)
@@ -704,17 +704,17 @@ private:
 
     RefPtr<nsIObserver> mObserver;
     RefPtr<nsIPrincipal> mPrincipal;
     RefPtr<nsIChannel> mChannel;
     char16_t* mScriptBuf;
     size_t mScriptLength;
 };
 
-NS_IMPL_ISUPPORTS(ScriptPrecompiler, nsIStreamLoaderObserver);
+NS_IMPL_ISUPPORTS(ScriptPrecompiler, nsIIncrementalStreamLoaderObserver);
 
 class NotifyPrecompilationCompleteRunnable : public nsRunnable
 {
 public:
     NS_DECL_NSIRUNNABLE
 
     explicit NotifyPrecompilationCompleteRunnable(ScriptPrecompiler* aPrecompiler)
         : mPrecompiler(aPrecompiler)
@@ -765,17 +765,17 @@ NotifyPrecompilationCompleteRunnable::Ru
         NS_ENSURE_TRUE(rt, NS_ERROR_FAILURE);
         JS::FinishOffThreadScript(nullptr, rt, mToken);
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-ScriptPrecompiler::OnStreamComplete(nsIStreamLoader* aLoader,
+ScriptPrecompiler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
                                     nsISupports* aContext,
                                     nsresult aStatus,
                                     uint32_t aLength,
                                     const uint8_t* aString)
 {
     AutoSendObserverNotification notifier(this);
 
     // Just notify that we are done with this load.
@@ -871,18 +871,18 @@ mozJSSubScriptLoader::PrecompileScript(n
                                 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                                 nsIContentPolicy::TYPE_OTHER);
 
     NS_ENSURE_SUCCESS(rv, rv);
 
     RefPtr<ScriptPrecompiler> loadObserver =
         new ScriptPrecompiler(aObserver, aPrincipal, channel);
 
-    nsCOMPtr<nsIStreamLoader> loader;
-    rv = NS_NewStreamLoader(getter_AddRefs(loader), loadObserver);
+    nsCOMPtr<nsIIncrementalStreamLoader> loader;
+    rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), loadObserver);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIStreamListener> listener = loader.get();
     rv = channel->AsyncOpen2(listener);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return NS_OK;
 }
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -43,16 +43,17 @@ XPIDL_SOURCES += [
     'nsIDownloader.idl',
     'nsIEncodedChannel.idl',
     'nsIExternalProtocolHandler.idl',
     'nsIFileStreams.idl',
     'nsIFileURL.idl',
     'nsIForcePendingChannel.idl',
     'nsIHttpPushListener.idl',
     'nsIIncrementalDownload.idl',
+    'nsIIncrementalStreamLoader.idl',
     'nsIInputStreamChannel.idl',
     'nsIInputStreamPump.idl',
     'nsIIOService.idl',
     'nsIIOService2.idl',
     'nsILoadContextInfo.idl',
     'nsILoadGroup.idl',
     'nsILoadGroupChild.idl',
     'nsILoadInfo.idl',
@@ -207,16 +208,17 @@ UNIFIED_SOURCES += [
     'nsBaseContentStream.cpp',
     'nsBufferedStreams.cpp',
     'nsChannelClassifier.cpp',
     'nsDirectoryIndexStream.cpp',
     'nsDNSPrefetch.cpp',
     'nsDownloader.cpp',
     'nsFileStreams.cpp',
     'nsIncrementalDownload.cpp',
+    'nsIncrementalStreamLoader.cpp',
     'nsInputStreamChannel.cpp',
     'nsInputStreamPump.cpp',
     'nsIOService.cpp',
     'nsLoadGroup.cpp',
     'nsMediaFragmentURIParser.cpp',
     'nsMIMEInputStream.cpp',
     'nsNetAddr.cpp',
     'nsNetUtil.cpp',
new file mode 100644
--- /dev/null
+++ b/netwerk/base/nsIIncrementalStreamLoader.idl
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIStreamListener.idl"
+
+interface nsIRequest;
+interface nsIIncrementalStreamLoader;
+
+[scriptable, uuid(2143eaad-674e-4613-87f8-359d4c40f590)]
+interface nsIIncrementalStreamLoaderObserver : nsISupports
+{
+    /**
+     * Called when the entire stream has been loaded.
+     *
+     * @param loader the stream loader that loaded the stream.
+     * @param ctxt the context parameter of the underlying channel
+     * @param status the status of the underlying channel
+     * @param resultLength the length of the data loaded
+     * @param result the data
+     *
+     * This method will always be called asynchronously by the
+     * nsIIncrementalStreamLoader involved, on the thread that called the
+     * loader's init() method.
+     *
+     * If the observer wants to take over responsibility for the
+     * data buffer (result), it returns NS_SUCCESS_ADOPTED_DATA
+     * in place of NS_OK as its success code. The loader will then
+     * "forget" about the data and not free() it after
+     * onStreamComplete() returns; observer must call free()
+     * when the data is no longer required.
+     */
+    void onStreamComplete(in nsIIncrementalStreamLoader loader,
+                          in nsISupports ctxt,
+                          in nsresult status,
+                          in unsigned long resultLength,
+                          [const,array,size_is(resultLength)] in octet result);
+};
+
+/**
+ * Asynchronously loads a channel into a memory buffer.
+ *
+ * To use this interface, first call init() with a nsIIncrementalStreamLoaderObserver
+ * that will be notified when the data has been loaded. Then call asyncOpen()
+ * on the channel with the nsIIncrementalStreamLoader as the listener. The context
+ * argument in the asyncOpen() call will be passed to the onStreamComplete()
+ * callback.
+ *
+ * XXX define behaviour for sizes >4 GB
+ */
+[scriptable, uuid(a023b060-ba23-431a-b449-2dd63e220554)]
+interface nsIIncrementalStreamLoader : nsIStreamListener
+{
+    /**
+     * Initialize this stream loader, and start loading the data.
+     *
+     * @param aObserver
+     *        An observer that will be notified when the data is complete.
+     */
+    void init(in nsIIncrementalStreamLoaderObserver aObserver);
+
+    /**
+     * Gets the number of bytes read so far.
+     */
+    readonly attribute unsigned long numBytesRead;
+
+    /**
+     * Gets the request that loaded this file.
+     * null after the request has finished loading.
+     */
+    readonly attribute nsIRequest request;
+};
new file mode 100644
--- /dev/null
+++ b/netwerk/base/nsIncrementalStreamLoader.cpp
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIncrementalStreamLoader.h"
+#include "nsIInputStream.h"
+#include "nsIChannel.h"
+#include "nsError.h"
+#include "GeckoProfiler.h"
+
+#include <limits>
+
+nsIncrementalStreamLoader::nsIncrementalStreamLoader()
+  : mData()
+{
+}
+
+nsIncrementalStreamLoader::~nsIncrementalStreamLoader()
+{
+}
+
+NS_IMETHODIMP
+nsIncrementalStreamLoader::Init(nsIIncrementalStreamLoaderObserver* observer)
+{
+  NS_ENSURE_ARG_POINTER(observer);
+  mObserver = observer;
+  return NS_OK;
+}
+
+nsresult
+nsIncrementalStreamLoader::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+  if (aOuter) return NS_ERROR_NO_AGGREGATION;
+
+  nsIncrementalStreamLoader* it = new nsIncrementalStreamLoader();
+  if (it == nullptr)
+    return NS_ERROR_OUT_OF_MEMORY;
+  NS_ADDREF(it);
+  nsresult rv = it->QueryInterface(aIID, aResult);
+  NS_RELEASE(it);
+  return rv;
+}
+
+NS_IMPL_ISUPPORTS(nsIncrementalStreamLoader, nsIIncrementalStreamLoader,
+                  nsIRequestObserver, nsIStreamListener,
+                  nsIThreadRetargetableStreamListener)
+
+NS_IMETHODIMP
+nsIncrementalStreamLoader::GetNumBytesRead(uint32_t* aNumBytes)
+{
+  *aNumBytes = mData.length();
+  return NS_OK;
+}
+
+/* readonly attribute nsIRequest request; */
+NS_IMETHODIMP
+nsIncrementalStreamLoader::GetRequest(nsIRequest **aRequest)
+{
+  NS_IF_ADDREF(*aRequest = mRequest);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsIncrementalStreamLoader::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
+{
+  nsCOMPtr<nsIChannel> chan( do_QueryInterface(request) );
+  if (chan) {
+    int64_t contentLength = -1;
+    chan->GetContentLength(&contentLength);
+    if (contentLength >= 0) {
+      if (uint64_t(contentLength) > std::numeric_limits<size_t>::max()) {
+        // Too big to fit into size_t, so let's bail.
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+      // preallocate buffer
+      if (!mData.initCapacity(contentLength)) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+    }
+  }
+  mContext = ctxt;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsIncrementalStreamLoader::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
+                                         nsresult aStatus)
+{
+  PROFILER_LABEL("nsIncrementalStreamLoader", "OnStopRequest",
+    js::ProfileEntry::Category::NETWORK);
+
+  if (mObserver) {
+    // provide nsIIncrementalStreamLoader::request during call to OnStreamComplete
+    mRequest = request;
+    size_t length = mData.length();
+    uint8_t* elems = mData.extractRawBuffer();
+    nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus,
+                                              length, elems);
+    if (rv != NS_SUCCESS_ADOPTED_DATA) {
+      // The observer didn't take ownership of the extracted data buffer, so
+      // put it back into mData.
+      mData.replaceRawBuffer(elems, length);
+    }
+    // done.. cleanup
+    ReleaseData();
+    mRequest = 0;
+    mObserver = 0;
+    mContext = 0;
+  }
+  return NS_OK;
+}
+
+NS_METHOD
+nsIncrementalStreamLoader::WriteSegmentFun(nsIInputStream *inStr,
+                                           void *closure,
+                                           const char *fromSegment,
+                                           uint32_t toOffset,
+                                           uint32_t count,
+                                           uint32_t *writeCount)
+{
+  nsIncrementalStreamLoader *self = (nsIncrementalStreamLoader *) closure;
+
+  if (!self->mData.append(fromSegment, count)) {
+    self->mData.clearAndFree();
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  *writeCount = count;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsIncrementalStreamLoader::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
+                                nsIInputStream *inStr,
+                                uint64_t sourceOffset, uint32_t count)
+{
+  uint32_t countRead;
+  return inStr->ReadSegments(WriteSegmentFun, this, count, &countRead);
+}
+
+void
+nsIncrementalStreamLoader::ReleaseData()
+{
+  mData.clearAndFree();
+}
+
+NS_IMETHODIMP
+nsIncrementalStreamLoader::CheckListenerChain()
+{
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/netwerk/base/nsIncrementalStreamLoader.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsIncrementalStreamLoader_h__
+#define nsIncrementalStreamLoader_h__
+
+#include "nsIThreadRetargetableStreamListener.h"
+#include "nsIIncrementalStreamLoader.h"
+#include "nsCOMPtr.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Vector.h"
+
+class nsIRequest;
+
+class nsIncrementalStreamLoader final : public nsIIncrementalStreamLoader
+                                      , public nsIThreadRetargetableStreamListener
+{
+public:
+  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_NSIINCREMENTALSTREAMLOADER
+  NS_DECL_NSIREQUESTOBSERVER
+  NS_DECL_NSISTREAMLISTENER
+  NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
+
+  nsIncrementalStreamLoader();
+
+  static nsresult
+  Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+protected:
+  ~nsIncrementalStreamLoader();
+
+  static NS_METHOD WriteSegmentFun(nsIInputStream *, void *, const char *,
+                                   uint32_t, uint32_t, uint32_t *);
+
+  // Utility method to free mData, if present, and update other state to
+  // reflect that no data has been allocated.
+  void ReleaseData();
+
+  nsCOMPtr<nsIIncrementalStreamLoaderObserver> mObserver;
+  nsCOMPtr<nsISupports>             mContext;  // the observer's context
+  nsCOMPtr<nsIRequest>              mRequest;
+
+  // Buffer to accumulate incoming data. We preallocate if contentSize is
+  // available.
+  mozilla::Vector<uint8_t, 0> mData;
+};
+
+#endif // nsIncrementalStreamLoader_h__
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -40,16 +40,17 @@
 #include "nsIRedirectChannelRegistrar.h"
 #include "nsIRequestObserverProxy.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISimpleStreamListener.h"
 #include "nsISocketProvider.h"
 #include "nsISocketProviderService.h"
 #include "nsIStandardURL.h"
 #include "nsIStreamLoader.h"
+#include "nsIIncrementalStreamLoader.h"
 #include "nsIStreamTransportService.h"
 #include "nsStringStream.h"
 #include "nsISyncStreamListener.h"
 #include "nsITransport.h"
 #include "nsIUnicharStreamLoader.h"
 #include "nsIURIWithPrincipal.h"
 #include "nsIURLParser.h"
 #include "nsIUUIDGenerator.h"
@@ -576,16 +577,33 @@ NS_NewDownloader(nsIStreamListener   **r
         if (NS_SUCCEEDED(rv)) {
             downloader.forget(result);
         }
     }
     return rv;
 }
 
 nsresult
+NS_NewIncrementalStreamLoader(nsIIncrementalStreamLoader        **result,
+                              nsIIncrementalStreamLoaderObserver *observer)
+{
+    nsresult rv;
+    nsCOMPtr<nsIIncrementalStreamLoader> loader =
+        do_CreateInstance(NS_INCREMENTALSTREAMLOADER_CONTRACTID, &rv);
+    if (NS_SUCCEEDED(rv)) {
+        rv = loader->Init(observer);
+        if (NS_SUCCEEDED(rv)) {
+            *result = nullptr;
+            loader.swap(*result);
+        }
+    }
+    return rv;
+}
+
+nsresult
 NS_NewStreamLoaderInternal(nsIStreamLoader        **outStream,
                            nsIURI                  *aUri,
                            nsIStreamLoaderObserver *aObserver,
                            nsINode                 *aLoadingNode,
                            nsIPrincipal            *aLoadingPrincipal,
                            nsSecurityFlags          aSecurityFlags,
                            nsContentPolicyType      aContentPolicyType,
                            nsILoadGroup            *aLoadGroup /* = nullptr */,
--- a/netwerk/base/nsNetUtil.h
+++ b/netwerk/base/nsNetUtil.h
@@ -37,16 +37,18 @@ class nsINetworkInterface;
 class nsIOutputStream;
 class nsIParentChannel;
 class nsIPersistentProperties;
 class nsIProxyInfo;
 class nsIRequestObserver;
 class nsIStreamListener;
 class nsIStreamLoader;
 class nsIStreamLoaderObserver;
+class nsIIncrementalStreamLoader;
+class nsIIncrementalStreamLoaderObserver;
 class nsIUnicharStreamLoader;
 class nsIUnicharStreamLoaderObserver;
 
 namespace mozilla { class NeckoOriginAttributes; }
 
 template <class> class nsCOMPtr;
 template <typename> struct already_AddRefed;
 
@@ -364,16 +366,19 @@ NS_LoadGroupMatchesPrincipal(nsILoadGrou
 nsresult NS_NewDownloader(nsIStreamListener   **result,
                           nsIDownloadObserver  *observer,
                           nsIFile              *downloadLocation = nullptr);
 
 nsresult NS_NewStreamLoader(nsIStreamLoader        **result,
                             nsIStreamLoaderObserver *observer,
                             nsIRequestObserver      *requestObserver = nullptr);
 
+nsresult NS_NewIncrementalStreamLoader(nsIIncrementalStreamLoader        **result,
+                                       nsIIncrementalStreamLoaderObserver *observer);
+
 nsresult NS_NewStreamLoaderInternal(nsIStreamLoader        **outStream,
                                     nsIURI                  *aUri,
                                     nsIStreamLoaderObserver *aObserver,
                                     nsINode                 *aLoadingNode,
                                     nsIPrincipal            *aLoadingPrincipal,
                                     nsSecurityFlags          aSecurityFlags,
                                     nsContentPolicyType      aContentPolicyType,
                                     nsILoadGroup            *aLoadGroup = nullptr,
--- a/netwerk/base/nsNetUtil.inl
+++ b/netwerk/base/nsNetUtil.inl
@@ -18,16 +18,17 @@
 #include "nsIHttpChannel.h"
 #include "nsIInputStreamChannel.h"
 #include "nsIIOService.h"
 #include "nsINestedURI.h"
 #include "nsINode.h"
 #include "nsIProtocolHandler.h"
 #include "nsIStandardURL.h"
 #include "nsIStreamLoader.h"
+#include "nsIIncrementalStreamLoader.h"
 #include "nsIURI.h"
 #include "nsIURIWithPrincipal.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsNetCID.h"
 #include "nsStringStream.h"
 
 #ifdef MOZILLA_INTERNAL_API
 // Don't allow functions that end up in nsNetUtil.cpp to be inlined out.
--- a/netwerk/build/nsNetCID.h
+++ b/netwerk/build/nsNetCID.h
@@ -221,16 +221,28 @@
 #define NS_STREAMLOADER_CID \
 { /* 5BA6D920-D4E9-11d3-A1A5-0050041CAF44 */         \
     0x5ba6d920,                                      \
     0xd4e9,                                          \
     0x11d3,                                          \
     { 0xa1, 0xa5, 0x0, 0x50, 0x4, 0x1c, 0xaf, 0x44 } \
 }
 
+// component implementing nsIStreamLoader.
+#define NS_INCREMENTALSTREAMLOADER_CONTRACTID \
+    "@mozilla.org/network/incremental-stream-loader;1"
+#define NS_INCREMENTALSTREAMLOADER_CID \
+{ /* 5d6352a3-b9c3-4fa3-87aa-b2a3c6e5a501 */         \
+    0x5d6352a3,                                      \
+    0xb9c3,                                          \
+    0x4fa3,                                          \
+    {0x87, 0xaa, 0xb2, 0xa3, 0xc6, 0xe5, 0xa5, 0x01} \
+}
+
+
 // component implementing nsIUnicharStreamLoader.
 #define NS_UNICHARSTREAMLOADER_CONTRACTID \
     "@mozilla.org/network/unichar-stream-loader;1"
 #define NS_UNICHARSTREAMLOADER_CID \
 { /* 9445791f-fa4c-4669-b174-df5032bb67b3 */           \
     0x9445791f,                                        \
     0xfa4c,                                            \
     0x4669,                                            \
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -16,16 +16,17 @@
 #include "nsIServiceManager.h"
 #include "nsICategoryManager.h"
 #include "nsSocketProviderService.h"
 #include "nscore.h"
 #include "nsSimpleURI.h"
 #include "nsSimpleNestedURI.h"
 #include "nsLoadGroup.h"
 #include "nsStreamLoader.h"
+#include "nsIncrementalStreamLoader.h"
 #include "nsUnicharStreamLoader.h"
 #include "nsFileStreams.h"
 #include "nsBufferedStreams.h"
 #include "nsMIMEInputStream.h"
 #include "nsSOCKSSocketProvider.h"
 #include "nsCacheService.h"
 #include "nsDiskCacheDeviceSQL.h"
 #include "nsApplicationCache.h"
@@ -702,16 +703,17 @@ NS_DEFINE_NAMED_CID(NS_DNSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_IDNSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_EFFECTIVETLDSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_SIMPLEURI_CID);
 NS_DEFINE_NAMED_CID(NS_SIMPLENESTEDURI_CID);
 NS_DEFINE_NAMED_CID(NS_ASYNCSTREAMCOPIER_CID);
 NS_DEFINE_NAMED_CID(NS_INPUTSTREAMPUMP_CID);
 NS_DEFINE_NAMED_CID(NS_INPUTSTREAMCHANNEL_CID);
 NS_DEFINE_NAMED_CID(NS_STREAMLOADER_CID);
+NS_DEFINE_NAMED_CID(NS_INCREMENTALSTREAMLOADER_CID);
 NS_DEFINE_NAMED_CID(NS_UNICHARSTREAMLOADER_CID);
 NS_DEFINE_NAMED_CID(NS_DOWNLOADER_CID);
 NS_DEFINE_NAMED_CID(NS_BACKGROUNDFILESAVEROUTPUTSTREAM_CID);
 NS_DEFINE_NAMED_CID(NS_BACKGROUNDFILESAVERSTREAMLISTENER_CID);
 NS_DEFINE_NAMED_CID(NS_SYNCSTREAMLISTENER_CID);
 NS_DEFINE_NAMED_CID(NS_REQUESTOBSERVERPROXY_CID);
 NS_DEFINE_NAMED_CID(NS_SIMPLESTREAMLISTENER_CID);
 NS_DEFINE_NAMED_CID(NS_STREAMLISTENERTEE_CID);
@@ -849,16 +851,17 @@ static const mozilla::Module::CIDEntry k
     { &kNS_IDNSERVICE_CID, false, nullptr, nsIDNServiceConstructor },
     { &kNS_EFFECTIVETLDSERVICE_CID, false, nullptr, nsEffectiveTLDServiceConstructor },
     { &kNS_SIMPLEURI_CID, false, nullptr, nsSimpleURIConstructor },
     { &kNS_SIMPLENESTEDURI_CID, false, nullptr, nsSimpleNestedURIConstructor },
     { &kNS_ASYNCSTREAMCOPIER_CID, false, nullptr, nsAsyncStreamCopierConstructor },
     { &kNS_INPUTSTREAMPUMP_CID, false, nullptr, nsInputStreamPumpConstructor },
     { &kNS_INPUTSTREAMCHANNEL_CID, false, nullptr, nsInputStreamChannelConstructor },
     { &kNS_STREAMLOADER_CID, false, nullptr, nsStreamLoader::Create },
+    { &kNS_INCREMENTALSTREAMLOADER_CID, false, nullptr, nsIncrementalStreamLoader::Create },
     { &kNS_UNICHARSTREAMLOADER_CID, false, nullptr, nsUnicharStreamLoader::Create },
     { &kNS_DOWNLOADER_CID, false, nullptr, nsDownloaderConstructor },
     { &kNS_BACKGROUNDFILESAVEROUTPUTSTREAM_CID, false, nullptr,
       mozilla::net::BackgroundFileSaverOutputStreamConstructor },
     { &kNS_BACKGROUNDFILESAVERSTREAMLISTENER_CID, false, nullptr,
       mozilla::net::BackgroundFileSaverStreamListenerConstructor },
     { &kNS_SYNCSTREAMLISTENER_CID, false, nullptr, nsSyncStreamListenerConstructor },
     { &kNS_REQUESTOBSERVERPROXY_CID, false, nullptr, nsRequestObserverProxyConstructor },
@@ -1002,16 +1005,17 @@ static const mozilla::Module::ContractID
     { NS_DNSSERVICE_CONTRACTID, &kNS_DNSSERVICE_CID },
     { NS_IDNSERVICE_CONTRACTID, &kNS_IDNSERVICE_CID },
     { NS_EFFECTIVETLDSERVICE_CONTRACTID, &kNS_EFFECTIVETLDSERVICE_CID },
     { NS_SIMPLEURI_CONTRACTID, &kNS_SIMPLEURI_CID },
     { NS_ASYNCSTREAMCOPIER_CONTRACTID, &kNS_ASYNCSTREAMCOPIER_CID },
     { NS_INPUTSTREAMPUMP_CONTRACTID, &kNS_INPUTSTREAMPUMP_CID },
     { NS_INPUTSTREAMCHANNEL_CONTRACTID, &kNS_INPUTSTREAMCHANNEL_CID },
     { NS_STREAMLOADER_CONTRACTID, &kNS_STREAMLOADER_CID },
+    { NS_INCREMENTALSTREAMLOADER_CONTRACTID, &kNS_INCREMENTALSTREAMLOADER_CID },
     { NS_UNICHARSTREAMLOADER_CONTRACTID, &kNS_UNICHARSTREAMLOADER_CID },
     { NS_DOWNLOADER_CONTRACTID, &kNS_DOWNLOADER_CID },
     { NS_BACKGROUNDFILESAVEROUTPUTSTREAM_CONTRACTID, &kNS_BACKGROUNDFILESAVEROUTPUTSTREAM_CID },
     { NS_BACKGROUNDFILESAVERSTREAMLISTENER_CONTRACTID, &kNS_BACKGROUNDFILESAVERSTREAMLISTENER_CID },
     { NS_SYNCSTREAMLISTENER_CONTRACTID, &kNS_SYNCSTREAMLISTENER_CID },
     { NS_REQUESTOBSERVERPROXY_CONTRACTID, &kNS_REQUESTOBSERVERPROXY_CID },
     { NS_SIMPLESTREAMLISTENER_CONTRACTID, &kNS_SIMPLESTREAMLISTENER_CID },
     { NS_STREAMLISTENERTEE_CONTRACTID, &kNS_STREAMLISTENERTEE_CID },