1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/mach_broker_mac.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/command_line.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/mach_ipc_mac.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h"
113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/sys_string_conversions.h"
123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_host.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/chrome_switches.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_process_host.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/child_process_info.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace {
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Prints a string representation of a Mach error code.
223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstd::string MachErrorCode(kern_return_t err) {
233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return StringPrintf("0x%x %s", err, mach_error_string(err));
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}  // namespace
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Required because notifications happen on the UI thread.
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass RegisterNotificationTask : public Task {
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RegisterNotificationTask(
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MachBroker* broker)
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : broker_(broker) { }
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void Run() {
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    broker_->registrar_.Add(broker_,
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotificationType::RENDERER_PROCESS_CLOSED,
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotificationService::AllSources());
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    broker_->registrar_.Add(broker_,
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotificationType::RENDERER_PROCESS_TERMINATED,
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotificationService::AllSources());
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    broker_->registrar_.Add(broker_,
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotificationType::CHILD_PROCESS_CRASHED,
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotificationService::AllSources());
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    broker_->registrar_.Add(broker_,
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotificationType::CHILD_PROCESS_HOST_DISCONNECTED,
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotificationService::AllSources());
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    broker_->registrar_.Add(broker_,
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotificationType::EXTENSION_PROCESS_TERMINATED,
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotificationService::AllSources());
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MachBroker* broker_;
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DISALLOW_COPY_AND_ASSIGN(RegisterNotificationTask);
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenclass MachListenerThreadDelegate : public base::PlatformThread::Delegate {
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MachListenerThreadDelegate(MachBroker* broker) : broker_(broker) {
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(broker_);
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string port_name = MachBroker::GetMachPortName();
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Create the receive port in the constructor, not in ThreadMain().  It is
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // important to create and register the receive port before starting the
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // thread so that child processes will always have someone who's listening.
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    receive_port_.reset(new base::ReceivePort(port_name.c_str()));
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Implement |PlatformThread::Delegate|.
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void ThreadMain() {
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    base::MachReceiveMessage message;
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    kern_return_t err;
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    while ((err = receive_port_->WaitForMessage(&message,
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                MACH_MSG_TIMEOUT_NONE)) ==
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick           KERN_SUCCESS) {
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // 0 was the secret message id.  Reject any messages that don't have it.
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (message.GetMessageID() != 0) {
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        LOG(ERROR) << "Received message with incorrect id: "
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                   << message.GetMessageID();
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        continue;
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const task_t child_task = message.GetTranslatedPort(0);
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (child_task == MACH_PORT_NULL) {
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        LOG(ERROR) << "parent GetTranslatedPort(0) failed.";
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        continue;
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // It is possible for the child process to die after the call to
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // |pid_for_task()| but before the call to |FinalizePid()|.  To prevent
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // leaking MachBroker map entries in this case, lock around both these
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // calls.  If the child dies, the death notification will be processed
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // after the call to FinalizePid(), ensuring proper cleanup.
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      base::AutoLock lock(broker_->GetLock());
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      int pid;
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      err = pid_for_task(child_task, &pid);
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (err == KERN_SUCCESS) {
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        broker_->FinalizePid(pid,
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             MachBroker::MachInfo().SetTask(child_task));
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      } else {
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        LOG(ERROR) << "Error getting pid for task " << child_task
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                   << ": " << MachErrorCode(err);
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(ERROR) << "Mach listener thread exiting; "
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               << "parent WaitForMessage() likely failed: "
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               << MachErrorCode(err);
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // The Mach port to listen on.  Created on thread startup.
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<base::ReceivePort> receive_port_;
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // The MachBroker to use when new child task rights are received.  Can be
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // NULL.
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MachBroker* broker_;  // weak
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate);
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the global MachBroker.
12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenMachBroker* MachBroker::GetInstance() {
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get();
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickMachBroker::MachBroker() : listener_thread_started_(false) {
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
131dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenMachBroker::~MachBroker() {}
132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MachBroker::PrepareForFork() {
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!listener_thread_started_) {
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    listener_thread_started_ = true;
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::UI, FROM_HERE, new RegisterNotificationTask(this));
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Intentional leak.  This thread is never joined or reaped.
1413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::PlatformThread::CreateNonJoinable(
1423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        0, new MachListenerThreadDelegate(this));
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Adds a placeholder to the map for the given pid with MACH_PORT_NULL.
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MachBroker::AddPlaceholderForPid(base::ProcessHandle pid) {
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  lock_.AssertAcquired();
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MachInfo mach_info;
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(0u, mach_map_.count(pid));
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  mach_map_[pid] = mach_info;
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Updates the mapping for |pid| to include the given |mach_info|.
1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MachBroker::FinalizePid(base::ProcessHandle pid,
1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             const MachInfo& mach_info) {
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  lock_.AssertAcquired();
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int count = mach_map_.count(pid);
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (count == 0) {
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Do nothing for unknown pids.
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_EQ(1, count);
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(mach_map_[pid].mach_task_ == MACH_PORT_NULL);
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (mach_map_[pid].mach_task_ == MACH_PORT_NULL)
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    mach_map_[pid] = mach_info;
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Removes all mappings belonging to |pid| from the broker.
1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MachBroker::InvalidatePid(base::ProcessHandle pid) {
17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MachBroker::MachMap::iterator it = mach_map_.find(pid);
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it == mach_map_.end())
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kern_return_t kr = mach_port_deallocate(mach_task_self(),
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          it->second.mach_task_);
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LOG_IF(WARNING, kr != KERN_SUCCESS)
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     << "Failed to mach_port_deallocate mach task " << it->second.mach_task_
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     << ", error " << MachErrorCode(kr);
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  mach_map_.erase(it);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbase::Lock& MachBroker::GetLock() {
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return lock_;
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the mach task belonging to |pid|.
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochmach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const {
19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MachBroker::MachMap::const_iterator it = mach_map_.find(pid);
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it == mach_map_.end())
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return MACH_PORT_NULL;
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return it->second.mach_task_;
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MachBroker::Observe(NotificationType type,
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         const NotificationSource& source,
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         const NotificationDetails& details) {
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(rohitrao): These notifications do not always carry the proper PIDs,
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // especially when the renderer is already gone or has crashed.  Find a better
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // way to listen for child process deaths.  http://crbug.com/55734
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::ProcessHandle handle = 0;
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (type.value) {
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::RENDERER_PROCESS_CLOSED:
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::RENDERER_PROCESS_TERMINATED:
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      handle = Source<RenderProcessHost>(source)->GetHandle();
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::EXTENSION_PROCESS_TERMINATED:
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      handle =
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          Details<ExtensionHost>(details)->render_process_host()->GetHandle();
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::CHILD_PROCESS_CRASHED:
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::CHILD_PROCESS_HOST_DISCONNECTED:
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      handle = Details<ChildProcessInfo>(details)->handle();
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED() << "Unexpected notification";
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  InvalidatePid(handle);
2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstd::string MachBroker::GetMachPortName() {
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kFormatString[] =
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(GOOGLE_CHROME_BUILD)
2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      "com.google.Chrome"
2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#else
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      "org.chromium.Chromium"
2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ".rohitfork.%d";
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const bool is_child = command_line.HasSwitch(switches::kProcessType);
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // In non-browser (child) processes, use the parent's pid.
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const pid_t pid = is_child ? getppid() : getpid();
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return StringPrintf(kFormatString, pid);
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
245