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