tor-browser

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

MessagePortParent.cpp (5619B)


      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 "MessagePortParent.h"
      8 
      9 #include "MessagePortService.h"
     10 #include "mozilla/dom/RefMessageBodyService.h"
     11 #include "mozilla/dom/SharedMessageBody.h"
     12 
     13 namespace mozilla::dom {
     14 
     15 MessagePortParent::MessagePortParent(const nsID& aUUID)
     16    : mService(MessagePortService::GetOrCreate()),
     17      mUUID(aUUID),
     18      mEntangled(false),
     19      mCanSendData(true) {
     20  MOZ_ASSERT(mService);
     21 }
     22 
     23 MessagePortParent::~MessagePortParent() {
     24  MOZ_ASSERT(!mService);
     25  MOZ_ASSERT(!mEntangled);
     26 }
     27 
     28 bool MessagePortParent::Entangle(const nsID& aDestinationUUID,
     29                                 const uint32_t& aSequenceID) {
     30  if (!mService) {
     31    NS_WARNING("Entangle is called after a shutdown!");
     32    return false;
     33  }
     34 
     35  MOZ_ASSERT(!mEntangled);
     36 
     37  return mService->RequestEntangling(this, aDestinationUUID, aSequenceID);
     38 }
     39 
     40 mozilla::ipc::IPCResult MessagePortParent::RecvPostMessages(
     41    nsTArray<MessageData>&& aMessages) {
     42  if (!mService) {
     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.
     46    return IPC_OK();
     47  }
     48 
     49  if (!mEntangled) {
     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");
     53  }
     54 
     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,
     58                                                                messages))) {
     59    // FromMessagesToSharedParent() returns false only if the array allocation
     60    // failed.
     61    // See bug 1750497 for further discussion if this is the wanted behavior.
     62    return IPC_FAIL(this, "SharedMessageBody::FromMessagesToSharedParent");
     63  }
     64 
     65  if (messages.IsEmpty()) {
     66    // An empty payload can be safely ignored.
     67    return IPC_OK();
     68  }
     69 
     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");
     74  }
     75  return IPC_OK();
     76 }
     77 
     78 mozilla::ipc::IPCResult MessagePortParent::RecvDisentangle(
     79    nsTArray<MessageData>&& aMessages) {
     80  if (!mService) {
     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.
     84    return IPC_OK();
     85  }
     86 
     87  if (!mEntangled) {
     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");
     91  }
     92 
     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,
     96                                                                messages))) {
     97    // TODO: Verify if failed allocations merit an IPC_FAIL. See bug 1750497.
     98    return IPC_FAIL(this, "SharedMessageBody::FromMessagesToSharedParent");
     99  }
    100 
    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");
    105  }
    106 
    107  CloseAndDelete();
    108  return IPC_OK();
    109 }
    110 
    111 mozilla::ipc::IPCResult MessagePortParent::RecvStopSendingData() {
    112  if (!mEntangled) {
    113    return IPC_OK();
    114  }
    115 
    116  mCanSendData = false;
    117  (void)SendStopSendingDataConfirmed();
    118  return IPC_OK();
    119 }
    120 
    121 mozilla::ipc::IPCResult MessagePortParent::RecvClose() {
    122  if (mService) {
    123    MOZ_ASSERT(mEntangled);
    124 
    125    if (!mService->ClosePort(this)) {
    126      return IPC_FAIL(this, "RecvClose->ClosePort");
    127    }
    128 
    129    Close();
    130  }
    131 
    132  MOZ_ASSERT(!mEntangled);
    133 
    134  (void)Send__delete__(this);
    135  return IPC_OK();
    136 }
    137 
    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);
    144  }
    145 }
    146 
    147 bool MessagePortParent::Entangled(nsTArray<MessageData>&& aMessages) {
    148  MOZ_ASSERT(!mEntangled);
    149  mEntangled = true;
    150  return SendEntangled(aMessages);
    151 }
    152 
    153 void MessagePortParent::CloseAndDelete() {
    154  Close();
    155  (void)Send__delete__(this);
    156 }
    157 
    158 void MessagePortParent::Close() {
    159  mService = nullptr;
    160  mEntangled = false;
    161 }
    162 
    163 /* static */
    164 bool MessagePortParent::ForceClose(const nsID& aUUID,
    165                                   const nsID& aDestinationUUID,
    166                                   const uint32_t& aSequenceID) {
    167  MessagePortService* service = MessagePortService::Get();
    168  if (!service) {
    169    NS_WARNING(
    170        "The service must exist if we want to close an existing MessagePort.");
    171    // There is nothing to close so we are ok.
    172    return true;
    173  }
    174 
    175  return service->ForceClose(aUUID, aDestinationUUID, aSequenceID);
    176 }
    177 
    178 }  // namespace mozilla::dom