1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "SharedMessagePortMessage.h"
7 #include "MessagePort.h"
8 #include "MessagePortChild.h"
9 #include "MessagePortParent.h"
10 #include "mozilla/dom/ipc/BlobChild.h"
11 #include "mozilla/dom/ipc/BlobParent.h"
12 #include "mozilla/dom/File.h"
13 #include "mozilla/dom/PMessagePort.h"
14 #include "mozilla/ipc/BackgroundChild.h"
15 #include "mozilla/ipc/BackgroundParent.h"
16 
17 namespace mozilla {
18 
19 using namespace ipc;
20 
21 namespace dom {
22 
23 /* static */ void
FromSharedToMessagesChild(MessagePortChild * aActor,const nsTArray<RefPtr<SharedMessagePortMessage>> & aData,nsTArray<MessagePortMessage> & aArray)24 SharedMessagePortMessage::FromSharedToMessagesChild(
25                       MessagePortChild* aActor,
26                       const nsTArray<RefPtr<SharedMessagePortMessage>>& aData,
27                       nsTArray<MessagePortMessage>& aArray)
28 {
29   MOZ_ASSERT(aActor);
30   MOZ_ASSERT(aArray.IsEmpty());
31   aArray.SetCapacity(aData.Length());
32 
33   PBackgroundChild* backgroundManager = aActor->Manager();
34   MOZ_ASSERT(backgroundManager);
35 
36   for (auto& data : aData) {
37     MessagePortMessage* message = aArray.AppendElement();
38     data->mBuffer->abandon();
39     data->mBuffer->steal(&message->data().data);
40 
41     const nsTArray<RefPtr<BlobImpl>>& blobImpls = data->BlobImpls();
42     if (!blobImpls.IsEmpty()) {
43       message->blobsChild().SetCapacity(blobImpls.Length());
44 
45       for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) {
46         PBlobChild* blobChild =
47           BackgroundChild::GetOrCreateActorForBlobImpl(backgroundManager,
48                                                        blobImpls[i]);
49         message->blobsChild().AppendElement(blobChild);
50       }
51     }
52 
53     message->transferredPorts().AppendElements(data->PortIdentifiers());
54   }
55 }
56 
57 /* static */ bool
FromMessagesToSharedChild(nsTArray<MessagePortMessage> & aArray,FallibleTArray<RefPtr<SharedMessagePortMessage>> & aData)58 SharedMessagePortMessage::FromMessagesToSharedChild(
59                       nsTArray<MessagePortMessage>& aArray,
60                       FallibleTArray<RefPtr<SharedMessagePortMessage>>& aData)
61 {
62   MOZ_ASSERT(aData.IsEmpty());
63 
64   if (NS_WARN_IF(!aData.SetCapacity(aArray.Length(), mozilla::fallible))) {
65     return false;
66   }
67 
68   for (auto& message : aArray) {
69     RefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();
70 
71     data->mBuffer = MakeUnique<JSAutoStructuredCloneBuffer>(
72       JS::StructuredCloneScope::DifferentProcess, nullptr, nullptr);
73     data->mBuffer->adopt(Move(message.data().data), JS_STRUCTURED_CLONE_VERSION,
74                          &StructuredCloneHolder::sCallbacks, data.get());
75 
76     const nsTArray<PBlobChild*>& blobs = message.blobsChild();
77     if (!blobs.IsEmpty()) {
78       data->BlobImpls().SetCapacity(blobs.Length());
79 
80       for (uint32_t i = 0, len = blobs.Length(); i < len; ++i) {
81         RefPtr<BlobImpl> impl =
82           static_cast<BlobChild*>(blobs[i])->GetBlobImpl();
83         data->BlobImpls().AppendElement(impl);
84       }
85     }
86 
87     data->PortIdentifiers().AppendElements(message.transferredPorts());
88 
89     if (!aData.AppendElement(data, mozilla::fallible)) {
90       return false;
91     }
92   }
93 
94   return true;
95 }
96 
97 /* static */ bool
FromSharedToMessagesParent(MessagePortParent * aActor,const nsTArray<RefPtr<SharedMessagePortMessage>> & aData,FallibleTArray<MessagePortMessage> & aArray)98 SharedMessagePortMessage::FromSharedToMessagesParent(
99                       MessagePortParent* aActor,
100                       const nsTArray<RefPtr<SharedMessagePortMessage>>& aData,
101                       FallibleTArray<MessagePortMessage>& aArray)
102 {
103   MOZ_ASSERT(aArray.IsEmpty());
104 
105   if (NS_WARN_IF(!aArray.SetCapacity(aData.Length(), mozilla::fallible))) {
106     return false;
107   }
108 
109   PBackgroundParent* backgroundManager = aActor->Manager();
110   MOZ_ASSERT(backgroundManager);
111 
112   for (auto& data : aData) {
113     MessagePortMessage* message = aArray.AppendElement(mozilla::fallible);
114     data->mBuffer->abandon();
115     data->mBuffer->steal(&message->data().data);
116 
117     const nsTArray<RefPtr<BlobImpl>>& blobImpls = data->BlobImpls();
118     if (!blobImpls.IsEmpty()) {
119       message->blobsParent().SetCapacity(blobImpls.Length());
120 
121       for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) {
122         PBlobParent* blobParent =
123           BackgroundParent::GetOrCreateActorForBlobImpl(backgroundManager,
124                                                         blobImpls[i]);
125         message->blobsParent().AppendElement(blobParent);
126       }
127     }
128 
129     message->transferredPorts().AppendElements(data->PortIdentifiers());
130   }
131 
132   return true;
133 }
134 
135 /* static */ bool
FromMessagesToSharedParent(nsTArray<MessagePortMessage> & aArray,FallibleTArray<RefPtr<SharedMessagePortMessage>> & aData)136 SharedMessagePortMessage::FromMessagesToSharedParent(
137                       nsTArray<MessagePortMessage>& aArray,
138                       FallibleTArray<RefPtr<SharedMessagePortMessage>>& aData)
139 {
140   MOZ_ASSERT(aData.IsEmpty());
141 
142   if (NS_WARN_IF(!aData.SetCapacity(aArray.Length(), mozilla::fallible))) {
143     return false;
144   }
145 
146   for (auto& message : aArray) {
147     RefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();
148 
149     data->mBuffer = MakeUnique<JSAutoStructuredCloneBuffer>(
150       JS::StructuredCloneScope::DifferentProcess, nullptr, nullptr);
151     data->mBuffer->adopt(Move(message.data().data), JS_STRUCTURED_CLONE_VERSION,
152                          &StructuredCloneHolder::sCallbacks, data.get());
153 
154     const nsTArray<PBlobParent*>& blobs = message.blobsParent();
155     if (!blobs.IsEmpty()) {
156       data->BlobImpls().SetCapacity(blobs.Length());
157 
158       for (uint32_t i = 0, len = blobs.Length(); i < len; ++i) {
159         RefPtr<BlobImpl> impl =
160           static_cast<BlobParent*>(blobs[i])->GetBlobImpl();
161         data->BlobImpls().AppendElement(impl);
162       }
163     }
164 
165     data->PortIdentifiers().AppendElements(message.transferredPorts());
166 
167     if (!aData.AppendElement(data, mozilla::fallible)) {
168       return false;
169     }
170   }
171 
172   return true;
173 }
174 
175 } // namespace dom
176 } // namespace mozilla
177