no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / ipc / glue / Endpoint.cpp
blob3391f8b359f709d09d8f7a8136513a990239ae1d
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 "mozilla/ipc/Endpoint.h"
8 #include "chrome/common/ipc_message.h"
9 #include "mozilla/ipc/IPDLParamTraits.h"
10 #include "nsThreadUtils.h"
11 #include "mozilla/ipc/ProtocolMessageUtils.h"
13 namespace mozilla::ipc {
15 UntypedManagedEndpoint::UntypedManagedEndpoint(IProtocol* aActor)
16 : mInner(Some(Inner{
17 /* mOtherSide */ aActor->GetWeakLifecycleProxy(),
18 /* mToplevel */ nullptr,
19 aActor->Id(),
20 aActor->GetProtocolId(),
21 aActor->Manager()->Id(),
22 aActor->Manager()->GetProtocolId(),
23 })) {}
25 UntypedManagedEndpoint::~UntypedManagedEndpoint() {
26 if (!IsValid()) {
27 return;
30 if (mInner->mOtherSide) {
31 // If this ManagedEndpoint was never sent over IPC, deliver a fake
32 // MANAGED_ENDPOINT_DROPPED_MESSAGE_TYPE message directly to the other side
33 // actor.
34 mInner->mOtherSide->ActorEventTarget()->Dispatch(NS_NewRunnableFunction(
35 "~ManagedEndpoint (Local)",
36 [otherSide = mInner->mOtherSide, id = mInner->mId] {
37 if (IProtocol* actor = otherSide->Get(); actor && actor->CanRecv()) {
38 MOZ_DIAGNOSTIC_ASSERT(actor->Id() == id, "Wrong Actor?");
39 RefPtr<ActorLifecycleProxy> strongProxy(actor->GetLifecycleProxy());
40 strongProxy->Get()->OnMessageReceived(
41 IPC::Message(id, MANAGED_ENDPOINT_DROPPED_MESSAGE_TYPE));
43 }));
44 } else if (mInner->mToplevel) {
45 // If it was sent over IPC, we'll need to send the message to the sending
46 // side. Let's send the message async.
47 mInner->mToplevel->ActorEventTarget()->Dispatch(NS_NewRunnableFunction(
48 "~ManagedEndpoint (Remote)",
49 [toplevel = mInner->mToplevel, id = mInner->mId] {
50 if (IProtocol* actor = toplevel->Get();
51 actor && actor->CanSend() && actor->GetIPCChannel()) {
52 actor->GetIPCChannel()->Send(MakeUnique<IPC::Message>(
53 id, MANAGED_ENDPOINT_DROPPED_MESSAGE_TYPE));
55 }));
59 bool UntypedManagedEndpoint::BindCommon(IProtocol* aActor,
60 IProtocol* aManager) {
61 MOZ_ASSERT(aManager);
62 if (!mInner) {
63 NS_WARNING("Cannot bind to invalid endpoint");
64 return false;
67 // Perform thread assertions.
68 if (mInner->mToplevel) {
69 MOZ_DIAGNOSTIC_ASSERT(
70 mInner->mToplevel->ActorEventTarget()->IsOnCurrentThread());
71 MOZ_DIAGNOSTIC_ASSERT(aManager->ToplevelProtocol() ==
72 mInner->mToplevel->Get());
75 if (NS_WARN_IF(aManager->Id() != mInner->mManagerId) ||
76 NS_WARN_IF(aManager->GetProtocolId() != mInner->mManagerType) ||
77 NS_WARN_IF(aActor->GetProtocolId() != mInner->mType)) {
78 MOZ_ASSERT_UNREACHABLE("Actor and manager do not match Endpoint");
79 return false;
82 if (!aManager->CanSend() || !aManager->GetIPCChannel()) {
83 NS_WARNING("Manager cannot send");
84 return false;
87 int32_t id = mInner->mId;
88 mInner.reset();
90 // Our typed caller will insert the actor into the managed container.
91 aActor->SetManagerAndRegister(aManager, id);
93 aManager->GetIPCChannel()->Send(
94 MakeUnique<IPC::Message>(id, MANAGED_ENDPOINT_BOUND_MESSAGE_TYPE));
95 return true;
98 /* static */
99 void IPDLParamTraits<UntypedManagedEndpoint>::Write(IPC::MessageWriter* aWriter,
100 IProtocol* aActor,
101 paramType&& aParam) {
102 bool isValid = aParam.mInner.isSome();
103 WriteIPDLParam(aWriter, aActor, isValid);
104 if (!isValid) {
105 return;
108 auto inner = std::move(*aParam.mInner);
109 aParam.mInner.reset();
111 MOZ_RELEASE_ASSERT(inner.mOtherSide, "Has not been sent over IPC yet");
112 MOZ_RELEASE_ASSERT(inner.mOtherSide->ActorEventTarget()->IsOnCurrentThread(),
113 "Must be being sent from the correct thread");
114 MOZ_RELEASE_ASSERT(
115 inner.mOtherSide->Get() && inner.mOtherSide->Get()->ToplevelProtocol() ==
116 aActor->ToplevelProtocol(),
117 "Must be being sent over the same toplevel protocol");
119 WriteIPDLParam(aWriter, aActor, inner.mId);
120 WriteIPDLParam(aWriter, aActor, inner.mType);
121 WriteIPDLParam(aWriter, aActor, inner.mManagerId);
122 WriteIPDLParam(aWriter, aActor, inner.mManagerType);
125 /* static */
126 bool IPDLParamTraits<UntypedManagedEndpoint>::Read(IPC::MessageReader* aReader,
127 IProtocol* aActor,
128 paramType* aResult) {
129 *aResult = UntypedManagedEndpoint{};
130 bool isValid = false;
131 if (!aActor || !ReadIPDLParam(aReader, aActor, &isValid)) {
132 return false;
134 if (!isValid) {
135 return true;
138 aResult->mInner.emplace();
139 auto& inner = *aResult->mInner;
140 inner.mToplevel = aActor->ToplevelProtocol()->GetWeakLifecycleProxy();
141 return ReadIPDLParam(aReader, aActor, &inner.mId) &&
142 ReadIPDLParam(aReader, aActor, &inner.mType) &&
143 ReadIPDLParam(aReader, aActor, &inner.mManagerId) &&
144 ReadIPDLParam(aReader, aActor, &inner.mManagerType);
147 } // namespace mozilla::ipc
149 namespace IPC {
151 void ParamTraits<mozilla::ipc::UntypedEndpoint>::Write(MessageWriter* aWriter,
152 paramType&& aParam) {
153 IPC::WriteParam(aWriter, std::move(aParam.mPort));
154 IPC::WriteParam(aWriter, aParam.mMessageChannelId);
155 IPC::WriteParam(aWriter, aParam.mMyPid);
156 IPC::WriteParam(aWriter, aParam.mOtherPid);
159 bool ParamTraits<mozilla::ipc::UntypedEndpoint>::Read(MessageReader* aReader,
160 paramType* aResult) {
161 return IPC::ReadParam(aReader, &aResult->mPort) &&
162 IPC::ReadParam(aReader, &aResult->mMessageChannelId) &&
163 IPC::ReadParam(aReader, &aResult->mMyPid) &&
164 IPC::ReadParam(aReader, &aResult->mOtherPid);
167 } // namespace IPC