tor-browser

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

nsPreloadedStream.cpp (3901B)


      1 /* -*- Mode: C++; tab-width: 4; 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 "nsPreloadedStream.h"
      7 #include "nsIRunnable.h"
      8 
      9 #include "nsThreadUtils.h"
     10 #include <algorithm>
     11 
     12 namespace mozilla {
     13 namespace net {
     14 
     15 NS_IMPL_ISUPPORTS(nsPreloadedStream, nsIInputStream, nsIAsyncInputStream,
     16                  nsIInputStreamCallback)
     17 
     18 nsPreloadedStream::nsPreloadedStream(nsIAsyncInputStream* aStream,
     19                                     const char* data, uint32_t datalen)
     20    : mStream(aStream),
     21      mOffset(0),
     22      mLen(datalen),
     23      mCallback("nsPreloadedStream") {
     24  mBuf = (char*)moz_xmalloc(datalen);
     25  memcpy(mBuf, data, datalen);
     26 }
     27 
     28 nsPreloadedStream::~nsPreloadedStream() { free(mBuf); }
     29 
     30 NS_IMETHODIMP
     31 nsPreloadedStream::Close() {
     32  mLen = 0;
     33  return mStream->Close();
     34 }
     35 
     36 NS_IMETHODIMP
     37 nsPreloadedStream::Available(uint64_t* _retval) {
     38  uint64_t avail = 0;
     39 
     40  nsresult rv = mStream->Available(&avail);
     41  if (NS_FAILED(rv)) return rv;
     42  *_retval = avail + mLen;
     43  return NS_OK;
     44 }
     45 
     46 NS_IMETHODIMP
     47 nsPreloadedStream::StreamStatus() { return mStream->StreamStatus(); }
     48 
     49 NS_IMETHODIMP
     50 nsPreloadedStream::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) {
     51  if (!mLen) return mStream->Read(aBuf, aCount, _retval);
     52 
     53  uint32_t toRead = std::min(mLen, aCount);
     54  memcpy(aBuf, mBuf + mOffset, toRead);
     55  mOffset += toRead;
     56  mLen -= toRead;
     57  *_retval = toRead;
     58  return NS_OK;
     59 }
     60 
     61 NS_IMETHODIMP
     62 nsPreloadedStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
     63                                uint32_t aCount, uint32_t* result) {
     64  if (!mLen) return mStream->ReadSegments(aWriter, aClosure, aCount, result);
     65 
     66  *result = 0;
     67  while (mLen > 0 && aCount > 0) {
     68    uint32_t toRead = std::min(mLen, aCount);
     69    uint32_t didRead = 0;
     70    nsresult rv;
     71 
     72    rv = aWriter(this, aClosure, mBuf + mOffset, *result, toRead, &didRead);
     73 
     74    if (NS_FAILED(rv)) return NS_OK;
     75 
     76    *result += didRead;
     77    mOffset += didRead;
     78    mLen -= didRead;
     79    aCount -= didRead;
     80  }
     81 
     82  return NS_OK;
     83 }
     84 
     85 NS_IMETHODIMP
     86 nsPreloadedStream::IsNonBlocking(bool* _retval) {
     87  return mStream->IsNonBlocking(_retval);
     88 }
     89 
     90 NS_IMETHODIMP
     91 nsPreloadedStream::CloseWithStatus(nsresult aStatus) {
     92  mLen = 0;
     93  return mStream->CloseWithStatus(aStatus);
     94 }
     95 
     96 class RunOnThread : public Runnable {
     97 public:
     98  RunOnThread(nsIAsyncInputStream* aStream, nsIInputStreamCallback* aCallback)
     99      : Runnable("net::RunOnThread"), mStream(aStream), mCallback(aCallback) {}
    100 
    101  virtual ~RunOnThread() = default;
    102 
    103  NS_IMETHOD Run() override {
    104    mCallback->OnInputStreamReady(mStream);
    105    return NS_OK;
    106  }
    107 
    108 private:
    109  nsCOMPtr<nsIAsyncInputStream> mStream;
    110  nsCOMPtr<nsIInputStreamCallback> mCallback;
    111 };
    112 
    113 NS_IMETHODIMP
    114 nsPreloadedStream::AsyncWait(nsIInputStreamCallback* aCallback, uint32_t aFlags,
    115                             uint32_t aRequestedCount,
    116                             nsIEventTarget* aEventTarget) {
    117  if (!mLen) {
    118    {
    119      auto lock = mCallback.Lock();
    120      *lock = aCallback;
    121    }
    122    return mStream->AsyncWait(aCallback ? this : nullptr, aFlags,
    123                              aRequestedCount, aEventTarget);
    124  }
    125 
    126  if (!aCallback) return NS_OK;
    127 
    128  if (!aEventTarget) return aCallback->OnInputStreamReady(this);
    129 
    130  nsCOMPtr<nsIRunnable> event = new RunOnThread(this, aCallback);
    131  return aEventTarget->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
    132 }
    133 
    134 NS_IMETHODIMP
    135 nsPreloadedStream::OnInputStreamReady(nsIAsyncInputStream* aStream) {
    136  nsCOMPtr<nsIInputStreamCallback> callback;
    137  {
    138    auto lock = mCallback.Lock();
    139    callback = lock->forget();
    140  }
    141  if (callback) {
    142    return callback->OnInputStreamReady(this);
    143  }
    144  return NS_OK;
    145 }
    146 
    147 }  // namespace net
    148 }  // namespace mozilla