Source code

Revision control

Other Tools

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 "GeckoProfiler.h"
11
12
#include <limits>
13
14
namespace mozilla {
15
namespace net {
16
17
nsStreamLoader::nsStreamLoader() : mData() {}
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(nsISupports* aOuter, REFNSIID aIID,
29
void** aResult) {
30
if (aOuter) return NS_ERROR_NO_AGGREGATION;
31
32
RefPtr<nsStreamLoader> it = new nsStreamLoader();
33
return it->QueryInterface(aIID, aResult);
34
}
35
36
NS_IMPL_ISUPPORTS(nsStreamLoader, nsIStreamLoader, nsIRequestObserver,
37
nsIStreamListener, nsIThreadRetargetableStreamListener)
38
39
NS_IMETHODIMP
40
nsStreamLoader::GetNumBytesRead(uint32_t* aNumBytes) {
41
*aNumBytes = mData.length();
42
return NS_OK;
43
}
44
45
NS_IMETHODIMP
46
nsStreamLoader::GetRequest(nsIRequest** aRequest) {
47
nsCOMPtr<nsIRequest> req = mRequest;
48
req.forget(aRequest);
49
return NS_OK;
50
}
51
52
NS_IMETHODIMP
53
nsStreamLoader::OnStartRequest(nsIRequest* request) {
54
nsCOMPtr<nsIChannel> chan(do_QueryInterface(request));
55
if (chan) {
56
int64_t contentLength = -1;
57
chan->GetContentLength(&contentLength);
58
if (contentLength >= 0) {
59
// On 64bit platforms size of uint64_t coincides with the size of size_t,
60
// so we want to compare with the minimum from size_t and int64_t.
61
if (static_cast<uint64_t>(contentLength) >
62
std::min(std::numeric_limits<size_t>::max(),
63
static_cast<size_t>(std::numeric_limits<int64_t>::max()))) {
64
// Too big to fit into size_t, so let's bail.
65
return NS_ERROR_OUT_OF_MEMORY;
66
}
67
// preallocate buffer
68
if (!mData.initCapacity(contentLength)) {
69
return NS_ERROR_OUT_OF_MEMORY;
70
}
71
}
72
}
73
if (mRequestObserver) {
74
mRequestObserver->OnStartRequest(request);
75
}
76
return NS_OK;
77
}
78
79
NS_IMETHODIMP
80
nsStreamLoader::OnStopRequest(nsIRequest* request, nsresult aStatus) {
81
AUTO_PROFILER_LABEL("nsStreamLoader::OnStopRequest", NETWORK);
82
83
if (mObserver) {
84
// provide nsIStreamLoader::request during call to OnStreamComplete
85
mRequest = request;
86
size_t length = mData.length();
87
uint8_t* elems = mData.extractOrCopyRawBuffer();
88
nsresult rv =
89
mObserver->OnStreamComplete(this, mContext, aStatus, length, elems);
90
if (rv != NS_SUCCESS_ADOPTED_DATA) {
91
// The observer didn't take ownership of the extracted data buffer, so
92
// put it back into mData.
93
mData.replaceRawBuffer(elems, length);
94
}
95
// done.. cleanup
96
ReleaseData();
97
mRequest = nullptr;
98
mObserver = nullptr;
99
}
100
101
if (mRequestObserver) {
102
mRequestObserver->OnStopRequest(request, aStatus);
103
mRequestObserver = nullptr;
104
}
105
106
return NS_OK;
107
}
108
109
nsresult nsStreamLoader::WriteSegmentFun(nsIInputStream* inStr, void* closure,
110
const char* fromSegment,
111
uint32_t toOffset, uint32_t count,
112
uint32_t* writeCount) {
113
nsStreamLoader* self = (nsStreamLoader*)closure;
114
115
if (!self->mData.append(fromSegment, count)) {
116
self->mData.clearAndFree();
117
return NS_ERROR_OUT_OF_MEMORY;
118
}
119
120
*writeCount = count;
121
122
return NS_OK;
123
}
124
125
NS_IMETHODIMP
126
nsStreamLoader::OnDataAvailable(nsIRequest* request, nsIInputStream* inStr,
127
uint64_t sourceOffset, uint32_t count) {
128
uint32_t countRead;
129
return inStr->ReadSegments(WriteSegmentFun, this, count, &countRead);
130
}
131
132
void nsStreamLoader::ReleaseData() { mData.clearAndFree(); }
133
134
NS_IMETHODIMP
135
nsStreamLoader::CheckListenerChain() { return NS_OK; }
136
137
} // namespace net
138
} // namespace mozilla