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 "InputStreamUtils.h"
9 #include "nsIIPCSerializableInputStream.h"
11 #include "mozilla/Assertions.h"
12 #include "mozilla/dom/File.h"
13 #include "mozilla/dom/quota/DecryptingInputStream_impl.h"
14 #include "mozilla/dom/quota/IPCStreamCipherStrategy.h"
15 #include "mozilla/ipc/DataPipe.h"
16 #include "mozilla/InputStreamLengthHelper.h"
17 #include "mozilla/RemoteLazyInputStream.h"
18 #include "mozilla/RemoteLazyInputStreamChild.h"
19 #include "mozilla/RemoteLazyInputStreamStorage.h"
20 #include "mozilla/SlicedInputStream.h"
21 #include "mozilla/InputStreamLengthWrapper.h"
22 #include "nsBufferedStreams.h"
23 #include "nsComponentManagerUtils.h"
25 #include "nsFileStreams.h"
26 #include "nsIAsyncInputStream.h"
27 #include "nsIAsyncOutputStream.h"
29 #include "nsIMIMEInputStream.h"
30 #include "nsIMultiplexInputStream.h"
32 #include "nsMIMEInputStream.h"
33 #include "nsMultiplexInputStream.h"
35 #include "nsStreamUtils.h"
36 #include "nsStringStream.h"
37 #include "nsXULAppAPI.h"
39 using namespace mozilla
;
40 using namespace mozilla::dom
;
45 void InputStreamHelper::SerializedComplexity(nsIInputStream
* aInputStream
,
49 uint32_t* aTransferables
) {
50 MOZ_ASSERT(aInputStream
);
52 nsCOMPtr
<nsIIPCSerializableInputStream
> serializable
=
53 do_QueryInterface(aInputStream
);
55 MOZ_CRASH("Input stream is not serializable!");
58 serializable
->SerializedComplexity(aMaxSize
, aSizeUsed
, aPipes
,
62 void InputStreamHelper::SerializeInputStream(nsIInputStream
* aInputStream
,
63 InputStreamParams
& aParams
,
65 uint32_t* aSizeUsed
) {
66 MOZ_ASSERT(aInputStream
);
68 nsCOMPtr
<nsIIPCSerializableInputStream
> serializable
=
69 do_QueryInterface(aInputStream
);
71 MOZ_CRASH("Input stream is not serializable!");
74 serializable
->Serialize(aParams
, aMaxSize
, aSizeUsed
);
76 if (aParams
.type() == InputStreamParams::T__None
) {
77 MOZ_CRASH("Serialize failed!");
81 void InputStreamHelper::SerializeInputStreamAsPipe(nsIInputStream
* aInputStream
,
82 InputStreamParams
& aParams
) {
83 MOZ_ASSERT(aInputStream
);
85 // Let's try to take the length using InputStreamLengthHelper. If the length
86 // cannot be taken synchronously, and its length is needed, the stream needs
87 // to be fully copied in memory on the deserialization side.
89 if (!InputStreamLengthHelper::GetSyncLength(aInputStream
, &length
)) {
93 RefPtr
<DataPipeSender
> sender
;
94 RefPtr
<DataPipeReceiver
> receiver
;
95 nsresult rv
= NewDataPipe(kDefaultDataPipeCapacity
, getter_AddRefs(sender
),
96 getter_AddRefs(receiver
));
97 if (NS_WARN_IF(NS_FAILED(rv
))) {
101 nsCOMPtr
<nsIEventTarget
> target
=
102 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID
);
105 NS_AsyncCopy(aInputStream
, sender
, target
, NS_ASYNCCOPY_VIA_WRITESEGMENTS
,
106 kDefaultDataPipeCapacity
, nullptr, nullptr);
107 if (NS_WARN_IF(NS_FAILED(rv
))) {
111 aParams
= DataPipeReceiverStreamParams(WrapNotNull(receiver
));
113 aParams
= InputStreamLengthWrapperParams(aParams
, length
, false);
117 already_AddRefed
<nsIInputStream
> InputStreamHelper::DeserializeInputStream(
118 const InputStreamParams
& aParams
) {
119 if (aParams
.type() == InputStreamParams::TRemoteLazyInputStreamParams
) {
120 const RemoteLazyInputStreamParams
& params
=
121 aParams
.get_RemoteLazyInputStreamParams();
123 // If the RemoteLazyInputStream already has an internal stream, unwrap it.
124 // This is required as some code unfortunately depends on the precise
125 // topology of received streams, and cannot handle being passed a
126 // `RemoteLazyInputStream` in the parent process.
127 nsCOMPtr
<nsIInputStream
> innerStream
;
128 if (XRE_IsParentProcess() &&
130 params
.stream()->TakeInternalStream(getter_AddRefs(innerStream
)))) {
131 return innerStream
.forget();
133 return do_AddRef(params
.stream().get());
136 if (aParams
.type() == InputStreamParams::TDataPipeReceiverStreamParams
) {
137 const DataPipeReceiverStreamParams
& pipeParams
=
138 aParams
.get_DataPipeReceiverStreamParams();
139 return do_AddRef(pipeParams
.pipe().get());
142 nsCOMPtr
<nsIIPCSerializableInputStream
> serializable
;
144 switch (aParams
.type()) {
145 case InputStreamParams::TStringInputStreamParams
: {
146 nsCOMPtr
<nsIInputStream
> stream
;
147 NS_NewCStringInputStream(getter_AddRefs(stream
), ""_ns
);
148 serializable
= do_QueryInterface(stream
);
151 case InputStreamParams::TFileInputStreamParams
: {
152 nsCOMPtr
<nsIFileInputStream
> stream
;
153 nsFileInputStream::Create(NS_GET_IID(nsIFileInputStream
),
154 getter_AddRefs(stream
));
155 serializable
= do_QueryInterface(stream
);
158 case InputStreamParams::TBufferedInputStreamParams
: {
159 nsCOMPtr
<nsIBufferedInputStream
> stream
;
160 nsBufferedInputStream::Create(NS_GET_IID(nsIBufferedInputStream
),
161 getter_AddRefs(stream
));
162 serializable
= do_QueryInterface(stream
);
165 case InputStreamParams::TMIMEInputStreamParams
: {
166 nsCOMPtr
<nsIMIMEInputStream
> stream
;
167 nsMIMEInputStreamConstructor(NS_GET_IID(nsIMIMEInputStream
),
168 getter_AddRefs(stream
));
169 serializable
= do_QueryInterface(stream
);
172 case InputStreamParams::TMultiplexInputStreamParams
: {
173 nsCOMPtr
<nsIMultiplexInputStream
> stream
;
174 nsMultiplexInputStreamConstructor(NS_GET_IID(nsIMultiplexInputStream
),
175 getter_AddRefs(stream
));
176 serializable
= do_QueryInterface(stream
);
179 case InputStreamParams::TSlicedInputStreamParams
:
180 serializable
= new SlicedInputStream();
183 case InputStreamParams::TInputStreamLengthWrapperParams
:
184 serializable
= new InputStreamLengthWrapper();
187 case InputStreamParams::TEncryptedFileInputStreamParams
:
188 serializable
= new dom::quota::DecryptingInputStream
<
189 dom::quota::IPCStreamCipherStrategy
>();
193 MOZ_ASSERT(false, "Unknown params!");
197 MOZ_ASSERT(serializable
);
199 if (!serializable
->Deserialize(aParams
)) {
200 MOZ_ASSERT(false, "Deserialize failed!");
204 nsCOMPtr
<nsIInputStream
> stream
= do_QueryInterface(serializable
);
207 return stream
.forget();
211 } // namespace mozilla