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 224688 91e1a0afee555a045c8e283934456556b1d4a43d
parent 224687 c1fac42ad172b1e88fe26f14ce8f6412df1469ba
child 224689 c2c0d8f26b9719e5f12b6977773df58c05dcb4ad
push id54319
push usermcmanus@ducksong.com
push dateTue, 20 Jan 2015 19:22:10 +0000
treeherdermozilla-inbound@91e1a0afee55 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer, bz
bugs1116867
milestone38.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 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;