123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "nsStreamLoader.h"
- #include "nsIInputStream.h"
- #include "nsIChannel.h"
- #include "nsError.h"
- #include "GeckoProfiler.h"
- #include <limits>
- namespace mozilla {
- namespace net {
- nsStreamLoader::nsStreamLoader()
- : mData()
- {
- }
- nsStreamLoader::~nsStreamLoader()
- {
- }
- NS_IMETHODIMP
- nsStreamLoader::Init(nsIStreamLoaderObserver* aStreamObserver,
- nsIRequestObserver* aRequestObserver)
- {
- NS_ENSURE_ARG_POINTER(aStreamObserver);
- mObserver = aStreamObserver;
- mRequestObserver = aRequestObserver;
- return NS_OK;
- }
- nsresult
- nsStreamLoader::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
- {
- if (aOuter) return NS_ERROR_NO_AGGREGATION;
- nsStreamLoader* it = new nsStreamLoader();
- if (it == nullptr)
- return NS_ERROR_OUT_OF_MEMORY;
- NS_ADDREF(it);
- nsresult rv = it->QueryInterface(aIID, aResult);
- NS_RELEASE(it);
- return rv;
- }
- NS_IMPL_ISUPPORTS(nsStreamLoader, nsIStreamLoader,
- nsIRequestObserver, nsIStreamListener,
- nsIThreadRetargetableStreamListener)
- NS_IMETHODIMP
- nsStreamLoader::GetNumBytesRead(uint32_t* aNumBytes)
- {
- *aNumBytes = mBytesRead;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsStreamLoader::GetRequest(nsIRequest **aRequest)
- {
- NS_IF_ADDREF(*aRequest = mRequest);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsStreamLoader::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
- {
- nsCOMPtr<nsIChannel> chan( do_QueryInterface(request) );
- if (chan) {
- int64_t contentLength = -1;
- chan->GetContentLength(&contentLength);
- if (contentLength >= 0) {
- if (uint64_t(contentLength) > std::numeric_limits<size_t>::max()) {
- // Too big to fit into size_t, so let's bail.
- return NS_ERROR_OUT_OF_MEMORY;
- }
- // preallocate buffer
- if (!mData.initCapacity(contentLength)) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- }
- }
- mContext = ctxt;
- if (mRequestObserver) {
- mRequestObserver->OnStartRequest(request, ctxt);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsStreamLoader::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
- nsresult aStatus)
- {
- PROFILER_LABEL("nsStreamLoader", "OnStopRequest",
- js::ProfileEntry::Category::NETWORK);
- if (mObserver) {
- // provide nsIStreamLoader::request during call to OnStreamComplete
- mRequest = request;
- size_t length = mData.length();
- uint8_t* elems = mData.extractOrCopyRawBuffer();
- nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus,
- length, elems);
- if (rv != NS_SUCCESS_ADOPTED_DATA) {
- // The observer didn't take ownership of the extracted data buffer, so
- // put it back into mData.
- mData.replaceRawBuffer(elems, length);
- }
- // done.. cleanup
- ReleaseData();
- mRequest = nullptr;
- mObserver = nullptr;
- mContext = nullptr;
- }
- if (mRequestObserver) {
- mRequestObserver->OnStopRequest(request, ctxt, aStatus);
- mRequestObserver = nullptr;
- }
- return NS_OK;
- }
- nsresult
- nsStreamLoader::WriteSegmentFun(nsIInputStream *inStr,
- void *closure,
- const char *fromSegment,
- uint32_t toOffset,
- uint32_t count,
- uint32_t *writeCount)
- {
- nsStreamLoader *self = (nsStreamLoader *) closure;
- if (!self->mData.append(fromSegment, count)) {
- self->mData.clearAndFree();
- return NS_ERROR_OUT_OF_MEMORY;
- }
- *writeCount = count;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsStreamLoader::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
- nsIInputStream *inStr,
- uint64_t sourceOffset, uint32_t count)
- {
- uint32_t countRead;
- nsresult rv = inStr->ReadSegments(WriteSegmentFun, this, count, &countRead);
- NS_ENSURE_SUCCESS(rv, rv);
- mBytesRead += countRead;
- return NS_OK;
- }
- void
- nsStreamLoader::ReleaseData()
- {
- mData.clearAndFree();
- }
- NS_IMETHODIMP
- nsStreamLoader::CheckListenerChain()
- {
- return NS_OK;
- }
- } // namespace net
- } // namespace mozilla
|