tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Endpoint.cpp (6028B)


      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/. */
      6 
      7 #include "mozilla/ipc/Endpoint.h"
      8 #include "chrome/common/ipc_message.h"
      9 #include "ipc/IPCMessageUtilsSpecializations.h"
     10 #include "nsThreadUtils.h"
     11 #include "mozilla/ipc/ProtocolMessageUtils.h"
     12 
     13 namespace mozilla::ipc {
     14 
     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      })) {}
     24 
     25 UntypedManagedEndpoint::~UntypedManagedEndpoint() {
     26  if (!IsValid()) {
     27    return;
     28  }
     29 
     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));
     42          }
     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));
     54          }
     55        }));
     56  }
     57 }
     58 
     59 bool UntypedManagedEndpoint::BindCommon(IProtocol* aActor,
     60                                        IRefCountedProtocol* aManager) {
     61  MOZ_ASSERT(aManager);
     62  if (!mInner) {
     63    NS_WARNING("Cannot bind to invalid endpoint");
     64    return false;
     65  }
     66 
     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());
     73  }
     74 
     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;
     80  }
     81 
     82  if (!aManager->CanSend() || !aManager->GetIPCChannel()) {
     83    NS_WARNING("Manager cannot send");
     84    return false;
     85  }
     86 
     87  ActorId id = mInner->mId;
     88  mInner.reset();
     89 
     90  // Our typed caller will insert the actor into the managed container.
     91  MOZ_ALWAYS_TRUE(aActor->SetManagerAndRegister(aManager, id));
     92 
     93  aManager->GetIPCChannel()->Send(
     94      MakeUnique<IPC::Message>(id, MANAGED_ENDPOINT_BOUND_MESSAGE_TYPE));
     95  return true;
     96 }
     97 
     98 }  // namespace mozilla::ipc
     99 
    100 namespace IPC {
    101 
    102 /* static */
    103 void ParamTraits<mozilla::ipc::UntypedManagedEndpoint>::Write(
    104    MessageWriter* aWriter, paramType&& aParam) {
    105  bool isValid = aParam.mInner.isSome();
    106  WriteParam(aWriter, isValid);
    107  if (!isValid) {
    108    return;
    109  }
    110 
    111  auto inner = std::move(*aParam.mInner);
    112  aParam.mInner.reset();
    113 
    114  MOZ_RELEASE_ASSERT(inner.mOtherSide, "Has not been sent over IPC yet");
    115  MOZ_RELEASE_ASSERT(inner.mOtherSide->ActorEventTarget()->IsOnCurrentThread(),
    116                     "Must be being sent from the correct thread");
    117  MOZ_RELEASE_ASSERT(inner.mOtherSide->Get() && aWriter->GetActor() &&
    118                         inner.mOtherSide->Get()->ToplevelProtocol() ==
    119                             aWriter->GetActor()->ToplevelProtocol(),
    120                     "Must be being sent over the same toplevel protocol");
    121 
    122  WriteParam(aWriter, inner.mId);
    123  WriteParam(aWriter, inner.mType);
    124  WriteParam(aWriter, inner.mManagerId);
    125  WriteParam(aWriter, inner.mManagerType);
    126 }
    127 
    128 /* static */
    129 bool ParamTraits<mozilla::ipc::UntypedManagedEndpoint>::Read(
    130    MessageReader* aReader, paramType* aResult) {
    131  *aResult = mozilla::ipc::UntypedManagedEndpoint{};
    132  bool isValid = false;
    133  if (!aReader->GetActor() || !ReadParam(aReader, &isValid)) {
    134    return false;
    135  }
    136  if (!isValid) {
    137    return true;
    138  }
    139 
    140  aResult->mInner.emplace();
    141  auto& inner = *aResult->mInner;
    142  inner.mToplevel =
    143      aReader->GetActor()->ToplevelProtocol()->GetWeakLifecycleProxy();
    144  return ReadParam(aReader, &inner.mId) && ReadParam(aReader, &inner.mType) &&
    145         ReadParam(aReader, &inner.mManagerId) &&
    146         ReadParam(aReader, &inner.mManagerType);
    147 }
    148 
    149 void ParamTraits<mozilla::ipc::UntypedEndpoint>::Write(MessageWriter* aWriter,
    150                                                       paramType&& aParam) {
    151  IPC::WriteParam(aWriter, std::move(aParam.mPort));
    152  IPC::WriteParam(aWriter, aParam.mMessageChannelId);
    153  IPC::WriteParam(aWriter, aParam.mMyProcInfo);
    154  IPC::WriteParam(aWriter, aParam.mOtherProcInfo);
    155 }
    156 
    157 bool ParamTraits<mozilla::ipc::UntypedEndpoint>::Read(MessageReader* aReader,
    158                                                      paramType* aResult) {
    159  return IPC::ReadParam(aReader, &aResult->mPort) &&
    160         IPC::ReadParam(aReader, &aResult->mMessageChannelId) &&
    161         IPC::ReadParam(aReader, &aResult->mMyProcInfo) &&
    162         IPC::ReadParam(aReader, &aResult->mOtherProcInfo);
    163 }
    164 
    165 }  // namespace IPC