1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/base/src/nsStreamLoader.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,164 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsStreamLoader.h" 1.10 +#include "nsIInputStream.h" 1.11 +#include "nsIChannel.h" 1.12 +#include "nsError.h" 1.13 +#include "GeckoProfiler.h" 1.14 + 1.15 +nsStreamLoader::nsStreamLoader() 1.16 + : mData(nullptr), 1.17 + mAllocated(0), 1.18 + mLength(0) 1.19 +{ 1.20 +} 1.21 + 1.22 +nsStreamLoader::~nsStreamLoader() 1.23 +{ 1.24 + ReleaseData(); 1.25 +} 1.26 + 1.27 +NS_IMETHODIMP 1.28 +nsStreamLoader::Init(nsIStreamLoaderObserver* observer) 1.29 +{ 1.30 + NS_ENSURE_ARG_POINTER(observer); 1.31 + mObserver = observer; 1.32 + return NS_OK; 1.33 +} 1.34 + 1.35 +nsresult 1.36 +nsStreamLoader::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) 1.37 +{ 1.38 + if (aOuter) return NS_ERROR_NO_AGGREGATION; 1.39 + 1.40 + nsStreamLoader* it = new nsStreamLoader(); 1.41 + if (it == nullptr) 1.42 + return NS_ERROR_OUT_OF_MEMORY; 1.43 + NS_ADDREF(it); 1.44 + nsresult rv = it->QueryInterface(aIID, aResult); 1.45 + NS_RELEASE(it); 1.46 + return rv; 1.47 +} 1.48 + 1.49 +NS_IMPL_ISUPPORTS(nsStreamLoader, nsIStreamLoader, 1.50 + nsIRequestObserver, nsIStreamListener) 1.51 + 1.52 +NS_IMETHODIMP 1.53 +nsStreamLoader::GetNumBytesRead(uint32_t* aNumBytes) 1.54 +{ 1.55 + *aNumBytes = mLength; 1.56 + return NS_OK; 1.57 +} 1.58 + 1.59 +/* readonly attribute nsIRequest request; */ 1.60 +NS_IMETHODIMP 1.61 +nsStreamLoader::GetRequest(nsIRequest **aRequest) 1.62 +{ 1.63 + NS_IF_ADDREF(*aRequest = mRequest); 1.64 + return NS_OK; 1.65 +} 1.66 + 1.67 +NS_IMETHODIMP 1.68 +nsStreamLoader::OnStartRequest(nsIRequest* request, nsISupports *ctxt) 1.69 +{ 1.70 + nsCOMPtr<nsIChannel> chan( do_QueryInterface(request) ); 1.71 + if (chan) { 1.72 + int64_t contentLength = -1; 1.73 + chan->GetContentLength(&contentLength); 1.74 + if (contentLength >= 0) { 1.75 + if (contentLength > UINT32_MAX) { 1.76 + // Too big to fit into uint32, so let's bail. 1.77 + // XXX we should really make mAllocated and mLength 64-bit instead. 1.78 + return NS_ERROR_OUT_OF_MEMORY; 1.79 + } 1.80 + uint32_t contentLength32 = uint32_t(contentLength); 1.81 + // preallocate buffer 1.82 + mData = static_cast<uint8_t*>(moz_malloc(contentLength32)); 1.83 + if (!mData) { 1.84 + return NS_ERROR_OUT_OF_MEMORY; 1.85 + } 1.86 + mAllocated = contentLength32; 1.87 + } 1.88 + } 1.89 + mContext = ctxt; 1.90 + return NS_OK; 1.91 +} 1.92 + 1.93 +NS_IMETHODIMP 1.94 +nsStreamLoader::OnStopRequest(nsIRequest* request, nsISupports *ctxt, 1.95 + nsresult aStatus) 1.96 +{ 1.97 + PROFILER_LABEL("network", "nsStreamLoader::OnStopRequest"); 1.98 + if (mObserver) { 1.99 + // provide nsIStreamLoader::request during call to OnStreamComplete 1.100 + mRequest = request; 1.101 + nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus, 1.102 + mLength, mData); 1.103 + if (rv == NS_SUCCESS_ADOPTED_DATA) { 1.104 + // the observer now owns the data buffer, and the loader must 1.105 + // not deallocate it 1.106 + mData = nullptr; 1.107 + } 1.108 + // done.. cleanup 1.109 + ReleaseData(); 1.110 + mRequest = 0; 1.111 + mObserver = 0; 1.112 + mContext = 0; 1.113 + } 1.114 + return NS_OK; 1.115 +} 1.116 + 1.117 +NS_METHOD 1.118 +nsStreamLoader::WriteSegmentFun(nsIInputStream *inStr, 1.119 + void *closure, 1.120 + const char *fromSegment, 1.121 + uint32_t toOffset, 1.122 + uint32_t count, 1.123 + uint32_t *writeCount) 1.124 +{ 1.125 + nsStreamLoader *self = (nsStreamLoader *) closure; 1.126 + 1.127 + if (count > UINT32_MAX - self->mLength) { 1.128 + return NS_ERROR_ILLEGAL_VALUE; // is there a better error to use here? 1.129 + } 1.130 + 1.131 + if (self->mLength + count > self->mAllocated) { 1.132 + self->mData = static_cast<uint8_t*>(NS_Realloc(self->mData, 1.133 + self->mLength + count)); 1.134 + if (!self->mData) { 1.135 + self->ReleaseData(); 1.136 + return NS_ERROR_OUT_OF_MEMORY; 1.137 + } 1.138 + self->mAllocated = self->mLength + count; 1.139 + } 1.140 + 1.141 + ::memcpy(self->mData + self->mLength, fromSegment, count); 1.142 + self->mLength += count; 1.143 + 1.144 + *writeCount = count; 1.145 + 1.146 + return NS_OK; 1.147 +} 1.148 + 1.149 +NS_IMETHODIMP 1.150 +nsStreamLoader::OnDataAvailable(nsIRequest* request, nsISupports *ctxt, 1.151 + nsIInputStream *inStr, 1.152 + uint64_t sourceOffset, uint32_t count) 1.153 +{ 1.154 + uint32_t countRead; 1.155 + return inStr->ReadSegments(WriteSegmentFun, this, count, &countRead); 1.156 +} 1.157 + 1.158 +void 1.159 +nsStreamLoader::ReleaseData() 1.160 +{ 1.161 + if (mData) { 1.162 + NS_Free(mData); 1.163 + mData = nullptr; 1.164 + } 1.165 + mLength = 0; 1.166 + mAllocated = 0; 1.167 +}