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

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.

michael@0 1 // Copyright (c) 2007, Google Inc.
michael@0 2 // All rights reserved.
michael@0 3 //
michael@0 4 // Redistribution and use in source and binary forms, with or without
michael@0 5 // modification, are permitted provided that the following conditions are
michael@0 6 // met:
michael@0 7 //
michael@0 8 // * Redistributions of source code must retain the above copyright
michael@0 9 // notice, this list of conditions and the following disclaimer.
michael@0 10 // * Redistributions in binary form must reproduce the above
michael@0 11 // copyright notice, this list of conditions and the following disclaimer
michael@0 12 // in the documentation and/or other materials provided with the
michael@0 13 // distribution.
michael@0 14 // * Neither the name of Google Inc. nor the names of its
michael@0 15 // contributors may be used to endorse or promote products derived from
michael@0 16 // this software without specific prior written permission.
michael@0 17 //
michael@0 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
michael@0 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
michael@0 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
michael@0 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@0 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@0 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
michael@0 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 29 //
michael@0 30 // MachIPC.h
michael@0 31 //
michael@0 32 // Some helpful wrappers for using Mach IPC calls
michael@0 33
michael@0 34 #ifndef MACH_IPC_H__
michael@0 35 #define MACH_IPC_H__
michael@0 36
michael@0 37 #import <mach/mach.h>
michael@0 38 #import <mach/message.h>
michael@0 39 #import <servers/bootstrap.h>
michael@0 40 #import <sys/types.h>
michael@0 41
michael@0 42 #import <CoreServices/CoreServices.h>
michael@0 43
michael@0 44 //==============================================================================
michael@0 45 // DISCUSSION:
michael@0 46 //
michael@0 47 // The three main classes of interest are
michael@0 48 //
michael@0 49 // MachMessage: a wrapper for a mach message of the following form
michael@0 50 // mach_msg_header_t
michael@0 51 // mach_msg_body_t
michael@0 52 // optional descriptors
michael@0 53 // optional extra message data
michael@0 54 //
michael@0 55 // MachReceiveMessage and MachSendMessage subclass MachMessage
michael@0 56 // and are used instead of MachMessage which is an abstract base class
michael@0 57 //
michael@0 58 // ReceivePort:
michael@0 59 // Represents a mach port for which we have receive rights
michael@0 60 //
michael@0 61 // MachPortSender:
michael@0 62 // Represents a mach port for which we have send rights
michael@0 63 //
michael@0 64 // Here's an example to receive a message on a server port:
michael@0 65 //
michael@0 66 // // This creates our named server port
michael@0 67 // ReceivePort receivePort("com.Google.MyService");
michael@0 68 //
michael@0 69 // MachReceiveMessage message;
michael@0 70 // kern_return_t result = receivePort.WaitForMessage(&message, 0);
michael@0 71 //
michael@0 72 // if (result == KERN_SUCCESS && message.GetMessageID() == 57) {
michael@0 73 // mach_port_t task = message.GetTranslatedPort(0);
michael@0 74 // mach_port_t thread = message.GetTranslatedPort(1);
michael@0 75 //
michael@0 76 // char *messageString = message.GetData();
michael@0 77 //
michael@0 78 // printf("message string = %s\n", messageString);
michael@0 79 // }
michael@0 80 //
michael@0 81 // Here is an example of using these classes to send a message to this port:
michael@0 82 //
michael@0 83 // // send to already named port
michael@0 84 // MachPortSender sender("com.Google.MyService");
michael@0 85 // MachSendMessage message(57); // our message ID is 57
michael@0 86 //
michael@0 87 // // add some ports to be translated for us
michael@0 88 // message.AddDescriptor(mach_task_self()); // our task
michael@0 89 // message.AddDescriptor(mach_thread_self()); // this thread
michael@0 90 //
michael@0 91 // char messageString[] = "Hello server!\n";
michael@0 92 // message.SetData(messageString, strlen(messageString)+1);
michael@0 93 //
michael@0 94 // kern_return_t result = sender.SendMessage(message, 1000); // timeout 1000ms
michael@0 95 //
michael@0 96
michael@0 97 namespace google_breakpad {
michael@0 98 #define PRINT_MACH_RESULT(result_, message_) \
michael@0 99 printf(message_" %s (%d)\n", mach_error_string(result_), result_ );
michael@0 100
michael@0 101 //==============================================================================
michael@0 102 // A wrapper class for mach_msg_port_descriptor_t (with same memory layout)
michael@0 103 // with convenient constructors and accessors
michael@0 104 class MachMsgPortDescriptor : public mach_msg_port_descriptor_t {
michael@0 105 public:
michael@0 106 // General-purpose constructor
michael@0 107 MachMsgPortDescriptor(mach_port_t in_name,
michael@0 108 mach_msg_type_name_t in_disposition) {
michael@0 109 name = in_name;
michael@0 110 pad1 = 0;
michael@0 111 pad2 = 0;
michael@0 112 disposition = in_disposition;
michael@0 113 type = MACH_MSG_PORT_DESCRIPTOR;
michael@0 114 }
michael@0 115
michael@0 116 // For passing send rights to a port
michael@0 117 MachMsgPortDescriptor(mach_port_t in_name) {
michael@0 118 name = in_name;
michael@0 119 pad1 = 0;
michael@0 120 pad2 = 0;
michael@0 121 disposition = MACH_MSG_TYPE_COPY_SEND;
michael@0 122 type = MACH_MSG_PORT_DESCRIPTOR;
michael@0 123 }
michael@0 124
michael@0 125 // Copy constructor
michael@0 126 MachMsgPortDescriptor(const MachMsgPortDescriptor& desc) {
michael@0 127 name = desc.name;
michael@0 128 pad1 = desc.pad1;
michael@0 129 pad2 = desc.pad2;
michael@0 130 disposition = desc.disposition;
michael@0 131 type = desc.type;
michael@0 132 }
michael@0 133
michael@0 134 mach_port_t GetMachPort() const {
michael@0 135 return name;
michael@0 136 }
michael@0 137
michael@0 138 mach_msg_type_name_t GetDisposition() const {
michael@0 139 return disposition;
michael@0 140 }
michael@0 141
michael@0 142 // For convenience
michael@0 143 operator mach_port_t() const {
michael@0 144 return GetMachPort();
michael@0 145 }
michael@0 146 };
michael@0 147
michael@0 148 //==============================================================================
michael@0 149 // MachMessage: a wrapper for a mach message
michael@0 150 // (mach_msg_header_t, mach_msg_body_t, extra data)
michael@0 151 //
michael@0 152 // This considerably simplifies the construction of a message for sending
michael@0 153 // and the getting at relevant data and descriptors for the receiver.
michael@0 154 //
michael@0 155 // Currently the combined size of the descriptors plus data must be
michael@0 156 // less than 1024. But as a benefit no memory allocation is necessary.
michael@0 157 //
michael@0 158 // TODO: could consider adding malloc() support for very large messages
michael@0 159 //
michael@0 160 // A MachMessage object is used by ReceivePort::WaitForMessage
michael@0 161 // and MachPortSender::SendMessage
michael@0 162 //
michael@0 163 class MachMessage {
michael@0 164 public:
michael@0 165
michael@0 166 // The receiver of the message can retrieve the raw data this way
michael@0 167 uint8_t *GetData() {
michael@0 168 return GetDataLength() > 0 ? GetDataPacket()->data : NULL;
michael@0 169 }
michael@0 170
michael@0 171 uint32_t GetDataLength() {
michael@0 172 return EndianU32_LtoN(GetDataPacket()->data_length);
michael@0 173 }
michael@0 174
michael@0 175 // The message ID may be used as a code identifying the type of message
michael@0 176 void SetMessageID(int32_t message_id) {
michael@0 177 GetDataPacket()->id = EndianU32_NtoL(message_id);
michael@0 178 }
michael@0 179
michael@0 180 int32_t GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); }
michael@0 181
michael@0 182 // Adds a descriptor (typically a mach port) to be translated
michael@0 183 // returns true if successful, otherwise not enough space
michael@0 184 bool AddDescriptor(const MachMsgPortDescriptor &desc);
michael@0 185
michael@0 186 int GetDescriptorCount() const { return body.msgh_descriptor_count; }
michael@0 187 MachMsgPortDescriptor *GetDescriptor(int n);
michael@0 188
michael@0 189 // Convenience method which gets the mach port described by the descriptor
michael@0 190 mach_port_t GetTranslatedPort(int n);
michael@0 191
michael@0 192 // A simple message is one with no descriptors
michael@0 193 bool IsSimpleMessage() const { return GetDescriptorCount() == 0; }
michael@0 194
michael@0 195 // Sets raw data for the message (returns false if not enough space)
michael@0 196 bool SetData(void *data, int32_t data_length);
michael@0 197
michael@0 198 protected:
michael@0 199 // Consider this an abstract base class - must create an actual instance
michael@0 200 // of MachReceiveMessage or MachSendMessage
michael@0 201
michael@0 202 MachMessage() {
michael@0 203 memset(this, 0, sizeof(MachMessage));
michael@0 204 }
michael@0 205
michael@0 206 friend class ReceivePort;
michael@0 207 friend class MachPortSender;
michael@0 208
michael@0 209 // Represents raw data in our message
michael@0 210 struct MessageDataPacket {
michael@0 211 int32_t id; // little-endian
michael@0 212 int32_t data_length; // little-endian
michael@0 213 uint8_t data[1]; // actual size limited by sizeof(MachMessage)
michael@0 214 };
michael@0 215
michael@0 216 MessageDataPacket* GetDataPacket();
michael@0 217
michael@0 218 void SetDescriptorCount(int n);
michael@0 219 void SetDescriptor(int n, const MachMsgPortDescriptor &desc);
michael@0 220
michael@0 221 // Returns total message size setting msgh_size in the header to this value
michael@0 222 mach_msg_size_t CalculateSize();
michael@0 223
michael@0 224 mach_msg_header_t head;
michael@0 225 mach_msg_body_t body;
michael@0 226 uint8_t padding[1024]; // descriptors and data may be embedded here
michael@0 227 };
michael@0 228
michael@0 229 //==============================================================================
michael@0 230 // MachReceiveMessage and MachSendMessage are useful to separate the idea
michael@0 231 // of a mach message being sent and being received, and adds increased type
michael@0 232 // safety:
michael@0 233 // ReceivePort::WaitForMessage() only accepts a MachReceiveMessage
michael@0 234 // MachPortSender::SendMessage() only accepts a MachSendMessage
michael@0 235
michael@0 236 //==============================================================================
michael@0 237 class MachReceiveMessage : public MachMessage {
michael@0 238 public:
michael@0 239 MachReceiveMessage() : MachMessage() {};
michael@0 240 };
michael@0 241
michael@0 242 //==============================================================================
michael@0 243 class MachSendMessage : public MachMessage {
michael@0 244 public:
michael@0 245 MachSendMessage(int32_t message_id);
michael@0 246 };
michael@0 247
michael@0 248 //==============================================================================
michael@0 249 // Represents a mach port for which we have receive rights
michael@0 250 class ReceivePort {
michael@0 251 public:
michael@0 252 // Creates a new mach port for receiving messages and registers a name for it
michael@0 253 explicit ReceivePort(const char *receive_port_name);
michael@0 254
michael@0 255 // Given an already existing mach port, use it. We take ownership of the
michael@0 256 // port and deallocate it in our destructor.
michael@0 257 explicit ReceivePort(mach_port_t receive_port);
michael@0 258
michael@0 259 // Create a new mach port for receiving messages
michael@0 260 ReceivePort();
michael@0 261
michael@0 262 ~ReceivePort();
michael@0 263
michael@0 264 // Waits on the mach port until message received or timeout
michael@0 265 kern_return_t WaitForMessage(MachReceiveMessage *out_message,
michael@0 266 mach_msg_timeout_t timeout);
michael@0 267
michael@0 268 // The underlying mach port that we wrap
michael@0 269 mach_port_t GetPort() const { return port_; }
michael@0 270
michael@0 271 private:
michael@0 272 ReceivePort(const ReceivePort&); // disable copy c-tor
michael@0 273
michael@0 274 mach_port_t port_;
michael@0 275 kern_return_t init_result_;
michael@0 276 };
michael@0 277
michael@0 278 //==============================================================================
michael@0 279 // Represents a mach port for which we have send rights
michael@0 280 class MachPortSender {
michael@0 281 public:
michael@0 282 // get a port with send rights corresponding to a named registered service
michael@0 283 explicit MachPortSender(const char *receive_port_name);
michael@0 284
michael@0 285
michael@0 286 // Given an already existing mach port, use it.
michael@0 287 explicit MachPortSender(mach_port_t send_port);
michael@0 288
michael@0 289 kern_return_t SendMessage(MachSendMessage &message,
michael@0 290 mach_msg_timeout_t timeout);
michael@0 291
michael@0 292 private:
michael@0 293 MachPortSender(const MachPortSender&); // disable copy c-tor
michael@0 294
michael@0 295 mach_port_t send_port_;
michael@0 296 kern_return_t init_result_;
michael@0 297 };
michael@0 298
michael@0 299 } // namespace google_breakpad
michael@0 300
michael@0 301 #endif // MACH_IPC_H__

mercurial