tor-browser

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

ipc_message.cc (7741B)


      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 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 
      7 #include "chrome/common/ipc_message.h"
      8 
      9 #include "base/logging.h"
     10 #include "mojo/core/ports/event.h"
     11 
     12 #include <utility>
     13 
     14 #include "nsISupportsImpl.h"
     15 
     16 namespace IPC {
     17 
     18 //------------------------------------------------------------------------------
     19 
     20 const mojo::core::ports::UserMessage::TypeInfo Message::kUserMessageTypeInfo{};
     21 
     22 Message::~Message() { MOZ_COUNT_DTOR(IPC::Message); }
     23 
     24 Message::Message(routeid_t routing_id, msgid_t type, uint32_t segment_capacity,
     25                 HeaderFlags flags)
     26    : UserMessage(&kUserMessageTypeInfo),
     27      Pickle(sizeof(Header), segment_capacity) {
     28  MOZ_COUNT_CTOR(IPC::Message);
     29  header()->routing = routing_id;
     30  header()->type = type;
     31  header()->flags = flags;
     32  header()->num_handles = 0;
     33  header()->txid = -1;
     34  header()->seqno = 0;
     35 #if defined(XP_DARWIN)
     36  header()->cookie = 0;
     37  header()->num_send_rights = 0;
     38 #endif
     39  header()->event_footer_size = 0;
     40  header()->_padding = 0;
     41 }
     42 
     43 Message::Message(const char* data, int data_len)
     44    : UserMessage(&kUserMessageTypeInfo),
     45      Pickle(sizeof(Header), data, data_len) {
     46  MOZ_COUNT_CTOR(IPC::Message);
     47 }
     48 
     49 /*static*/ mozilla::UniquePtr<Message> Message::IPDLMessage(
     50    routeid_t routing_id, msgid_t type, uint32_t segment_capacity,
     51    HeaderFlags flags) {
     52  return mozilla::MakeUnique<Message>(routing_id, type, segment_capacity,
     53                                      flags);
     54 }
     55 
     56 /*static*/ mozilla::UniquePtr<Message> Message::ForSyncDispatchError(
     57    NestedLevel level) {
     58  auto m = mozilla::MakeUnique<Message>(0, 0, 0, HeaderFlags(level));
     59  auto& flags = m->header()->flags;
     60  flags.SetSync();
     61  flags.SetReply();
     62  flags.SetReplyError();
     63  return m;
     64 }
     65 
     66 void Message::WriteFooter(const void* data, uint32_t data_len) {
     67  if (data_len == 0) {
     68    return;
     69  }
     70 
     71  WriteBytes(data, data_len);
     72 }
     73 
     74 bool Message::ReadFooter(void* buffer, uint32_t buffer_len, bool truncate) {
     75  if (buffer_len == 0) {
     76    return true;
     77  }
     78 
     79  if (NS_WARN_IF(AlignInt(header()->payload_size) != header()->payload_size) ||
     80      NS_WARN_IF(AlignInt(buffer_len) > header()->payload_size)) {
     81    return false;
     82  }
     83 
     84  // Seek to the start of the footer, and read it in. We read in with a
     85  // duplicate of the iterator so we can use it to truncate later.
     86  uint32_t offset = header()->payload_size - AlignInt(buffer_len);
     87  PickleIterator footer_iter(*this);
     88  if (NS_WARN_IF(!IgnoreBytes(&footer_iter, offset))) {
     89    return false;
     90  }
     91 
     92  PickleIterator read_iter(footer_iter);
     93  bool ok = ReadBytesInto(&read_iter, buffer, buffer_len);
     94 
     95  // If requested, truncate the buffer to the start of the footer.
     96  if (truncate) {
     97    Truncate(&footer_iter);
     98  }
     99  return ok;
    100 }
    101 
    102 bool Message::WriteFileHandle(mozilla::UniqueFileHandle handle) {
    103  uint32_t handle_index = attached_handles_.Length();
    104  WriteUInt32(handle_index);
    105  if (handle_index == MAX_DESCRIPTORS_PER_MESSAGE) {
    106    return false;
    107  }
    108  attached_handles_.AppendElement(std::move(handle));
    109  return true;
    110 }
    111 
    112 bool Message::ConsumeFileHandle(PickleIterator* iter,
    113                                mozilla::UniqueFileHandle* handle) const {
    114  uint32_t handle_index;
    115  if (!ReadUInt32(iter, &handle_index)) {
    116    return false;
    117  }
    118  if (handle_index >= attached_handles_.Length()) {
    119    return false;
    120  }
    121  // NOTE: This mutates the underlying array, replacing the handle with an
    122  // invalid handle.
    123  *handle = std::exchange(attached_handles_[handle_index], nullptr);
    124  return true;
    125 }
    126 
    127 void Message::SetAttachedFileHandles(
    128    nsTArray<mozilla::UniqueFileHandle> handles) {
    129  MOZ_DIAGNOSTIC_ASSERT(attached_handles_.IsEmpty());
    130  attached_handles_ = std::move(handles);
    131 }
    132 
    133 bool Message::has_any_attachments() const {
    134  return !attached_ports_.IsEmpty() || !attached_handles_.IsEmpty()
    135 #if defined(XP_DARWIN)
    136         || !attached_send_rights_.IsEmpty() ||
    137         !attached_receive_rights_.IsEmpty()
    138 #endif
    139      ;
    140 }
    141 
    142 uint32_t Message::num_handles() const { return attached_handles_.Length(); }
    143 
    144 void Message::WritePort(mozilla::ipc::ScopedPort port) {
    145  uint32_t port_index = attached_ports_.Length();
    146  WriteUInt32(port_index);
    147  attached_ports_.AppendElement(std::move(port));
    148 }
    149 
    150 bool Message::ConsumePort(PickleIterator* iter,
    151                          mozilla::ipc::ScopedPort* port) const {
    152  uint32_t port_index;
    153  if (!ReadUInt32(iter, &port_index)) {
    154    return false;
    155  }
    156  if (port_index >= attached_ports_.Length()) {
    157    return false;
    158  }
    159  // NOTE: This mutates the underlying array, replacing the port with a consumed
    160  // port.
    161  *port = std::exchange(attached_ports_[port_index], {});
    162  return true;
    163 }
    164 
    165 void Message::SetAttachedPorts(nsTArray<mozilla::ipc::ScopedPort> ports) {
    166  MOZ_DIAGNOSTIC_ASSERT(attached_ports_.IsEmpty());
    167  attached_ports_ = std::move(ports);
    168 }
    169 
    170 #if defined(XP_DARWIN)
    171 bool Message::WriteMachSendRight(mozilla::UniqueMachSendRight port) {
    172  uint32_t index = attached_send_rights_.Length();
    173  WriteUInt32(index);
    174  if (index == MAX_DESCRIPTORS_PER_MESSAGE) {
    175    return false;
    176  }
    177  attached_send_rights_.AppendElement(std::move(port));
    178  return true;
    179 }
    180 
    181 bool Message::ConsumeMachSendRight(PickleIterator* iter,
    182                                   mozilla::UniqueMachSendRight* port) const {
    183  uint32_t index;
    184  if (!ReadUInt32(iter, &index)) {
    185    return false;
    186  }
    187  if (index >= attached_send_rights_.Length()) {
    188    return false;
    189  }
    190  // NOTE: This mutates the underlying array, replacing the send right with a
    191  // null right.
    192  *port = std::exchange(attached_send_rights_[index], nullptr);
    193  return true;
    194 }
    195 
    196 uint32_t Message::num_send_rights() const {
    197  return attached_send_rights_.Length();
    198 }
    199 
    200 bool Message::WriteMachReceiveRight(mozilla::UniqueMachReceiveRight port) {
    201  uint32_t index = attached_receive_rights_.Length();
    202  WriteUInt32(index);
    203  if (index == MAX_DESCRIPTORS_PER_MESSAGE) {
    204    return false;
    205  }
    206  attached_receive_rights_.AppendElement(std::move(port));
    207  return true;
    208 }
    209 
    210 bool Message::ConsumeMachReceiveRight(
    211    PickleIterator* iter, mozilla::UniqueMachReceiveRight* port) const {
    212  uint32_t index;
    213  if (!ReadUInt32(iter, &index)) {
    214    return false;
    215  }
    216  if (index >= attached_receive_rights_.Length()) {
    217    return false;
    218  }
    219  // NOTE: This mutates the underlying array, replacing the receive right with a
    220  // null right.
    221  *port = std::exchange(attached_receive_rights_[index], nullptr);
    222  return true;
    223 }
    224 
    225 uint32_t Message::num_receive_rights() const {
    226  return attached_receive_rights_.Length();
    227 }
    228 #endif
    229 
    230 bool Message::WillBeRoutedExternally(
    231    mojo::core::ports::UserMessageEvent& event) {
    232  if (!attached_ports_.IsEmpty()) {
    233    // Explicitly attach any ports which were attached to this Message to this
    234    // UserMessageEvent before we route it externally so that they can be
    235    // transferred correctly. These ports will be recovered if needed in
    236    // `GetMessage`.
    237    MOZ_DIAGNOSTIC_ASSERT(
    238        event.num_ports() == 0,
    239        "Must not have previously attached ports to the UserMessageEvent");
    240    event.ReservePorts(attached_ports_.Length());
    241    for (size_t i = 0; i < event.num_ports(); ++i) {
    242      event.ports()[i] = attached_ports_[i].Release().name();
    243    }
    244    attached_ports_.Clear();
    245  }
    246  return true;
    247 }
    248 
    249 void Message::AssertAsLargeAsHeader() const {
    250  MOZ_DIAGNOSTIC_ASSERT(size() >= sizeof(Header));
    251  MOZ_DIAGNOSTIC_ASSERT(CurrentSize() >= sizeof(Header));
    252  // Our buffers should agree with what our header specifies.
    253  MOZ_DIAGNOSTIC_ASSERT(size() == CurrentSize());
    254 }
    255 
    256 }  // namespace IPC