Merge autoland to mozilla-central. a=merge
[gecko.git] / xpcom / io / InputStreamLengthWrapper.cpp
blob9ba4968ad2735c47f44c3265a2046775d7866cf5
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "InputStreamLengthWrapper.h"
8 #include "mozilla/ipc/InputStreamUtils.h"
9 #include "nsISeekableStream.h"
10 #include "nsStreamUtils.h"
12 namespace mozilla {
14 using namespace ipc;
16 NS_IMPL_ADDREF(InputStreamLengthWrapper);
17 NS_IMPL_RELEASE(InputStreamLengthWrapper);
19 NS_INTERFACE_MAP_BEGIN(InputStreamLengthWrapper)
20 NS_INTERFACE_MAP_ENTRY(nsIInputStream)
21 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
22 mWeakCloneableInputStream || !mInputStream)
23 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(
24 nsIIPCSerializableInputStream,
25 mWeakIPCSerializableInputStream || !mInputStream)
26 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream,
27 mWeakSeekableInputStream || !mInputStream)
28 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream,
29 mWeakTellableInputStream || !mInputStream)
30 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
31 mWeakAsyncInputStream || !mInputStream)
32 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
33 mWeakAsyncInputStream || !mInputStream)
34 NS_INTERFACE_MAP_ENTRY(nsIInputStreamLength)
35 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
36 NS_INTERFACE_MAP_END
38 /* static */
39 already_AddRefed<nsIInputStream> InputStreamLengthWrapper::MaybeWrap(
40 already_AddRefed<nsIInputStream> aInputStream, int64_t aLength) {
41 nsCOMPtr<nsIInputStream> inputStream = std::move(aInputStream);
42 MOZ_ASSERT(inputStream);
44 nsCOMPtr<nsIInputStreamLength> length = do_QueryInterface(inputStream);
45 if (length) {
46 return inputStream.forget();
49 nsCOMPtr<nsIAsyncInputStreamLength> asyncLength =
50 do_QueryInterface(inputStream);
51 if (asyncLength) {
52 return inputStream.forget();
55 nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(inputStream);
56 if (!asyncStream) {
57 return inputStream.forget();
60 inputStream = new InputStreamLengthWrapper(inputStream.forget(), aLength);
61 return inputStream.forget();
64 InputStreamLengthWrapper::InputStreamLengthWrapper(
65 already_AddRefed<nsIInputStream> aInputStream, int64_t aLength)
66 : mWeakCloneableInputStream(nullptr),
67 mWeakIPCSerializableInputStream(nullptr),
68 mWeakSeekableInputStream(nullptr),
69 mWeakTellableInputStream(nullptr),
70 mWeakAsyncInputStream(nullptr),
71 mLength(aLength),
72 mConsumed(false),
73 mMutex("InputStreamLengthWrapper::mMutex") {
74 MOZ_ASSERT(mLength >= 0);
76 nsCOMPtr<nsIInputStream> inputStream = std::move(aInputStream);
77 SetSourceStream(inputStream.forget());
80 InputStreamLengthWrapper::InputStreamLengthWrapper()
81 : mWeakCloneableInputStream(nullptr),
82 mWeakIPCSerializableInputStream(nullptr),
83 mWeakSeekableInputStream(nullptr),
84 mWeakTellableInputStream(nullptr),
85 mWeakAsyncInputStream(nullptr),
86 mLength(-1),
87 mConsumed(false),
88 mMutex("InputStreamLengthWrapper::mMutex") {}
90 InputStreamLengthWrapper::~InputStreamLengthWrapper() = default;
92 void InputStreamLengthWrapper::SetSourceStream(
93 already_AddRefed<nsIInputStream> aInputStream) {
94 MOZ_ASSERT(!mInputStream);
96 mInputStream = std::move(aInputStream);
98 nsCOMPtr<nsICloneableInputStream> cloneableStream =
99 do_QueryInterface(mInputStream);
100 if (cloneableStream && SameCOMIdentity(mInputStream, cloneableStream)) {
101 mWeakCloneableInputStream = cloneableStream;
104 nsCOMPtr<nsIIPCSerializableInputStream> serializableStream =
105 do_QueryInterface(mInputStream);
106 if (serializableStream && SameCOMIdentity(mInputStream, serializableStream)) {
107 mWeakIPCSerializableInputStream = serializableStream;
110 nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mInputStream);
111 if (seekableStream && SameCOMIdentity(mInputStream, seekableStream)) {
112 mWeakSeekableInputStream = seekableStream;
115 nsCOMPtr<nsITellableStream> tellableStream = do_QueryInterface(mInputStream);
116 if (tellableStream && SameCOMIdentity(mInputStream, tellableStream)) {
117 mWeakTellableInputStream = tellableStream;
120 nsCOMPtr<nsIAsyncInputStream> asyncInputStream =
121 do_QueryInterface(mInputStream);
122 if (asyncInputStream && SameCOMIdentity(mInputStream, asyncInputStream)) {
123 mWeakAsyncInputStream = asyncInputStream;
127 // nsIInputStream interface
129 NS_IMETHODIMP
130 InputStreamLengthWrapper::Close() {
131 NS_ENSURE_STATE(mInputStream);
132 return mInputStream->Close();
135 NS_IMETHODIMP
136 InputStreamLengthWrapper::Available(uint64_t* aLength) {
137 NS_ENSURE_STATE(mInputStream);
138 return mInputStream->Available(aLength);
141 NS_IMETHODIMP
142 InputStreamLengthWrapper::StreamStatus() {
143 NS_ENSURE_STATE(mInputStream);
144 return mInputStream->StreamStatus();
147 NS_IMETHODIMP
148 InputStreamLengthWrapper::Read(char* aBuffer, uint32_t aCount,
149 uint32_t* aReadCount) {
150 NS_ENSURE_STATE(mInputStream);
151 mConsumed = true;
152 return mInputStream->Read(aBuffer, aCount, aReadCount);
155 NS_IMETHODIMP
156 InputStreamLengthWrapper::ReadSegments(nsWriteSegmentFun aWriter,
157 void* aClosure, uint32_t aCount,
158 uint32_t* aResult) {
159 return NS_ERROR_NOT_IMPLEMENTED;
162 NS_IMETHODIMP
163 InputStreamLengthWrapper::IsNonBlocking(bool* aNonBlocking) {
164 NS_ENSURE_STATE(mInputStream);
165 return mInputStream->IsNonBlocking(aNonBlocking);
168 // nsICloneableInputStream interface
170 NS_IMETHODIMP
171 InputStreamLengthWrapper::GetCloneable(bool* aCloneable) {
172 NS_ENSURE_STATE(mInputStream);
173 NS_ENSURE_STATE(mWeakCloneableInputStream);
174 mWeakCloneableInputStream->GetCloneable(aCloneable);
175 return NS_OK;
178 NS_IMETHODIMP
179 InputStreamLengthWrapper::Clone(nsIInputStream** aResult) {
180 NS_ENSURE_STATE(mInputStream);
181 NS_ENSURE_STATE(mWeakCloneableInputStream);
183 nsCOMPtr<nsIInputStream> clonedStream;
184 nsresult rv = mWeakCloneableInputStream->Clone(getter_AddRefs(clonedStream));
185 if (NS_WARN_IF(NS_FAILED(rv))) {
186 return rv;
189 nsCOMPtr<nsIInputStream> stream =
190 new InputStreamLengthWrapper(clonedStream.forget(), mLength);
192 stream.forget(aResult);
193 return NS_OK;
196 // nsIAsyncInputStream interface
198 NS_IMETHODIMP
199 InputStreamLengthWrapper::CloseWithStatus(nsresult aStatus) {
200 NS_ENSURE_STATE(mInputStream);
201 NS_ENSURE_STATE(mWeakAsyncInputStream);
203 mConsumed = true;
204 return mWeakAsyncInputStream->CloseWithStatus(aStatus);
207 NS_IMETHODIMP
208 InputStreamLengthWrapper::AsyncWait(nsIInputStreamCallback* aCallback,
209 uint32_t aFlags, uint32_t aRequestedCount,
210 nsIEventTarget* aEventTarget) {
211 NS_ENSURE_STATE(mInputStream);
212 NS_ENSURE_STATE(mWeakAsyncInputStream);
214 nsCOMPtr<nsIInputStreamCallback> callback = aCallback ? this : nullptr;
216 MutexAutoLock lock(mMutex);
218 if (NS_WARN_IF(mAsyncWaitCallback && aCallback &&
219 mAsyncWaitCallback != aCallback)) {
220 return NS_ERROR_FAILURE;
223 mAsyncWaitCallback = aCallback;
226 return mWeakAsyncInputStream->AsyncWait(callback, aFlags, aRequestedCount,
227 aEventTarget);
230 // nsIInputStreamCallback
232 NS_IMETHODIMP
233 InputStreamLengthWrapper::OnInputStreamReady(nsIAsyncInputStream* aStream) {
234 MOZ_ASSERT(mInputStream);
235 MOZ_ASSERT(mWeakAsyncInputStream);
236 MOZ_ASSERT(mWeakAsyncInputStream == aStream);
238 nsCOMPtr<nsIInputStreamCallback> callback;
240 MutexAutoLock lock(mMutex);
241 // We have been canceled in the meanwhile.
242 if (!mAsyncWaitCallback) {
243 return NS_OK;
246 callback.swap(mAsyncWaitCallback);
249 MOZ_ASSERT(callback);
250 return callback->OnInputStreamReady(this);
253 // nsIIPCSerializableInputStream
255 void InputStreamLengthWrapper::SerializedComplexity(uint32_t aMaxSize,
256 uint32_t* aSizeUsed,
257 uint32_t* aPipes,
258 uint32_t* aTransferables) {
259 InputStreamHelper::SerializedComplexity(mInputStream, aMaxSize, aSizeUsed,
260 aPipes, aTransferables);
263 void InputStreamLengthWrapper::Serialize(
264 mozilla::ipc::InputStreamParams& aParams, uint32_t aMaxSize,
265 uint32_t* aSizeUsed) {
266 MOZ_ASSERT(mInputStream);
267 MOZ_ASSERT(mWeakIPCSerializableInputStream);
269 InputStreamLengthWrapperParams params;
270 InputStreamHelper::SerializeInputStream(mInputStream, params.stream(),
271 aMaxSize, aSizeUsed);
272 params.length() = mLength;
273 params.consumed() = mConsumed;
275 aParams = params;
278 bool InputStreamLengthWrapper::Deserialize(
279 const mozilla::ipc::InputStreamParams& aParams) {
280 MOZ_ASSERT(!mInputStream);
281 MOZ_ASSERT(!mWeakIPCSerializableInputStream);
283 if (aParams.type() != InputStreamParams::TInputStreamLengthWrapperParams) {
284 NS_ERROR("Received unknown parameters from the other process!");
285 return false;
288 const InputStreamLengthWrapperParams& params =
289 aParams.get_InputStreamLengthWrapperParams();
291 nsCOMPtr<nsIInputStream> stream =
292 InputStreamHelper::DeserializeInputStream(params.stream());
293 if (!stream) {
294 NS_WARNING("Deserialize failed!");
295 return false;
298 SetSourceStream(stream.forget());
300 mLength = params.length();
301 mConsumed = params.consumed();
303 return true;
306 // nsISeekableStream
308 NS_IMETHODIMP
309 InputStreamLengthWrapper::Seek(int32_t aWhence, int64_t aOffset) {
310 NS_ENSURE_STATE(mInputStream);
311 NS_ENSURE_STATE(mWeakSeekableInputStream);
313 mConsumed = true;
314 return mWeakSeekableInputStream->Seek(aWhence, aOffset);
317 NS_IMETHODIMP
318 InputStreamLengthWrapper::SetEOF() {
319 NS_ENSURE_STATE(mInputStream);
320 NS_ENSURE_STATE(mWeakSeekableInputStream);
322 mConsumed = true;
323 return mWeakSeekableInputStream->SetEOF();
326 // nsITellableStream
328 NS_IMETHODIMP
329 InputStreamLengthWrapper::Tell(int64_t* aResult) {
330 NS_ENSURE_STATE(mInputStream);
331 NS_ENSURE_STATE(mWeakTellableInputStream);
333 return mWeakTellableInputStream->Tell(aResult);
336 // nsIInputStreamLength
338 NS_IMETHODIMP
339 InputStreamLengthWrapper::Length(int64_t* aLength) {
340 NS_ENSURE_STATE(mInputStream);
341 *aLength = mLength;
342 return NS_OK;
345 } // namespace mozilla