Another take on menu's. This uses the hosting menu scroll view container as a menuba...
[chromium-blink-merge.git] / base / mach_ipc_mac.h
blob5836c3a9774d7a5e469be43f11ef2d7e197dc31a
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef BASE_MACH_IPC_MAC_H_
6 #define BASE_MACH_IPC_MAC_H_
7 #pragma once
9 #include <mach/mach.h>
10 #include <mach/message.h>
11 #include <servers/bootstrap.h>
12 #include <sys/types.h>
14 #include <CoreServices/CoreServices.h>
16 #include "base/basictypes.h"
18 //==============================================================================
19 // DISCUSSION:
21 // The three main classes of interest are
23 // MachMessage: a wrapper for a mach message of the following form
24 // mach_msg_header_t
25 // mach_msg_body_t
26 // optional descriptors
27 // optional extra message data
29 // MachReceiveMessage and MachSendMessage subclass MachMessage
30 // and are used instead of MachMessage which is an abstract base class
32 // ReceivePort:
33 // Represents a mach port for which we have receive rights
35 // MachPortSender:
36 // Represents a mach port for which we have send rights
38 // Here's an example to receive a message on a server port:
40 // // This creates our named server port
41 // ReceivePort receivePort("com.Google.MyService");
43 // MachReceiveMessage message;
44 // kern_return_t result = receivePort.WaitForMessage(&message, 0);
46 // if (result == KERN_SUCCESS && message.GetMessageID() == 57) {
47 // mach_port_t task = message.GetTranslatedPort(0);
48 // mach_port_t thread = message.GetTranslatedPort(1);
50 // char *messageString = message.GetData();
52 // printf("message string = %s\n", messageString);
53 // }
55 // Here is an example of using these classes to send a message to this port:
57 // // send to already named port
58 // MachPortSender sender("com.Google.MyService");
59 // MachSendMessage message(57); // our message ID is 57
61 // // add some ports to be translated for us
62 // message.AddDescriptor(mach_task_self()); // our task
63 // message.AddDescriptor(mach_thread_self()); // this thread
65 // char messageString[] = "Hello server!\n";
66 // message.SetData(messageString, strlen(messageString)+1);
67 // // timeout 1000ms
68 // kern_return_t result = sender.SendMessage(message, 1000);
71 #define PRINT_MACH_RESULT(result_, message_) \
72 printf(message_" %s (%d)\n", mach_error_string(result_), result_ );
74 namespace base {
76 //==============================================================================
77 // A wrapper class for mach_msg_port_descriptor_t (with same memory layout)
78 // with convenient constructors and accessors
79 class MachMsgPortDescriptor : public mach_msg_port_descriptor_t {
80 public:
81 // General-purpose constructor
82 MachMsgPortDescriptor(mach_port_t in_name,
83 mach_msg_type_name_t in_disposition) {
84 name = in_name;
85 pad1 = 0;
86 pad2 = 0;
87 disposition = in_disposition;
88 type = MACH_MSG_PORT_DESCRIPTOR;
91 // For passing send rights to a port
92 MachMsgPortDescriptor(mach_port_t in_name) {
93 name = in_name;
94 pad1 = 0;
95 pad2 = 0;
96 disposition = MACH_MSG_TYPE_PORT_SEND;
97 type = MACH_MSG_PORT_DESCRIPTOR;
100 // Copy constructor
101 MachMsgPortDescriptor(const MachMsgPortDescriptor& desc) {
102 name = desc.name;
103 pad1 = desc.pad1;
104 pad2 = desc.pad2;
105 disposition = desc.disposition;
106 type = desc.type;
109 mach_port_t GetMachPort() const {
110 return name;
113 mach_msg_type_name_t GetDisposition() const {
114 return disposition;
117 // We're just a simple wrapper for mach_msg_port_descriptor_t
118 // and have the same memory layout
119 operator mach_msg_port_descriptor_t&() {
120 return *this;
123 // For convenience
124 operator mach_port_t() const {
125 return GetMachPort();
129 //==============================================================================
130 // MachMessage: a wrapper for a mach message
131 // (mach_msg_header_t, mach_msg_body_t, extra data)
133 // This considerably simplifies the construction of a message for sending
134 // and the getting at relevant data and descriptors for the receiver.
136 // This class can be initialized using external storage of an arbitrary size
137 // or it can manage storage internally.
138 // 1. If storage is allocated internally, the combined size of the descriptors
139 // plus data must be less than 1024. But as a benefit no memory allocation is
140 // necessary.
141 // 2. For external storage, a buffer of at least EmptyMessageSize() must be
142 // provided.
144 // A MachMessage object is used by ReceivePort::WaitForMessage
145 // and MachPortSender::SendMessage
147 class MachMessage {
148 public:
150 virtual ~MachMessage();
152 // The receiver of the message can retrieve the raw data this way
153 u_int8_t *GetData() {
154 return GetDataLength() > 0 ? GetDataPacket()->data : NULL;
157 u_int32_t GetDataLength() {
158 return EndianU32_LtoN(GetDataPacket()->data_length);
161 // The message ID may be used as a code identifying the type of message
162 void SetMessageID(int32_t message_id) {
163 GetDataPacket()->id = EndianU32_NtoL(message_id);
166 int32_t GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); }
168 // Adds a descriptor (typically a mach port) to be translated
169 // returns true if successful, otherwise not enough space
170 bool AddDescriptor(const MachMsgPortDescriptor &desc);
172 int GetDescriptorCount() const {
173 return storage_->body.msgh_descriptor_count;
176 MachMsgPortDescriptor *GetDescriptor(int n);
178 // Convenience method which gets the mach port described by the descriptor
179 mach_port_t GetTranslatedPort(int n);
181 // A simple message is one with no descriptors
182 bool IsSimpleMessage() const { return GetDescriptorCount() == 0; }
184 // Sets raw data for the message (returns false if not enough space)
185 bool SetData(const void* data, int32_t data_length);
187 protected:
188 // Consider this an abstract base class - must create an actual instance
189 // of MachReceiveMessage or MachSendMessage
190 MachMessage();
192 // Constructor for use with preallocate storage.
193 // storage_length must be >= EmptyMessageSize()
194 MachMessage(void *storage, size_t storage_length);
196 friend class ReceivePort;
197 friend class MachPortSender;
199 // Represents raw data in our message
200 struct MessageDataPacket {
201 int32_t id; // little-endian
202 int32_t data_length; // little-endian
203 u_int8_t data[1]; // actual size limited by storage_length_bytes_
206 MessageDataPacket* GetDataPacket();
208 void SetDescriptorCount(int n);
209 void SetDescriptor(int n, const MachMsgPortDescriptor &desc);
211 // Returns total message size setting msgh_size in the header to this value
212 int CalculateSize();
214 // Returns total storage size that this object can grow to, this is inclusive
215 // of the mach header.
216 size_t MaxSize() const { return storage_length_bytes_; }
218 protected:
219 mach_msg_header_t *Head() { return &(storage_->head); }
221 private:
222 struct MachMessageData {
223 mach_msg_header_t head;
224 mach_msg_body_t body;
225 // descriptors and data may be embedded here.
226 u_int8_t padding[1024];
229 // kEmptyMessageSize needs to have the definition of MachMessageData before
230 // it.
231 public:
232 // The size of an empty message with no data.
233 static const size_t kEmptyMessageSize = sizeof(mach_msg_header_t) +
234 sizeof(mach_msg_body_t) +
235 sizeof(MessageDataPacket);
237 private:
238 MachMessageData *storage_;
239 size_t storage_length_bytes_;
240 bool own_storage_; // Is storage owned by this object?
243 //==============================================================================
244 // MachReceiveMessage and MachSendMessage are useful to separate the idea
245 // of a mach message being sent and being received, and adds increased type
246 // safety:
247 // ReceivePort::WaitForMessage() only accepts a MachReceiveMessage
248 // MachPortSender::SendMessage() only accepts a MachSendMessage
250 //==============================================================================
251 class MachReceiveMessage : public MachMessage {
252 public:
253 MachReceiveMessage() : MachMessage() {}
254 MachReceiveMessage(void *storage, size_t storage_length)
255 : MachMessage(storage, storage_length) {}
257 private:
258 DISALLOW_COPY_AND_ASSIGN(MachReceiveMessage);
261 //==============================================================================
262 class MachSendMessage : public MachMessage {
263 public:
264 explicit MachSendMessage(int32_t message_id);
265 MachSendMessage(void *storage, size_t storage_length, int32_t message_id);
267 private:
268 void Initialize(int32_t message_id);
270 DISALLOW_COPY_AND_ASSIGN(MachSendMessage);
273 //==============================================================================
274 // Represents a mach port for which we have receive rights
275 class ReceivePort {
276 public:
277 // Creates a new mach port for receiving messages and registers a name for it
278 explicit ReceivePort(const char *receive_port_name);
280 // Given an already existing mach port, use it. We take ownership of the
281 // port and deallocate it in our destructor.
282 explicit ReceivePort(mach_port_t receive_port);
284 // Create a new mach port for receiving messages
285 ReceivePort();
287 ~ReceivePort();
289 // Waits on the mach port until message received or timeout
290 kern_return_t WaitForMessage(MachReceiveMessage *out_message,
291 mach_msg_timeout_t timeout);
293 // The underlying mach port that we wrap
294 mach_port_t GetPort() const { return port_; }
296 private:
297 mach_port_t port_;
298 kern_return_t init_result_;
300 DISALLOW_COPY_AND_ASSIGN(ReceivePort);
303 //==============================================================================
304 // Represents a mach port for which we have send rights
305 class MachPortSender {
306 public:
307 // get a port with send rights corresponding to a named registered service
308 explicit MachPortSender(const char *receive_port_name);
311 // Given an already existing mach port, use it. Does not take ownership of
312 // |send_port|.
313 explicit MachPortSender(mach_port_t send_port);
315 kern_return_t SendMessage(MachSendMessage &message,
316 mach_msg_timeout_t timeout);
318 private:
319 mach_port_t send_port_;
320 kern_return_t init_result_;
322 DISALLOW_COPY_AND_ASSIGN(MachPortSender);
325 } // namespace base
327 #endif // BASE_MACH_IPC_MAC_H_