Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: base/mach_ipc_mac.mm

Issue 14137013: Remove base/mac/mach_ipc_mac.{h,mm}. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/mach_ipc_mac.h ('k') | chrome/browser/automation/testing_automation_provider.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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.
4
5 #include "base/mach_ipc_mac.h"
6
7 #import <Foundation/Foundation.h>
8 #include <mach/vm_map.h>
9
10 #include <stdio.h>
11 #include "base/logging.h"
12
13 namespace base {
14
15 // static
16 const size_t MachMessage::kEmptyMessageSize = sizeof(mach_msg_header_t) +
17 sizeof(mach_msg_body_t) + sizeof(MessageDataPacket);
18
19 //==============================================================================
20 MachSendMessage::MachSendMessage(int32_t message_id) : MachMessage() {
21 Initialize(message_id);
22 }
23
24 MachSendMessage::MachSendMessage(void *storage, size_t storage_length,
25 int32_t message_id)
26 : MachMessage(storage, storage_length) {
27 Initialize(message_id);
28 }
29
30 void MachSendMessage::Initialize(int32_t message_id) {
31 Head()->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
32
33 // head.msgh_remote_port = ...; // filled out in MachPortSender::SendMessage()
34 Head()->msgh_local_port = MACH_PORT_NULL;
35 Head()->msgh_reserved = 0;
36 Head()->msgh_id = 0;
37
38 SetDescriptorCount(0); // start out with no descriptors
39
40 SetMessageID(message_id);
41 SetData(NULL, 0); // client may add data later
42 }
43
44 //==============================================================================
45 MachMessage::MachMessage()
46 : storage_(new MachMessageData), // Allocate storage_ ourselves
47 storage_length_bytes_(sizeof(MachMessageData)),
48 own_storage_(true) {
49 memset(storage_, 0, storage_length_bytes_);
50 }
51
52 //==============================================================================
53 MachMessage::MachMessage(void *storage, size_t storage_length)
54 : storage_(static_cast<MachMessageData*>(storage)),
55 storage_length_bytes_(storage_length),
56 own_storage_(false) {
57 DCHECK(storage);
58 DCHECK_GE(storage_length, kEmptyMessageSize);
59 }
60
61 //==============================================================================
62 MachMessage::~MachMessage() {
63 if (own_storage_) {
64 delete storage_;
65 storage_ = NULL;
66 }
67 }
68
69 //==============================================================================
70 // returns true if successful
71 bool MachMessage::SetData(const void* data,
72 int32_t data_length) {
73 // Enforce the fact that it's only safe to call this method once on a
74 // message.
75 DCHECK(GetDataPacket()->data_length == 0);
76
77 // first check to make sure we have enough space
78 int size = CalculateSize();
79 int new_size = size + data_length;
80
81 if ((unsigned)new_size > storage_length_bytes_) {
82 return false; // not enough space
83 }
84
85 GetDataPacket()->data_length = EndianU32_NtoL(data_length);
86 if (data) memcpy(GetDataPacket()->data, data, data_length);
87
88 // Update the Mach header with the new aligned size of the message.
89 CalculateSize();
90
91 return true;
92 }
93
94 //==============================================================================
95 // calculates and returns the total size of the message
96 // Currently, the entire message MUST fit inside of the MachMessage
97 // messsage size <= EmptyMessageSize()
98 int MachMessage::CalculateSize() {
99 int size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t);
100
101 // add space for MessageDataPacket
102 int32_t alignedDataLength = (GetDataLength() + 3) & ~0x3;
103 size += 2*sizeof(int32_t) + alignedDataLength;
104
105 // add space for descriptors
106 size += GetDescriptorCount() * sizeof(MachMsgPortDescriptor);
107
108 Head()->msgh_size = size;
109
110 return size;
111 }
112
113 //==============================================================================
114 MachMessage::MessageDataPacket *MachMessage::GetDataPacket() const {
115 int desc_size = sizeof(MachMsgPortDescriptor)*GetDescriptorCount();
116 MessageDataPacket *packet =
117 reinterpret_cast<MessageDataPacket*>(storage_->padding + desc_size);
118
119 return packet;
120 }
121
122 //==============================================================================
123 void MachMessage::SetDescriptor(int n,
124 const MachMsgPortDescriptor &desc) {
125 MachMsgPortDescriptor *desc_array =
126 reinterpret_cast<MachMsgPortDescriptor*>(storage_->padding);
127 desc_array[n] = desc;
128 }
129
130 //==============================================================================
131 // returns true if successful otherwise there was not enough space
132 bool MachMessage::AddDescriptor(const MachMsgPortDescriptor &desc) {
133 // first check to make sure we have enough space
134 int size = CalculateSize();
135 int new_size = size + sizeof(MachMsgPortDescriptor);
136
137 if ((unsigned)new_size > storage_length_bytes_) {
138 return false; // not enough space
139 }
140
141 // unfortunately, we need to move the data to allow space for the
142 // new descriptor
143 u_int8_t *p = reinterpret_cast<u_int8_t*>(GetDataPacket());
144 bcopy(p, p+sizeof(MachMsgPortDescriptor), GetDataLength()+2*sizeof(int32_t));
145
146 SetDescriptor(GetDescriptorCount(), desc);
147 SetDescriptorCount(GetDescriptorCount() + 1);
148
149 CalculateSize();
150
151 return true;
152 }
153
154 //==============================================================================
155 void MachMessage::SetDescriptorCount(int n) {
156 storage_->body.msgh_descriptor_count = n;
157
158 if (n > 0) {
159 Head()->msgh_bits |= MACH_MSGH_BITS_COMPLEX;
160 } else {
161 Head()->msgh_bits &= ~MACH_MSGH_BITS_COMPLEX;
162 }
163 }
164
165 //==============================================================================
166 MachMsgPortDescriptor *MachMessage::GetDescriptor(int n) const {
167 if (n < GetDescriptorCount()) {
168 MachMsgPortDescriptor *desc =
169 reinterpret_cast<MachMsgPortDescriptor*>(storage_->padding);
170 return desc + n;
171 }
172
173 return nil;
174 }
175
176 //==============================================================================
177 mach_port_t MachMessage::GetTranslatedPort(int n) const {
178 if (n < GetDescriptorCount()) {
179 return GetDescriptor(n)->GetMachPort();
180 }
181 return MACH_PORT_NULL;
182 }
183
184 #pragma mark -
185
186 //==============================================================================
187 // create a new mach port for receiving messages and register a name for it
188 ReceivePort::ReceivePort(const char *receive_port_name) {
189 mach_port_t current_task = mach_task_self();
190
191 init_result_ = mach_port_allocate(current_task,
192 MACH_PORT_RIGHT_RECEIVE,
193 &port_);
194
195 if (init_result_ != KERN_SUCCESS)
196 return;
197
198 init_result_ = mach_port_insert_right(current_task,
199 port_,
200 port_,
201 MACH_MSG_TYPE_MAKE_SEND);
202
203 if (init_result_ != KERN_SUCCESS)
204 return;
205
206 // Without |NSMachPortDeallocateNone|, the NSMachPort seems to deallocate
207 // receive rights on port when it is eventually released. It is not necessary
208 // to deallocate any rights here as |port_| is fully deallocated in the
209 // ReceivePort destructor.
210 NSPort *ns_port = [NSMachPort portWithMachPort:port_
211 options:NSMachPortDeallocateNone];
212 NSString *port_name = [NSString stringWithUTF8String:receive_port_name];
213 [[NSMachBootstrapServer sharedInstance] registerPort:ns_port name:port_name];
214 }
215
216 //==============================================================================
217 // create a new mach port for receiving messages
218 ReceivePort::ReceivePort() {
219 mach_port_t current_task = mach_task_self();
220
221 init_result_ = mach_port_allocate(current_task,
222 MACH_PORT_RIGHT_RECEIVE,
223 &port_);
224
225 if (init_result_ != KERN_SUCCESS)
226 return;
227
228 init_result_ = mach_port_insert_right(current_task,
229 port_,
230 port_,
231 MACH_MSG_TYPE_MAKE_SEND);
232 }
233
234 //==============================================================================
235 // Given an already existing mach port, use it. We take ownership of the
236 // port and deallocate it in our destructor.
237 ReceivePort::ReceivePort(mach_port_t receive_port)
238 : port_(receive_port),
239 init_result_(KERN_SUCCESS) {
240 }
241
242 //==============================================================================
243 ReceivePort::~ReceivePort() {
244 if (init_result_ == KERN_SUCCESS)
245 mach_port_deallocate(mach_task_self(), port_);
246 }
247
248 //==============================================================================
249 kern_return_t ReceivePort::WaitForMessage(MachReceiveMessage *out_message,
250 mach_msg_timeout_t timeout) {
251 if (!out_message) {
252 return KERN_INVALID_ARGUMENT;
253 }
254
255 // return any error condition encountered in constructor
256 if (init_result_ != KERN_SUCCESS)
257 return init_result_;
258
259 out_message->Head()->msgh_bits = 0;
260 out_message->Head()->msgh_local_port = port_;
261 out_message->Head()->msgh_remote_port = MACH_PORT_NULL;
262 out_message->Head()->msgh_reserved = 0;
263 out_message->Head()->msgh_id = 0;
264
265 mach_msg_option_t rcv_options = MACH_RCV_MSG;
266 if (timeout != MACH_MSG_TIMEOUT_NONE)
267 rcv_options |= MACH_RCV_TIMEOUT;
268
269 kern_return_t result = mach_msg(out_message->Head(),
270 rcv_options,
271 0,
272 out_message->MaxSize(),
273 port_,
274 timeout, // timeout in ms
275 MACH_PORT_NULL);
276
277 return result;
278 }
279
280 #pragma mark -
281
282 //==============================================================================
283 // get a port with send rights corresponding to a named registered service
284 MachPortSender::MachPortSender(const char *receive_port_name) {
285 mach_port_t bootstrap_port = 0;
286 init_result_ = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
287
288 if (init_result_ != KERN_SUCCESS)
289 return;
290
291 init_result_ = bootstrap_look_up(bootstrap_port,
292 const_cast<char*>(receive_port_name),
293 &send_port_);
294 }
295
296 //==============================================================================
297 MachPortSender::MachPortSender(mach_port_t send_port)
298 : send_port_(send_port),
299 init_result_(KERN_SUCCESS) {
300 }
301
302 //==============================================================================
303 kern_return_t MachPortSender::SendMessage(const MachSendMessage& message,
304 mach_msg_timeout_t timeout) {
305 if (message.Head()->msgh_size == 0) {
306 NOTREACHED();
307 return KERN_INVALID_VALUE; // just for safety -- never should occur
308 };
309
310 if (init_result_ != KERN_SUCCESS)
311 return init_result_;
312
313 message.Head()->msgh_remote_port = send_port_;
314
315 kern_return_t result = mach_msg(message.Head(),
316 MACH_SEND_MSG | MACH_SEND_TIMEOUT,
317 message.Head()->msgh_size,
318 0,
319 MACH_PORT_NULL,
320 timeout, // timeout in ms
321 MACH_PORT_NULL);
322
323 return result;
324 }
325
326 //==============================================================================
327
328 namespace mac {
329
330 kern_return_t GetNumberOfMachPorts(mach_port_t task_port, int* num_ports) {
331 mach_port_name_array_t names;
332 mach_msg_type_number_t names_count;
333 mach_port_type_array_t types;
334 mach_msg_type_number_t types_count;
335
336 // A friendlier interface would allow NULL buffers to only get the counts.
337 kern_return_t kr = mach_port_names(task_port, &names, &names_count,
338 &types, &types_count);
339 if (kr != KERN_SUCCESS)
340 return kr;
341
342 // The documentation states this is an invariant.
343 DCHECK_EQ(names_count, types_count);
344 *num_ports = names_count;
345
346 kr = vm_deallocate(mach_task_self(),
347 reinterpret_cast<vm_address_t>(names),
348 names_count * sizeof(mach_port_name_array_t));
349 kr = vm_deallocate(mach_task_self(),
350 reinterpret_cast<vm_address_t>(types),
351 types_count * sizeof(mach_port_type_array_t));
352
353 return kr;
354 }
355
356 } // namespace mac
357
358 } // namespace base
OLDNEW
« no previous file with comments | « base/mach_ipc_mac.h ('k') | chrome/browser/automation/testing_automation_provider.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698