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

Side by Side Diff: content/browser/mach_broker_mac.mm

Issue 1137453002: content: Pass IOSurface references using Mach IPC. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: dcastagna's review Created 5 years, 7 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/mach_broker_mac.h" 5 #include "content/browser/mach_broker_mac.h"
6 6
7 #include <bsm/libbsm.h> 7 #include <bsm/libbsm.h>
8 #include <servers/bootstrap.h> 8 #include <servers/bootstrap.h>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/lazy_instance.h"
13 #include "base/logging.h" 14 #include "base/logging.h"
14 #include "base/mac/foundation_util.h" 15 #include "base/mac/foundation_util.h"
15 #include "base/mac/mach_logging.h" 16 #include "base/mac/mach_logging.h"
16 #include "base/mac/scoped_mach_port.h" 17 #include "base/mac/scoped_mach_port.h"
17 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
19 #include "base/strings/sys_string_conversions.h" 20 #include "base/strings/sys_string_conversions.h"
20 #include "base/threading/platform_thread.h" 21 #include "base/threading/platform_thread.h"
21 #include "content/browser/renderer_host/render_process_host_impl.h" 22 #include "content/browser/renderer_host/render_process_host_impl.h"
22 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/child_process_data.h" 24 #include "content/public/browser/child_process_data.h"
24 #include "content/public/browser/notification_service.h" 25 #include "content/public/browser/notification_service.h"
25 #include "content/public/browser/notification_types.h" 26 #include "content/public/browser/notification_types.h"
26 #include "content/public/common/content_switches.h" 27 #include "content/public/common/content_switches.h"
27 28
28 namespace content { 29 namespace content {
29
30 namespace { 30 namespace {
31 31
32 // Mach message structure used in the child as a sending message. 32 // Message IDs.
33 struct MachBroker_ChildSendMsg { 33 // Note: we currently use __LINE__ to give unique IDs to messages.
34 mach_msg_header_t header; 34 // They're unique since all messages are defined in this file.
35 #define MACH_MESSAGE_ID() __LINE__
36
37 #define MACH_MESSAGE_STRUCT_HEADER() \
38 mach_msg_header_t header; \
35 mach_msg_body_t body; 39 mach_msg_body_t body;
40
41 #define MACH_HOST_MESSAGE_STRUCT_HEADER() \
42 enum { ID = MACH_MESSAGE_ID() }; \
43 mach_msg_header_t header; \
44 mach_msg_body_t body;
45
46 struct MachBroker_ChildMsg {
47 MACH_HOST_MESSAGE_STRUCT_HEADER()
48
36 mach_msg_port_descriptor_t child_task_port; 49 mach_msg_port_descriptor_t child_task_port;
37 }; 50 };
38 51
39 // Complement to the ChildSendMsg, this is used in the parent for receiving 52 // Complement to the ChildMsg, this is used in the parent for receiving
40 // a message. Contains a message trailer with audit information. 53 // a message. Contains a message trailer with audit information.
41 struct MachBroker_ParentRecvMsg : public MachBroker_ChildSendMsg { 54 struct MachBroker_ChildRecvMsg : public MachBroker_ChildMsg {
42 mach_msg_audit_trailer_t trailer; 55 mach_msg_audit_trailer_t trailer;
43 }; 56 };
44 57
58 // Mach message structure used in the child as a sending message.
59 struct MachBroker_RegisterIOSurfaceMsg {
60 MACH_HOST_MESSAGE_STRUCT_HEADER()
61
62 mach_msg_port_descriptor_t io_surface_port;
63 int io_surface_id;
64 int client_id;
65 };
66
67 // Complement to the RegisterIOSurfaceMsg, this is used in the parent for
68 // receiving a message. Contains a message trailer with audit information.
69 struct MachBroker_RegisterIOSurfaceRecvMsg
70 : public MachBroker_RegisterIOSurfaceMsg {
71 mach_msg_audit_trailer_t trailer;
72 };
73
74 // Mach message structure used in the parent as a sending message.
75 struct MachBroker_RegisterIOSurfaceReplyMsg {
76 MACH_HOST_MESSAGE_STRUCT_HEADER()
77
78 boolean_t result;
79 };
80
81 // Complement to the RegisterIOSurfaceReplyMsg, this is used in the child
82 // for receiving a message. Contains a message trailer.
83 struct MachBroker_RegisterIOSurfaceReplyRecvMsg
84 : public MachBroker_RegisterIOSurfaceReplyMsg {
85 mach_msg_trailer_t trailer;
86 };
87
88 // Mach message structure used in the child as a sending message.
89 struct MachBroker_UnregisterIOSurfaceMsg {
90 MACH_HOST_MESSAGE_STRUCT_HEADER()
91
92 int io_surface_id;
93 int client_id;
94 };
95
96 // Complement to the UnregisterIOSurfaceMsg, this is used in the parent for
97 // receiving a message. Contains a message trailer with audit information.
98 struct MachBroker_UnregisterIOSurfaceRecvMsg
99 : public MachBroker_UnregisterIOSurfaceMsg {
100 mach_msg_audit_trailer_t trailer;
101 };
102
103 // Mach message structure used in the child as a sending message.
104 struct MachBroker_AcquireIOSurfaceMsg {
105 MACH_HOST_MESSAGE_STRUCT_HEADER()
106
107 int io_surface_id;
108 };
109
110 // Complement to the AcquireIOSurfaceMsg, this is used in the parent for
111 // receiving a message. Contains a message trailer with audit information.
112 struct MachBroker_AcquireIOSurfaceRecvMsg
113 : public MachBroker_AcquireIOSurfaceMsg {
114 mach_msg_audit_trailer_t trailer;
115 };
116
117 // Mach message structure used in the parent as a sending message.
118 struct MachBroker_AcquireIOSurfaceReplyMsg {
119 MACH_MESSAGE_STRUCT_HEADER()
120
121 mach_msg_port_descriptor_t io_surface_port;
122 };
123
124 // Complement to the AcquireIOSurfaceReplyMsg, this is used in the child for
125 // receiving a message. Contains a message trailer.
126 struct MachBroker_AcquireIOSurfaceReplyRecvMsg
127 : public MachBroker_AcquireIOSurfaceReplyMsg {
128 mach_msg_trailer_t trailer;
129 };
130
131 // Returns the Mach port name to use when sending or receiving messages.
132 // Does the Right Thing in the browser and in child processes.
133 std::string GetMachPortName() {
134 const base::CommandLine* command_line =
135 base::CommandLine::ForCurrentProcess();
136 const bool is_child = command_line->HasSwitch(switches::kProcessType);
137
138 // In non-browser (child) processes, use the parent's pid.
139 const pid_t pid = is_child ? getppid() : getpid();
140 return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid);
141 }
142
143 struct ChildSendPortLazyInstanceTraits
144 : public base::internal::LeakyLazyInstanceTraits<
145 base::mac::ScopedMachSendRight> {
146 static base::mac::ScopedMachSendRight* New(void* instance) {
147 mach_port_t send_port = MACH_PORT_NULL;
148 // Look up the named MachBroker port that's been registered with the
149 // bootstrap server.
150 kern_return_t kr = bootstrap_look_up(
151 bootstrap_port, const_cast<char*>(GetMachPortName().c_str()),
152 &send_port);
153 if (kr != KERN_SUCCESS)
154 BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up";
155
156 // Use placement new to initialize our instance in our preallocated space.
157 return new (instance) base::mac::ScopedMachSendRight(send_port);
158 }
159 };
160
161 base::LazyInstance<base::mac::ScopedMachSendRight,
162 ChildSendPortLazyInstanceTraits> g_child_send_port =
163 LAZY_INSTANCE_INITIALIZER;
164
165 struct ChildReceivePortLazyInstanceTraits
166 : public base::internal::LeakyLazyInstanceTraits<
167 base::mac::ScopedMachSendRight> {
168 static base::mac::ScopedMachSendRight* New(void* instance) {
169 mach_port_t receive_port = MACH_PORT_NULL;
170 kern_return_t kr = mach_port_allocate(
171 mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &receive_port);
172 if (kr != KERN_SUCCESS)
173 MACH_LOG(ERROR, kr) << "mach_port_allocate";
174
175 // Use placement new to initialize our instance in our preallocated space.
176 return new (instance) base::mac::ScopedMachSendRight(receive_port);
177 }
178 };
179
180 base::LazyInstance<base::mac::ScopedMachSendRight,
181 ChildReceivePortLazyInstanceTraits> g_child_receive_port =
182 LAZY_INSTANCE_INITIALIZER;
183
184 base::LazyInstance<base::Lock> g_child_lock = LAZY_INSTANCE_INITIALIZER;
185
45 } // namespace 186 } // namespace
46 187
47 class MachListenerThreadDelegate : public base::PlatformThread::Delegate { 188 class MachListenerThreadDelegate : public base::PlatformThread::Delegate {
48 public: 189 public:
49 explicit MachListenerThreadDelegate(MachBroker* broker) 190 explicit MachListenerThreadDelegate(MachBroker* broker)
50 : broker_(broker), 191 : broker_(broker),
51 server_port_(MACH_PORT_NULL) { 192 server_port_(MACH_PORT_NULL) {
52 DCHECK(broker_); 193 DCHECK(broker_);
53 } 194 }
54 195
(...skipping 17 matching lines...) Expand all
72 MACH_LOG(ERROR, kr) << "mach_port_insert_right"; 213 MACH_LOG(ERROR, kr) << "mach_port_insert_right";
73 return false; 214 return false;
74 } 215 }
75 // Deallocate the right after registering with the bootstrap server. 216 // Deallocate the right after registering with the bootstrap server.
76 base::mac::ScopedMachSendRight send_right(port); 217 base::mac::ScopedMachSendRight send_right(port);
77 218
78 // Register the port with the bootstrap server. Because bootstrap_register 219 // Register the port with the bootstrap server. Because bootstrap_register
79 // is deprecated, this has to be wraped in an ObjC interface. 220 // is deprecated, this has to be wraped in an ObjC interface.
80 NSPort* ns_port = [NSMachPort portWithMachPort:port 221 NSPort* ns_port = [NSMachPort portWithMachPort:port
81 options:NSMachPortDeallocateNone]; 222 options:NSMachPortDeallocateNone];
82 NSString* name = base::SysUTF8ToNSString(broker_->GetMachPortName()); 223 NSString* name = base::SysUTF8ToNSString(GetMachPortName());
83 return [[NSMachBootstrapServer sharedInstance] registerPort:ns_port 224 return [[NSMachBootstrapServer sharedInstance] registerPort:ns_port
84 name:name]; 225 name:name];
85 } 226 }
86 227
87 // Implement |PlatformThread::Delegate|. 228 // Implement |PlatformThread::Delegate|.
88 void ThreadMain() override { 229 void ThreadMain() override {
89 MachBroker_ParentRecvMsg msg; 230 union {
231 mach_msg_header_t header;
232 MachBroker_ChildRecvMsg child;
233 MachBroker_RegisterIOSurfaceRecvMsg register_io_surface;
234 MachBroker_UnregisterIOSurfaceRecvMsg unregister_io_surface;
235 MachBroker_AcquireIOSurfaceRecvMsg acquire_io_surface;
236 } msg;
90 bzero(&msg, sizeof(msg)); 237 bzero(&msg, sizeof(msg));
91 msg.header.msgh_size = sizeof(msg); 238 msg.header.msgh_size = sizeof(msg);
92 msg.header.msgh_local_port = server_port_.get(); 239 msg.header.msgh_local_port = server_port_.get();
93 240
94 const mach_msg_option_t options = MACH_RCV_MSG | 241 const mach_msg_option_t options = MACH_RCV_MSG |
95 MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) | 242 MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) |
96 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT); 243 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT);
97 244
98 kern_return_t kr; 245 kern_return_t kr;
99 while ((kr = mach_msg(&msg.header, 246 while ((kr = mach_msg(&msg.header,
100 options, 247 options,
101 0, 248 0,
102 sizeof(msg), 249 sizeof(msg),
103 server_port_, 250 server_port_,
104 MACH_MSG_TIMEOUT_NONE, 251 MACH_MSG_TIMEOUT_NONE,
105 MACH_PORT_NULL)) == KERN_SUCCESS) { 252 MACH_PORT_NULL)) == KERN_SUCCESS) {
106 // Use the kernel audit information to make sure this message is from 253 // Use the kernel audit information to make sure this message is from
107 // a task that this process spawned. The kernel audit token contains the 254 // a task that this process spawned. The kernel audit token contains
108 // unspoofable pid of the task that sent the message. 255 // the unspoofable pid of the task that sent the message.
109 // 256 mach_msg_audit_trailer_t* trailer =
257 reinterpret_cast<mach_msg_audit_trailer_t*>(
258 reinterpret_cast<vm_address_t>(&msg.header) +
259 round_msg(msg.header.msgh_size));
110 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid(). 260 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid().
111 pid_t child_pid; 261 pid_t child_pid;
112 audit_token_to_au32(msg.trailer.msgh_audit, 262 audit_token_to_au32(trailer->msgh_audit, NULL, NULL, NULL, NULL, NULL,
113 NULL, NULL, NULL, NULL, NULL, &child_pid, NULL, NULL); 263 &child_pid, NULL, NULL);
114 264
115 mach_port_t child_task_port = msg.child_task_port.name; 265 // Take the lock.
266 base::AutoLock lock(broker_->GetLock());
116 267
117 // Take the lock and update the broker information. 268 switch (msg.header.msgh_id) {
118 base::AutoLock lock(broker_->GetLock()); 269 case MachBroker_ChildMsg::ID: {
119 broker_->FinalizePid(child_pid, child_task_port); 270 mach_port_t child_task_port = msg.child.child_task_port.name;
271
272 // Update the broker information.
273 broker_->FinalizePid(child_pid, child_task_port);
274 } break;
275 case MachBroker_RegisterIOSurfaceMsg::ID: {
276 mach_port_t io_surface_port =
277 msg.register_io_surface.io_surface_port.name;
278 int io_surface_id = msg.register_io_surface.io_surface_id;
279 int client_id = msg.register_io_surface.client_id;
280
281 bool result = broker_->RegisterIOSurface(child_pid, io_surface_id,
282 client_id, io_surface_port);
283
284 MachBroker_RegisterIOSurfaceReplyMsg reply;
285 bzero(&reply, sizeof(reply));
286 reply.header.msgh_bits = MACH_MSGH_BITS_REMOTE(msg.header.msgh_bits);
287 reply.header.msgh_remote_port = msg.header.msgh_remote_port;
288 reply.header.msgh_size = sizeof(reply);
289 reply.result = result;
290 kern_return_t kr = mach_msg(
291 &reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(reply),
292 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL);
293 if (kr != KERN_SUCCESS) {
294 MACH_LOG(ERROR, kr) << "mach_msg";
295 }
296
297 } break;
298 case MachBroker_UnregisterIOSurfaceMsg::ID: {
299 int io_surface_id = msg.unregister_io_surface.io_surface_id;
300 int client_id = msg.unregister_io_surface.client_id;
301
302 broker_->UnregisterIOSurface(child_pid, io_surface_id, client_id);
303 } break;
304 case MachBroker_AcquireIOSurfaceMsg::ID: {
305 int io_surface_id = msg.acquire_io_surface.io_surface_id;
306
307 mach_port_t io_surface_port =
308 broker_->AcquireIOSurface(child_pid, io_surface_id);
309
310 MachBroker_AcquireIOSurfaceReplyMsg reply;
311 bzero(&reply, sizeof(reply));
312 reply.header.msgh_bits = MACH_MSGH_BITS_REMOTE(msg.header.msgh_bits) |
313 MACH_MSGH_BITS_COMPLEX;
314 reply.header.msgh_remote_port = msg.header.msgh_remote_port;
315 reply.header.msgh_size = sizeof(reply);
316 reply.body.msgh_descriptor_count = 1;
317 reply.io_surface_port.name = io_surface_port;
318 reply.io_surface_port.disposition = MACH_MSG_TYPE_COPY_SEND;
319 reply.io_surface_port.type = MACH_MSG_PORT_DESCRIPTOR;
320 kern_return_t kr = mach_msg(
321 &reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(reply),
322 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL);
323 if (kr != KERN_SUCCESS) {
324 MACH_LOG(ERROR, kr) << "mach_msg";
325 }
326 } break;
327 }
120 } 328 }
121 329
122 MACH_LOG(ERROR, kr) << "mach_msg"; 330 MACH_LOG(ERROR, kr) << "mach_msg";
123 } 331 }
124 332
125 private: 333 private:
126 // The MachBroker to use when new child task rights are received. Can be 334 // The MachBroker to use when new child task rights are received. Can be
127 // NULL. 335 // NULL.
128 MachBroker* broker_; // weak 336 MachBroker* broker_; // weak
129 337
130 base::mac::ScopedMachReceiveRight server_port_; 338 base::mac::ScopedMachReceiveRight server_port_;
131 339
132 DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate); 340 DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate);
133 }; 341 };
134 342
343 MachBroker::MachPortSet::MachPortSet()
344 : is_gpu_process(false), task_port(MACH_PORT_NULL) {
345 }
346
347 MachBroker::MachPortSet::MachPortSet(bool is_gpu_process)
348 : is_gpu_process(is_gpu_process), task_port(MACH_PORT_NULL) {
349 }
350
351 MachBroker::MachPortSet::~MachPortSet() {
352 }
353
135 bool MachBroker::ChildSendTaskPortToParent() { 354 bool MachBroker::ChildSendTaskPortToParent() {
136 // Look up the named MachBroker port that's been registered with the 355 base::AutoLock lock(g_child_lock.Get());
137 // bootstrap server. 356
138 mach_port_t parent_port; 357 mach_port_t child_send_port = g_child_send_port.Get();
139 kern_return_t kr = bootstrap_look_up(bootstrap_port, 358 if (child_send_port == MACH_PORT_NULL)
140 const_cast<char*>(GetMachPortName().c_str()), &parent_port);
141 if (kr != KERN_SUCCESS) {
142 BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up";
143 return false; 359 return false;
144 } 360
145 base::mac::ScopedMachSendRight scoped_right(parent_port); 361 // Make sure we have valid receive port before we send the check in message.
362 mach_port_t child_receive_port = g_child_receive_port.Get();
363 if (child_receive_port == MACH_PORT_NULL)
364 return false;
146 365
147 // Create the check in message. This will copy a send right on this process' 366 // Create the check in message. This will copy a send right on this process'
148 // (the child's) task port and send it to the parent. 367 // (the child's) task port and send it to the parent.
149 MachBroker_ChildSendMsg msg; 368 MachBroker_ChildMsg msg;
150 bzero(&msg, sizeof(msg)); 369 bzero(&msg, sizeof(msg));
151 msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) | 370 msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) |
152 MACH_MSGH_BITS_COMPLEX; 371 MACH_MSGH_BITS_COMPLEX;
153 msg.header.msgh_remote_port = parent_port; 372 msg.header.msgh_remote_port = child_send_port;
154 msg.header.msgh_size = sizeof(msg); 373 msg.header.msgh_size = sizeof(msg);
374 msg.header.msgh_id = MachBroker_ChildMsg::ID;
155 msg.body.msgh_descriptor_count = 1; 375 msg.body.msgh_descriptor_count = 1;
156 msg.child_task_port.name = mach_task_self(); 376 msg.child_task_port.name = mach_task_self();
157 msg.child_task_port.disposition = MACH_MSG_TYPE_PORT_SEND; 377 msg.child_task_port.disposition = MACH_MSG_TYPE_PORT_SEND;
158 msg.child_task_port.type = MACH_MSG_PORT_DESCRIPTOR; 378 msg.child_task_port.type = MACH_MSG_PORT_DESCRIPTOR;
159 379
160 kr = mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), 380 kern_return_t kr =
161 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); 381 mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), 0,
382 MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL);
162 if (kr != KERN_SUCCESS) { 383 if (kr != KERN_SUCCESS) {
163 MACH_LOG(ERROR, kr) << "mach_msg"; 384 MACH_LOG(ERROR, kr) << "mach_msg";
164 return false; 385 return false;
165 } 386 }
166 387
167 return true; 388 return true;
168 } 389 }
169 390
391 bool MachBroker::ChildRegisterIOSurfaceWithParent(int io_surface_id,
392 int client_id,
393 mach_port_t io_surface_port) {
394 base::AutoLock lock(g_child_lock.Get());
395
396 mach_port_t child_receive_port = g_child_receive_port.Get();
397
398 // Deallocate the right after sending a copy to the parent.
399 base::mac::ScopedMachSendRight io_surface_send_right(io_surface_port);
400
401 union {
402 MachBroker_RegisterIOSurfaceMsg request;
403 MachBroker_RegisterIOSurfaceReplyRecvMsg reply;
404 } msg;
405 bzero(&msg, sizeof(msg));
406 msg.request.header.msgh_bits =
407 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE) |
408 MACH_MSGH_BITS_COMPLEX;
409 msg.request.header.msgh_remote_port = g_child_send_port.Get();
410 msg.request.header.msgh_local_port = child_receive_port;
411 msg.request.header.msgh_size = sizeof(msg.request);
412 msg.request.header.msgh_id = MachBroker_RegisterIOSurfaceMsg::ID;
413 msg.request.body.msgh_descriptor_count = 1;
414 msg.request.io_surface_port.name = io_surface_port;
415 msg.request.io_surface_port.disposition = MACH_MSG_TYPE_COPY_SEND;
416 msg.request.io_surface_port.type = MACH_MSG_PORT_DESCRIPTOR;
417 msg.request.io_surface_id = io_surface_id;
418 msg.request.client_id = client_id;
419
420 kern_return_t kr =
421 mach_msg(&msg.request.header, MACH_SEND_MSG | MACH_RCV_MSG,
422 sizeof(msg.request), sizeof(msg.reply), child_receive_port,
423 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
424 if (kr != KERN_SUCCESS) {
425 MACH_LOG(ERROR, kr) << "mach_msg";
426 return false;
427 }
428
429 return msg.reply.result;
430 }
431
432 bool MachBroker::ChildUnregisterIOSurfaceWithParent(int io_surface_id,
433 int client_id) {
434 base::AutoLock lock(g_child_lock.Get());
435
436 MachBroker_UnregisterIOSurfaceMsg msg;
437 bzero(&msg, sizeof(msg));
438 msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
439 msg.header.msgh_remote_port = g_child_send_port.Get();
440 msg.header.msgh_local_port = MACH_PORT_NULL;
441 msg.header.msgh_size = sizeof(msg);
442 msg.header.msgh_id = MachBroker_UnregisterIOSurfaceMsg::ID;
443 msg.io_surface_id = io_surface_id;
444 msg.client_id = client_id;
445
446 kern_return_t kr =
447 mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), 0,
448 MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL);
449 if (kr != KERN_SUCCESS) {
450 MACH_LOG(ERROR, kr) << "mach_msg";
451 return false;
452 }
453
454 return true;
455 }
456
457 mach_port_t MachBroker::ChildAcquireIOSurfaceFromParent(int io_surface_id) {
458 base::AutoLock lock(g_child_lock.Get());
459
460 mach_port_t child_receive_port = g_child_receive_port.Get();
461
462 union {
463 MachBroker_AcquireIOSurfaceMsg request;
464 MachBroker_AcquireIOSurfaceReplyRecvMsg reply;
465 } msg;
466 bzero(&msg, sizeof(msg));
467 msg.request.header.msgh_bits =
468 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
469 msg.request.header.msgh_remote_port = g_child_send_port.Get();
470 msg.request.header.msgh_local_port = child_receive_port;
471 msg.request.header.msgh_size = sizeof(msg.request);
472 msg.request.header.msgh_id = MachBroker_AcquireIOSurfaceMsg::ID;
473 msg.request.io_surface_id = io_surface_id;
474
475 kern_return_t kr =
476 mach_msg(&msg.request.header, MACH_SEND_MSG | MACH_RCV_MSG,
477 sizeof(msg.request), sizeof(msg.reply), child_receive_port,
478 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
479 if (kr != KERN_SUCCESS) {
480 MACH_LOG(ERROR, kr) << "mach_msg";
481 return MACH_PORT_NULL;
482 }
483
484 return msg.reply.io_surface_port.name;
485 }
486
170 MachBroker* MachBroker::GetInstance() { 487 MachBroker* MachBroker::GetInstance() {
171 return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get(); 488 return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get();
172 } 489 }
173 490
174 base::Lock& MachBroker::GetLock() { 491 base::Lock& MachBroker::GetLock() {
175 return lock_; 492 return lock_;
176 } 493 }
177 494
178 void MachBroker::EnsureRunning() { 495 void MachBroker::EnsureRunning() {
179 lock_.AssertAcquired(); 496 lock_.AssertAcquired();
180 497
181 if (!listener_thread_started_) { 498 if (!listener_thread_started_) {
182 listener_thread_started_ = true; 499 listener_thread_started_ = true;
183 500
184 BrowserThread::PostTask( 501 BrowserThread::PostTask(
185 BrowserThread::UI, FROM_HERE, 502 BrowserThread::UI, FROM_HERE,
186 base::Bind(&MachBroker::RegisterNotifications, base::Unretained(this))); 503 base::Bind(&MachBroker::RegisterNotifications, base::Unretained(this)));
187 504
188 // Intentional leak. This thread is never joined or reaped. 505 // Intentional leak. This thread is never joined or reaped.
189 MachListenerThreadDelegate* thread = new MachListenerThreadDelegate(this); 506 MachListenerThreadDelegate* thread = new MachListenerThreadDelegate(this);
190 if (thread->Init()) { 507 if (thread->Init()) {
191 base::PlatformThread::CreateNonJoinable(0, thread); 508 base::PlatformThread::CreateNonJoinable(0, thread);
192 } else { 509 } else {
193 LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate"; 510 LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate";
194 } 511 }
195 } 512 }
196 } 513 }
197 514
198 void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid, 515 void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid,
199 int child_process_id) { 516 int child_process_id,
517 bool is_gpu_process) {
200 lock_.AssertAcquired(); 518 lock_.AssertAcquired();
201 519
202 DCHECK_EQ(0u, mach_map_.count(pid)); 520 DCHECK_EQ(0u, mach_map_.count(pid));
203 mach_map_[pid] = MACH_PORT_NULL; 521 mach_map_[pid] = MachPortSet(is_gpu_process);
204 child_process_id_map_[child_process_id] = pid; 522 child_process_id_map_[child_process_id] = pid;
205 } 523 }
206 524
207 mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const { 525 mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const {
208 base::AutoLock lock(lock_); 526 base::AutoLock lock(lock_);
209 MachBroker::MachMap::const_iterator it = mach_map_.find(pid); 527 MachBroker::MachMap::const_iterator it = mach_map_.find(pid);
210 if (it == mach_map_.end()) 528 if (it == mach_map_.end())
211 return MACH_PORT_NULL; 529 return MACH_PORT_NULL;
212 return it->second; 530 return it->second.task_port;
213 } 531 }
214 532
215 void MachBroker::BrowserChildProcessHostDisconnected( 533 void MachBroker::BrowserChildProcessHostDisconnected(
216 const ChildProcessData& data) { 534 const ChildProcessData& data) {
217 InvalidateChildProcessId(data.id); 535 InvalidateChildProcessId(data.id);
218 } 536 }
219 537
220 void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data, 538 void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data,
221 int exit_code) { 539 int exit_code) {
222 InvalidateChildProcessId(data.id); 540 InvalidateChildProcessId(data.id);
(...skipping 24 matching lines...) Expand all
247 mach_port_t task_port) { 565 mach_port_t task_port) {
248 lock_.AssertAcquired(); 566 lock_.AssertAcquired();
249 567
250 MachMap::iterator it = mach_map_.find(pid); 568 MachMap::iterator it = mach_map_.find(pid);
251 if (it == mach_map_.end()) { 569 if (it == mach_map_.end()) {
252 // Do nothing for unknown pids. 570 // Do nothing for unknown pids.
253 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; 571 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
254 return; 572 return;
255 } 573 }
256 574
257 DCHECK(it->second == MACH_PORT_NULL); 575 if (it->second.task_port == MACH_PORT_NULL)
258 if (it->second == MACH_PORT_NULL) 576 it->second.task_port = task_port;
259 it->second = task_port;
260 } 577 }
261 578
262 void MachBroker::InvalidateChildProcessId(int child_process_id) { 579 void MachBroker::InvalidateChildProcessId(int child_process_id) {
263 base::AutoLock lock(lock_); 580 base::AutoLock lock(lock_);
264 MachBroker::ChildProcessIdMap::iterator it = 581 MachBroker::ChildProcessIdMap::iterator it =
265 child_process_id_map_.find(child_process_id); 582 child_process_id_map_.find(child_process_id);
266 if (it == child_process_id_map_.end()) 583 if (it == child_process_id_map_.end())
267 return; 584 return;
268 585
269 MachMap::iterator mach_it = mach_map_.find(it->second); 586 MachMap::iterator mach_it = mach_map_.find(it->second);
270 if (mach_it != mach_map_.end()) { 587 if (mach_it != mach_map_.end()) {
271 kern_return_t kr = mach_port_deallocate(mach_task_self(), 588 kern_return_t kr =
272 mach_it->second); 589 mach_port_deallocate(mach_task_self(), mach_it->second.task_port);
273 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; 590 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
591 for (const auto& io_surface_port : mach_it->second.io_surface_ports) {
592 kr = mach_port_deallocate(mach_task_self(), io_surface_port.second);
593 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
594 }
274 mach_map_.erase(mach_it); 595 mach_map_.erase(mach_it);
275 } 596 }
276 child_process_id_map_.erase(it); 597 child_process_id_map_.erase(it);
277 } 598 }
278 599
279 // static 600 bool MachBroker::RegisterIOSurface(base::ProcessHandle pid,
280 std::string MachBroker::GetMachPortName() { 601 int io_surface_id,
281 const base::CommandLine* command_line = 602 int client_id,
282 base::CommandLine::ForCurrentProcess(); 603 mach_port_t io_surface_port) {
283 const bool is_child = command_line->HasSwitch(switches::kProcessType); 604 lock_.AssertAcquired();
284 605
285 // In non-browser (child) processes, use the parent's pid. 606 MachMap::iterator mach_it = mach_map_.find(pid);
286 const pid_t pid = is_child ? getppid() : getpid(); 607 if (mach_it == mach_map_.end()) {
287 return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid); 608 // Do nothing for unknown pids.
609 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
610 return false;
611 }
612
613 if (!mach_it->second.is_gpu_process) {
614 LOG(ERROR) << "Illegal message from non-GPU process!";
615 return false;
616 }
617
618 ChildProcessIdMap::iterator it = child_process_id_map_.find(client_id);
619 if (it == child_process_id_map_.end())
620 return false;
621
622 MachMap::iterator client_it = mach_map_.find(it->second);
623 if (client_it == mach_map_.end()) {
624 LOG(ERROR) << "Unknown client process " << it->second;
625 return false;
626 }
627
628 if (client_it->second.io_surface_ports.count(io_surface_id)) {
629 LOG(ERROR) << "IOSurface " << io_surface_id << " already exists!";
630 return false;
631 }
632
633 client_it->second.io_surface_ports[io_surface_id] = io_surface_port;
634 return true;
635 }
636
637 void MachBroker::UnregisterIOSurface(base::ProcessHandle pid,
638 int io_surface_id,
639 int client_id) {
640 lock_.AssertAcquired();
641
642 MachMap::iterator mach_it = mach_map_.find(pid);
643 if (mach_it == mach_map_.end()) {
644 // Do nothing for unknown pids.
645 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
646 return;
647 }
648
649 if (!mach_it->second.is_gpu_process) {
650 LOG(ERROR) << "Illegal message from non-GPU process!";
651 return;
652 }
653
654 ChildProcessIdMap::iterator it = child_process_id_map_.find(client_id);
655 if (it == child_process_id_map_.end())
656 return;
657
658 mach_it = mach_map_.find(it->second);
659 if (mach_it != mach_map_.end()) {
660 auto io_surface_mach_it =
661 mach_it->second.io_surface_ports.find(io_surface_id);
662 if (io_surface_mach_it != mach_it->second.io_surface_ports.end()) {
663 kern_return_t kr =
664 mach_port_deallocate(mach_task_self(), io_surface_mach_it->second);
665 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
666 mach_it->second.io_surface_ports.erase(io_surface_mach_it);
667 }
668 }
669 }
670
671 mach_port_t MachBroker::AcquireIOSurface(base::ProcessHandle pid,
672 int io_surface_id) {
673 lock_.AssertAcquired();
674
675 MachMap::iterator it = mach_map_.find(pid);
676 if (it == mach_map_.end()) {
677 // Do nothing for unknown pids.
678 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
679 return MACH_PORT_NULL;
680 }
681
682 auto io_surface_mach_it = it->second.io_surface_ports.find(io_surface_id);
683 if (io_surface_mach_it == it->second.io_surface_ports.end()) {
684 LOG(ERROR) << "Invalid Id for IOSurface " << io_surface_id;
685 return MACH_PORT_NULL;
686 }
687
688 return io_surface_mach_it->second;
288 } 689 }
289 690
290 void MachBroker::RegisterNotifications() { 691 void MachBroker::RegisterNotifications() {
291 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, 692 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED,
292 NotificationService::AllBrowserContextsAndSources()); 693 NotificationService::AllBrowserContextsAndSources());
293 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, 694 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
294 NotificationService::AllBrowserContextsAndSources()); 695 NotificationService::AllBrowserContextsAndSources());
295 696
296 // No corresponding StopObservingBrowserChildProcesses, 697 // No corresponding StopObservingBrowserChildProcesses,
297 // we leak this singleton. 698 // we leak this singleton.
298 BrowserChildProcessObserver::Add(this); 699 BrowserChildProcessObserver::Add(this);
299 } 700 }
300 701
301 } // namespace content 702 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698