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"
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
)
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
);
46 return inputStream
.forget();
49 nsCOMPtr
<nsIAsyncInputStreamLength
> asyncLength
=
50 do_QueryInterface(inputStream
);
52 return inputStream
.forget();
55 nsCOMPtr
<nsIAsyncInputStream
> asyncStream
= do_QueryInterface(inputStream
);
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),
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),
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
130 InputStreamLengthWrapper::Close() {
131 NS_ENSURE_STATE(mInputStream
);
132 return mInputStream
->Close();
136 InputStreamLengthWrapper::Available(uint64_t* aLength
) {
137 NS_ENSURE_STATE(mInputStream
);
138 return mInputStream
->Available(aLength
);
142 InputStreamLengthWrapper::StreamStatus() {
143 NS_ENSURE_STATE(mInputStream
);
144 return mInputStream
->StreamStatus();
148 InputStreamLengthWrapper::Read(char* aBuffer
, uint32_t aCount
,
149 uint32_t* aReadCount
) {
150 NS_ENSURE_STATE(mInputStream
);
152 return mInputStream
->Read(aBuffer
, aCount
, aReadCount
);
156 InputStreamLengthWrapper::ReadSegments(nsWriteSegmentFun aWriter
,
157 void* aClosure
, uint32_t aCount
,
159 return NS_ERROR_NOT_IMPLEMENTED
;
163 InputStreamLengthWrapper::IsNonBlocking(bool* aNonBlocking
) {
164 NS_ENSURE_STATE(mInputStream
);
165 return mInputStream
->IsNonBlocking(aNonBlocking
);
168 // nsICloneableInputStream interface
171 InputStreamLengthWrapper::GetCloneable(bool* aCloneable
) {
172 NS_ENSURE_STATE(mInputStream
);
173 NS_ENSURE_STATE(mWeakCloneableInputStream
);
174 mWeakCloneableInputStream
->GetCloneable(aCloneable
);
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
))) {
189 nsCOMPtr
<nsIInputStream
> stream
=
190 new InputStreamLengthWrapper(clonedStream
.forget(), mLength
);
192 stream
.forget(aResult
);
196 // nsIAsyncInputStream interface
199 InputStreamLengthWrapper::CloseWithStatus(nsresult aStatus
) {
200 NS_ENSURE_STATE(mInputStream
);
201 NS_ENSURE_STATE(mWeakAsyncInputStream
);
204 return mWeakAsyncInputStream
->CloseWithStatus(aStatus
);
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
,
230 // nsIInputStreamCallback
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
) {
246 callback
.swap(mAsyncWaitCallback
);
249 MOZ_ASSERT(callback
);
250 return callback
->OnInputStreamReady(this);
253 // nsIIPCSerializableInputStream
255 void InputStreamLengthWrapper::SerializedComplexity(uint32_t aMaxSize
,
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
;
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!");
288 const InputStreamLengthWrapperParams
& params
=
289 aParams
.get_InputStreamLengthWrapperParams();
291 nsCOMPtr
<nsIInputStream
> stream
=
292 InputStreamHelper::DeserializeInputStream(params
.stream());
294 NS_WARNING("Deserialize failed!");
298 SetSourceStream(stream
.forget());
300 mLength
= params
.length();
301 mConsumed
= params
.consumed();
309 InputStreamLengthWrapper::Seek(int32_t aWhence
, int64_t aOffset
) {
310 NS_ENSURE_STATE(mInputStream
);
311 NS_ENSURE_STATE(mWeakSeekableInputStream
);
314 return mWeakSeekableInputStream
->Seek(aWhence
, aOffset
);
318 InputStreamLengthWrapper::SetEOF() {
319 NS_ENSURE_STATE(mInputStream
);
320 NS_ENSURE_STATE(mWeakSeekableInputStream
);
323 return mWeakSeekableInputStream
->SetEOF();
329 InputStreamLengthWrapper::Tell(int64_t* aResult
) {
330 NS_ENSURE_STATE(mInputStream
);
331 NS_ENSURE_STATE(mWeakTellableInputStream
);
333 return mWeakTellableInputStream
->Tell(aResult
);
336 // nsIInputStreamLength
339 InputStreamLengthWrapper::Length(int64_t* aLength
) {
340 NS_ENSURE_STATE(mInputStream
);
345 } // namespace mozilla