no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / ipc / glue / InputStreamUtils.cpp
blob039582c94aa2d2c27ace5dce33361248e51d273f
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"
24 #include "nsDebug.h"
25 #include "nsFileStreams.h"
26 #include "nsIAsyncInputStream.h"
27 #include "nsIAsyncOutputStream.h"
28 #include "nsID.h"
29 #include "nsIMIMEInputStream.h"
30 #include "nsIMultiplexInputStream.h"
31 #include "nsIPipe.h"
32 #include "nsMIMEInputStream.h"
33 #include "nsMultiplexInputStream.h"
34 #include "nsNetCID.h"
35 #include "nsStreamUtils.h"
36 #include "nsStringStream.h"
37 #include "nsXULAppAPI.h"
39 using namespace mozilla;
40 using namespace mozilla::dom;
42 namespace mozilla {
43 namespace ipc {
45 void InputStreamHelper::SerializedComplexity(nsIInputStream* aInputStream,
46 uint32_t aMaxSize,
47 uint32_t* aSizeUsed,
48 uint32_t* aPipes,
49 uint32_t* aTransferables) {
50 MOZ_ASSERT(aInputStream);
52 nsCOMPtr<nsIIPCSerializableInputStream> serializable =
53 do_QueryInterface(aInputStream);
54 if (!serializable) {
55 MOZ_CRASH("Input stream is not serializable!");
58 serializable->SerializedComplexity(aMaxSize, aSizeUsed, aPipes,
59 aTransferables);
62 void InputStreamHelper::SerializeInputStream(nsIInputStream* aInputStream,
63 InputStreamParams& aParams,
64 uint32_t aMaxSize,
65 uint32_t* aSizeUsed) {
66 MOZ_ASSERT(aInputStream);
68 nsCOMPtr<nsIIPCSerializableInputStream> serializable =
69 do_QueryInterface(aInputStream);
70 if (!serializable) {
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.
88 int64_t length;
89 if (!InputStreamLengthHelper::GetSyncLength(aInputStream, &length)) {
90 length = -1;
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))) {
98 return;
101 nsCOMPtr<nsIEventTarget> target =
102 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
104 rv =
105 NS_AsyncCopy(aInputStream, sender, target, NS_ASYNCCOPY_VIA_WRITESEGMENTS,
106 kDefaultDataPipeCapacity, nullptr, nullptr);
107 if (NS_WARN_IF(NS_FAILED(rv))) {
108 return;
111 aParams = DataPipeReceiverStreamParams(WrapNotNull(receiver));
112 if (length != -1) {
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() &&
129 NS_SUCCEEDED(
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);
149 } break;
151 case InputStreamParams::TFileInputStreamParams: {
152 nsCOMPtr<nsIFileInputStream> stream;
153 nsFileInputStream::Create(NS_GET_IID(nsIFileInputStream),
154 getter_AddRefs(stream));
155 serializable = do_QueryInterface(stream);
156 } break;
158 case InputStreamParams::TBufferedInputStreamParams: {
159 nsCOMPtr<nsIBufferedInputStream> stream;
160 nsBufferedInputStream::Create(NS_GET_IID(nsIBufferedInputStream),
161 getter_AddRefs(stream));
162 serializable = do_QueryInterface(stream);
163 } break;
165 case InputStreamParams::TMIMEInputStreamParams: {
166 nsCOMPtr<nsIMIMEInputStream> stream;
167 nsMIMEInputStreamConstructor(NS_GET_IID(nsIMIMEInputStream),
168 getter_AddRefs(stream));
169 serializable = do_QueryInterface(stream);
170 } break;
172 case InputStreamParams::TMultiplexInputStreamParams: {
173 nsCOMPtr<nsIMultiplexInputStream> stream;
174 nsMultiplexInputStreamConstructor(NS_GET_IID(nsIMultiplexInputStream),
175 getter_AddRefs(stream));
176 serializable = do_QueryInterface(stream);
177 } break;
179 case InputStreamParams::TSlicedInputStreamParams:
180 serializable = new SlicedInputStream();
181 break;
183 case InputStreamParams::TInputStreamLengthWrapperParams:
184 serializable = new InputStreamLengthWrapper();
185 break;
187 case InputStreamParams::TEncryptedFileInputStreamParams:
188 serializable = new dom::quota::DecryptingInputStream<
189 dom::quota::IPCStreamCipherStrategy>();
190 break;
192 default:
193 MOZ_ASSERT(false, "Unknown params!");
194 return nullptr;
197 MOZ_ASSERT(serializable);
199 if (!serializable->Deserialize(aParams)) {
200 MOZ_ASSERT(false, "Deserialize failed!");
201 return nullptr;
204 nsCOMPtr<nsIInputStream> stream = do_QueryInterface(serializable);
205 MOZ_ASSERT(stream);
207 return stream.forget();
210 } // namespace ipc
211 } // namespace mozilla