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

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

Powered by Google App Engine
This is Rietveld 408576698