| Index: content/browser/mach_broker_mac.mm | 
| diff --git a/content/browser/mach_broker_mac.mm b/content/browser/mach_broker_mac.mm | 
| index 7c527e55b6f5faaf1e677d2096947c2d4f66a54d..8fb482f507f0dbf949d561295da1c92872c9141b 100644 | 
| --- a/content/browser/mach_broker_mac.mm | 
| +++ b/content/browser/mach_broker_mac.mm | 
| @@ -10,6 +10,7 @@ | 
| #include "base/bind.h" | 
| #include "base/bind_helpers.h" | 
| #include "base/command_line.h" | 
| +#include "base/lazy_instance.h" | 
| #include "base/logging.h" | 
| #include "base/mac/foundation_util.h" | 
| #include "base/mac/mach_logging.h" | 
| @@ -26,22 +27,162 @@ | 
| #include "content/public/common/content_switches.h" | 
|  | 
| namespace content { | 
| - | 
| namespace { | 
|  | 
| -// Mach message structure used in the child as a sending message. | 
| -struct MachBroker_ChildSendMsg { | 
| -  mach_msg_header_t header; | 
| +// Message IDs. | 
| +// Note: we currently use __LINE__ to give unique IDs to messages. | 
| +// They're unique since all messages are defined in this file. | 
| +#define MACH_MESSAGE_ID() __LINE__ | 
| + | 
| +#define MACH_MESSAGE_STRUCT_HEADER() \ | 
| +  mach_msg_header_t header;          \ | 
| mach_msg_body_t body; | 
| + | 
| +#define MACH_HOST_MESSAGE_STRUCT_HEADER() \ | 
| +  enum { ID = MACH_MESSAGE_ID() };        \ | 
| +  mach_msg_header_t header;               \ | 
| +  mach_msg_body_t body; | 
| + | 
| +struct MachBroker_ChildMsg { | 
| +  MACH_HOST_MESSAGE_STRUCT_HEADER() | 
| + | 
| mach_msg_port_descriptor_t child_task_port; | 
| }; | 
|  | 
| -// Complement to the ChildSendMsg, this is used in the parent for receiving | 
| +// Complement to the ChildMsg, this is used in the parent for receiving | 
| // a message. Contains a message trailer with audit information. | 
| -struct MachBroker_ParentRecvMsg : public MachBroker_ChildSendMsg { | 
| +struct MachBroker_ChildRecvMsg : public MachBroker_ChildMsg { | 
| mach_msg_audit_trailer_t trailer; | 
| }; | 
|  | 
| +// Mach message structure used in the child as a sending message. | 
| +struct MachBroker_RegisterIOSurfaceMsg { | 
| +  MACH_HOST_MESSAGE_STRUCT_HEADER() | 
| + | 
| +  mach_msg_port_descriptor_t io_surface_port; | 
| +  int io_surface_id; | 
| +  int client_id; | 
| +}; | 
| + | 
| +// Complement to the RegisterIOSurfaceMsg, this is used in the parent for | 
| +// receiving a message. Contains a message trailer with audit information. | 
| +struct MachBroker_RegisterIOSurfaceRecvMsg | 
| +    : public MachBroker_RegisterIOSurfaceMsg { | 
| +  mach_msg_audit_trailer_t trailer; | 
| +}; | 
| + | 
| +// Mach message structure used in the parent as a sending message. | 
| +struct MachBroker_RegisterIOSurfaceReplyMsg { | 
| +  MACH_HOST_MESSAGE_STRUCT_HEADER() | 
| + | 
| +  boolean_t result; | 
| +}; | 
| + | 
| +// Complement to the RegisterIOSurfaceReplyMsg, this is used in the child | 
| +// for receiving a message. Contains a message trailer. | 
| +struct MachBroker_RegisterIOSurfaceReplyRecvMsg | 
| +    : public MachBroker_RegisterIOSurfaceReplyMsg { | 
| +  mach_msg_trailer_t trailer; | 
| +}; | 
| + | 
| +// Mach message structure used in the child as a sending message. | 
| +struct MachBroker_UnregisterIOSurfaceMsg { | 
| +  MACH_HOST_MESSAGE_STRUCT_HEADER() | 
| + | 
| +  int io_surface_id; | 
| +  int client_id; | 
| +}; | 
| + | 
| +// Complement to the UnregisterIOSurfaceMsg, this is used in the parent for | 
| +// receiving a message. Contains a message trailer with audit information. | 
| +struct MachBroker_UnregisterIOSurfaceRecvMsg | 
| +    : public MachBroker_UnregisterIOSurfaceMsg { | 
| +  mach_msg_audit_trailer_t trailer; | 
| +}; | 
| + | 
| +// Mach message structure used in the child as a sending message. | 
| +struct MachBroker_AcquireIOSurfaceMsg { | 
| +  MACH_HOST_MESSAGE_STRUCT_HEADER() | 
| + | 
| +  int io_surface_id; | 
| +}; | 
| + | 
| +// Complement to the AcquireIOSurfaceMsg, this is used in the parent for | 
| +// receiving a message. Contains a message trailer with audit information. | 
| +struct MachBroker_AcquireIOSurfaceRecvMsg | 
| +    : public MachBroker_AcquireIOSurfaceMsg { | 
| +  mach_msg_audit_trailer_t trailer; | 
| +}; | 
| + | 
| +// Mach message structure used in the parent as a sending message. | 
| +struct MachBroker_AcquireIOSurfaceReplyMsg { | 
| +  MACH_MESSAGE_STRUCT_HEADER() | 
| + | 
| +  mach_msg_port_descriptor_t io_surface_port; | 
| +}; | 
| + | 
| +// Complement to the AcquireIOSurfaceReplyMsg, this is used in the child for | 
| +// receiving a message. Contains a message trailer. | 
| +struct MachBroker_AcquireIOSurfaceReplyRecvMsg | 
| +    : public MachBroker_AcquireIOSurfaceReplyMsg { | 
| +  mach_msg_trailer_t trailer; | 
| +}; | 
| + | 
| +// Returns the Mach port name to use when sending or receiving messages. | 
| +// Does the Right Thing in the browser and in child processes. | 
| +std::string GetMachPortName() { | 
| +  const base::CommandLine* command_line = | 
| +      base::CommandLine::ForCurrentProcess(); | 
| +  const bool is_child = command_line->HasSwitch(switches::kProcessType); | 
| + | 
| +  // In non-browser (child) processes, use the parent's pid. | 
| +  const pid_t pid = is_child ? getppid() : getpid(); | 
| +  return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid); | 
| +} | 
| + | 
| +struct ChildSendPortLazyInstanceTraits | 
| +    : public base::internal::LeakyLazyInstanceTraits< | 
| +          base::mac::ScopedMachSendRight> { | 
| +  static base::mac::ScopedMachSendRight* New(void* instance) { | 
| +    mach_port_t send_port = MACH_PORT_NULL; | 
| +    // Look up the named MachBroker port that's been registered with the | 
| +    // bootstrap server. | 
| +    kern_return_t kr = bootstrap_look_up( | 
| +        bootstrap_port, const_cast<char*>(GetMachPortName().c_str()), | 
| +        &send_port); | 
| +    if (kr != KERN_SUCCESS) | 
| +      BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up"; | 
| + | 
| +    // Use placement new to initialize our instance in our preallocated space. | 
| +    return new (instance) base::mac::ScopedMachSendRight(send_port); | 
| +  } | 
| +}; | 
| + | 
| +base::LazyInstance<base::mac::ScopedMachSendRight, | 
| +                   ChildSendPortLazyInstanceTraits> g_child_send_port = | 
| +    LAZY_INSTANCE_INITIALIZER; | 
| + | 
| +struct ChildReceivePortLazyInstanceTraits | 
| +    : public base::internal::LeakyLazyInstanceTraits< | 
| +          base::mac::ScopedMachSendRight> { | 
| +  static base::mac::ScopedMachSendRight* New(void* instance) { | 
| +    mach_port_t receive_port = MACH_PORT_NULL; | 
| +    kern_return_t kr = mach_port_allocate( | 
| +        mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &receive_port); | 
| +    if (kr != KERN_SUCCESS) | 
| +      MACH_LOG(ERROR, kr) << "mach_port_allocate"; | 
| + | 
| +    // Use placement new to initialize our instance in our preallocated space. | 
| +    return new (instance) base::mac::ScopedMachSendRight(receive_port); | 
| +  } | 
| +}; | 
| + | 
| +base::LazyInstance<base::mac::ScopedMachSendRight, | 
| +                   ChildReceivePortLazyInstanceTraits> g_child_receive_port = | 
| +    LAZY_INSTANCE_INITIALIZER; | 
| + | 
| +base::LazyInstance<base::Lock> g_child_lock = LAZY_INSTANCE_INITIALIZER; | 
| + | 
| }  // namespace | 
|  | 
| class MachListenerThreadDelegate : public base::PlatformThread::Delegate { | 
| @@ -79,14 +220,20 @@ class MachListenerThreadDelegate : public base::PlatformThread::Delegate { | 
| // is deprecated, this has to be wraped in an ObjC interface. | 
| NSPort* ns_port = [NSMachPort portWithMachPort:port | 
| options:NSMachPortDeallocateNone]; | 
| -    NSString* name = base::SysUTF8ToNSString(broker_->GetMachPortName()); | 
| +    NSString* name = base::SysUTF8ToNSString(GetMachPortName()); | 
| return [[NSMachBootstrapServer sharedInstance] registerPort:ns_port | 
| name:name]; | 
| } | 
|  | 
| // Implement |PlatformThread::Delegate|. | 
| void ThreadMain() override { | 
| -    MachBroker_ParentRecvMsg msg; | 
| +    union { | 
| +      mach_msg_header_t header; | 
| +      MachBroker_ChildRecvMsg child; | 
| +      MachBroker_RegisterIOSurfaceRecvMsg register_io_surface; | 
| +      MachBroker_UnregisterIOSurfaceRecvMsg unregister_io_surface; | 
| +      MachBroker_AcquireIOSurfaceRecvMsg acquire_io_surface; | 
| +    } msg; | 
| bzero(&msg, sizeof(msg)); | 
| msg.header.msgh_size = sizeof(msg); | 
| msg.header.msgh_local_port = server_port_.get(); | 
| @@ -104,19 +251,80 @@ class MachListenerThreadDelegate : public base::PlatformThread::Delegate { | 
| MACH_MSG_TIMEOUT_NONE, | 
| MACH_PORT_NULL)) == KERN_SUCCESS) { | 
| // Use the kernel audit information to make sure this message is from | 
| -      // a task that this process spawned. The kernel audit token contains the | 
| -      // unspoofable pid of the task that sent the message. | 
| -      // | 
| +      // a task that this process spawned. The kernel audit token contains | 
| +      // the unspoofable pid of the task that sent the message. | 
| +      mach_msg_audit_trailer_t* trailer = | 
| +          reinterpret_cast<mach_msg_audit_trailer_t*>( | 
| +              reinterpret_cast<vm_address_t>(&msg.header) + | 
| +              round_msg(msg.header.msgh_size)); | 
| // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid(). | 
| pid_t child_pid; | 
| -      audit_token_to_au32(msg.trailer.msgh_audit, | 
| -          NULL, NULL, NULL, NULL, NULL, &child_pid, NULL, NULL); | 
| - | 
| -      mach_port_t child_task_port = msg.child_task_port.name; | 
| +      audit_token_to_au32(trailer->msgh_audit, NULL, NULL, NULL, NULL, NULL, | 
| +                          &child_pid, NULL, NULL); | 
|  | 
| -      // Take the lock and update the broker information. | 
| +      // Take the lock. | 
| base::AutoLock lock(broker_->GetLock()); | 
| -      broker_->FinalizePid(child_pid, child_task_port); | 
| + | 
| +      switch (msg.header.msgh_id) { | 
| +        case MachBroker_ChildMsg::ID: { | 
| +          mach_port_t child_task_port = msg.child.child_task_port.name; | 
| + | 
| +          // Update the broker information. | 
| +          broker_->FinalizePid(child_pid, child_task_port); | 
| +        } break; | 
| +        case MachBroker_RegisterIOSurfaceMsg::ID: { | 
| +          mach_port_t io_surface_port = | 
| +              msg.register_io_surface.io_surface_port.name; | 
| +          int io_surface_id = msg.register_io_surface.io_surface_id; | 
| +          int client_id = msg.register_io_surface.client_id; | 
| + | 
| +          bool result = broker_->RegisterIOSurface(child_pid, io_surface_id, | 
| +                                                   client_id, io_surface_port); | 
| + | 
| +          MachBroker_RegisterIOSurfaceReplyMsg reply; | 
| +          bzero(&reply, sizeof(reply)); | 
| +          reply.header.msgh_bits = MACH_MSGH_BITS_REMOTE(msg.header.msgh_bits); | 
| +          reply.header.msgh_remote_port = msg.header.msgh_remote_port; | 
| +          reply.header.msgh_size = sizeof(reply); | 
| +          reply.result = result; | 
| +          kern_return_t kr = mach_msg( | 
| +              &reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(reply), | 
| +              0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); | 
| +          if (kr != KERN_SUCCESS) { | 
| +            MACH_LOG(ERROR, kr) << "mach_msg"; | 
| +          } | 
| + | 
| +        } break; | 
| +        case MachBroker_UnregisterIOSurfaceMsg::ID: { | 
| +          int io_surface_id = msg.unregister_io_surface.io_surface_id; | 
| +          int client_id = msg.unregister_io_surface.client_id; | 
| + | 
| +          broker_->UnregisterIOSurface(child_pid, io_surface_id, client_id); | 
| +        } break; | 
| +        case MachBroker_AcquireIOSurfaceMsg::ID: { | 
| +          int io_surface_id = msg.acquire_io_surface.io_surface_id; | 
| + | 
| +          mach_port_t io_surface_port = | 
| +              broker_->AcquireIOSurface(child_pid, io_surface_id); | 
| + | 
| +          MachBroker_AcquireIOSurfaceReplyMsg reply; | 
| +          bzero(&reply, sizeof(reply)); | 
| +          reply.header.msgh_bits = MACH_MSGH_BITS_REMOTE(msg.header.msgh_bits) | | 
| +                                   MACH_MSGH_BITS_COMPLEX; | 
| +          reply.header.msgh_remote_port = msg.header.msgh_remote_port; | 
| +          reply.header.msgh_size = sizeof(reply); | 
| +          reply.body.msgh_descriptor_count = 1; | 
| +          reply.io_surface_port.name = io_surface_port; | 
| +          reply.io_surface_port.disposition = MACH_MSG_TYPE_COPY_SEND; | 
| +          reply.io_surface_port.type = MACH_MSG_PORT_DESCRIPTOR; | 
| +          kern_return_t kr = mach_msg( | 
| +              &reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(reply), | 
| +              0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); | 
| +          if (kr != KERN_SUCCESS) { | 
| +            MACH_LOG(ERROR, kr) << "mach_msg"; | 
| +          } | 
| +        } break; | 
| +      } | 
| } | 
|  | 
| MACH_LOG(ERROR, kr) << "mach_msg"; | 
| @@ -132,33 +340,46 @@ class MachListenerThreadDelegate : public base::PlatformThread::Delegate { | 
| DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate); | 
| }; | 
|  | 
| +MachBroker::MachPortSet::MachPortSet() | 
| +    : is_gpu_process(false), task_port(MACH_PORT_NULL) { | 
| +} | 
| + | 
| +MachBroker::MachPortSet::MachPortSet(bool is_gpu_process) | 
| +    : is_gpu_process(is_gpu_process), task_port(MACH_PORT_NULL) { | 
| +} | 
| + | 
| +MachBroker::MachPortSet::~MachPortSet() { | 
| +} | 
| + | 
| bool MachBroker::ChildSendTaskPortToParent() { | 
| -  // Look up the named MachBroker port that's been registered with the | 
| -  // bootstrap server. | 
| -  mach_port_t parent_port; | 
| -  kern_return_t kr = bootstrap_look_up(bootstrap_port, | 
| -      const_cast<char*>(GetMachPortName().c_str()), &parent_port); | 
| -  if (kr != KERN_SUCCESS) { | 
| -    BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up"; | 
| +  base::AutoLock lock(g_child_lock.Get()); | 
| + | 
| +  mach_port_t child_send_port = g_child_send_port.Get(); | 
| +  if (child_send_port == MACH_PORT_NULL) | 
| +    return false; | 
| + | 
| +  // Make sure we have valid receive port before we send the check in message. | 
| +  mach_port_t child_receive_port = g_child_receive_port.Get(); | 
| +  if (child_receive_port == MACH_PORT_NULL) | 
| return false; | 
| -  } | 
| -  base::mac::ScopedMachSendRight scoped_right(parent_port); | 
|  | 
| // Create the check in message. This will copy a send right on this process' | 
| // (the child's) task port and send it to the parent. | 
| -  MachBroker_ChildSendMsg msg; | 
| +  MachBroker_ChildMsg msg; | 
| bzero(&msg, sizeof(msg)); | 
| msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) | | 
| MACH_MSGH_BITS_COMPLEX; | 
| -  msg.header.msgh_remote_port = parent_port; | 
| +  msg.header.msgh_remote_port = child_send_port; | 
| msg.header.msgh_size = sizeof(msg); | 
| +  msg.header.msgh_id = MachBroker_ChildMsg::ID; | 
| msg.body.msgh_descriptor_count = 1; | 
| msg.child_task_port.name = mach_task_self(); | 
| msg.child_task_port.disposition = MACH_MSG_TYPE_PORT_SEND; | 
| msg.child_task_port.type = MACH_MSG_PORT_DESCRIPTOR; | 
|  | 
| -  kr = mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), | 
| -      0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); | 
| +  kern_return_t kr = | 
| +      mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), 0, | 
| +               MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); | 
| if (kr != KERN_SUCCESS) { | 
| MACH_LOG(ERROR, kr) << "mach_msg"; | 
| return false; | 
| @@ -167,6 +388,102 @@ bool MachBroker::ChildSendTaskPortToParent() { | 
| return true; | 
| } | 
|  | 
| +bool MachBroker::ChildRegisterIOSurfaceWithParent(int io_surface_id, | 
| +                                                  int client_id, | 
| +                                                  mach_port_t io_surface_port) { | 
| +  base::AutoLock lock(g_child_lock.Get()); | 
| + | 
| +  mach_port_t child_receive_port = g_child_receive_port.Get(); | 
| + | 
| +  // Deallocate the right after sending a copy to the parent. | 
| +  base::mac::ScopedMachSendRight io_surface_send_right(io_surface_port); | 
| + | 
| +  union { | 
| +    MachBroker_RegisterIOSurfaceMsg request; | 
| +    MachBroker_RegisterIOSurfaceReplyRecvMsg reply; | 
| +  } msg; | 
| +  bzero(&msg, sizeof(msg)); | 
| +  msg.request.header.msgh_bits = | 
| +      MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE) | | 
| +      MACH_MSGH_BITS_COMPLEX; | 
| +  msg.request.header.msgh_remote_port = g_child_send_port.Get(); | 
| +  msg.request.header.msgh_local_port = child_receive_port; | 
| +  msg.request.header.msgh_size = sizeof(msg.request); | 
| +  msg.request.header.msgh_id = MachBroker_RegisterIOSurfaceMsg::ID; | 
| +  msg.request.body.msgh_descriptor_count = 1; | 
| +  msg.request.io_surface_port.name = io_surface_port; | 
| +  msg.request.io_surface_port.disposition = MACH_MSG_TYPE_COPY_SEND; | 
| +  msg.request.io_surface_port.type = MACH_MSG_PORT_DESCRIPTOR; | 
| +  msg.request.io_surface_id = io_surface_id; | 
| +  msg.request.client_id = client_id; | 
| + | 
| +  kern_return_t kr = | 
| +      mach_msg(&msg.request.header, MACH_SEND_MSG | MACH_RCV_MSG, | 
| +               sizeof(msg.request), sizeof(msg.reply), child_receive_port, | 
| +               MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | 
| +  if (kr != KERN_SUCCESS) { | 
| +    MACH_LOG(ERROR, kr) << "mach_msg"; | 
| +    return false; | 
| +  } | 
| + | 
| +  return msg.reply.result; | 
| +} | 
| + | 
| +bool MachBroker::ChildUnregisterIOSurfaceWithParent(int io_surface_id, | 
| +                                                    int client_id) { | 
| +  base::AutoLock lock(g_child_lock.Get()); | 
| + | 
| +  MachBroker_UnregisterIOSurfaceMsg msg; | 
| +  bzero(&msg, sizeof(msg)); | 
| +  msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); | 
| +  msg.header.msgh_remote_port = g_child_send_port.Get(); | 
| +  msg.header.msgh_local_port = MACH_PORT_NULL; | 
| +  msg.header.msgh_size = sizeof(msg); | 
| +  msg.header.msgh_id = MachBroker_UnregisterIOSurfaceMsg::ID; | 
| +  msg.io_surface_id = io_surface_id; | 
| +  msg.client_id = client_id; | 
| + | 
| +  kern_return_t kr = | 
| +      mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), 0, | 
| +               MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); | 
| +  if (kr != KERN_SUCCESS) { | 
| +    MACH_LOG(ERROR, kr) << "mach_msg"; | 
| +    return false; | 
| +  } | 
| + | 
| +  return true; | 
| +} | 
| + | 
| +mach_port_t MachBroker::ChildAcquireIOSurfaceFromParent(int io_surface_id) { | 
| +  base::AutoLock lock(g_child_lock.Get()); | 
| + | 
| +  mach_port_t child_receive_port = g_child_receive_port.Get(); | 
| + | 
| +  union { | 
| +    MachBroker_AcquireIOSurfaceMsg request; | 
| +    MachBroker_AcquireIOSurfaceReplyRecvMsg reply; | 
| +  } msg; | 
| +  bzero(&msg, sizeof(msg)); | 
| +  msg.request.header.msgh_bits = | 
| +      MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); | 
| +  msg.request.header.msgh_remote_port = g_child_send_port.Get(); | 
| +  msg.request.header.msgh_local_port = child_receive_port; | 
| +  msg.request.header.msgh_size = sizeof(msg.request); | 
| +  msg.request.header.msgh_id = MachBroker_AcquireIOSurfaceMsg::ID; | 
| +  msg.request.io_surface_id = io_surface_id; | 
| + | 
| +  kern_return_t kr = | 
| +      mach_msg(&msg.request.header, MACH_SEND_MSG | MACH_RCV_MSG, | 
| +               sizeof(msg.request), sizeof(msg.reply), child_receive_port, | 
| +               MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | 
| +  if (kr != KERN_SUCCESS) { | 
| +    MACH_LOG(ERROR, kr) << "mach_msg"; | 
| +    return MACH_PORT_NULL; | 
| +  } | 
| + | 
| +  return msg.reply.io_surface_port.name; | 
| +} | 
| + | 
| MachBroker* MachBroker::GetInstance() { | 
| return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get(); | 
| } | 
| @@ -196,11 +513,12 @@ void MachBroker::EnsureRunning() { | 
| } | 
|  | 
| void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid, | 
| -                                      int child_process_id) { | 
| +                                      int child_process_id, | 
| +                                      bool is_gpu_process) { | 
| lock_.AssertAcquired(); | 
|  | 
| DCHECK_EQ(0u, mach_map_.count(pid)); | 
| -  mach_map_[pid] = MACH_PORT_NULL; | 
| +  mach_map_[pid] = MachPortSet(is_gpu_process); | 
| child_process_id_map_[child_process_id] = pid; | 
| } | 
|  | 
| @@ -209,7 +527,7 @@ mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const { | 
| MachBroker::MachMap::const_iterator it = mach_map_.find(pid); | 
| if (it == mach_map_.end()) | 
| return MACH_PORT_NULL; | 
| -  return it->second; | 
| +  return it->second.task_port; | 
| } | 
|  | 
| void MachBroker::BrowserChildProcessHostDisconnected( | 
| @@ -254,9 +572,8 @@ void MachBroker::FinalizePid(base::ProcessHandle pid, | 
| return; | 
| } | 
|  | 
| -  DCHECK(it->second == MACH_PORT_NULL); | 
| -  if (it->second == MACH_PORT_NULL) | 
| -    it->second = task_port; | 
| +  if (it->second.task_port == MACH_PORT_NULL) | 
| +    it->second.task_port = task_port; | 
| } | 
|  | 
| void MachBroker::InvalidateChildProcessId(int child_process_id) { | 
| @@ -268,23 +585,107 @@ void MachBroker::InvalidateChildProcessId(int child_process_id) { | 
|  | 
| MachMap::iterator mach_it = mach_map_.find(it->second); | 
| if (mach_it != mach_map_.end()) { | 
| -    kern_return_t kr = mach_port_deallocate(mach_task_self(), | 
| -                                            mach_it->second); | 
| +    kern_return_t kr = | 
| +        mach_port_deallocate(mach_task_self(), mach_it->second.task_port); | 
| MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; | 
| +    for (const auto& io_surface_port : mach_it->second.io_surface_ports) { | 
| +      kr = mach_port_deallocate(mach_task_self(), io_surface_port.second); | 
| +      MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; | 
| +    } | 
| mach_map_.erase(mach_it); | 
| } | 
| child_process_id_map_.erase(it); | 
| } | 
|  | 
| -// static | 
| -std::string MachBroker::GetMachPortName() { | 
| -  const base::CommandLine* command_line = | 
| -      base::CommandLine::ForCurrentProcess(); | 
| -  const bool is_child = command_line->HasSwitch(switches::kProcessType); | 
| +bool MachBroker::RegisterIOSurface(base::ProcessHandle pid, | 
| +                                   int io_surface_id, | 
| +                                   int client_id, | 
| +                                   mach_port_t io_surface_port) { | 
| +  lock_.AssertAcquired(); | 
|  | 
| -  // In non-browser (child) processes, use the parent's pid. | 
| -  const pid_t pid = is_child ? getppid() : getpid(); | 
| -  return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid); | 
| +  MachMap::iterator mach_it = mach_map_.find(pid); | 
| +  if (mach_it == mach_map_.end()) { | 
| +    // Do nothing for unknown pids. | 
| +    LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; | 
| +    return false; | 
| +  } | 
| + | 
| +  if (!mach_it->second.is_gpu_process) { | 
| +    LOG(ERROR) << "Illegal message from non-GPU process!"; | 
| +    return false; | 
| +  } | 
| + | 
| +  ChildProcessIdMap::iterator it = child_process_id_map_.find(client_id); | 
| +  if (it == child_process_id_map_.end()) | 
| +    return false; | 
| + | 
| +  MachMap::iterator client_it = mach_map_.find(it->second); | 
| +  if (client_it == mach_map_.end()) { | 
| +    LOG(ERROR) << "Unknown client process " << it->second; | 
| +    return false; | 
| +  } | 
| + | 
| +  if (client_it->second.io_surface_ports.count(io_surface_id)) { | 
| +    LOG(ERROR) << "IOSurface " << io_surface_id << " already exists!"; | 
| +    return false; | 
| +  } | 
| + | 
| +  client_it->second.io_surface_ports[io_surface_id] = io_surface_port; | 
| +  return true; | 
| +} | 
| + | 
| +void MachBroker::UnregisterIOSurface(base::ProcessHandle pid, | 
| +                                     int io_surface_id, | 
| +                                     int client_id) { | 
| +  lock_.AssertAcquired(); | 
| + | 
| +  MachMap::iterator mach_it = mach_map_.find(pid); | 
| +  if (mach_it == mach_map_.end()) { | 
| +    // Do nothing for unknown pids. | 
| +    LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; | 
| +    return; | 
| +  } | 
| + | 
| +  if (!mach_it->second.is_gpu_process) { | 
| +    LOG(ERROR) << "Illegal message from non-GPU process!"; | 
| +    return; | 
| +  } | 
| + | 
| +  ChildProcessIdMap::iterator it = child_process_id_map_.find(client_id); | 
| +  if (it == child_process_id_map_.end()) | 
| +    return; | 
| + | 
| +  mach_it = mach_map_.find(it->second); | 
| +  if (mach_it != mach_map_.end()) { | 
| +    auto io_surface_mach_it = | 
| +        mach_it->second.io_surface_ports.find(io_surface_id); | 
| +    if (io_surface_mach_it != mach_it->second.io_surface_ports.end()) { | 
| +      kern_return_t kr = | 
| +          mach_port_deallocate(mach_task_self(), io_surface_mach_it->second); | 
| +      MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; | 
| +      mach_it->second.io_surface_ports.erase(io_surface_mach_it); | 
| +    } | 
| +  } | 
| +} | 
| + | 
| +mach_port_t MachBroker::AcquireIOSurface(base::ProcessHandle pid, | 
| +                                         int io_surface_id) { | 
| +  lock_.AssertAcquired(); | 
| + | 
| +  MachMap::iterator it = mach_map_.find(pid); | 
| +  if (it == mach_map_.end()) { | 
| +    // Do nothing for unknown pids. | 
| +    LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; | 
| +    return MACH_PORT_NULL; | 
| +  } | 
| + | 
| +  auto io_surface_mach_it = it->second.io_surface_ports.find(io_surface_id); | 
| +  if (io_surface_mach_it == it->second.io_surface_ports.end()) { | 
| +    LOG(ERROR) << "Invalid Id for IOSurface " << io_surface_id; | 
| +    return MACH_PORT_NULL; | 
| +  } | 
| + | 
| +  return io_surface_mach_it->second; | 
| } | 
|  | 
| void MachBroker::RegisterNotifications() { | 
|  |