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