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 "RemoteLazyInputStreamUtils.h"
8 #include "RemoteLazyInputStream.h"
9 #include "RemoteLazyInputStreamChild.h"
10 #include "RemoteLazyInputStreamParent.h"
11 #include "mozilla/ipc/BackgroundParent.h"
12 #include "mozilla/ipc/PBackgroundParent.h"
13 #include "mozilla/dom/ContentParent.h"
14 #include "mozilla/ipc/IPCStreamUtils.h"
15 #include "RemoteLazyInputStreamStorage.h"
16 #include "StreamBlobImpl.h"
17
18 namespace mozilla {
19
20 namespace {
21
22 template <typename M>
SerializeInputStreamParent(nsIInputStream * aInputStream,uint64_t aSize,uint64_t aChildID,PRemoteLazyInputStreamParent * & aActorParent,M * aManager)23 nsresult SerializeInputStreamParent(nsIInputStream* aInputStream,
24 uint64_t aSize, uint64_t aChildID,
25 PRemoteLazyInputStreamParent*& aActorParent,
26 M* aManager) {
27 // Parent to Child we always send a RemoteLazyInputStream.
28 MOZ_ASSERT(XRE_IsParentProcess());
29
30 nsCOMPtr<nsIInputStream> stream = aInputStream;
31
32 // In case this is a RemoteLazyInputStream, we don't want to create a loop:
33 // RemoteLazyInputStreamParent -> RemoteLazyInputStream ->
34 // RemoteLazyInputStreamParent. Let's use the underlying inputStream instead.
35 nsCOMPtr<mozIRemoteLazyInputStream> remoteLazyInputStream =
36 do_QueryInterface(aInputStream);
37 if (remoteLazyInputStream) {
38 stream = remoteLazyInputStream->GetInternalStream();
39 // If we don't have an underlying stream, it's better to terminate here
40 // instead of sending an 'empty' RemoteLazyInputStream actor on the other
41 // side, unable to be used.
42 if (NS_WARN_IF(!stream)) {
43 return NS_ERROR_FAILURE;
44 }
45 }
46
47 nsresult rv;
48 RefPtr<RemoteLazyInputStreamParent> parentActor =
49 RemoteLazyInputStreamParent::Create(stream, aSize, aChildID, &rv,
50 aManager);
51 if (!parentActor) {
52 return rv;
53 }
54
55 if (!aManager->SendPRemoteLazyInputStreamConstructor(
56 parentActor, parentActor->ID(), parentActor->Size())) {
57 return NS_ERROR_FAILURE;
58 }
59
60 aActorParent = parentActor;
61 return NS_OK;
62 }
63
64 } // anonymous namespace
65
66 // static
SerializeInputStream(nsIInputStream * aInputStream,uint64_t aSize,RemoteLazyStream & aOutStream,dom::ContentParent * aManager)67 nsresult RemoteLazyInputStreamUtils::SerializeInputStream(
68 nsIInputStream* aInputStream, uint64_t aSize, RemoteLazyStream& aOutStream,
69 dom::ContentParent* aManager) {
70 PRemoteLazyInputStreamParent* actor = nullptr;
71 nsresult rv = SerializeInputStreamParent(
72 aInputStream, aSize, aManager->ChildID(), actor, aManager);
73 NS_ENSURE_SUCCESS(rv, rv);
74
75 aOutStream = actor;
76 return NS_OK;
77 }
78
79 // static
SerializeInputStream(nsIInputStream * aInputStream,uint64_t aSize,RemoteLazyStream & aOutStream,mozilla::ipc::PBackgroundParent * aManager)80 nsresult RemoteLazyInputStreamUtils::SerializeInputStream(
81 nsIInputStream* aInputStream, uint64_t aSize, RemoteLazyStream& aOutStream,
82 mozilla::ipc::PBackgroundParent* aManager) {
83 PRemoteLazyInputStreamParent* actor = nullptr;
84 nsresult rv = SerializeInputStreamParent(
85 aInputStream, aSize, mozilla::ipc::BackgroundParent::GetChildID(aManager),
86 actor, aManager);
87 NS_ENSURE_SUCCESS(rv, rv);
88
89 aOutStream = actor;
90 return NS_OK;
91 }
92
93 // static
SerializeInputStream(nsIInputStream * aInputStream,uint64_t aSize,RemoteLazyStream & aOutStream,dom::ContentChild * aManager)94 nsresult RemoteLazyInputStreamUtils::SerializeInputStream(
95 nsIInputStream* aInputStream, uint64_t aSize, RemoteLazyStream& aOutStream,
96 dom::ContentChild* aManager) {
97 mozilla::ipc::AutoIPCStream ipcStream(true /* delayed start */);
98 if (!ipcStream.Serialize(aInputStream, aManager)) {
99 return NS_ERROR_FAILURE;
100 }
101
102 aOutStream = ipcStream.TakeValue();
103 return NS_OK;
104 }
105
106 // static
SerializeInputStream(nsIInputStream * aInputStream,uint64_t aSize,RemoteLazyStream & aOutStream,mozilla::ipc::PBackgroundChild * aManager)107 nsresult RemoteLazyInputStreamUtils::SerializeInputStream(
108 nsIInputStream* aInputStream, uint64_t aSize, RemoteLazyStream& aOutStream,
109 mozilla::ipc::PBackgroundChild* aManager) {
110 mozilla::ipc::AutoIPCStream ipcStream(true /* delayed start */);
111 if (!ipcStream.Serialize(aInputStream, aManager)) {
112 return NS_ERROR_FAILURE;
113 }
114
115 aOutStream = ipcStream.TakeValue();
116 return NS_OK;
117 }
118
119 } // namespace mozilla
120