bug 1116867 - make nsIProgressEventSink and nsITransportEventSink safely scriptable r=mayhemer r=bz
authorPatrick McManus <mcmanus@ducksong.com>
Thu, 08 Jan 2015 14:48:52 -0500
changeset 242232 91e1a0afee555a045c8e283934456556b1d4a43d
parent 242231 c1fac42ad172b1e88fe26f14ce8f6412df1469ba
child 242233 c2c0d8f26b9719e5f12b6977773df58c05dcb4ad
push id7677
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 18:11:24 +0000
treeherdermozilla-aurora@f531d838c055 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer, bz
bugs1116867
milestone38.0a1
bug 1116867 - make nsIProgressEventSink and nsITransportEventSink safely scriptable r=mayhemer r=bz These scriptable interfaces use uint_64 arguments with sentinel values of UINT64_MAX. However, UINT64_MAX exceeds MAX_SAFE_INTEGER and cannot be gatewayed to/from javascript - so they cannot be used correctly. Change them to use signed 64 bit numbers and -1 as the sentinnel. C++ implementations ought to be enough to audit as the special value could never be used correctly in JS anyhow - also audited OnProgressChange() uses for downstream use of this data. --- dom/base/nsXMLHttpRequest.cpp | 19 +++++++---- dom/base/nsXMLHttpRequest.h | 10 +++--- dom/plugins/base/nsPluginStreamListenerPeer.cpp | 4 +-- .../webbrowserpersist/nsWebBrowserPersist.cpp | 14 ++++---- image/src/imgLoader.cpp | 4 +-- modules/libjar/nsJARChannel.cpp | 3 +- netwerk/base/public/nsIProgressEventSink.idl | 8 ++--- netwerk/base/public/nsITransport.idl | 8 ++--- netwerk/base/public/nsNetUtil.h | 24 ++++++++++++++ netwerk/base/src/Dashboard.cpp | 2 +- netwerk/base/src/nsBaseChannel.cpp | 12 +++---- netwerk/base/src/nsIncrementalDownload.cpp | 4 +-- netwerk/base/src/nsSocketTransport2.cpp | 5 +-- netwerk/base/src/nsStreamTransportService.cpp | 38 +++++++++++++--------- netwerk/base/src/nsTransportUtils.cpp | 12 +++---- netwerk/protocol/file/nsFileChannel.cpp | 8 +++-- netwerk/protocol/ftp/nsFtpConnectionThread.cpp | 4 +-- netwerk/protocol/http/Http2Push.cpp | 2 +- netwerk/protocol/http/Http2Session.cpp | 2 +- netwerk/protocol/http/HttpChannelChild.cpp | 31 +++++++++--------- netwerk/protocol/http/HttpChannelChild.h | 6 ++-- netwerk/protocol/http/HttpChannelParent.cpp | 4 +-- netwerk/protocol/http/HttpChannelParent.h | 4 +-- netwerk/protocol/http/NullHttpTransaction.cpp | 2 +- netwerk/protocol/http/PHttpChannel.ipdl | 2 +- netwerk/protocol/http/SpdyPush31.cpp | 2 +- netwerk/protocol/http/SpdySession31.cpp | 2 +- netwerk/protocol/http/TunnelUtils.cpp | 2 +- netwerk/protocol/http/nsAHttpTransaction.h | 4 +-- netwerk/protocol/http/nsHttpChannel.cpp | 30 +++++++++++------ netwerk/protocol/http/nsHttpConnection.cpp | 4 +-- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 4 +-- netwerk/protocol/http/nsHttpPipeline.cpp | 4 +-- netwerk/protocol/http/nsHttpPipeline.h | 6 ++-- netwerk/protocol/http/nsHttpResponseHead.cpp | 2 +- netwerk/protocol/http/nsHttpResponseHead.h | 2 +- netwerk/protocol/http/nsHttpTransaction.cpp | 32 +++++++++--------- netwerk/protocol/http/nsHttpTransaction.h | 2 +- netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp | 2 +- netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp | 3 +- netwerk/test/TestIncrementalDownload.cpp | 7 ++-- uriloader/base/nsDocLoader.cpp | 14 ++++---- 42 files changed, 203 insertions(+), 151 deletions(-)
dom/base/nsXMLHttpRequest.cpp
dom/base/nsXMLHttpRequest.h
dom/plugins/base/nsPluginStreamListenerPeer.cpp
embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
image/src/imgLoader.cpp
modules/libjar/nsJARChannel.cpp
netwerk/base/public/nsIProgressEventSink.idl
netwerk/base/public/nsITransport.idl
netwerk/base/public/nsNetUtil.h
netwerk/base/src/Dashboard.cpp
netwerk/base/src/nsBaseChannel.cpp
netwerk/base/src/nsIncrementalDownload.cpp
netwerk/base/src/nsSocketTransport2.cpp
netwerk/base/src/nsStreamTransportService.cpp
netwerk/base/src/nsTransportUtils.cpp
netwerk/protocol/file/nsFileChannel.cpp
netwerk/protocol/ftp/nsFtpConnectionThread.cpp
netwerk/protocol/http/Http2Push.cpp
netwerk/protocol/http/Http2Session.cpp
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/HttpChannelParent.h
netwerk/protocol/http/NullHttpTransaction.cpp
netwerk/protocol/http/PHttpChannel.ipdl
netwerk/protocol/http/SpdyPush31.cpp
netwerk/protocol/http/SpdySession31.cpp
netwerk/protocol/http/TunnelUtils.cpp
netwerk/protocol/http/nsAHttpTransaction.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpConnection.cpp
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/protocol/http/nsHttpPipeline.cpp
netwerk/protocol/http/nsHttpPipeline.h
netwerk/protocol/http/nsHttpResponseHead.cpp
netwerk/protocol/http/nsHttpResponseHead.h
netwerk/protocol/http/nsHttpTransaction.cpp
netwerk/protocol/http/nsHttpTransaction.h
netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
netwerk/test/TestIncrementalDownload.cpp
uriloader/base/nsDocLoader.cpp
--- a/dom/base/nsXMLHttpRequest.cpp
+++ b/dom/base/nsXMLHttpRequest.cpp
@@ -1472,17 +1472,17 @@ nsXMLHttpRequest::CreateReadystatechange
 
   return NS_OK;
 }
 
 void
 nsXMLHttpRequest::DispatchProgressEvent(DOMEventTargetHelper* aTarget,
                                         const nsAString& aType,
                                         bool aLengthComputable,
-                                        uint64_t aLoaded, uint64_t aTotal)
+                                        int64_t aLoaded, int64_t aTotal)
 {
   NS_ASSERTION(aTarget, "null target");
   NS_ASSERTION(!aType.IsEmpty(), "missing event type");
 
   if (NS_FAILED(CheckInnerWindowCorrectness()) ||
       (!AllowUploadProgress() && aTarget == mUpload)) {
     return;
   }
@@ -1492,17 +1492,17 @@ nsXMLHttpRequest::DispatchProgressEvent(
                          aType.EqualsLiteral(TIMEOUT_STR) ||
                          aType.EqualsLiteral(ABORT_STR);
 
   ProgressEventInit init;
   init.mBubbles = false;
   init.mCancelable = false;
   init.mLengthComputable = aLengthComputable;
   init.mLoaded = aLoaded;
-  init.mTotal = (aTotal == UINT64_MAX) ? 0 : aTotal;
+  init.mTotal = (aTotal == -1) ? 0 : aTotal;
 
   nsRefPtr<ProgressEvent> event =
     ProgressEvent::Constructor(aTarget, aType, init);
   event->SetTrusted(true);
 
   aTarget->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
 
   if (dispatchLoadend) {
@@ -2776,20 +2776,25 @@ nsXMLHttpRequest::Send(nsIVariant* aVari
   if ((aVariant || !aBody.IsNull()) && httpChannel &&
       !method.LowerCaseEqualsLiteral("get") &&
       !method.LowerCaseEqualsLiteral("head")) {
 
     nsAutoCString charset;
     nsAutoCString defaultContentType;
     nsCOMPtr<nsIInputStream> postDataStream;
 
+    uint64_t size_u64;
     rv = GetRequestBody(aVariant, aBody, getter_AddRefs(postDataStream),
-                        &mUploadTotal, defaultContentType, charset);
+                        &size_u64, defaultContentType, charset);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    // make sure it fits within js MAX_SAFE_INTEGER
+    mUploadTotal =
+      net::InScriptableRange(size_u64) ? static_cast<int64_t>(size_u64) : -1;
+
     if (postDataStream) {
       // If no content type header was set by the client, we set it to
       // application/xml.
       nsAutoCString contentType;
       if (NS_FAILED(httpChannel->
                       GetRequestHeader(NS_LITERAL_CSTRING("Content-Type"),
                                        contentType)) ||
           contentType.IsEmpty()) {
@@ -3583,28 +3588,28 @@ nsXMLHttpRequest::MaybeDispatchProgressE
       mArrayBufferBuilder.reset();
     }
   }
 
   mProgressSinceLastProgressEvent = false;
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::OnProgress(nsIRequest *aRequest, nsISupports *aContext, uint64_t aProgress, uint64_t aProgressMax)
+nsXMLHttpRequest::OnProgress(nsIRequest *aRequest, nsISupports *aContext, int64_t aProgress, int64_t aProgressMax)
 {
   // We're uploading if our state is XML_HTTP_REQUEST_OPENED or
   // XML_HTTP_REQUEST_SENT
   bool upload = !!((XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT) & mState);
   // When uploading, OnProgress reports also headers in aProgress and aProgressMax.
   // So, try to remove the headers, if possible.
-  bool lengthComputable = (aProgressMax != UINT64_MAX);
+  bool lengthComputable = (aProgressMax != -1);
   if (upload) {
-    uint64_t loaded = aProgress;
+    int64_t loaded = aProgress;
     if (lengthComputable) {
-      uint64_t headerSize = aProgressMax - mUploadTotal;
+      int64_t headerSize = aProgressMax - mUploadTotal;
       loaded -= headerSize;
     }
     mUploadLengthComputable = lengthComputable;
     mUploadTransferred = loaded;
     mProgressSinceLastProgressEvent = true;
 
     MaybeDispatchProgressEvents(false);
   } else {
--- a/dom/base/nsXMLHttpRequest.h
+++ b/dom/base/nsXMLHttpRequest.h
@@ -544,17 +544,17 @@ public:
                     JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);
 
   // This creates a trusted readystatechange event, which is not cancelable and
   // doesn't bubble.
   nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent);
   void DispatchProgressEvent(mozilla::DOMEventTargetHelper* aTarget,
                              const nsAString& aType,
                              bool aLengthComputable,
-                             uint64_t aLoaded, uint64_t aTotal);
+                             int64_t aLoaded, int64_t aTotal);
 
   // Dispatch the "progress" event on the XHR or XHR.upload object if we've
   // received data since the last "progress" event. Also dispatches
   // "uploadprogress" as needed.
   void MaybeDispatchProgressEvents(bool aFinalProgress);
 
   // This is called by the factory constructor.
   nsresult Init();
@@ -719,18 +719,18 @@ protected:
   nsIRequestObserver* mRequestObserver;
 
   nsCOMPtr<nsIURI> mBaseURI;
   nsCOMPtr<nsILoadGroup> mLoadGroup;
 
   uint32_t mState;
 
   nsRefPtr<nsXMLHttpRequestUpload> mUpload;
-  uint64_t mUploadTransferred;
-  uint64_t mUploadTotal;
+  int64_t mUploadTransferred;
+  int64_t mUploadTotal;
   bool mUploadLengthComputable;
   bool mUploadComplete;
   bool mProgressSinceLastProgressEvent;
 
   // Timeout support
   PRTime mRequestSentTime;
   uint32_t mTimeoutMilliseconds;
   nsCOMPtr<nsITimer> mTimeoutTimer;
@@ -739,28 +739,28 @@ protected:
 
   bool mErrorLoad;
   bool mWaitingForOnStopRequest;
   bool mProgressTimerIsActive;
   bool mIsHtml;
   bool mWarnAboutMultipartHtml;
   bool mWarnAboutSyncHtml;
   bool mLoadLengthComputable;
-  uint64_t mLoadTotal; // 0 if not known.
+  int64_t mLoadTotal; // 0 if not known.
   // Amount of script-exposed (i.e. after undoing gzip compresion) data
   // received.
   uint64_t mDataAvailable;
   // Number of HTTP message body bytes received so far. This quantity is
   // in the same units as Content-Length and mLoadTotal, and hence counts
   // compressed bytes when the channel has gzip Content-Encoding. If the
   // channel does not have Content-Encoding, this will be the same as
   // mDataReceived except between the OnProgress that changes mLoadTransferred
   // and the corresponding OnDataAvailable (which changes mDataReceived).
   // Ordering of OnProgress and OnDataAvailable is undefined.
-  uint64_t mLoadTransferred;
+  int64_t mLoadTransferred;
   nsCOMPtr<nsITimer> mProgressNotifier;
   void HandleProgressTimerCallback();
 
   bool mIsSystem;
   bool mIsAnon;
 
   /**
    * Close the XMLHttpRequest's channels and dispatch appropriate progress
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -567,18 +567,18 @@ nsPluginStreamListenerPeer::OnStartReque
     return rv;
   }
 
   return rv;
 }
 
 NS_IMETHODIMP nsPluginStreamListenerPeer::OnProgress(nsIRequest *request,
                                                      nsISupports* aContext,
-                                                     uint64_t aProgress,
-                                                     uint64_t aProgressMax)
+                                                     int64_t aProgress,
+                                                     int64_t aProgressMax)
 {
   nsresult rv = NS_OK;
   return rv;
 }
 
 NS_IMETHODIMP nsPluginStreamListenerPeer::OnStatus(nsIRequest *request,
                                                    nsISupports* aContext,
                                                    nsresult aStatus,
--- a/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -905,41 +905,41 @@ nsWebBrowserPersist::OnDataAvailable(
 }
 
 
 //*****************************************************************************
 // nsWebBrowserPersist::nsIProgressEventSink
 //*****************************************************************************
 
 /* void onProgress (in nsIRequest request, in nsISupports ctxt,
-    in unsigned long long aProgress, in unsigned long long aProgressMax); */
+    in long long aProgress, in long long aProgressMax); */
 NS_IMETHODIMP nsWebBrowserPersist::OnProgress(
-    nsIRequest *request, nsISupports *ctxt, uint64_t aProgress,
-    uint64_t aProgressMax)
+    nsIRequest *request, nsISupports *ctxt, int64_t aProgress,
+    int64_t aProgressMax)
 {
     if (!mProgressListener)
     {
         return NS_OK;
     }
 
     // Store the progress of this request
     nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(request);
     OutputData *data = mOutputMap.Get(keyPtr);
     if (data)
     {
-        data->mSelfProgress = int64_t(aProgress);
-        data->mSelfProgressMax = int64_t(aProgressMax);
+        data->mSelfProgress = aProgress;
+        data->mSelfProgressMax = aProgressMax;
     }
     else
     {
         UploadData *upData = mUploadList.Get(keyPtr);
         if (upData)
         {
-            upData->mSelfProgress = int64_t(aProgress);
-            upData->mSelfProgressMax = int64_t(aProgressMax);
+            upData->mSelfProgress = aProgress;
+            upData->mSelfProgressMax = aProgressMax;
         }
     }
 
     // Notify listener of total progress
     CalcTotalProgress();
     if (mProgressListener2)
     {
       mProgressListener2->OnProgressChange64(nullptr, request, aProgress,
--- a/image/src/imgLoader.cpp
+++ b/image/src/imgLoader.cpp
@@ -455,18 +455,18 @@ NS_IMPL_ISUPPORTS(imgMemoryReporter, nsI
 NS_IMPL_ISUPPORTS(nsProgressNotificationProxy,
                   nsIProgressEventSink,
                   nsIChannelEventSink,
                   nsIInterfaceRequestor)
 
 NS_IMETHODIMP
 nsProgressNotificationProxy::OnProgress(nsIRequest* request,
                                         nsISupports* ctxt,
-                                        uint64_t progress,
-                                        uint64_t progressMax)
+                                        int64_t progress,
+                                        int64_t progressMax)
 {
   nsCOMPtr<nsILoadGroup> loadGroup;
   request->GetLoadGroup(getter_AddRefs(loadGroup));
 
   nsCOMPtr<nsIProgressEventSink> target;
   NS_QueryNotificationCallbacks(mOriginalCallbacks,
                                 loadGroup,
                                 NS_GET_IID(nsIProgressEventSink),
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -480,18 +480,17 @@ nsJARChannel::NotifyError(nsresult aErro
 }
 
 void
 nsJARChannel::FireOnProgress(uint64_t aProgress)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mProgressSink);
 
-  mProgressSink->OnProgress(this, nullptr, aProgress,
-                            uint64_t(mContentLength));
+  mProgressSink->OnProgress(this, nullptr, aProgress, mContentLength);
 }
 
 nsresult
 nsJARChannel::SetRemoteNSPRFileDesc(PRFileDesc *fd)
 {
     PROsfd osfd = dup(PR_FileDesc2NativeHandle(fd));
     if (osfd == -1) {
         return NS_ERROR_FAILURE;
--- a/netwerk/base/public/nsIProgressEventSink.idl
+++ b/netwerk/base/public/nsIProgressEventSink.idl
@@ -22,39 +22,39 @@ interface nsIRequest;
  * The channel will begin passing notifications to the progress event sink
  * after its asyncOpen method has been called.  Notifications will cease once
  * the channel calls its listener's onStopRequest method or once the channel
  * is canceled (via nsIRequest::cancel).
  *
  * NOTE: This interface is actually not specific to channels and may be used
  * with other implementations of nsIRequest.
  */
-[scriptable, uuid(D974C99E-4148-4df9-8D98-DE834A2F6462)]
+[scriptable, uuid(87d55fba-cb7e-4f38-84c1-5c6c2b2a55e9)]
 interface nsIProgressEventSink : nsISupports
 {
     /**
      * Called to notify the event sink that progress has occurred for the
      * given request.
      *
      * @param aRequest
      *        the request being observed (may QI to nsIChannel).
      * @param aContext
      *        if aRequest is a channel, then this parameter is the listener
      *        context passed to nsIChannel::asyncOpen.
      * @param aProgress
      *        numeric value in the range 0 to aProgressMax indicating the
      *        number of bytes transfered thus far.
      * @param aProgressMax
      *        numeric value indicating maximum number of bytes that will be
-     *        transfered (or 0xFFFFFFFFFFFFFFFF if total is unknown).
+     *        transfered (or -1 if total is unknown).
      */
     void onProgress(in nsIRequest aRequest,
                     in nsISupports aContext,
-                    in unsigned long long aProgress,
-                    in unsigned long long aProgressMax);
+                    in long long aProgress,
+                    in long long aProgressMax);
 
     /**
      * Called to notify the event sink with a status message for the given
      * request.
      *
      * @param aRequest
      *        the request being observed (may QI to nsIChannel).
      * @param aContext
--- a/netwerk/base/public/nsITransport.idl
+++ b/netwerk/base/public/nsITransport.idl
@@ -19,17 +19,17 @@ interface nsIEventTarget;
  * inherent data transfer implied by this interface (i.e., data is being
  * transfered in some fashion via the streams exposed by this interface).
  *
  * A transport can have an event sink associated with it.  The event sink 
  * receives transport-specific events as the transfer is occuring.  For a
  * socket transport, these events can include status about the connection.
  * See nsISocketTransport for more info about socket transport specifics.
  */
-[scriptable, uuid(d8786c64-eb49-4a0b-b42c-0936a745fbe8)]
+[scriptable, uuid(2a8c6334-a5e6-4ec3-9865-1256541446fb)]
 interface nsITransport : nsISupports
 {
     /**
      * Open flags.
      */
     const unsigned long OPEN_BLOCKING   = 1<<0;
     const unsigned long OPEN_UNBUFFERED = 1<<1;
 
@@ -149,15 +149,15 @@ interface nsITransportEventSink : nsISup
      *        the transport status (resolvable to a string using
      *        nsIErrorService). See nsISocketTransport for socket specific
      *        status codes and more comments.
      * @param aProgress
      *        the amount of data either read or written depending on the value
      *        of the status code.  this value is relative to aProgressMax.
      * @param aProgressMax
      *        the maximum amount of data that will be read or written.  if
-     *        unknown, 0xFFFFFFFF will be passed.
+     *        unknown, -1 will be passed.
      */
     void onTransportStatus(in nsITransport aTransport,
                            in nsresult aStatus,
-                           in unsigned long long aProgress,
-                           in unsigned long long aProgressMax);
+                           in long long aProgress,
+                           in long long aProgressMax);
 };
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -2764,9 +2764,33 @@ NS_IsSrcdocChannel(nsIChannel *aChannel)
 bool NS_IsReasonableHTTPHeaderValue(const nsACString& aValue);
 
 /**
  * Return true if the given string is a valid HTTP token per RFC 2616 section
  * 2.2.
  */
 bool NS_IsValidHTTPToken(const nsACString& aToken);
 
+namespace mozilla {
+namespace net {
+
+const static uint64_t kJS_MAX_SAFE_UINTEGER = +9007199254740991ULL;
+const static  int64_t kJS_MIN_SAFE_INTEGER  = -9007199254740991LL;
+const static  int64_t kJS_MAX_SAFE_INTEGER  = +9007199254740991LL;
+
+// Make sure a 64bit value can be captured by JS MAX_SAFE_INTEGER
+inline bool
+InScriptableRange(int64_t val)
+{
+    return (val <= kJS_MAX_SAFE_INTEGER) && (val >= kJS_MIN_SAFE_INTEGER);
+}
+
+// Make sure a 64bit value can be captured by JS MAX_SAFE_INTEGER
+inline bool
+InScriptableRange(uint64_t val)
+{
+    return val <= kJS_MAX_SAFE_UINTEGER;
+}
+
+} // namespace mozilla
+} // namespace mozilla::net
+
 #endif // !nsNetUtil_h__
--- a/netwerk/base/src/Dashboard.cpp
+++ b/netwerk/base/src/Dashboard.cpp
@@ -163,17 +163,17 @@ public:
 
     nsString mStatus;
 };
 
 NS_IMPL_ISUPPORTS(ConnectionData, nsITransportEventSink, nsITimerCallback)
 
 NS_IMETHODIMP
 ConnectionData::OnTransportStatus(nsITransport *aTransport, nsresult aStatus,
-                                  uint64_t aProgress, uint64_t aProgressMax)
+                                  int64_t aProgress, int64_t aProgressMax)
 {
     if (aStatus == NS_NET_STATUS_CONNECTED_TO) {
         StopTimer();
     }
 
     GetErrorString(aStatus, mStatus);
     nsCOMPtr<nsIRunnable> event =
         NS_NewRunnableMethodWithArg<nsRefPtr<ConnectionData> >
--- a/netwerk/base/src/nsBaseChannel.cpp
+++ b/netwerk/base/src/nsBaseChannel.cpp
@@ -648,17 +648,17 @@ nsBaseChannel::AsyncOpen(nsIStreamListen
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsBaseChannel::nsITransportEventSink
 
 NS_IMETHODIMP
 nsBaseChannel::OnTransportStatus(nsITransport *transport, nsresult status,
-                                 uint64_t progress, uint64_t progressMax)
+                                 int64_t progress, int64_t progressMax)
 {
   // In some cases, we may wish to suppress transport-layer status events.
 
   if (!mPump || NS_FAILED(mStatus)) {
     return NS_OK;
   }
 
   SUSPEND_PUMP_FOR_SCOPE();
@@ -791,29 +791,29 @@ nsBaseChannel::OnDataAvailable(nsIReques
                                nsIInputStream *stream, uint64_t offset,
                                uint32_t count)
 {
   SUSPEND_PUMP_FOR_SCOPE();
 
   nsresult rv = mListener->OnDataAvailable(this, mListenerContext, stream,
                                            offset, count);
   if (mSynthProgressEvents && NS_SUCCEEDED(rv)) {
-    uint64_t prog = offset + count;
+    int64_t prog = offset + count;
     if (NS_IsMainThread()) {
       OnTransportStatus(nullptr, NS_NET_STATUS_READING, prog, mContentLength);
     } else {
       class OnTransportStatusAsyncEvent : public nsRunnable
       {
         nsRefPtr<nsBaseChannel> mChannel;
-        uint64_t mProgress;
-        uint64_t mContentLength;
+        int64_t mProgress;
+        int64_t mContentLength;
       public:
         OnTransportStatusAsyncEvent(nsBaseChannel* aChannel,
-                                    uint64_t aProgress,
-                                    uint64_t aContentLength)
+                                    int64_t aProgress,
+                                    int64_t aContentLength)
           : mChannel(aChannel),
             mProgress(aProgress),
             mContentLength(aContentLength)
         { }
 
         NS_IMETHOD Run() MOZ_OVERRIDE
         {
           return mChannel->OnTransportStatus(nullptr, NS_NET_STATUS_READING,
--- a/netwerk/base/src/nsIncrementalDownload.cpp
+++ b/netwerk/base/src/nsIncrementalDownload.cpp
@@ -200,18 +200,18 @@ nsIncrementalDownload::FlushChunk()
 
 void
 nsIncrementalDownload::UpdateProgress()
 {
   mLastProgressUpdate = PR_Now();
 
   if (mProgressSink)
     mProgressSink->OnProgress(this, mObserverContext,
-                              uint64_t(int64_t(mCurrentSize) + mChunkLen),
-                              uint64_t(int64_t(mTotalSize)));
+                              mCurrentSize + mChunkLen,
+                              mTotalSize);
 }
 
 nsresult
 nsIncrementalDownload::CallOnStartRequest()
 {
   if (!mObserver || mDidOnStartRequest)
     return NS_OK;
 
--- a/netwerk/base/src/nsSocketTransport2.cpp
+++ b/netwerk/base/src/nsSocketTransport2.cpp
@@ -978,18 +978,19 @@ nsSocketTransport::SendStatus(nsresult s
         case NS_NET_STATUS_RECEIVING_FROM:
             progress = mInput.ByteCount();
             break;
         default:
             progress = 0;
             break;
         }
     }
-    if (sink)
-        sink->OnTransportStatus(this, status, progress, UINT64_MAX);
+    if (sink) {
+        sink->OnTransportStatus(this, status, progress, -1);
+    }
 }
 
 nsresult
 nsSocketTransport::ResolveHost()
 {
     SOCKET_LOG(("nsSocketTransport::ResolveHost [this=%p %s:%d%s]\n",
                 this, SocketHost().get(), SocketPort(),
                 mConnectionFlags & nsSocketTransport::BYPASS_CACHE ?
--- a/netwerk/base/src/nsStreamTransportService.cpp
+++ b/netwerk/base/src/nsStreamTransportService.cpp
@@ -54,18 +54,18 @@ private:
     }
 
     nsCOMPtr<nsIAsyncInputStream>   mPipeIn;
 
     // while the copy is active, these members may only be accessed from the
     // nsIInputStream implementation.
     nsCOMPtr<nsITransportEventSink> mEventSink;
     nsCOMPtr<nsIInputStream>        mSource;
-    uint64_t                        mOffset;
-    uint64_t                        mLimit;
+    int64_t                         mOffset;
+    int64_t                         mLimit;
     bool                            mCloseWhenDone;
     bool                            mFirstTime;
 
     // this variable serves as a lock to prevent the state of the transport
     // from being modified once the copy is in progress.
     bool                            mInProgress;
 };
 
@@ -169,31 +169,34 @@ nsInputStreamTransport::Available(uint64
 
 NS_IMETHODIMP
 nsInputStreamTransport::Read(char *buf, uint32_t count, uint32_t *result)
 {
     if (mFirstTime) {
         mFirstTime = false;
         if (mOffset != 0) {
             // read from current position if offset equal to max
-            if (mOffset != UINT64_MAX) {
+            if (mOffset != -1) {
                 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mSource);
                 if (seekable)
                     seekable->Seek(nsISeekableStream::NS_SEEK_SET, mOffset);
             }
             // reset offset to zero so we can use it to enforce limit
             mOffset = 0;
         }
     }
 
     // limit amount read
-    uint64_t max = mLimit - mOffset;
-    if (max == 0) {
-        *result = 0;
-        return NS_OK;
+    uint64_t max = count;
+    if (mLimit != -1) {
+        max = mLimit - mOffset;
+        if (max == 0) {
+            *result = 0;
+            return NS_OK;
+        }
     }
 
     if (count > max)
         count = static_cast<uint32_t>(max);
 
     nsresult rv = mSource->Read(buf, count, result);
 
     if (NS_SUCCEEDED(rv)) {
@@ -231,18 +234,18 @@ class nsOutputStreamTransport : public n
                               , public nsIOutputStream
 {
 public:
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSITRANSPORT
     NS_DECL_NSIOUTPUTSTREAM
 
     nsOutputStreamTransport(nsIOutputStream *sink,
-                            uint64_t offset,
-                            uint64_t limit,
+                            int64_t offset,
+                            int64_t limit,
                             bool closeWhenDone)
         : mSink(sink)
         , mOffset(offset)
         , mLimit(limit)
         , mCloseWhenDone(closeWhenDone)
         , mFirstTime(true)
         , mInProgress(false)
     {
@@ -254,18 +257,18 @@ private:
     }
 
     nsCOMPtr<nsIAsyncOutputStream>  mPipeOut;
  
     // while the copy is active, these members may only be accessed from the
     // nsIOutputStream implementation.
     nsCOMPtr<nsITransportEventSink> mEventSink;
     nsCOMPtr<nsIOutputStream>       mSink;
-    uint64_t                        mOffset;
-    uint64_t                        mLimit;
+    int64_t                         mOffset;
+    int64_t                         mLimit;
     bool                            mCloseWhenDone;
     bool                            mFirstTime;
 
     // this variable serves as a lock to prevent the state of the transport
     // from being modified once the copy is in progress.
     bool                            mInProgress;
 };
 
@@ -369,31 +372,34 @@ nsOutputStreamTransport::Flush()
 
 NS_IMETHODIMP
 nsOutputStreamTransport::Write(const char *buf, uint32_t count, uint32_t *result)
 {
     if (mFirstTime) {
         mFirstTime = false;
         if (mOffset != 0) {
             // write to current position if offset equal to max
-            if (mOffset != UINT64_MAX) {
+            if (mOffset != -1) {
                 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mSink);
                 if (seekable)
                     seekable->Seek(nsISeekableStream::NS_SEEK_SET, mOffset);
             }
             // reset offset to zero so we can use it to enforce limit
             mOffset = 0;
         }
     }
 
     // limit amount written
-    uint64_t max = mLimit - mOffset;
-    if (max == 0) {
-        *result = 0;
-        return NS_OK;
+    uint64_t max = count;
+    if (mLimit != -1) {
+        max = mLimit - mOffset;
+        if (max == 0) {
+            *result = 0;
+            return NS_OK;
+        }
     }
 
     if (count > max)
         count = static_cast<uint32_t>(max);
 
     nsresult rv = mSink->Write(buf, count, result);
 
     if (NS_SUCCEEDED(rv)) {
--- a/netwerk/base/src/nsTransportUtils.cpp
+++ b/netwerk/base/src/nsTransportUtils.cpp
@@ -51,18 +51,18 @@ public:
 };
 
 class nsTransportStatusEvent : public nsRunnable
 {
 public:
     nsTransportStatusEvent(nsTransportEventSinkProxy *proxy,
                            nsITransport *transport,
                            nsresult status,
-                           uint64_t progress,
-                           uint64_t progressMax)
+                           int64_t progress,
+                           int64_t progressMax)
         : mProxy(proxy)
         , mTransport(transport)
         , mStatus(status)
         , mProgress(progress)
         , mProgressMax(progressMax)
     {}
 
     ~nsTransportStatusEvent() {}
@@ -82,27 +82,27 @@ public:
         return NS_OK;
     }
 
     nsRefPtr<nsTransportEventSinkProxy> mProxy;
 
     // parameters to OnTransportStatus
     nsCOMPtr<nsITransport> mTransport;
     nsresult               mStatus;
-    uint64_t               mProgress;
-    uint64_t               mProgressMax;
+    int64_t                mProgress;
+    int64_t                mProgressMax;
 };
 
 NS_IMPL_ISUPPORTS(nsTransportEventSinkProxy, nsITransportEventSink)
 
 NS_IMETHODIMP
 nsTransportEventSinkProxy::OnTransportStatus(nsITransport *transport,
                                              nsresult status,
-                                             uint64_t progress,
-                                             uint64_t progressMax)
+                                             int64_t progress,
+                                             int64_t progressMax)
 {
     nsresult rv = NS_OK;
     nsRefPtr<nsTransportStatusEvent> event;
     {
         MutexAutoLock lock(mLock);
 
         // try to coalesce events! ;-)
         if (mLastEvent && (mCoalesceAll || mLastEvent->mStatus == status)) {
--- a/netwerk/protocol/file/nsFileChannel.cpp
+++ b/netwerk/protocol/file/nsFileChannel.cpp
@@ -17,16 +17,19 @@
 #include "nsAutoPtr.h"
 #include "nsIContentPolicy.h"
 #include "nsContentUtils.h"
 
 #include "nsIFileURL.h"
 #include "nsIMIMEService.h"
 #include <algorithm>
 
+using namespace mozilla;
+using namespace mozilla::net;
+
 //-----------------------------------------------------------------------------
 
 class nsFileCopyEvent : public nsRunnable {
 public:
   nsFileCopyEvent(nsIOutputStream *dest, nsIInputStream *source, int64_t len)
     : mDest(dest)
     , mSource(source)
     , mLen(len)
@@ -448,18 +451,19 @@ nsFileChannel::SetUploadStream(nsIInputS
   if ((mUploadStream = stream)) {
     mUploadLength = contentLength;
     if (mUploadLength < 0) {
       // Make sure we know how much data we are uploading.
       uint64_t avail;
       nsresult rv = mUploadStream->Available(&avail);
       if (NS_FAILED(rv))
         return rv;
-      if (avail < INT64_MAX)
-        mUploadLength = avail;
+      // if this doesn't fit in the javascript MAX_SAFE_INTEGER
+      // pretend we don't know the size
+      mUploadLength = InScriptableRange(avail) ? avail : -1;
     }
   } else {
     mUploadLength = -1;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -75,17 +75,17 @@ NS_IMPL_ISUPPORTS_INHERITED(nsFtpState,
 nsFtpState::nsFtpState()
     : nsBaseContentStream(true)
     , mState(FTP_INIT)
     , mNextState(FTP_S_USER)
     , mKeepRunning(true)
     , mReceivedControlData(false)
     , mTryingCachedControl(false)
     , mRETRFailed(false)
-    , mFileSize(UINT64_MAX)
+    , mFileSize(kJS_MAX_SAFE_UINTEGER)
     , mServerType(FTP_GENERIC_TYPE)
     , mAction(GET)
     , mAnonymous(true)
     , mRetryPass(false)
     , mStorReplyReceived(false)
     , mInternalError(NS_OK)
     , mReconnectAndLoginAgain(false)
     , mCacheConnection(true)
@@ -2164,17 +2164,17 @@ nsFtpState::ConvertDirspecFromVMS(nsCStr
     }
     LOG(("FTP:(%x) ConvertDirspecFromVMS   to: \"%s\"\n", this, dirSpec.get()));
 }
 
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsFtpState::OnTransportStatus(nsITransport *transport, nsresult status,
-                              uint64_t progress, uint64_t progressMax)
+                              int64_t progress, int64_t progressMax)
 {
     // Mix signals from both the control and data connections.
 
     // Ignore data transfer events on the control connection.
     if (mControlConnection && transport == mControlConnection->Transport()) {
         switch (status) {
         case NS_NET_STATUS_RESOLVING_HOST:
         case NS_NET_STATUS_RESOLVED_HOST:
--- a/netwerk/protocol/http/Http2Push.cpp
+++ b/netwerk/protocol/http/Http2Push.cpp
@@ -276,17 +276,17 @@ Http2PushTransactionBuffer::Connection()
 void
 Http2PushTransactionBuffer::GetSecurityCallbacks(nsIInterfaceRequestor **outCB)
 {
   *outCB = nullptr;
 }
 
 void
 Http2PushTransactionBuffer::OnTransportStatus(nsITransport* transport,
-                                              nsresult status, uint64_t progress)
+                                              nsresult status, int64_t progress)
 {
 }
 
 nsHttpConnectionInfo *
 Http2PushTransactionBuffer::ConnectionInfo()
 {
   if (!mPushStream) {
     return nullptr;
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -2220,17 +2220,17 @@ Http2Session::RecvAltSvc(Http2Session *s
 
 //-----------------------------------------------------------------------------
 // nsAHttpTransaction. It is expected that nsHttpConnection is the caller
 // of these methods
 //-----------------------------------------------------------------------------
 
 void
 Http2Session::OnTransportStatus(nsITransport* aTransport,
-                                nsresult aStatus, uint64_t aProgress)
+                                nsresult aStatus, int64_t aProgress)
 {
   MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
 
   switch (aStatus) {
     // These should appear only once, deliver to the first
     // transaction on the session.
   case NS_NET_STATUS_RESOLVING_HOST:
   case NS_NET_STATUS_RESOLVED_HOST:
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -526,17 +526,17 @@ HttpChannelChild::DoOnStatus(nsIRequest*
     nsAutoCString host;
     mURI->GetHost(host);
     mProgressSink->OnStatus(aRequest, nullptr, status,
                             NS_ConvertUTF8toUTF16(host).get());
   }
 }
 
 void
-HttpChannelChild::DoOnProgress(nsIRequest* aRequest, uint64_t progress, uint64_t progressMax)
+HttpChannelChild::DoOnProgress(nsIRequest* aRequest, int64_t progress, int64_t progressMax)
 {
   LOG(("HttpChannelChild::DoOnProgress [this=%p]\n", this));
   if (mCanceled)
     return;
 
   // cache the progress sink so we don't have to query for it each time.
   if (!mProgressSink)
     GetCallback(mProgressSink);
@@ -544,17 +544,18 @@ HttpChannelChild::DoOnProgress(nsIReques
   // block status/progress after Cancel or OnStopRequest has been called,
   // or if channel has LOAD_BACKGROUND set.
   if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
       !(mLoadFlags & LOAD_BACKGROUND))
   {
     // OnProgress
     //
     if (progress > 0) {
-      MOZ_ASSERT(progress <= progressMax, "unexpected progress values");
+      MOZ_ASSERT((progressMax == -1) || (progress <= progressMax),
+                 "unexpected progress values");
       mProgressSink->OnProgress(aRequest, nullptr, progress, progressMax);
     }
   }
 }
 
 void
 HttpChannelChild::DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
                                     nsIInputStream* aStream,
@@ -687,62 +688,63 @@ HttpChannelChild::DoOnStopRequest(nsIReq
   if (mLoadGroup)
     mLoadGroup->RemoveRequest(this, nullptr, mStatus);
 }
 
 class ProgressEvent : public ChannelEvent
 {
  public:
   ProgressEvent(HttpChannelChild* child,
-                const uint64_t& progress,
-                const uint64_t& progressMax)
+                const int64_t& progress,
+                const int64_t& progressMax)
   : mChild(child)
   , mProgress(progress)
   , mProgressMax(progressMax) {}
 
   void Run() { mChild->OnProgress(mProgress, mProgressMax); }
  private:
   HttpChannelChild* mChild;
-  uint64_t mProgress, mProgressMax;
+  int64_t mProgress, mProgressMax;
 };
 
 bool
-HttpChannelChild::RecvOnProgress(const uint64_t& progress,
-                                 const uint64_t& progressMax)
+HttpChannelChild::RecvOnProgress(const int64_t& progress,
+                                 const int64_t& progressMax)
 {
   if (mEventQ->ShouldEnqueue())  {
     mEventQ->Enqueue(new ProgressEvent(this, progress, progressMax));
   } else {
     OnProgress(progress, progressMax);
   }
   return true;
 }
 
 void
-HttpChannelChild::OnProgress(const uint64_t& progress,
-                             const uint64_t& progressMax)
+HttpChannelChild::OnProgress(const int64_t& progress,
+                             const int64_t& progressMax)
 {
-  LOG(("HttpChannelChild::OnProgress [this=%p progress=%llu/%llu]\n",
+  LOG(("HttpChannelChild::OnProgress [this=%p progress=%lld/%lld]\n",
        this, progress, progressMax));
 
   if (mCanceled)
     return;
 
   // cache the progress sink so we don't have to query for it each time.
   if (!mProgressSink) {
     GetCallback(mProgressSink);
   }
 
   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
 
   // Block socket status event after Cancel or OnStopRequest has been called.
   if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending)
   {
     if (progress > 0) {
-      MOZ_ASSERT(progress <= progressMax, "unexpected progress values");
+      MOZ_ASSERT((progressMax == -1) || (progress <= progressMax),
+                 "unexpected progress values");
       mProgressSink->OnProgress(this, nullptr, progress, progressMax);
     }
   }
 }
 
 class StatusEvent : public ChannelEvent
 {
  public:
@@ -1368,17 +1370,17 @@ InterceptStreamListener::OnStatus(nsIReq
                                   nsresult status, const char16_t* aStatusArg)
 {
   mOwner->DoOnStatus(mOwner, status);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InterceptStreamListener::OnProgress(nsIRequest* aRequest, nsISupports* aContext,
-                                    uint64_t aProgress, uint64_t aProgressMax)
+                                    int64_t aProgress, int64_t aProgressMax)
 {
   mOwner->DoOnProgress(mOwner, aProgress, aProgressMax);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InterceptStreamListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
                                          nsIInputStream* aInputStream, uint64_t aOffset,
@@ -1391,19 +1393,18 @@ InterceptStreamListener::OnDataAvailable
     nsCOMPtr<nsIURI> uri;
     mOwner->GetURI(getter_AddRefs(uri));
 
     nsAutoCString host;
     uri->GetHost(host);
 
     OnStatus(mOwner, aContext, NS_NET_STATUS_READING, NS_ConvertUTF8toUTF16(host).get());
 
-    uint64_t progressMax(uint64_t(mOwner->GetResponseHead()->ContentLength()));
-    uint64_t progress = aOffset + uint64_t(aCount);
-    OnProgress(mOwner, aContext, progress, progressMax);
+    int64_t progress = aOffset + aCount;
+    OnProgress(mOwner, aContext, progress, mOwner->GetResponseHead()->ContentLength());
   }
 
   mOwner->DoOnDataAvailable(mOwner, mContext, aInputStream, aOffset, aCount);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InterceptStreamListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatusCode)
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -121,17 +121,17 @@ protected:
   bool RecvOnTransportAndData(const nsresult& channelStatus,
                               const nsresult& status,
                               const uint64_t& progress,
                               const uint64_t& progressMax,
                               const nsCString& data,
                               const uint64_t& offset,
                               const uint32_t& count) MOZ_OVERRIDE;
   bool RecvOnStopRequest(const nsresult& statusCode, const ResourceTimingStruct& timing) MOZ_OVERRIDE;
-  bool RecvOnProgress(const uint64_t& progress, const uint64_t& progressMax) MOZ_OVERRIDE;
+  bool RecvOnProgress(const int64_t& progress, const int64_t& progressMax) MOZ_OVERRIDE;
   bool RecvOnStatus(const nsresult& status) MOZ_OVERRIDE;
   bool RecvFailedAsyncOpen(const nsresult& status) MOZ_OVERRIDE;
   bool RecvRedirect1Begin(const uint32_t& newChannel,
                           const URIParams& newURI,
                           const uint32_t& redirectFlags,
                           const nsHttpResponseHead& responseHead) MOZ_OVERRIDE;
   bool RecvRedirect3Complete() MOZ_OVERRIDE;
   bool RecvAssociateApplicationCache(const nsCString& groupID,
@@ -143,17 +143,17 @@ protected:
   bool GetAssociatedContentSecurity(nsIAssociatedContentSecurity** res = nullptr);
   virtual void DoNotifyListenerCleanup() MOZ_OVERRIDE;
 
 private:
   nsresult ContinueAsyncOpen();
 
   void DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext);
   void DoOnStatus(nsIRequest* aRequest, nsresult status);
-  void DoOnProgress(nsIRequest* aRequest, uint64_t progress, uint64_t progressMax);
+  void DoOnProgress(nsIRequest* aRequest, int64_t progress, int64_t progressMax);
   void DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, nsIInputStream* aStream,
                          uint64_t offset, uint32_t count);
   void DoPreOnStopRequest(nsresult aStatus);
   void DoOnStopRequest(nsIRequest* aRequest, nsISupports* aContext);
 
   // Discard the prior interception and continue with the original network request.
   void ResetInterception();
 
@@ -207,17 +207,17 @@ private:
   void OnTransportAndData(const nsresult& channelStatus,
                           const nsresult& status,
                           const uint64_t progress,
                           const uint64_t& progressMax,
                           const nsCString& data,
                           const uint64_t& offset,
                           const uint32_t& count);
   void OnStopRequest(const nsresult& channelStatus, const ResourceTimingStruct& timing);
-  void OnProgress(const uint64_t& progress, const uint64_t& progressMax);
+  void OnProgress(const int64_t& progress, const int64_t& progressMax);
   void OnStatus(const nsresult& status);
   void FailedAsyncOpen(const nsresult& status);
   void HandleAsyncAbort();
   void Redirect1Begin(const uint32_t& newChannelId,
                       const URIParams& newUri,
                       const uint32_t& redirectFlags,
                       const nsHttpResponseHead& responseHead);
   void Redirect3Complete();
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -814,18 +814,18 @@ HttpChannelParent::OnDataAvailable(nsIRe
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsIProgressEventSink
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelParent::OnProgress(nsIRequest *aRequest,
                               nsISupports *aContext,
-                              uint64_t aProgress,
-                              uint64_t aProgressMax)
+                              int64_t aProgress,
+                              int64_t aProgressMax)
 {
   // OnStatus has always just set mStoredStatus. If it indicates this precedes
   // OnDataAvailable, store and ODA will send to child.
   if (mStoredStatus == NS_NET_STATUS_RECEIVING_FROM ||
       mStoredStatus == NS_NET_STATUS_READING)
   {
     mStoredProgress = aProgress;
     mStoredProgressMax = aProgressMax;
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -158,18 +158,18 @@ private:
   nsCOMPtr<nsIChannel> mRedirectChannel;
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
 
   nsAutoPtr<class nsHttpChannel::OfflineCacheEntryAsForeignMarker> mOfflineForeignMarker;
 
   // state for combining OnStatus/OnProgress with OnDataAvailable
   // into one IPDL call to child.
   nsresult mStoredStatus;
-  uint64_t mStoredProgress;
-  uint64_t mStoredProgressMax;
+  int64_t mStoredProgress;
+  int64_t mStoredProgressMax;
 
   bool mSentRedirect1Begin          : 1;
   bool mSentRedirect1BeginFailed    : 1;
   bool mReceivedRedirect2Verify     : 1;
 
   nsRefPtr<OfflineObserver> mObserver;
 
   PBOverrideStatus mPBOverride;
--- a/netwerk/protocol/http/NullHttpTransaction.cpp
+++ b/netwerk/protocol/http/NullHttpTransaction.cpp
@@ -142,17 +142,17 @@ void
 NullHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **outCB)
 {
   nsCOMPtr<nsIInterfaceRequestor> copyCB(mCallbacks);
   *outCB = copyCB.forget().take();
 }
 
 void
 NullHttpTransaction::OnTransportStatus(nsITransport* transport,
-                                       nsresult status, uint64_t progress)
+                                       nsresult status, int64_t progress)
 {
   if (mActivityDistributor) {
     NS_DispatchToMainThread(new CallObserveActivity(mActivityDistributor,
                                   mConnectionInfo->GetHost(),
                                   mConnectionInfo->Port(),
                                   mConnectionInfo->EndToEndSSL(),
                                   NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT,
                                   static_cast<uint32_t>(status),
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -102,17 +102,17 @@ child:
                      uint64_t  progress,
                      uint64_t  progressMax,
                      nsCString data,
                      uint64_t  offset,
                      uint32_t  count);
 
   OnStopRequest(nsresult channelStatus, ResourceTimingStruct timing);
 
-  OnProgress(uint64_t progress, uint64_t progressMax);
+  OnProgress(int64_t progress, int64_t progressMax);
 
   OnStatus(nsresult status);
 
   // Used to cancel child channel if we hit errors during creating and
   // AsyncOpen of nsHttpChannel on the parent.
   FailedAsyncOpen(nsresult status);
 
   // Called to initiate content channel redirect, starts talking to sinks
--- a/netwerk/protocol/http/SpdyPush31.cpp
+++ b/netwerk/protocol/http/SpdyPush31.cpp
@@ -205,17 +205,17 @@ SpdyPush31TransactionBuffer::Connection(
 void
 SpdyPush31TransactionBuffer::GetSecurityCallbacks(nsIInterfaceRequestor **outCB)
 {
   *outCB = nullptr;
 }
 
 void
 SpdyPush31TransactionBuffer::OnTransportStatus(nsITransport* transport,
-                                               nsresult status, uint64_t progress)
+                                               nsresult status, int64_t progress)
 {
 }
 
 nsHttpConnectionInfo *
 SpdyPush31TransactionBuffer::ConnectionInfo()
 {
   if (!mPushStream) {
     return nullptr;
--- a/netwerk/protocol/http/SpdySession31.cpp
+++ b/netwerk/protocol/http/SpdySession31.cpp
@@ -1762,17 +1762,17 @@ SpdySession31::HandleCredential(SpdySess
 //-----------------------------------------------------------------------------
 // nsAHttpTransaction. It is expected that nsHttpConnection is the caller
 // of these methods
 //-----------------------------------------------------------------------------
 
 void
 SpdySession31::OnTransportStatus(nsITransport* aTransport,
                                  nsresult aStatus,
-                                 uint64_t aProgress)
+                                 int64_t aProgress)
 {
   MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
 
   switch (aStatus) {
     // These should appear only once, deliver to the first
     // transaction on the session.
   case NS_NET_STATUS_RESOLVING_HOST:
   case NS_NET_STATUS_RESOLVED_HOST:
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -551,17 +551,17 @@ TLSFilterTransaction::GetSecurityCallbac
   if (!mTransaction) {
     return;
   }
   mTransaction->GetSecurityCallbacks(outCB);
 }
 
 void
 TLSFilterTransaction::OnTransportStatus(nsITransport* aTransport,
-                                        nsresult aStatus, uint64_t aProgress)
+                                        nsresult aStatus, int64_t aProgress)
 {
   if (!mTransaction) {
     return;
   }
   mTransaction->OnTransportStatus(aTransport, aStatus, aProgress);
 }
 
 nsHttpConnectionInfo *
--- a/netwerk/protocol/http/nsAHttpTransaction.h
+++ b/netwerk/protocol/http/nsAHttpTransaction.h
@@ -50,17 +50,17 @@ public:
     virtual nsAHttpConnection *Connection() = 0;
 
     // called by the connection to get security callbacks to set on the
     // socket transport.
     virtual void GetSecurityCallbacks(nsIInterfaceRequestor **) = 0;
 
     // called to report socket status (see nsITransportEventSink)
     virtual void OnTransportStatus(nsITransport* transport,
-                                   nsresult status, uint64_t progress) = 0;
+                                   nsresult status, int64_t progress) = 0;
 
     // called to check the transaction status.
     virtual bool     IsDone() = 0;
     virtual nsresult Status() = 0;
     virtual uint32_t Caps() = 0;
 
     // called to notify that a requested DNS cache entry was refreshed.
     virtual void     SetDNSWasRefreshed() = 0;
@@ -193,17 +193,17 @@ public:
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpTransaction, NS_AHTTPTRANSACTION_IID)
 
 #define NS_DECL_NSAHTTPTRANSACTION \
     void SetConnection(nsAHttpConnection *) MOZ_OVERRIDE; \
     nsAHttpConnection *Connection() MOZ_OVERRIDE; \
     void GetSecurityCallbacks(nsIInterfaceRequestor **) MOZ_OVERRIDE;       \
     void OnTransportStatus(nsITransport* transport, \
-                           nsresult status, uint64_t progress) MOZ_OVERRIDE; \
+                           nsresult status, int64_t progress) MOZ_OVERRIDE; \
     bool     IsDone() MOZ_OVERRIDE; \
     nsresult Status() MOZ_OVERRIDE; \
     uint32_t Caps() MOZ_OVERRIDE;   \
     void     SetDNSWasRefreshed() MOZ_OVERRIDE; \
     uint64_t Available() MOZ_OVERRIDE; \
     virtual nsresult ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *) MOZ_OVERRIDE; \
     virtual nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *) MOZ_OVERRIDE; \
     virtual void Close(nsresult reason) MOZ_OVERRIDE;                                \
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -5589,18 +5589,18 @@ nsHttpChannel::OnStopRequest(nsIRequest 
 // nsHttpChannel::nsIStreamListener
 //-----------------------------------------------------------------------------
 
 class OnTransportStatusAsyncEvent : public nsRunnable
 {
 public:
     OnTransportStatusAsyncEvent(nsITransportEventSink* aEventSink,
                                 nsresult aTransportStatus,
-                                uint64_t aProgress,
-                                uint64_t aProgressMax)
+                                int64_t aProgress,
+                                int64_t aProgressMax)
     : mEventSink(aEventSink)
     , mTransportStatus(aTransportStatus)
     , mProgress(aProgress)
     , mProgressMax(aProgressMax)
     {
         MOZ_ASSERT(!NS_IsMainThread(), "Shouldn't be created on main thread");
     }
 
@@ -5611,18 +5611,18 @@ public:
             mEventSink->OnTransportStatus(nullptr, mTransportStatus,
                                           mProgress, mProgressMax);
         }
         return NS_OK;
     }
 private:
     nsCOMPtr<nsITransportEventSink> mEventSink;
     nsresult mTransportStatus;
-    uint64_t mProgress;
-    uint64_t mProgressMax;
+    int64_t mProgress;
+    int64_t mProgressMax;
 };
 
 NS_IMETHODIMP
 nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
                                nsIInputStream *input,
                                uint64_t offset, uint32_t count)
 {
     PROFILER_LABEL("nsHttpChannel", "OnDataAvailable",
@@ -5657,22 +5657,32 @@ nsHttpChannel::OnDataAvailable(nsIReques
         else
             transportStatus = NS_NET_STATUS_RECEIVING_FROM;
 
         // mResponseHead may reference new or cached headers, but either way it
         // holds our best estimate of the total content length.  Even in the case
         // of a byte range request, the content length stored in the cached
         // response headers is what we want to use here.
 
-        uint64_t progressMax(uint64_t(mResponseHead->ContentLength()));
-        uint64_t progress = mLogicalOffset + uint64_t(count);
-
-        if (progress > progressMax)
+        int64_t progressMax(mResponseHead->ContentLength());
+        int64_t progress = mLogicalOffset + count;
+
+        if ((progress > progressMax) && (progressMax != -1)) {
             NS_WARNING("unexpected progress values - "
                        "is server exceeding content length?");
+        }
+
+        // make sure params are in range for js
+        if (!InScriptableRange(progressMax)) {
+            progressMax = -1;
+        }
+
+        if (!InScriptableRange(progress)) {
+            progress = -1;
+        }
 
         if (NS_IsMainThread()) {
             OnTransportStatus(nullptr, transportStatus, progress, progressMax);
         } else {
             nsresult rv = NS_DispatchToMainThread(
                 new OnTransportStatusAsyncEvent(this, transportStatus,
                                                 progress, progressMax));
             NS_ENSURE_SUCCESS(rv, rv);
@@ -5791,17 +5801,17 @@ nsHttpChannel::CheckListenerChain()
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsITransportEventSink
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpChannel::OnTransportStatus(nsITransport *trans, nsresult status,
-                                 uint64_t progress, uint64_t progressMax)
+                                 int64_t progress, int64_t progressMax)
 {
     MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread only");
     // cache the progress sink so we don't have to query for it each time.
     if (!mProgressSink)
         GetCallback(mProgressSink);
 
     if (status == NS_NET_STATUS_CONNECTED_TO ||
         status == NS_NET_STATUS_WAITING_FOR) {
@@ -5811,29 +5821,29 @@ nsHttpChannel::OnTransportStatus(nsITran
             socketTransport->GetSelfAddr(&mSelfAddr);
             socketTransport->GetPeerAddr(&mPeerAddr);
         }
     }
 
     // block socket status event after Cancel or OnStopRequest has been called.
     if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending) {
         LOG(("sending progress%s notification [this=%p status=%x"
-             " progress=%llu/%llu]\n",
+             " progress=%lld/%lld]\n",
             (mLoadFlags & LOAD_BACKGROUND)? "" : " and status",
             this, status, progress, progressMax));
 
         if (!(mLoadFlags & LOAD_BACKGROUND)) {
             nsAutoCString host;
             mURI->GetHost(host);
             mProgressSink->OnStatus(this, nullptr, status,
                                     NS_ConvertUTF8toUTF16(host).get());
         }
 
         if (progress > 0) {
-            if (progress > progressMax) {
+            if ((progress > progressMax) && (progressMax != -1)) {
                 NS_WARNING("unexpected progress values");
             }
 
             // Try to get mProgressSink if it was nulled out during OnStatus.
             if (!mProgressSink) {
                 GetCallback(mProgressSink);
             }
             if (mProgressSink) {
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -2075,18 +2075,18 @@ nsHttpConnection::OnOutputStreamReady(ns
 
 //-----------------------------------------------------------------------------
 // nsHttpConnection::nsITransportEventSink
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpConnection::OnTransportStatus(nsITransport *trans,
                                     nsresult status,
-                                    uint64_t progress,
-                                    uint64_t progressMax)
+                                    int64_t progress,
+                                    int64_t progressMax)
 {
     if (mTransaction)
         mTransaction->OnTransportStatus(trans, status, progress);
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpConnection::nsIInterfaceRequestor
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -3421,18 +3421,18 @@ nsHalfOpenSocket::OnOutputStreamReady(ns
 
     return rv;
 }
 
 // method for nsITransportEventSink
 NS_IMETHODIMP
 nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport *trans,
                                                          nsresult status,
-                                                         uint64_t progress,
-                                                         uint64_t progressMax)
+                                                         int64_t progress,
+                                                         int64_t progressMax)
 {
     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
 
     if (mTransaction)
         mTransaction->OnTransportStatus(trans, status, progress);
 
     MOZ_ASSERT(trans == mSocketTransport || trans == mBackupTransport);
     if (status == NS_NET_STATUS_CONNECTED_TO) {
--- a/netwerk/protocol/http/nsHttpPipeline.cpp
+++ b/netwerk/protocol/http/nsHttpPipeline.cpp
@@ -435,19 +435,19 @@ nsHttpPipeline::GetSecurityCallbacks(nsI
         trans->GetSecurityCallbacks(result);
     else {
         *result = nullptr;
     }
 }
 
 void
 nsHttpPipeline::OnTransportStatus(nsITransport* transport,
-                                  nsresult status, uint64_t progress)
+                                  nsresult status, int64_t progress)
 {
-    LOG(("nsHttpPipeline::OnStatus [this=%p status=%x progress=%llu]\n",
+    LOG(("nsHttpPipeline::OnStatus [this=%p status=%x progress=%lld]\n",
         this, status, progress));
 
     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
 
     nsAHttpTransaction *trans;
     int32_t i, count;
 
     switch (status) {
--- a/netwerk/protocol/http/nsHttpPipeline.h
+++ b/netwerk/protocol/http/nsHttpPipeline.h
@@ -89,16 +89,16 @@ private:
     char     *mPushBackBuf;
     uint32_t  mPushBackLen;
     uint32_t  mPushBackMax;
 
     // The number of transactions completed on this pipeline.
     uint32_t  mHttp1xTransactionCount;
 
     // For support of OnTransportStatus()
-    uint64_t  mReceivingFromProgress;
-    uint64_t  mSendingToProgress;
-    bool      mSuppressSendEvents;
+    int64_t  mReceivingFromProgress;
+    int64_t  mSendingToProgress;
+    bool     mSuppressSendEvents;
 };
 
 }} // namespace mozilla::net
 
 #endif // nsHttpPipeline_h__
--- a/netwerk/protocol/http/nsHttpResponseHead.cpp
+++ b/netwerk/protocol/http/nsHttpResponseHead.cpp
@@ -618,17 +618,17 @@ void
 nsHttpResponseHead::Reset()
 {
     LOG(("nsHttpResponseHead::Reset\n"));
 
     ClearHeaders();
 
     mVersion = NS_HTTP_VERSION_1_1;
     mStatus = 200;
-    mContentLength = UINT64_MAX;
+    mContentLength = -1;
     mCacheControlPrivate = false;
     mCacheControlNoStore = false;
     mCacheControlNoCache = false;
     mPragmaNoCache = false;
     mStatusText.Truncate();
     mContentType.Truncate();
     mContentCharset.Truncate();
 }
--- a/netwerk/protocol/http/nsHttpResponseHead.h
+++ b/netwerk/protocol/http/nsHttpResponseHead.h
@@ -17,17 +17,17 @@ namespace mozilla { namespace net {
 // response.
 //-----------------------------------------------------------------------------
 
 class nsHttpResponseHead
 {
 public:
     nsHttpResponseHead() : mVersion(NS_HTTP_VERSION_1_1)
                          , mStatus(200)
-                         , mContentLength(UINT64_MAX)
+                         , mContentLength(-1)
                          , mCacheControlPrivate(false)
                          , mCacheControlNoStore(false)
                          , mCacheControlNoCache(false)
                          , mPragmaNoCache(false) {}
 
     const nsHttpHeaderArray & Headers()   const { return mHeaders; }
     nsHttpHeaderArray    &Headers()             { return mHeaders; }
     nsHttpVersion         Version()       const { return mVersion; }
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -362,18 +362,24 @@ nsHttpTransaction::Init(uint32_t caps,
         // necessary to workaround some common server bugs (see bug 137155).
         rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), multi,
                                        nsIOService::gDefaultSegmentSize);
         if (NS_FAILED(rv)) return rv;
     }
     else
         mRequestStream = headers;
 
-    rv = mRequestStream->Available(&mRequestSize);
-    if (NS_FAILED(rv)) return rv;
+    uint64_t size_u64;
+    rv = mRequestStream->Available(&size_u64);
+    if (NS_FAILED(rv)) {
+        return rv;
+    }
+
+    // make sure it fits within js MAX_SAFE_INTEGER
+    mRequestSize = InScriptableRange(size_u64) ? static_cast<int64_t>(size_u64) : -1;
 
     // create pipe for response stream
     rv = NS_NewPipe2(getter_AddRefs(mPipeIn),
                      getter_AddRefs(mPipeOut),
                      true, true,
                      nsIOService::gDefaultSegmentSize,
                      nsIOService::gDefaultSegmentCount);
     if (NS_FAILED(rv)) return rv;
@@ -494,19 +500,19 @@ nsHttpTransaction::SetSecurityCallbacks(
     if (gSocketTransportService) {
         nsRefPtr<UpdateSecurityCallbacks> event = new UpdateSecurityCallbacks(this, aCallbacks);
         gSocketTransportService->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
     }
 }
 
 void
 nsHttpTransaction::OnTransportStatus(nsITransport* transport,
-                                     nsresult status, uint64_t progress)
+                                     nsresult status, int64_t progress)
 {
-    LOG(("nsHttpTransaction::OnSocketStatus [this=%p status=%x progress=%llu]\n",
+    LOG(("nsHttpTransaction::OnSocketStatus [this=%p status=%x progress=%lld]\n",
         this, status, progress));
 
     if (TimingEnabled()) {
         if (status == NS_NET_STATUS_RESOLVING_HOST) {
             mTimings.domainLookupStart = TimeStamp::Now();
         } else if (status == NS_NET_STATUS_RESOLVED_HOST) {
             mTimings.domainLookupEnd = TimeStamp::Now();
         } else if (status == NS_NET_STATUS_CONNECTING_TO) {
@@ -543,40 +549,40 @@ nsHttpTransaction::OnTransportStatus(nsI
                 progress,
                 EmptyCString());
     }
 
     // nsHttpChannel synthesizes progress events in OnDataAvailable
     if (status == NS_NET_STATUS_RECEIVING_FROM)
         return;
 
-    uint64_t progressMax;
+    int64_t progressMax;
 
     if (status == NS_NET_STATUS_SENDING_TO) {
         // suppress progress when only writing request headers
         if (!mHasRequestBody) {
             LOG(("nsHttpTransaction::OnTransportStatus %p "
                  "SENDING_TO without request body\n", this));
             return;
         }
 
         nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mRequestStream);
         if (!seekable) {
             LOG(("nsHttpTransaction::OnTransportStatus %p "
                  "SENDING_TO without seekable request stream\n", this));
-            return;
+            progress = 0;
+        } else {
+            int64_t prog = 0;
+            seekable->Tell(&prog);
+            progress = prog;
         }
 
-        int64_t prog = 0;
-        seekable->Tell(&prog);
-        progress = prog;
-
         // when uploading, we include the request headers in the progress
         // notifications.
-        progressMax = mRequestSize; // XXX mRequestSize is 32-bit!
+        progressMax = mRequestSize;
     }
     else {
         progress = 0;
         progressMax = 0;
     }
 
     mTransportSink->OnTransportStatus(transport, status, progress, progressMax);
 }
@@ -1614,20 +1620,16 @@ nsHttpTransaction::HandleContent(char *b
         mContentRead += ignore;
         mRestartInProgressVerifier.HaveReadBeforeRestart(ignore);
         memmove(buf, buf + ignore, *contentRead + *contentRemaining);
     }
 
     if (*contentRead) {
         // update count of content bytes read and report progress...
         mContentRead += *contentRead;
-        /* when uncommenting, take care of 64-bit integers w/ std::max...
-        if (mProgressSink)
-            mProgressSink->OnProgress(nullptr, nullptr, mContentRead, std::max(0, mContentLength));
-        */
     }
 
     LOG(("nsHttpTransaction::HandleContent [this=%p count=%u read=%u mContentRead=%lld mContentLength=%lld]\n",
         this, count, *contentRead, mContentRead, mContentLength));
 
     // Check the size of chunked responses. If we exceed the max pipeline size
     // for this response reschedule the pipeline
     if ((mClassification != CLASS_SOLO) &&
--- a/netwerk/protocol/http/nsHttpTransaction.h
+++ b/netwerk/protocol/http/nsHttpTransaction.h
@@ -209,17 +209,17 @@ private:
     nsCOMPtr<nsIAsyncOutputStream>  mPipeOut;
     nsCOMPtr<nsILoadGroupConnectionInfo> mLoadGroupCI;
 
     nsCOMPtr<nsISupports>             mChannel;
     nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;
 
     nsCString                       mReqHeaderBuf;    // flattened request headers
     nsCOMPtr<nsIInputStream>        mRequestStream;
-    uint64_t                        mRequestSize;
+    int64_t                         mRequestSize;
 
     nsRefPtr<nsAHttpConnection>     mConnection;
     nsRefPtr<nsHttpConnectionInfo>  mConnInfo;
     nsHttpRequestHead              *mRequestHead;     // weak ref
     nsHttpResponseHead             *mResponseHead;    // owning pointer
 
     nsAHttpSegmentReader           *mReader;
     nsAHttpSegmentWriter           *mWriter;
--- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
+++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
@@ -249,17 +249,17 @@ WyciwygChannelChild::OnDataAvailable(con
   
   rv = mListener->OnDataAvailable(this, mListenerContext,
                                   stringStream, offset, data.Length());
   if (NS_FAILED(rv))
     Cancel(rv);
 
   if (mProgressSink && NS_SUCCEEDED(rv)) {
     mProgressSink->OnProgress(this, nullptr, offset + data.Length(),
-                              uint64_t(mContentLength));
+                              mContentLength);
   }
 }
 
 class WyciwygStopRequestEvent : public ChannelEvent
 {
 public:
   WyciwygStopRequestEvent(WyciwygChannelChild* child,
                           const nsresult& statusCode)
--- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
+++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
@@ -704,18 +704,17 @@ nsWyciwygChannel::OnDataAvailable(nsIReq
       this, request, offset, count));
 
   nsresult rv;
   
   rv = mListener->OnDataAvailable(this, mListenerContext, input, offset, count);
 
   // XXX handle 64-bit stuff for real
   if (mProgressSink && NS_SUCCEEDED(rv)) {
-    mProgressSink->OnProgress(this, nullptr, offset + count,
-                              uint64_t(mContentLength));
+    mProgressSink->OnProgress(this, nullptr, offset + count, mContentLength);
   }
 
   return rv; // let the pump cancel on failure
 }
 
 //////////////////////////////////////////////////////////////////////////////
 // nsIRequestObserver
 //////////////////////////////////////////////////////////////////////////////
--- a/netwerk/test/TestIncrementalDownload.cpp
+++ b/netwerk/test/TestIncrementalDownload.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 cin et: */
 /* 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 <inttypes.h>
 #include <stdlib.h>
 #include "TestCommon.h"
 #include "nsNetUtil.h"
 #include "nsIIncrementalDownload.h"
 #include "nsIRequestObserver.h"
 #include "nsIProgressEventSink.h"
 #include "nsThreadUtils.h"
 #include "nsAutoPtr.h"
@@ -35,20 +36,20 @@ NS_IMETHODIMP
 FetchObserver::OnStartRequest(nsIRequest *request, nsISupports *context)
 {
   printf("FetchObserver::OnStartRequest\n");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 FetchObserver::OnProgress(nsIRequest *request, nsISupports *context,
-                          uint64_t progress, uint64_t progressMax)
+                          int64_t progress, int64_t progressMax)
 {
-  printf("FetchObserver::OnProgress [%lu/%lu]\n",
-         (unsigned long)progress, (unsigned long)progressMax);
+  printf("FetchObserver::OnProgress [%" PRId64 "/%" PRId64 "]\n",
+         progress, progressMax);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 FetchObserver::OnStatus(nsIRequest *request, nsISupports *context,
                         nsresult status, const char16_t *statusText)
 {
   return NS_OK;
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -980,29 +980,29 @@ int64_t nsDocLoader::GetMaxTotalProgress
 
 ////////////////////////////////////////////////////////////////////////////////////
 // The following section contains support for nsIProgressEventSink which is used to 
 // pass progress and status between the actual request and the doc loader. The doc loader
 // then turns around and makes the right web progress calls based on this information.
 ////////////////////////////////////////////////////////////////////////////////////
 
 NS_IMETHODIMP nsDocLoader::OnProgress(nsIRequest *aRequest, nsISupports* ctxt, 
-                                      uint64_t aProgress, uint64_t aProgressMax)
+                                      int64_t aProgress, int64_t aProgressMax)
 {
   int64_t progressDelta = 0;
 
   //
   // Update the RequestInfo entry with the new progress data
   //
   if (nsRequestInfo* info = GetRequestInfo(aRequest)) {
     // Update info->mCurrentProgress before we call FireOnStateChange,
     // since that can make the "info" pointer invalid.
     int64_t oldCurrentProgress = info->mCurrentProgress;
-    progressDelta = int64_t(aProgress) - oldCurrentProgress;
-    info->mCurrentProgress = int64_t(aProgress);
+    progressDelta = aProgress - oldCurrentProgress;
+    info->mCurrentProgress = aProgress;
 
     // suppress sending STATE_TRANSFERRING if this is upload progress (see bug 240053)
     if (!info->mUploading && (int64_t(0) == oldCurrentProgress) && (int64_t(0) == info->mMaxProgress)) {
       //
       // If we receive an OnProgress event from a toplevel channel that the URI Loader
       // has not yet targeted, then we must suppress the event.  This is necessary to
       // ensure that webprogresslisteners do not get confused when the channel is
       // finally targeted.  See bug 257308.
@@ -1012,23 +1012,23 @@ NS_IMETHODIMP nsDocLoader::OnProgress(ns
       if ((lf & nsIChannel::LOAD_DOCUMENT_URI) && !(lf & nsIChannel::LOAD_TARGETED)) {
         PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, 
             ("DocLoader:%p Ignoring OnProgress while load is not targeted\n", this));
         return NS_OK;
       }
 
       //
       // This is the first progress notification for the entry.  If
-      // (aMaxProgress > 0) then the content-length of the data is known,
+      // (aMaxProgress != -1) then the content-length of the data is known,
       // so update mMaxSelfProgress...  Otherwise, set it to -1 to indicate
       // that the content-length is no longer known.
       //
-      if (uint64_t(aProgressMax) != UINT64_MAX) {
-        mMaxSelfProgress  += int64_t(aProgressMax);
-        info->mMaxProgress = int64_t(aProgressMax);
+      if (aProgressMax != -1) {
+        mMaxSelfProgress  += aProgressMax;
+        info->mMaxProgress = aProgressMax;
       } else {
         mMaxSelfProgress   =  int64_t(-1);
         info->mMaxProgress =  int64_t(-1);
       }
 
       // Send a STATE_TRANSFERRING notification for the request.
       int32_t flags;