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

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: remove parameter from MachBroker::InitChildProcess 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/logging.h" 13 #include "base/logging.h"
14 #include "base/mac/foundation_util.h" 14 #include "base/mac/foundation_util.h"
15 #include "base/mac/mach_logging.h" 15 #include "base/mac/mach_logging.h"
16 #include "base/mac/scoped_mach_port.h" 16 #include "base/mac/scoped_mach_port.h"
17 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
19 #include "base/strings/sys_string_conversions.h" 19 #include "base/strings/sys_string_conversions.h"
20 #include "base/threading/platform_thread.h" 20 #include "base/threading/platform_thread.h"
21 #include "content/browser/renderer_host/render_process_host_impl.h" 21 #include "content/browser/renderer_host/render_process_host_impl.h"
22 #include "content/common/mac/io_surface_manager.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 // Message IDs.
33 // Note: we currently use __LINE__ to give unique IDs to messages.
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; \
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
49 mach_msg_port_descriptor_t child_task_port;
50 };
51
52 // Complement to the ChildMsg, this is used in the parent for receiving
53 // a message. Contains a message trailer with audit information.
54 struct MachBroker_ChildRecvMsg : public MachBroker_ChildMsg {
55 mach_msg_audit_trailer_t trailer;
56 };
57
32 // Mach message structure used in the child as a sending message. 58 // Mach message structure used in the child as a sending message.
33 struct MachBroker_ChildSendMsg { 59 struct MachBroker_RegisterIOSurfaceMsg {
34 mach_msg_header_t header; 60 MACH_HOST_MESSAGE_STRUCT_HEADER()
35 mach_msg_body_t body; 61
36 mach_msg_port_descriptor_t child_task_port; 62 mach_msg_port_descriptor_t io_surface_port;
37 }; 63 int io_surface_id;
38 64 int client_id;
39 // Complement to the ChildSendMsg, this is used in the parent for receiving 65 };
40 // a message. Contains a message trailer with audit information. 66
41 struct MachBroker_ParentRecvMsg : public MachBroker_ChildSendMsg { 67 // Complement to the RegisterIOSurfaceMsg, this is used in the parent for
42 mach_msg_audit_trailer_t trailer; 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 class IOSurfaceManagerImpl : public IOSurfaceManager {
132 public:
133 IOSurfaceManagerImpl(mach_port_t send_port, mach_port_t receive_port)
134 : send_port_(send_port), receive_port_(receive_port) {}
135
136 // Overridden from IOSurfaceManager:
137 bool RegisterIOSurface(int io_surface_id,
138 int client_id,
139 IOSurfaceRef io_surface) override {
140 base::AutoLock lock(lock_);
141
142 // Deallocate the right after sending a copy to the parent.
143 base::mac::ScopedMachSendRight scoped_io_surface_right(
144 IOSurfaceCreateMachPort(io_surface));
145
146 union {
147 MachBroker_RegisterIOSurfaceMsg request;
148 MachBroker_RegisterIOSurfaceReplyRecvMsg reply;
149 } msg;
150 bzero(&msg, sizeof(msg));
151 msg.request.header.msgh_bits =
152 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE) |
153 MACH_MSGH_BITS_COMPLEX;
154 msg.request.header.msgh_remote_port = send_port_;
155 msg.request.header.msgh_local_port = receive_port_;
156 msg.request.header.msgh_size = sizeof(msg.request);
157 msg.request.header.msgh_id = MachBroker_RegisterIOSurfaceMsg::ID;
158 msg.request.body.msgh_descriptor_count = 1;
159 msg.request.io_surface_port.name = scoped_io_surface_right;
160 msg.request.io_surface_port.disposition = MACH_MSG_TYPE_COPY_SEND;
161 msg.request.io_surface_port.type = MACH_MSG_PORT_DESCRIPTOR;
162 msg.request.io_surface_id = io_surface_id;
163 msg.request.client_id = client_id;
164
165 kern_return_t kr =
166 mach_msg(&msg.request.header, MACH_SEND_MSG | MACH_RCV_MSG,
167 sizeof(msg.request), sizeof(msg.reply), receive_port_,
168 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
169 if (kr != KERN_SUCCESS) {
170 MACH_LOG(ERROR, kr) << "mach_msg";
171 return false;
172 }
173
174 return msg.reply.result;
175 }
176 void UnregisterIOSurface(int io_surface_id, int client_id) override {
177 base::AutoLock lock(lock_);
178
179 MachBroker_UnregisterIOSurfaceMsg msg;
180 bzero(&msg, sizeof(msg));
181 msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
182 msg.header.msgh_remote_port = send_port_;
183 msg.header.msgh_local_port = MACH_PORT_NULL;
184 msg.header.msgh_size = sizeof(msg);
185 msg.header.msgh_id = MachBroker_UnregisterIOSurfaceMsg::ID;
186 msg.io_surface_id = io_surface_id;
187 msg.client_id = client_id;
188
189 kern_return_t kr =
190 mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), 0,
191 MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL);
192 if (kr != KERN_SUCCESS) {
193 MACH_LOG(ERROR, kr) << "mach_msg";
194 }
195 }
196 IOSurfaceRef AcquireIOSurface(int io_surface_id) override {
197 base::AutoLock lock(lock_);
198
199 union {
200 MachBroker_AcquireIOSurfaceMsg request;
201 MachBroker_AcquireIOSurfaceReplyRecvMsg reply;
202 } msg;
203 bzero(&msg, sizeof(msg));
204 msg.request.header.msgh_bits =
205 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
206 msg.request.header.msgh_remote_port = send_port_;
207 msg.request.header.msgh_local_port = receive_port_;
208 msg.request.header.msgh_size = sizeof(msg.request);
209 msg.request.header.msgh_id = MachBroker_AcquireIOSurfaceMsg::ID;
210 msg.request.io_surface_id = io_surface_id;
211
212 kern_return_t kr =
213 mach_msg(&msg.request.header, MACH_SEND_MSG | MACH_RCV_MSG,
214 sizeof(msg.request), sizeof(msg.reply), receive_port_,
215 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
216 if (kr != KERN_SUCCESS) {
217 MACH_LOG(ERROR, kr) << "mach_msg";
218 return nullptr;
219 }
220
221 return IOSurfaceLookupFromMachPort(msg.reply.io_surface_port.name);
222 }
223
224 private:
225 base::mac::ScopedMachSendRight send_port_;
226 base::mac::ScopedMachSendRight receive_port_;
227 base::Lock lock_;
228
229 DISALLOW_COPY_AND_ASSIGN(IOSurfaceManagerImpl);
43 }; 230 };
44 231
45 } // namespace 232 } // namespace
46 233
47 class MachListenerThreadDelegate : public base::PlatformThread::Delegate { 234 class MachListenerThreadDelegate : public base::PlatformThread::Delegate {
48 public: 235 public:
49 explicit MachListenerThreadDelegate(MachBroker* broker) 236 explicit MachListenerThreadDelegate(MachBroker* broker)
50 : broker_(broker), 237 : broker_(broker),
51 server_port_(MACH_PORT_NULL) { 238 server_port_(MACH_PORT_NULL) {
52 DCHECK(broker_); 239 DCHECK(broker_);
(...skipping 26 matching lines...) Expand all
79 // is deprecated, this has to be wraped in an ObjC interface. 266 // is deprecated, this has to be wraped in an ObjC interface.
80 NSPort* ns_port = [NSMachPort portWithMachPort:port 267 NSPort* ns_port = [NSMachPort portWithMachPort:port
81 options:NSMachPortDeallocateNone]; 268 options:NSMachPortDeallocateNone];
82 NSString* name = base::SysUTF8ToNSString(broker_->GetMachPortName()); 269 NSString* name = base::SysUTF8ToNSString(broker_->GetMachPortName());
83 return [[NSMachBootstrapServer sharedInstance] registerPort:ns_port 270 return [[NSMachBootstrapServer sharedInstance] registerPort:ns_port
84 name:name]; 271 name:name];
85 } 272 }
86 273
87 // Implement |PlatformThread::Delegate|. 274 // Implement |PlatformThread::Delegate|.
88 void ThreadMain() override { 275 void ThreadMain() override {
89 MachBroker_ParentRecvMsg msg; 276 union {
277 mach_msg_header_t header;
278 MachBroker_ChildRecvMsg child;
279 MachBroker_RegisterIOSurfaceRecvMsg register_io_surface;
280 MachBroker_UnregisterIOSurfaceRecvMsg unregister_io_surface;
281 MachBroker_AcquireIOSurfaceRecvMsg acquire_io_surface;
282 } msg;
90 bzero(&msg, sizeof(msg)); 283 bzero(&msg, sizeof(msg));
91 msg.header.msgh_size = sizeof(msg); 284 msg.header.msgh_size = sizeof(msg);
92 msg.header.msgh_local_port = server_port_.get(); 285 msg.header.msgh_local_port = server_port_.get();
93 286
94 const mach_msg_option_t options = MACH_RCV_MSG | 287 const mach_msg_option_t options = MACH_RCV_MSG |
95 MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) | 288 MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) |
96 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT); 289 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT);
97 290
98 kern_return_t kr; 291 kern_return_t kr;
99 while ((kr = mach_msg(&msg.header, 292 while ((kr = mach_msg(&msg.header,
100 options, 293 options,
101 0, 294 0,
102 sizeof(msg), 295 sizeof(msg),
103 server_port_, 296 server_port_,
104 MACH_MSG_TIMEOUT_NONE, 297 MACH_MSG_TIMEOUT_NONE,
105 MACH_PORT_NULL)) == KERN_SUCCESS) { 298 MACH_PORT_NULL)) == KERN_SUCCESS) {
106 // Use the kernel audit information to make sure this message is from 299 // 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 300 // a task that this process spawned. The kernel audit token contains
108 // unspoofable pid of the task that sent the message. 301 // the unspoofable pid of the task that sent the message.
109 // 302 mach_msg_audit_trailer_t* trailer =
303 reinterpret_cast<mach_msg_audit_trailer_t*>(
304 reinterpret_cast<vm_address_t>(&msg.header) +
305 round_msg(msg.header.msgh_size));
110 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid(). 306 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid().
111 pid_t child_pid; 307 pid_t child_pid;
112 audit_token_to_au32(msg.trailer.msgh_audit, 308 audit_token_to_au32(trailer->msgh_audit, NULL, NULL, NULL, NULL, NULL,
113 NULL, NULL, NULL, NULL, NULL, &child_pid, NULL, NULL); 309 &child_pid, NULL, NULL);
114 310
115 mach_port_t child_task_port = msg.child_task_port.name; 311 // Take the lock.
312 base::AutoLock lock(broker_->GetLock());
116 313
117 // Take the lock and update the broker information. 314 switch (msg.header.msgh_id) {
118 base::AutoLock lock(broker_->GetLock()); 315 case MachBroker_ChildMsg::ID: {
119 broker_->FinalizePid(child_pid, child_task_port); 316 mach_port_t child_task_port = msg.child.child_task_port.name;
317
318 // Update the broker information.
319 broker_->FinalizePid(child_pid, child_task_port);
320 } break;
321 case MachBroker_RegisterIOSurfaceMsg::ID: {
322 mach_port_t io_surface_port =
323 msg.register_io_surface.io_surface_port.name;
324 int io_surface_id = msg.register_io_surface.io_surface_id;
325 int client_id = msg.register_io_surface.client_id;
326
327 bool result = broker_->RegisterIOSurface(child_pid, io_surface_id,
328 client_id, io_surface_port);
329
330 MachBroker_RegisterIOSurfaceReplyMsg reply;
331 bzero(&reply, sizeof(reply));
332 reply.header.msgh_bits = MACH_MSGH_BITS_REMOTE(msg.header.msgh_bits);
333 reply.header.msgh_remote_port = msg.header.msgh_remote_port;
334 reply.header.msgh_size = sizeof(reply);
335 reply.result = result;
336 kern_return_t kr = mach_msg(
337 &reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(reply),
338 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL);
339 if (kr != KERN_SUCCESS) {
340 MACH_LOG(ERROR, kr) << "mach_msg";
341 }
342
343 } break;
344 case MachBroker_UnregisterIOSurfaceMsg::ID: {
345 int io_surface_id = msg.unregister_io_surface.io_surface_id;
346 int client_id = msg.unregister_io_surface.client_id;
347
348 broker_->UnregisterIOSurface(child_pid, io_surface_id, client_id);
349 } break;
350 case MachBroker_AcquireIOSurfaceMsg::ID: {
351 int io_surface_id = msg.acquire_io_surface.io_surface_id;
352
353 mach_port_t io_surface_port =
354 broker_->AcquireIOSurface(child_pid, io_surface_id);
355
356 MachBroker_AcquireIOSurfaceReplyMsg reply;
357 bzero(&reply, sizeof(reply));
358 reply.header.msgh_bits = MACH_MSGH_BITS_REMOTE(msg.header.msgh_bits) |
359 MACH_MSGH_BITS_COMPLEX;
360 reply.header.msgh_remote_port = msg.header.msgh_remote_port;
361 reply.header.msgh_size = sizeof(reply);
362 reply.body.msgh_descriptor_count = 1;
363 reply.io_surface_port.name = io_surface_port;
364 reply.io_surface_port.disposition = MACH_MSG_TYPE_COPY_SEND;
365 reply.io_surface_port.type = MACH_MSG_PORT_DESCRIPTOR;
366 kern_return_t kr = mach_msg(
367 &reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(reply),
368 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL);
369 if (kr != KERN_SUCCESS) {
370 MACH_LOG(ERROR, kr) << "mach_msg";
371 }
372 } break;
373 }
120 } 374 }
121 375
122 MACH_LOG(ERROR, kr) << "mach_msg"; 376 MACH_LOG(ERROR, kr) << "mach_msg";
123 } 377 }
124 378
125 private: 379 private:
126 // The MachBroker to use when new child task rights are received. Can be 380 // The MachBroker to use when new child task rights are received. Can be
127 // NULL. 381 // NULL.
128 MachBroker* broker_; // weak 382 MachBroker* broker_; // weak
129 383
130 base::mac::ScopedMachReceiveRight server_port_; 384 base::mac::ScopedMachReceiveRight server_port_;
131 385
132 DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate); 386 DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate);
133 }; 387 };
134 388
135 bool MachBroker::ChildSendTaskPortToParent() { 389 MachBroker::MachPortSet::MachPortSet()
390 : is_gpu_process(false), task_port(MACH_PORT_NULL) {
391 }
392
393 MachBroker::MachPortSet::MachPortSet(bool is_gpu_process)
394 : is_gpu_process(is_gpu_process), task_port(MACH_PORT_NULL) {
395 }
396
397 MachBroker::MachPortSet::~MachPortSet() {
398 }
399
400 // static
401 bool MachBroker::InitChildProcess() {
136 // Look up the named MachBroker port that's been registered with the 402 // Look up the named MachBroker port that's been registered with the
137 // bootstrap server. 403 // bootstrap server.
138 mach_port_t parent_port; 404 mach_port_t parent_port;
139 kern_return_t kr = bootstrap_look_up(bootstrap_port, 405 kern_return_t kr = bootstrap_look_up(bootstrap_port,
140 const_cast<char*>(GetMachPortName().c_str()), &parent_port); 406 const_cast<char*>(GetMachPortName().c_str()), &parent_port);
141 if (kr != KERN_SUCCESS) { 407 if (kr != KERN_SUCCESS) {
142 BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up"; 408 BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up";
143 return false; 409 return false;
144 } 410 }
145 base::mac::ScopedMachSendRight scoped_right(parent_port); 411 base::mac::ScopedMachSendRight scoped_parent_right(parent_port);
412
413 mach_port_t child_port;
414 kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
415 &child_port);
416 if (kr != KERN_SUCCESS) {
417 MACH_LOG(ERROR, kr) << "mach_port_allocate";
418 return false;
419 }
420 base::mac::ScopedMachSendRight scoped_child_right(child_port);
146 421
147 // Create the check in message. This will copy a send right on this process' 422 // 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. 423 // (the child's) task port and send it to the parent.
149 MachBroker_ChildSendMsg msg; 424 MachBroker_ChildMsg msg;
150 bzero(&msg, sizeof(msg)); 425 bzero(&msg, sizeof(msg));
151 msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) | 426 msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) |
152 MACH_MSGH_BITS_COMPLEX; 427 MACH_MSGH_BITS_COMPLEX;
153 msg.header.msgh_remote_port = parent_port; 428 msg.header.msgh_remote_port = parent_port;
154 msg.header.msgh_size = sizeof(msg); 429 msg.header.msgh_size = sizeof(msg);
430 msg.header.msgh_id = MachBroker_ChildMsg::ID;
155 msg.body.msgh_descriptor_count = 1; 431 msg.body.msgh_descriptor_count = 1;
156 msg.child_task_port.name = mach_task_self(); 432 msg.child_task_port.name = mach_task_self();
157 msg.child_task_port.disposition = MACH_MSG_TYPE_PORT_SEND; 433 msg.child_task_port.disposition = MACH_MSG_TYPE_PORT_SEND;
158 msg.child_task_port.type = MACH_MSG_PORT_DESCRIPTOR; 434 msg.child_task_port.type = MACH_MSG_PORT_DESCRIPTOR;
159 435
160 kr = mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), 436 kr = mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg),
161 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); 437 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL);
162 if (kr != KERN_SUCCESS) { 438 if (kr != KERN_SUCCESS) {
163 MACH_LOG(ERROR, kr) << "mach_msg"; 439 MACH_LOG(ERROR, kr) << "mach_msg";
164 return false; 440 return false;
165 } 441 }
166 442
443 IOSurfaceManager::InitInstance(new IOSurfaceManagerImpl(
444 scoped_parent_right.release(), scoped_child_right.release()));
445
167 return true; 446 return true;
168 } 447 }
169 448
170 MachBroker* MachBroker::GetInstance() { 449 MachBroker* MachBroker::GetInstance() {
171 return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get(); 450 return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get();
172 } 451 }
173 452
174 base::Lock& MachBroker::GetLock() { 453 base::Lock& MachBroker::GetLock() {
175 return lock_; 454 return lock_;
176 } 455 }
(...skipping 12 matching lines...) Expand all
189 MachListenerThreadDelegate* thread = new MachListenerThreadDelegate(this); 468 MachListenerThreadDelegate* thread = new MachListenerThreadDelegate(this);
190 if (thread->Init()) { 469 if (thread->Init()) {
191 base::PlatformThread::CreateNonJoinable(0, thread); 470 base::PlatformThread::CreateNonJoinable(0, thread);
192 } else { 471 } else {
193 LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate"; 472 LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate";
194 } 473 }
195 } 474 }
196 } 475 }
197 476
198 void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid, 477 void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid,
199 int child_process_id) { 478 int child_process_id,
479 bool is_gpu_process) {
200 lock_.AssertAcquired(); 480 lock_.AssertAcquired();
201 481
202 DCHECK_EQ(0u, mach_map_.count(pid)); 482 DCHECK_EQ(0u, mach_map_.count(pid));
203 mach_map_[pid] = MACH_PORT_NULL; 483 mach_map_[pid] = MachPortSet(is_gpu_process);
204 child_process_id_map_[child_process_id] = pid; 484 child_process_id_map_[child_process_id] = pid;
205 } 485 }
206 486
207 mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const { 487 mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const {
208 base::AutoLock lock(lock_); 488 base::AutoLock lock(lock_);
209 MachBroker::MachMap::const_iterator it = mach_map_.find(pid); 489 MachBroker::MachMap::const_iterator it = mach_map_.find(pid);
210 if (it == mach_map_.end()) 490 if (it == mach_map_.end())
211 return MACH_PORT_NULL; 491 return MACH_PORT_NULL;
212 return it->second; 492 return it->second.task_port;
213 } 493 }
214 494
215 void MachBroker::BrowserChildProcessHostDisconnected( 495 void MachBroker::BrowserChildProcessHostDisconnected(
216 const ChildProcessData& data) { 496 const ChildProcessData& data) {
217 InvalidateChildProcessId(data.id); 497 InvalidateChildProcessId(data.id);
218 } 498 }
219 499
220 void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data, 500 void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data,
221 int exit_code) { 501 int exit_code) {
222 InvalidateChildProcessId(data.id); 502 InvalidateChildProcessId(data.id);
(...skipping 24 matching lines...) Expand all
247 mach_port_t task_port) { 527 mach_port_t task_port) {
248 lock_.AssertAcquired(); 528 lock_.AssertAcquired();
249 529
250 MachMap::iterator it = mach_map_.find(pid); 530 MachMap::iterator it = mach_map_.find(pid);
251 if (it == mach_map_.end()) { 531 if (it == mach_map_.end()) {
252 // Do nothing for unknown pids. 532 // Do nothing for unknown pids.
253 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; 533 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
254 return; 534 return;
255 } 535 }
256 536
257 DCHECK(it->second == MACH_PORT_NULL); 537 if (it->second.task_port == MACH_PORT_NULL)
258 if (it->second == MACH_PORT_NULL) 538 it->second.task_port = task_port;
259 it->second = task_port;
260 } 539 }
261 540
262 void MachBroker::InvalidateChildProcessId(int child_process_id) { 541 void MachBroker::InvalidateChildProcessId(int child_process_id) {
263 base::AutoLock lock(lock_); 542 base::AutoLock lock(lock_);
264 MachBroker::ChildProcessIdMap::iterator it = 543 MachBroker::ChildProcessIdMap::iterator it =
265 child_process_id_map_.find(child_process_id); 544 child_process_id_map_.find(child_process_id);
266 if (it == child_process_id_map_.end()) 545 if (it == child_process_id_map_.end())
267 return; 546 return;
268 547
269 MachMap::iterator mach_it = mach_map_.find(it->second); 548 MachMap::iterator mach_it = mach_map_.find(it->second);
270 if (mach_it != mach_map_.end()) { 549 if (mach_it != mach_map_.end()) {
271 kern_return_t kr = mach_port_deallocate(mach_task_self(), 550 kern_return_t kr =
272 mach_it->second); 551 mach_port_deallocate(mach_task_self(), mach_it->second.task_port);
273 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; 552 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
553 for (const auto& io_surface_port : mach_it->second.io_surface_ports) {
554 kr = mach_port_deallocate(mach_task_self(), io_surface_port.second);
555 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
556 }
274 mach_map_.erase(mach_it); 557 mach_map_.erase(mach_it);
275 } 558 }
276 child_process_id_map_.erase(it); 559 child_process_id_map_.erase(it);
277 } 560 }
278 561
562 bool MachBroker::RegisterIOSurface(base::ProcessHandle pid,
563 int io_surface_id,
564 int client_id,
565 mach_port_t io_surface_port) {
566 lock_.AssertAcquired();
567
568 MachMap::iterator mach_it = mach_map_.find(pid);
569 if (mach_it == mach_map_.end()) {
570 // Do nothing for unknown pids.
571 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
572 return false;
573 }
574
575 if (!mach_it->second.is_gpu_process) {
576 LOG(ERROR) << "Illegal message from non-GPU process!";
577 return false;
578 }
579
580 ChildProcessIdMap::iterator it = child_process_id_map_.find(client_id);
581 if (it == child_process_id_map_.end())
582 return false;
583
584 MachMap::iterator client_it = mach_map_.find(it->second);
585 if (client_it == mach_map_.end()) {
586 LOG(ERROR) << "Unknown client process " << it->second;
587 return false;
588 }
589
590 if (client_it->second.io_surface_ports.count(io_surface_id)) {
591 LOG(ERROR) << "IOSurface " << io_surface_id << " already exists!";
592 return false;
593 }
594
595 client_it->second.io_surface_ports[io_surface_id] = io_surface_port;
596 return true;
597 }
598
599 void MachBroker::UnregisterIOSurface(base::ProcessHandle pid,
600 int io_surface_id,
601 int client_id) {
602 lock_.AssertAcquired();
603
604 MachMap::iterator mach_it = mach_map_.find(pid);
605 if (mach_it == mach_map_.end()) {
606 // Do nothing for unknown pids.
607 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
608 return;
609 }
610
611 if (!mach_it->second.is_gpu_process) {
612 LOG(ERROR) << "Illegal message from non-GPU process!";
613 return;
614 }
615
616 ChildProcessIdMap::iterator it = child_process_id_map_.find(client_id);
617 if (it == child_process_id_map_.end())
618 return;
619
620 mach_it = mach_map_.find(it->second);
621 if (mach_it != mach_map_.end()) {
622 auto io_surface_mach_it =
623 mach_it->second.io_surface_ports.find(io_surface_id);
624 if (io_surface_mach_it != mach_it->second.io_surface_ports.end()) {
625 kern_return_t kr =
626 mach_port_deallocate(mach_task_self(), io_surface_mach_it->second);
627 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
628 mach_it->second.io_surface_ports.erase(io_surface_mach_it);
629 }
630 }
631 }
632
633 mach_port_t MachBroker::AcquireIOSurface(base::ProcessHandle pid,
634 int io_surface_id) {
635 lock_.AssertAcquired();
636
637 MachMap::iterator it = mach_map_.find(pid);
638 if (it == mach_map_.end()) {
639 // Do nothing for unknown pids.
640 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
641 return MACH_PORT_NULL;
642 }
643
644 auto io_surface_mach_it = it->second.io_surface_ports.find(io_surface_id);
645 if (io_surface_mach_it == it->second.io_surface_ports.end()) {
646 LOG(ERROR) << "Invalid Id for IOSurface " << io_surface_id;
647 return MACH_PORT_NULL;
648 }
649
650 return io_surface_mach_it->second;
651 }
652
279 // static 653 // static
280 std::string MachBroker::GetMachPortName() { 654 std::string MachBroker::GetMachPortName() {
281 const base::CommandLine* command_line = 655 const base::CommandLine* command_line =
282 base::CommandLine::ForCurrentProcess(); 656 base::CommandLine::ForCurrentProcess();
283 const bool is_child = command_line->HasSwitch(switches::kProcessType); 657 const bool is_child = command_line->HasSwitch(switches::kProcessType);
284 658
285 // In non-browser (child) processes, use the parent's pid. 659 // In non-browser (child) processes, use the parent's pid.
286 const pid_t pid = is_child ? getppid() : getpid(); 660 const pid_t pid = is_child ? getppid() : getpid();
287 return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid); 661 return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid);
288 } 662 }
289 663
290 void MachBroker::RegisterNotifications() { 664 void MachBroker::RegisterNotifications() {
291 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, 665 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED,
292 NotificationService::AllBrowserContextsAndSources()); 666 NotificationService::AllBrowserContextsAndSources());
293 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, 667 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
294 NotificationService::AllBrowserContextsAndSources()); 668 NotificationService::AllBrowserContextsAndSources());
295 669
296 // No corresponding StopObservingBrowserChildProcesses, 670 // No corresponding StopObservingBrowserChildProcesses,
297 // we leak this singleton. 671 // we leak this singleton.
298 BrowserChildProcessObserver::Add(this); 672 BrowserChildProcessObserver::Add(this);
299 } 673 }
300 674
301 } // namespace content 675 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698