Line data Source code
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/. */
6 :
7 : #include "IPCBlobUtils.h"
8 : #include "IPCBlobInputStream.h"
9 : #include "IPCBlobInputStreamChild.h"
10 : #include "IPCBlobInputStreamParent.h"
11 : #include "IPCBlobInputStreamStorage.h"
12 : #include "mozilla/dom/IPCBlob.h"
13 : #include "mozilla/dom/nsIContentParent.h"
14 : #include "mozilla/ipc/BackgroundParent.h"
15 : #include "mozilla/ipc/IPCStreamUtils.h"
16 : #include "StreamBlobImpl.h"
17 : #include "prtime.h"
18 :
19 : namespace mozilla {
20 :
21 : using namespace ipc;
22 :
23 : namespace dom {
24 : namespace IPCBlobUtils {
25 :
26 : already_AddRefed<BlobImpl>
27 0 : Deserialize(const IPCBlob& aIPCBlob)
28 : {
29 0 : nsCOMPtr<nsIInputStream> inputStream;
30 :
31 0 : const IPCBlobStream& stream = aIPCBlob.inputStream();
32 0 : switch (stream.type()) {
33 :
34 : // Parent to child: when an nsIInputStream is sent from parent to child, the
35 : // child receives a IPCBlobInputStream actor.
36 : case IPCBlobStream::TPIPCBlobInputStreamChild: {
37 : IPCBlobInputStreamChild* actor =
38 0 : static_cast<IPCBlobInputStreamChild*>(stream.get_PIPCBlobInputStreamChild());
39 0 : inputStream = actor->CreateStream();
40 0 : break;
41 : }
42 :
43 : // Child to Parent: when a blob is created on the content process send it's
44 : // sent to the parent, we have an IPCStream object.
45 : case IPCBlobStream::TIPCStream:
46 0 : MOZ_ASSERT(XRE_IsParentProcess());
47 0 : inputStream = DeserializeIPCStream(stream.get_IPCStream());
48 0 : break;
49 :
50 : default:
51 0 : MOZ_CRASH("Unknown type.");
52 : break;
53 : }
54 :
55 0 : MOZ_ASSERT(inputStream);
56 :
57 0 : RefPtr<StreamBlobImpl> blobImpl;
58 :
59 0 : if (aIPCBlob.file().type() == IPCFileUnion::Tvoid_t) {
60 0 : blobImpl = StreamBlobImpl::Create(inputStream,
61 0 : aIPCBlob.type(),
62 0 : aIPCBlob.size());
63 : } else {
64 0 : const IPCFile& file = aIPCBlob.file().get_IPCFile();
65 0 : blobImpl = StreamBlobImpl::Create(inputStream,
66 0 : file.name(),
67 0 : aIPCBlob.type(),
68 0 : file.lastModified(),
69 0 : aIPCBlob.size());
70 0 : blobImpl->SetDOMPath(file.DOMPath());
71 0 : blobImpl->SetFullPath(file.fullPath());
72 0 : blobImpl->SetIsDirectory(file.isDirectory());
73 : }
74 :
75 0 : blobImpl->SetFileId(aIPCBlob.fileId());
76 :
77 0 : return blobImpl.forget();
78 : }
79 :
80 : template<typename M>
81 : nsresult
82 0 : SerializeInputStreamParent(nsIInputStream* aInputStream, uint64_t aSize,
83 : uint64_t aChildID, IPCBlob& aIPCBlob, M* aManager)
84 : {
85 : // Parent to Child we always send a IPCBlobInputStream.
86 0 : MOZ_ASSERT(XRE_IsParentProcess());
87 :
88 : nsresult rv;
89 : IPCBlobInputStreamParent* parentActor =
90 : IPCBlobInputStreamParent::Create(aInputStream, aSize, aChildID, &rv,
91 0 : aManager);
92 0 : if (!parentActor) {
93 0 : return rv;
94 : }
95 :
96 0 : if (!aManager->SendPIPCBlobInputStreamConstructor(parentActor,
97 : parentActor->ID(),
98 0 : parentActor->Size())) {
99 0 : return NS_ERROR_FAILURE;
100 : }
101 :
102 0 : aIPCBlob.inputStream() = parentActor;
103 0 : return NS_OK;
104 : }
105 :
106 : template<typename M>
107 : nsresult
108 0 : SerializeInputStreamChild(nsIInputStream* aInputStream, IPCBlob& aIPCBlob,
109 : M* aManager)
110 : {
111 0 : AutoIPCStream ipcStream(true /* delayed start */);
112 0 : if (!ipcStream.Serialize(aInputStream, aManager)) {
113 0 : return NS_ERROR_FAILURE;
114 : }
115 :
116 0 : aIPCBlob.inputStream() = ipcStream.TakeValue();
117 0 : return NS_OK;
118 : }
119 :
120 : nsresult
121 0 : SerializeInputStream(nsIInputStream* aInputStream, uint64_t aSize,
122 : uint64_t aChildID, IPCBlob& aIPCBlob,
123 : nsIContentParent* aManager)
124 : {
125 : return SerializeInputStreamParent(aInputStream, aSize, aChildID, aIPCBlob,
126 0 : aManager);
127 : }
128 :
129 : nsresult
130 0 : SerializeInputStream(nsIInputStream* aInputStream, uint64_t aSize,
131 : uint64_t aChildID, IPCBlob& aIPCBlob,
132 : PBackgroundParent* aManager)
133 : {
134 : return SerializeInputStreamParent(aInputStream, aSize, aChildID, aIPCBlob,
135 0 : aManager);
136 : }
137 :
138 : nsresult
139 0 : SerializeInputStream(nsIInputStream* aInputStream, uint64_t aSize,
140 : uint64_t aChildID, IPCBlob& aIPCBlob,
141 : nsIContentChild* aManager)
142 : {
143 0 : return SerializeInputStreamChild(aInputStream, aIPCBlob, aManager);
144 : }
145 :
146 : nsresult
147 0 : SerializeInputStream(nsIInputStream* aInputStream, uint64_t aSize,
148 : uint64_t aChildID, IPCBlob& aIPCBlob,
149 : PBackgroundChild* aManager)
150 : {
151 0 : return SerializeInputStreamChild(aInputStream, aIPCBlob, aManager);
152 : }
153 :
154 : uint64_t
155 0 : ChildIDFromManager(nsIContentParent* aManager)
156 : {
157 0 : return aManager->ChildID();
158 : }
159 :
160 : uint64_t
161 0 : ChildIDFromManager(PBackgroundParent* aManager)
162 : {
163 0 : return BackgroundParent::GetChildID(aManager);
164 : }
165 :
166 : uint64_t
167 0 : ChildIDFromManager(nsIContentChild* aManager)
168 : {
169 0 : return 0;
170 : }
171 :
172 : uint64_t
173 0 : ChildIDFromManager(PBackgroundChild* aManager)
174 : {
175 0 : return 0;
176 : }
177 :
178 : template<typename M>
179 : nsresult
180 0 : SerializeInternal(BlobImpl* aBlobImpl, M* aManager, IPCBlob& aIPCBlob)
181 : {
182 0 : MOZ_ASSERT(aBlobImpl);
183 :
184 0 : nsAutoString value;
185 0 : aBlobImpl->GetType(value);
186 0 : aIPCBlob.type() = value;
187 :
188 0 : ErrorResult rv;
189 0 : aIPCBlob.size() = aBlobImpl->GetSize(rv);
190 0 : if (NS_WARN_IF(rv.Failed())) {
191 0 : return rv.StealNSResult();
192 : }
193 :
194 0 : if (!aBlobImpl->IsFile()) {
195 0 : aIPCBlob.file() = void_t();
196 : } else {
197 0 : IPCFile file;
198 :
199 0 : aBlobImpl->GetName(value);
200 0 : file.name() = value;
201 :
202 0 : file.lastModified() = aBlobImpl->GetLastModified(rv) * PR_USEC_PER_MSEC;
203 0 : if (NS_WARN_IF(rv.Failed())) {
204 0 : return rv.StealNSResult();
205 : }
206 :
207 0 : aBlobImpl->GetDOMPath(value);
208 0 : file.DOMPath() = value;
209 :
210 0 : aBlobImpl->GetMozFullPathInternal(value, rv);
211 0 : if (NS_WARN_IF(rv.Failed())) {
212 0 : return rv.StealNSResult();
213 : }
214 0 : file.fullPath() = value;
215 :
216 0 : file.isDirectory() = aBlobImpl->IsDirectory();
217 :
218 0 : aIPCBlob.file() = file;
219 : }
220 :
221 0 : aIPCBlob.fileId() = aBlobImpl->GetFileId();
222 :
223 0 : nsCOMPtr<nsIInputStream> inputStream;
224 0 : aBlobImpl->GetInternalStream(getter_AddRefs(inputStream), rv);
225 0 : if (NS_WARN_IF(rv.Failed())) {
226 0 : return rv.StealNSResult();
227 : }
228 :
229 0 : rv = SerializeInputStream(inputStream, aIPCBlob.size(),
230 : ChildIDFromManager(aManager), aIPCBlob, aManager);
231 0 : if (NS_WARN_IF(rv.Failed())) {
232 0 : return rv.StealNSResult();
233 : }
234 :
235 0 : return NS_OK;
236 : }
237 :
238 : nsresult
239 0 : Serialize(BlobImpl* aBlobImpl, nsIContentChild* aManager, IPCBlob& aIPCBlob)
240 : {
241 0 : return SerializeInternal(aBlobImpl, aManager, aIPCBlob);
242 : }
243 :
244 : nsresult
245 0 : Serialize(BlobImpl* aBlobImpl, PBackgroundChild* aManager, IPCBlob& aIPCBlob)
246 : {
247 0 : return SerializeInternal(aBlobImpl, aManager, aIPCBlob);
248 : }
249 :
250 : nsresult
251 0 : Serialize(BlobImpl* aBlobImpl, nsIContentParent* aManager, IPCBlob& aIPCBlob)
252 : {
253 0 : return SerializeInternal(aBlobImpl, aManager, aIPCBlob);
254 : }
255 :
256 : nsresult
257 0 : Serialize(BlobImpl* aBlobImpl, PBackgroundParent* aManager, IPCBlob& aIPCBlob)
258 : {
259 0 : return SerializeInternal(aBlobImpl, aManager, aIPCBlob);
260 : }
261 :
262 : } // IPCBlobUtils namespace
263 : } // dom namespace
264 : } // mozilla namespace
|