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/. */
7 #include "MessagePortParent.h"
8 #include "MessagePortService.h"
9 #include "mozilla/dom/RefMessageBodyService.h"
10 #include "mozilla/dom/SharedMessageBody.h"
11 #include "mozilla/Unused.h"
13 namespace mozilla::dom
{
15 MessagePortParent::MessagePortParent(const nsID
& aUUID
)
16 : mService(MessagePortService::GetOrCreate()),
23 MessagePortParent::~MessagePortParent() {
24 MOZ_ASSERT(!mService
);
25 MOZ_ASSERT(!mEntangled
);
28 bool MessagePortParent::Entangle(const nsID
& aDestinationUUID
,
29 const uint32_t& aSequenceID
) {
31 NS_WARNING("Entangle is called after a shutdown!");
35 MOZ_ASSERT(!mEntangled
);
37 return mService
->RequestEntangling(this, aDestinationUUID
, aSequenceID
);
40 mozilla::ipc::IPCResult
MessagePortParent::RecvPostMessages(
41 nsTArray
<MessageData
>&& aMessages
) {
43 NS_WARNING("PostMessages is called after a shutdown!");
44 // This implies most probably that CloseAndDelete() has been already called
45 // such that we have no better option than to silently ignore this call.
50 // If we were shut down, the above condition already bailed out. So this
51 // should actually never happen and returning a failure is fine.
52 return IPC_FAIL(this, "RecvPostMessages not entangled");
55 // This converts the object in a data struct where we have BlobImpls.
56 FallibleTArray
<RefPtr
<SharedMessageBody
>> messages
;
57 if (NS_WARN_IF(!SharedMessageBody::FromMessagesToSharedParent(aMessages
,
59 // FromMessagesToSharedParent() returns false only if the array allocation
61 // See bug 1750497 for further discussion if this is the wanted behavior.
62 return IPC_FAIL(this, "SharedMessageBody::FromMessagesToSharedParent");
65 if (messages
.IsEmpty()) {
66 // An empty payload can be safely ignored.
70 if (!mService
->PostMessages(this, std::move(messages
))) {
71 // TODO: Verify if all failure conditions of PostMessages() merit an
72 // IPC_FAIL. See bug 1750499.
73 return IPC_FAIL(this, "RecvPostMessages->PostMessages");
78 mozilla::ipc::IPCResult
MessagePortParent::RecvDisentangle(
79 nsTArray
<MessageData
>&& aMessages
) {
81 NS_WARNING("Entangle is called after a shutdown!");
82 // This implies most probably that CloseAndDelete() has been already called
83 // such that we can silently ignore this call.
88 // If we were shut down, the above condition already bailed out. So this
89 // should actually never happen and returning a failure is fine.
90 return IPC_FAIL(this, "RecvDisentangle not entangled");
93 // This converts the object in a data struct where we have BlobImpls.
94 FallibleTArray
<RefPtr
<SharedMessageBody
>> messages
;
95 if (NS_WARN_IF(!SharedMessageBody::FromMessagesToSharedParent(aMessages
,
97 // TODO: Verify if failed allocations merit an IPC_FAIL. See bug 1750497.
98 return IPC_FAIL(this, "SharedMessageBody::FromMessagesToSharedParent");
101 if (!mService
->DisentanglePort(this, std::move(messages
))) {
102 // TODO: Verify if all failure conditions of DisentanglePort() merit an
103 // IPC_FAIL. See bug 1750501.
104 return IPC_FAIL(this, "RecvDisentangle->DisentanglePort");
111 mozilla::ipc::IPCResult
MessagePortParent::RecvStopSendingData() {
116 mCanSendData
= false;
117 Unused
<< SendStopSendingDataConfirmed();
121 mozilla::ipc::IPCResult
MessagePortParent::RecvClose() {
123 MOZ_ASSERT(mEntangled
);
125 if (!mService
->ClosePort(this)) {
126 return IPC_FAIL(this, "RecvClose->ClosePort");
132 MOZ_ASSERT(!mEntangled
);
134 Unused
<< Send__delete__(this);
138 void MessagePortParent::ActorDestroy(ActorDestroyReason aWhy
) {
139 if (mService
&& mEntangled
) {
140 // When the last parent is deleted, this service is freed but this cannot
141 // be done when the hashtables are written by CloseAll.
142 RefPtr
<MessagePortService
> kungFuDeathGrip
= mService
;
143 kungFuDeathGrip
->ParentDestroy(this);
147 bool MessagePortParent::Entangled(nsTArray
<MessageData
>&& aMessages
) {
148 MOZ_ASSERT(!mEntangled
);
150 return SendEntangled(aMessages
);
153 void MessagePortParent::CloseAndDelete() {
155 Unused
<< Send__delete__(this);
158 void MessagePortParent::Close() {
164 bool MessagePortParent::ForceClose(const nsID
& aUUID
,
165 const nsID
& aDestinationUUID
,
166 const uint32_t& aSequenceID
) {
167 MessagePortService
* service
= MessagePortService::Get();
170 "The service must exist if we want to close an existing MessagePort.");
171 // There is nothing to close so we are ok.
175 return service
->ForceClose(aUUID
, aDestinationUUID
, aSequenceID
);
178 } // namespace mozilla::dom