toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 // Copyright (c) 2007, Google Inc.
     2 // All rights reserved.
     3 //
     4 // Redistribution and use in source and binary forms, with or without
     5 // modification, are permitted provided that the following conditions are
     6 // met:
     7 //
     8 //     * Redistributions of source code must retain the above copyright
     9 // notice, this list of conditions and the following disclaimer.
    10 //     * Redistributions in binary form must reproduce the above
    11 // copyright notice, this list of conditions and the following disclaimer
    12 // in the documentation and/or other materials provided with the
    13 // distribution.
    14 //     * Neither the name of Google Inc. nor the names of its
    15 // contributors may be used to endorse or promote products derived from
    16 // this software without specific prior written permission.
    17 //
    18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    29 //
    30 //  MachIPC.mm
    31 //  Wrapper for mach IPC calls
    33 #import <stdio.h>
    34 #import "MachIPC.h"
    35 #include "common/mac/bootstrap_compat.h"
    37 namespace google_breakpad {
    38 //==============================================================================
    39 MachSendMessage::MachSendMessage(int32_t message_id) : MachMessage() {
    40   head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
    42   // head.msgh_remote_port = ...; // filled out in MachPortSender::SendMessage()
    43   head.msgh_local_port = MACH_PORT_NULL;
    44   head.msgh_reserved = 0;
    45   head.msgh_id = 0;
    47   SetDescriptorCount(0);  // start out with no descriptors
    49   SetMessageID(message_id);
    50   SetData(NULL, 0);       // client may add data later
    51 }
    53 //==============================================================================
    54 // returns true if successful
    55 bool MachMessage::SetData(void *data,
    56                           int32_t data_length) {
    57   // first check to make sure we have enough space
    58   size_t size = CalculateSize();
    59   size_t new_size = size + data_length;
    61   if (new_size > sizeof(MachMessage)) {
    62     return false;  // not enough space
    63   }
    65   GetDataPacket()->data_length = EndianU32_NtoL(data_length);
    66   if (data) memcpy(GetDataPacket()->data, data, data_length);
    68   CalculateSize();
    70   return true;
    71 }
    73 //==============================================================================
    74 // calculates and returns the total size of the message
    75 // Currently, the entire message MUST fit inside of the MachMessage
    76 //    messsage size <= sizeof(MachMessage)
    77 mach_msg_size_t MachMessage::CalculateSize() {
    78   size_t size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t);
    80   // add space for MessageDataPacket
    81   int32_t alignedDataLength = (GetDataLength() + 3) & ~0x3;
    82   size += 2*sizeof(int32_t) + alignedDataLength;
    84   // add space for descriptors
    85   size += GetDescriptorCount() * sizeof(MachMsgPortDescriptor);
    87   head.msgh_size = static_cast<mach_msg_size_t>(size);
    89   return head.msgh_size;
    90 }
    92 //==============================================================================
    93 MachMessage::MessageDataPacket *MachMessage::GetDataPacket() {
    94   size_t desc_size = sizeof(MachMsgPortDescriptor)*GetDescriptorCount();
    95   MessageDataPacket *packet =
    96     reinterpret_cast<MessageDataPacket*>(padding + desc_size);
    98   return packet;
    99 }
   101 //==============================================================================
   102 void MachMessage::SetDescriptor(int n,
   103                                 const MachMsgPortDescriptor &desc) {
   104   MachMsgPortDescriptor *desc_array =
   105     reinterpret_cast<MachMsgPortDescriptor*>(padding);
   106   desc_array[n] = desc;
   107 }
   109 //==============================================================================
   110 // returns true if successful otherwise there was not enough space
   111 bool MachMessage::AddDescriptor(const MachMsgPortDescriptor &desc) {
   112   // first check to make sure we have enough space
   113   int size = CalculateSize();
   114   size_t new_size = size + sizeof(MachMsgPortDescriptor);
   116   if (new_size > sizeof(MachMessage)) {
   117     return false;  // not enough space
   118   }
   120   // unfortunately, we need to move the data to allow space for the
   121   // new descriptor
   122   u_int8_t *p = reinterpret_cast<u_int8_t*>(GetDataPacket());
   123   bcopy(p, p+sizeof(MachMsgPortDescriptor), GetDataLength()+2*sizeof(int32_t));
   125   SetDescriptor(GetDescriptorCount(), desc);
   126   SetDescriptorCount(GetDescriptorCount() + 1);
   128   CalculateSize();
   130   return true;
   131 }
   133 //==============================================================================
   134 void MachMessage::SetDescriptorCount(int n) {
   135   body.msgh_descriptor_count = n;
   137   if (n > 0) {
   138     head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
   139   } else {
   140     head.msgh_bits &= ~MACH_MSGH_BITS_COMPLEX;
   141   }
   142 }
   144 //==============================================================================
   145 MachMsgPortDescriptor *MachMessage::GetDescriptor(int n) {
   146   if (n < GetDescriptorCount()) {
   147     MachMsgPortDescriptor *desc =
   148       reinterpret_cast<MachMsgPortDescriptor*>(padding);
   149     return desc + n;
   150   }
   152   return nil;
   153 }
   155 //==============================================================================
   156 mach_port_t MachMessage::GetTranslatedPort(int n) {
   157   if (n < GetDescriptorCount()) {
   158     return GetDescriptor(n)->GetMachPort();
   159   }
   160   return MACH_PORT_NULL;
   161 }
   163 #pragma mark -
   165 //==============================================================================
   166 // create a new mach port for receiving messages and register a name for it
   167 ReceivePort::ReceivePort(const char *receive_port_name) {
   168   mach_port_t current_task = mach_task_self();
   170   init_result_ = mach_port_allocate(current_task,
   171                                     MACH_PORT_RIGHT_RECEIVE,
   172                                     &port_);
   174   if (init_result_ != KERN_SUCCESS)
   175     return;
   177   init_result_ = mach_port_insert_right(current_task,
   178                                         port_,
   179                                         port_,
   180                                         MACH_MSG_TYPE_MAKE_SEND);
   182   if (init_result_ != KERN_SUCCESS)
   183     return;
   185   mach_port_t task_bootstrap_port = 0;
   186   init_result_ = task_get_bootstrap_port(current_task, &task_bootstrap_port);
   188   if (init_result_ != KERN_SUCCESS)
   189     return;
   191   init_result_ = breakpad::BootstrapRegister(
   192       bootstrap_port,
   193       const_cast<char*>(receive_port_name),
   194       port_);
   195 }
   197 //==============================================================================
   198 // create a new mach port for receiving messages
   199 ReceivePort::ReceivePort() {
   200   mach_port_t current_task = mach_task_self();
   202   init_result_ = mach_port_allocate(current_task,
   203                                     MACH_PORT_RIGHT_RECEIVE,
   204                                     &port_);
   206   if (init_result_ != KERN_SUCCESS)
   207     return;
   209   init_result_ =   mach_port_insert_right(current_task,
   210                                           port_,
   211                                           port_,
   212                                           MACH_MSG_TYPE_MAKE_SEND);
   213 }
   215 //==============================================================================
   216 // Given an already existing mach port, use it.  We take ownership of the
   217 // port and deallocate it in our destructor.
   218 ReceivePort::ReceivePort(mach_port_t receive_port)
   219   : port_(receive_port),
   220     init_result_(KERN_SUCCESS) {
   221 }
   223 //==============================================================================
   224 ReceivePort::~ReceivePort() {
   225   if (init_result_ == KERN_SUCCESS)
   226     mach_port_deallocate(mach_task_self(), port_);
   227 }
   229 //==============================================================================
   230 kern_return_t ReceivePort::WaitForMessage(MachReceiveMessage *out_message,
   231                                           mach_msg_timeout_t timeout) {
   232   if (!out_message) {
   233     return KERN_INVALID_ARGUMENT;
   234   }
   236   // return any error condition encountered in constructor
   237   if (init_result_ != KERN_SUCCESS)
   238     return init_result_;
   240   out_message->head.msgh_bits = 0;
   241   out_message->head.msgh_local_port = port_;
   242   out_message->head.msgh_remote_port = MACH_PORT_NULL;
   243   out_message->head.msgh_reserved = 0;
   244   out_message->head.msgh_id = 0;
   246   mach_msg_option_t options = MACH_RCV_MSG;
   247   if (timeout != MACH_MSG_TIMEOUT_NONE)
   248     options |= MACH_RCV_TIMEOUT;
   249   kern_return_t result = mach_msg(&out_message->head,
   250                                   options,
   251                                   0,
   252                                   sizeof(MachMessage),
   253                                   port_,
   254                                   timeout,              // timeout in ms
   255                                   MACH_PORT_NULL);
   257   return result;
   258 }
   260 #pragma mark -
   262 //==============================================================================
   263 // get a port with send rights corresponding to a named registered service
   264 MachPortSender::MachPortSender(const char *receive_port_name) {
   265   mach_port_t task_bootstrap_port = 0;
   266   init_result_ = task_get_bootstrap_port(mach_task_self(), 
   267                                          &task_bootstrap_port);
   269   if (init_result_ != KERN_SUCCESS)
   270     return;
   272   init_result_ = bootstrap_look_up(task_bootstrap_port,
   273                     const_cast<char*>(receive_port_name),
   274                     &send_port_);
   275 }
   277 //==============================================================================
   278 MachPortSender::MachPortSender(mach_port_t send_port) 
   279   : send_port_(send_port),
   280     init_result_(KERN_SUCCESS) {
   281 }
   283 //==============================================================================
   284 kern_return_t MachPortSender::SendMessage(MachSendMessage &message,
   285                                           mach_msg_timeout_t timeout) {
   286   if (message.head.msgh_size == 0) {
   287     return KERN_INVALID_VALUE;    // just for safety -- never should occur
   288   };
   290   if (init_result_ != KERN_SUCCESS)
   291     return init_result_;
   293   message.head.msgh_remote_port = send_port_;
   295   kern_return_t result = mach_msg(&message.head,
   296                                   MACH_SEND_MSG | MACH_SEND_TIMEOUT,
   297                                   message.head.msgh_size,
   298                                   0,
   299                                   MACH_PORT_NULL,
   300                                   timeout,              // timeout in ms
   301                                   MACH_PORT_NULL);
   303   return result;
   304 }
   306 }  // namespace google_breakpad

mercurial