tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsStreamLoader.cpp (4253B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "nsStreamLoader.h"
      7 #include "nsIInputStream.h"
      8 #include "nsIChannel.h"
      9 #include "nsError.h"
     10 #include "mozilla/ProfilerLabels.h"
     11 
     12 #include <limits>
     13 
     14 namespace mozilla {
     15 namespace net {
     16 
     17 nsStreamLoader::nsStreamLoader() = default;
     18 
     19 NS_IMETHODIMP
     20 nsStreamLoader::Init(nsIStreamLoaderObserver* aStreamObserver,
     21                     nsIRequestObserver* aRequestObserver) {
     22  NS_ENSURE_ARG_POINTER(aStreamObserver);
     23  mObserver = aStreamObserver;
     24  mRequestObserver = aRequestObserver;
     25  return NS_OK;
     26 }
     27 
     28 nsresult nsStreamLoader::Create(REFNSIID aIID, void** aResult) {
     29  RefPtr<nsStreamLoader> it = new nsStreamLoader();
     30  return it->QueryInterface(aIID, aResult);
     31 }
     32 
     33 NS_IMPL_ISUPPORTS(nsStreamLoader, nsIStreamLoader, nsIRequestObserver,
     34                  nsIStreamListener, nsIThreadRetargetableStreamListener)
     35 
     36 NS_IMETHODIMP
     37 nsStreamLoader::GetNumBytesRead(uint32_t* aNumBytes) {
     38  *aNumBytes = mBytesRead;
     39  return NS_OK;
     40 }
     41 
     42 NS_IMETHODIMP
     43 nsStreamLoader::GetRequest(nsIRequest** aRequest) {
     44  nsCOMPtr<nsIRequest> req = mRequest;
     45  req.forget(aRequest);
     46  return NS_OK;
     47 }
     48 
     49 NS_IMETHODIMP
     50 nsStreamLoader::OnStartRequest(nsIRequest* request) {
     51  nsCOMPtr<nsIChannel> chan(do_QueryInterface(request));
     52  if (chan) {
     53    int64_t contentLength = -1;
     54    chan->GetContentLength(&contentLength);
     55    if (contentLength >= 0) {
     56      // On 64bit platforms size of uint64_t coincides with the size of size_t,
     57      // so we want to compare with the minimum from size_t and int64_t.
     58      if (static_cast<uint64_t>(contentLength) >
     59          std::min(std::numeric_limits<size_t>::max(),
     60                   static_cast<size_t>(std::numeric_limits<int64_t>::max()))) {
     61        // Too big to fit into size_t, so let's bail.
     62        return NS_ERROR_OUT_OF_MEMORY;
     63      }
     64      // preallocate buffer
     65      if (!mData.initCapacity(contentLength)) {
     66        return NS_ERROR_OUT_OF_MEMORY;
     67      }
     68    }
     69  }
     70  if (mRequestObserver) {
     71    mRequestObserver->OnStartRequest(request);
     72  }
     73  return NS_OK;
     74 }
     75 
     76 NS_IMETHODIMP
     77 nsStreamLoader::OnStopRequest(nsIRequest* request, nsresult aStatus) {
     78  AUTO_PROFILER_LABEL("nsStreamLoader::OnStopRequest", NETWORK);
     79 
     80  if (mObserver) {
     81    // provide nsIStreamLoader::request during call to OnStreamComplete
     82    mRequest = request;
     83    size_t length = mData.length();
     84    uint8_t* elems = mData.extractOrCopyRawBuffer();
     85    nsresult rv =
     86        mObserver->OnStreamComplete(this, mContext, aStatus, length, elems);
     87    if (rv != NS_SUCCESS_ADOPTED_DATA) {
     88      // The observer didn't take ownership of the extracted data buffer, so
     89      // put it back into mData.
     90      mData.replaceRawBuffer(elems, length);
     91    }
     92    // done.. cleanup
     93    ReleaseData();
     94    mRequest = nullptr;
     95    mObserver = nullptr;
     96  }
     97 
     98  if (mRequestObserver) {
     99    mRequestObserver->OnStopRequest(request, aStatus);
    100    mRequestObserver = nullptr;
    101  }
    102 
    103  return NS_OK;
    104 }
    105 
    106 nsresult nsStreamLoader::WriteSegmentFun(nsIInputStream* inStr, void* closure,
    107                                         const char* fromSegment,
    108                                         uint32_t toOffset, uint32_t count,
    109                                         uint32_t* writeCount) {
    110  nsStreamLoader* self = (nsStreamLoader*)closure;
    111 
    112  if (!self->mData.append(fromSegment, count)) {
    113    self->mData.clearAndFree();
    114    return NS_ERROR_OUT_OF_MEMORY;
    115  }
    116 
    117  *writeCount = count;
    118  return NS_OK;
    119 }
    120 
    121 NS_IMETHODIMP
    122 nsStreamLoader::OnDataAvailable(nsIRequest* request, nsIInputStream* inStr,
    123                                uint64_t sourceOffset, uint32_t count) {
    124  uint32_t countRead;
    125  nsresult rv = inStr->ReadSegments(WriteSegmentFun, this, count, &countRead);
    126  NS_ENSURE_SUCCESS(rv, rv);
    127  mBytesRead += countRead;
    128  return NS_OK;
    129 }
    130 
    131 void nsStreamLoader::ReleaseData() { mData.clearAndFree(); }
    132 
    133 NS_IMETHODIMP
    134 nsStreamLoader::CheckListenerChain() { return NS_OK; }
    135 
    136 NS_IMETHODIMP
    137 nsStreamLoader::OnDataFinished(nsresult) { return NS_OK; }
    138 
    139 }  // namespace net
    140 }  // namespace mozilla