diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /ipc/glue/Endpoint.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ipc/glue/Endpoint.cpp')
-rw-r--r-- | ipc/glue/Endpoint.cpp | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/ipc/glue/Endpoint.cpp b/ipc/glue/Endpoint.cpp new file mode 100644 index 0000000000..3391f8b359 --- /dev/null +++ b/ipc/glue/Endpoint.cpp @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/ipc/Endpoint.h" +#include "chrome/common/ipc_message.h" +#include "mozilla/ipc/IPDLParamTraits.h" +#include "nsThreadUtils.h" +#include "mozilla/ipc/ProtocolMessageUtils.h" + +namespace mozilla::ipc { + +UntypedManagedEndpoint::UntypedManagedEndpoint(IProtocol* aActor) + : mInner(Some(Inner{ + /* mOtherSide */ aActor->GetWeakLifecycleProxy(), + /* mToplevel */ nullptr, + aActor->Id(), + aActor->GetProtocolId(), + aActor->Manager()->Id(), + aActor->Manager()->GetProtocolId(), + })) {} + +UntypedManagedEndpoint::~UntypedManagedEndpoint() { + if (!IsValid()) { + return; + } + + if (mInner->mOtherSide) { + // If this ManagedEndpoint was never sent over IPC, deliver a fake + // MANAGED_ENDPOINT_DROPPED_MESSAGE_TYPE message directly to the other side + // actor. + mInner->mOtherSide->ActorEventTarget()->Dispatch(NS_NewRunnableFunction( + "~ManagedEndpoint (Local)", + [otherSide = mInner->mOtherSide, id = mInner->mId] { + if (IProtocol* actor = otherSide->Get(); actor && actor->CanRecv()) { + MOZ_DIAGNOSTIC_ASSERT(actor->Id() == id, "Wrong Actor?"); + RefPtr<ActorLifecycleProxy> strongProxy(actor->GetLifecycleProxy()); + strongProxy->Get()->OnMessageReceived( + IPC::Message(id, MANAGED_ENDPOINT_DROPPED_MESSAGE_TYPE)); + } + })); + } else if (mInner->mToplevel) { + // If it was sent over IPC, we'll need to send the message to the sending + // side. Let's send the message async. + mInner->mToplevel->ActorEventTarget()->Dispatch(NS_NewRunnableFunction( + "~ManagedEndpoint (Remote)", + [toplevel = mInner->mToplevel, id = mInner->mId] { + if (IProtocol* actor = toplevel->Get(); + actor && actor->CanSend() && actor->GetIPCChannel()) { + actor->GetIPCChannel()->Send(MakeUnique<IPC::Message>( + id, MANAGED_ENDPOINT_DROPPED_MESSAGE_TYPE)); + } + })); + } +} + +bool UntypedManagedEndpoint::BindCommon(IProtocol* aActor, + IProtocol* aManager) { + MOZ_ASSERT(aManager); + if (!mInner) { + NS_WARNING("Cannot bind to invalid endpoint"); + return false; + } + + // Perform thread assertions. + if (mInner->mToplevel) { + MOZ_DIAGNOSTIC_ASSERT( + mInner->mToplevel->ActorEventTarget()->IsOnCurrentThread()); + MOZ_DIAGNOSTIC_ASSERT(aManager->ToplevelProtocol() == + mInner->mToplevel->Get()); + } + + if (NS_WARN_IF(aManager->Id() != mInner->mManagerId) || + NS_WARN_IF(aManager->GetProtocolId() != mInner->mManagerType) || + NS_WARN_IF(aActor->GetProtocolId() != mInner->mType)) { + MOZ_ASSERT_UNREACHABLE("Actor and manager do not match Endpoint"); + return false; + } + + if (!aManager->CanSend() || !aManager->GetIPCChannel()) { + NS_WARNING("Manager cannot send"); + return false; + } + + int32_t id = mInner->mId; + mInner.reset(); + + // Our typed caller will insert the actor into the managed container. + aActor->SetManagerAndRegister(aManager, id); + + aManager->GetIPCChannel()->Send( + MakeUnique<IPC::Message>(id, MANAGED_ENDPOINT_BOUND_MESSAGE_TYPE)); + return true; +} + +/* static */ +void IPDLParamTraits<UntypedManagedEndpoint>::Write(IPC::MessageWriter* aWriter, + IProtocol* aActor, + paramType&& aParam) { + bool isValid = aParam.mInner.isSome(); + WriteIPDLParam(aWriter, aActor, isValid); + if (!isValid) { + return; + } + + auto inner = std::move(*aParam.mInner); + aParam.mInner.reset(); + + MOZ_RELEASE_ASSERT(inner.mOtherSide, "Has not been sent over IPC yet"); + MOZ_RELEASE_ASSERT(inner.mOtherSide->ActorEventTarget()->IsOnCurrentThread(), + "Must be being sent from the correct thread"); + MOZ_RELEASE_ASSERT( + inner.mOtherSide->Get() && inner.mOtherSide->Get()->ToplevelProtocol() == + aActor->ToplevelProtocol(), + "Must be being sent over the same toplevel protocol"); + + WriteIPDLParam(aWriter, aActor, inner.mId); + WriteIPDLParam(aWriter, aActor, inner.mType); + WriteIPDLParam(aWriter, aActor, inner.mManagerId); + WriteIPDLParam(aWriter, aActor, inner.mManagerType); +} + +/* static */ +bool IPDLParamTraits<UntypedManagedEndpoint>::Read(IPC::MessageReader* aReader, + IProtocol* aActor, + paramType* aResult) { + *aResult = UntypedManagedEndpoint{}; + bool isValid = false; + if (!aActor || !ReadIPDLParam(aReader, aActor, &isValid)) { + return false; + } + if (!isValid) { + return true; + } + + aResult->mInner.emplace(); + auto& inner = *aResult->mInner; + inner.mToplevel = aActor->ToplevelProtocol()->GetWeakLifecycleProxy(); + return ReadIPDLParam(aReader, aActor, &inner.mId) && + ReadIPDLParam(aReader, aActor, &inner.mType) && + ReadIPDLParam(aReader, aActor, &inner.mManagerId) && + ReadIPDLParam(aReader, aActor, &inner.mManagerType); +} + +} // namespace mozilla::ipc + +namespace IPC { + +void ParamTraits<mozilla::ipc::UntypedEndpoint>::Write(MessageWriter* aWriter, + paramType&& aParam) { + IPC::WriteParam(aWriter, std::move(aParam.mPort)); + IPC::WriteParam(aWriter, aParam.mMessageChannelId); + IPC::WriteParam(aWriter, aParam.mMyPid); + IPC::WriteParam(aWriter, aParam.mOtherPid); +} + +bool ParamTraits<mozilla::ipc::UntypedEndpoint>::Read(MessageReader* aReader, + paramType* aResult) { + return IPC::ReadParam(aReader, &aResult->mPort) && + IPC::ReadParam(aReader, &aResult->mMessageChannelId) && + IPC::ReadParam(aReader, &aResult->mMyPid) && + IPC::ReadParam(aReader, &aResult->mOtherPid); +} + +} // namespace IPC |