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