diff --git a/base/process_util.h b/base/process_util.h
index ca4328939ef49c6e0426541beb2eb8ec69620abd..ccbb687f5f32b28e56ddf2fb0563fe74045e8b49 100644
--- a/base/process_util.h
+++ b/base/process_util.h
@@ -118,13 +118,15 @@ const uint32 kProcessAccessQueryLimitedInfomation = 0;
 const uint32 kProcessAccessWaitForTermination     = 0;
 #endif  // defined(OS_POSIX)
 
-// A minimalistic but hopefully cross-platform set of exit codes.
-// Do not change the enumeration values or you will break third-party
-// installers.
-enum {
-  PROCESS_END_NORMAL_TERMINATION = 0,
-  PROCESS_END_KILLED_BY_USER     = 1,
-  PROCESS_END_PROCESS_WAS_HUNG   = 2
+// Return status values from GetTerminationStatus.  Don't use these as
+// exit code arguments to KillProcess*(), use platform/application
+// specific values instead.
+enum TerminationStatus {
+  TERMINATION_STATUS_NORMAL_TERMINATION,   // zero exit status
+  TERMINATION_STATUS_ABNORMAL_TERMINATION, // non-zero exit status
+  TERMINATION_STATUS_PROCESS_WAS_KILLED,   // e.g. SIGKILL or task manager kill
+  TERMINATION_STATUS_PROCESS_CRASHED,      // e.g. Segmentation fault
+  TERMINATION_STATUS_STILL_RUNNING         // child hasn't exited yet
 };
 
 // Returns the id of the current process.
@@ -180,7 +182,7 @@ bool AdjustOOMScore(ProcessId process, int score);
 #endif
 
 #if defined(OS_POSIX)
-// Close all file descriptors, expect those which are a destination in the
+// Close all file descriptors, except those which are a destination in the
 // given multimap. Only call this function in a child process where you know
 // that there aren't any other threads.
 void CloseSuperfluousFds(const InjectiveMultimap& saved_map);
@@ -347,10 +349,15 @@ bool KillProcessGroup(ProcessHandle process_group_id);
 bool KillProcessById(ProcessId process_id, int exit_code, bool wait);
 #endif
 
-// Get the termination status (exit code) of the process and return true if the
-// status indicates the process crashed. |child_exited| is set to true iff the
-// child process has terminated. (|child_exited| may be NULL.)
-bool DidProcessCrash(bool* child_exited, ProcessHandle handle);
+// Get the termination status of the process by interpreting the
+// circumstances of the child process' death. |exit_code| is set to
+// the status returned by waitpid() on POSIX, and from
+// GetExitCodeProcess() on Windows.  |exit_code| may be NULL if the
+// caller is not interested in it.  Note that on Linux, this function
+// will only return a useful result the first time it is called after
+// the child exits (because it will reap the child and the information
+// will no longer be available).
+TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code);
 
 // Waits for process to exit. In POSIX systems, if the process hasn't been
 // signaled then puts the exit code in |exit_code|; otherwise it's considered
diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc
index 92ef9643f3358ea0ef4b42798b1e7c8ea3b7facb..3d296748daa4ab6caf2440b380a8f4c2d96f81ed 100644
--- a/base/process_util_posix.cc
+++ b/base/process_util_posix.cc
@@ -237,6 +237,8 @@ bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) {
         sleep_ms *= 2;
     }
 
+    // If we're waiting and the child hasn't died by now, force it
+    // with a SIGKILL.
     if (!exited)
       result = kill(process_id, SIGKILL) == 0;
   }
@@ -634,40 +636,45 @@ void RaiseProcessToHighPriority() {
   // setpriority() or sched_getscheduler, but these all require extra rights.
 }
 
-bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
-  int status;
+TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
+  int status = 0;
   const pid_t result = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
   if (result == -1) {
     PLOG(ERROR) << "waitpid(" << handle << ")";
-    if (child_exited)
-      *child_exited = false;
-    return false;
+    if (exit_code)
+      *exit_code = 0;
+    return TERMINATION_STATUS_NORMAL_TERMINATION;
   } else if (result == 0) {
     // the child hasn't exited yet.
-    if (child_exited)
-      *child_exited = false;
-    return false;
+    if (exit_code)
+      *exit_code = 0;
+    return TERMINATION_STATUS_STILL_RUNNING;
   }
 
-  if (child_exited)
-    *child_exited = true;
+  if (exit_code)
+    *exit_code = status;
 
   if (WIFSIGNALED(status)) {
     switch (WTERMSIG(status)) {
-      case SIGSEGV:
-      case SIGILL:
       case SIGABRT:
+      case SIGBUS:
       case SIGFPE:
-        return true;
+      case SIGILL:
+      case SIGSEGV:
+        return TERMINATION_STATUS_PROCESS_CRASHED;
+      case SIGINT:
+      case SIGKILL:
+      case SIGTERM:
+        return TERMINATION_STATUS_PROCESS_WAS_KILLED;
       default:
-        return false;
+        break;
     }
   }
 
-  if (WIFEXITED(status))
-    return WEXITSTATUS(status) != 0;
+  if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
+    return TERMINATION_STATUS_ABNORMAL_TERMINATION;
 
-  return false;
+  return TERMINATION_STATUS_NORMAL_TERMINATION;
 }
 
 bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
diff --git a/base/process_util_unittest.cc b/base/process_util_unittest.cc
index 34c444cc9723389b4ff06d0c160b0a2990b6108a..0eaf5d43d68847d7ca5c613c9b8f30e477afa82b 100644
--- a/base/process_util_unittest.cc
+++ b/base/process_util_unittest.cc
@@ -7,6 +7,7 @@
 #include <limits>
 
 #include "base/command_line.h"
+#include "base/debug_util.h"
 #include "base/eintr_wrapper.h"
 #include "base/file_path.h"
 #include "base/logging.h"
@@ -15,6 +16,7 @@
 #include "base/process_util.h"
 #include "base/scoped_ptr.h"
 #include "base/test/multiprocess_test.h"
+#include "base/test/test_timeouts.h"
 #include "base/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/multiprocess_func_list.h"
@@ -27,6 +29,7 @@
 #if defined(OS_POSIX)
 #include <dlfcn.h>
 #include <fcntl.h>
+#include <signal.h>
 #include <sys/resource.h>
 #include <sys/socket.h>
 #endif
@@ -41,11 +44,25 @@
 namespace {
 
 #if defined(OS_WIN)
-const wchar_t* const kProcessName = L"base_unittests.exe";
+const wchar_t kProcessName[] = L"base_unittests.exe";
 #else
-const wchar_t* const kProcessName = L"base_unittests";
+const wchar_t kProcessName[] = L"base_unittests";
 #endif  // defined(OS_WIN)
 
+const char kSignalFileSlow[] = "SlowChildProcess.die";
+const char kSignalFileCrash[] = "CrashingChildProcess.die";
+const char kSignalFileKill[] = "KilledChildProcess.die";
+
+#if defined(OS_WIN)
+const int kExpectedStillRunningExitCode = 0x102;
+const int kExpectedKilledExitCode = 1;
+#else
+const int kExpectedStillRunningExitCode = 0;
+#endif
+
+// The longest we'll wait for a process, in milliseconds.
+const int kMaxWaitTimeMs = TestTimeouts::action_max_timeout_ms();
+
 // Sleeps until file filename is created.
 void WaitToDie(const char* filename) {
   FILE *fp;
@@ -62,6 +79,27 @@ void SignalChildren(const char* filename) {
   fclose(fp);
 }
 
+// Using a pipe to the child to wait for an event was considered, but
+// there were cases in the past where pipes caused problems (other
+// libraries closing the fds, child deadlocking). This is a simple
+// case, so it's not worth the risk.  Using wait loops is discouraged
+// in most instances.
+base::TerminationStatus WaitForChildTermination(base::ProcessHandle handle,
+                                                int* exit_code) {
+  // Now we wait until the result is something other than STILL_RUNNING.
+  base::TerminationStatus status = base::TERMINATION_STATUS_STILL_RUNNING;
+  const int kIntervalMs = 20;
+  int waited = 0;
+  do {
+    status = base::GetTerminationStatus(handle, exit_code);
+    PlatformThread::Sleep(kIntervalMs);
+    waited += kIntervalMs;
+  } while (status == base::TERMINATION_STATUS_STILL_RUNNING &&
+           waited < kMaxWaitTimeMs);
+
+  return status;
+}
+
 }  // namespace
 
 class ProcessUtilTest : public base::MultiProcessTest {
@@ -79,40 +117,140 @@ MULTIPROCESS_TEST_MAIN(SimpleChildProcess) {
 TEST_F(ProcessUtilTest, SpawnChild) {
   base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false);
   ASSERT_NE(base::kNullProcessHandle, handle);
-  EXPECT_TRUE(base::WaitForSingleProcess(handle, 5000));
+  EXPECT_TRUE(base::WaitForSingleProcess(handle, kMaxWaitTimeMs));
   base::CloseProcessHandle(handle);
 }
 
 MULTIPROCESS_TEST_MAIN(SlowChildProcess) {
-  WaitToDie("SlowChildProcess.die");
+  WaitToDie(kSignalFileSlow);
   return 0;
 }
 
 TEST_F(ProcessUtilTest, KillSlowChild) {
-  remove("SlowChildProcess.die");
+  remove(kSignalFileSlow);
   base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false);
   ASSERT_NE(base::kNullProcessHandle, handle);
-  SignalChildren("SlowChildProcess.die");
-  EXPECT_TRUE(base::WaitForSingleProcess(handle, 5000));
+  SignalChildren(kSignalFileSlow);
+  EXPECT_TRUE(base::WaitForSingleProcess(handle, kMaxWaitTimeMs));
   base::CloseProcessHandle(handle);
-  remove("SlowChildProcess.die");
+  remove(kSignalFileSlow);
 }
 
-TEST_F(ProcessUtilTest, DidProcessCrash) {
-  remove("SlowChildProcess.die");
+TEST_F(ProcessUtilTest, GetTerminationStatusExit) {
+  remove(kSignalFileSlow);
   base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false);
   ASSERT_NE(base::kNullProcessHandle, handle);
 
-  bool child_exited = true;
-  EXPECT_FALSE(base::DidProcessCrash(&child_exited, handle));
-  EXPECT_FALSE(child_exited);
+  int exit_code = 42;
+  EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
+            base::GetTerminationStatus(handle, &exit_code));
+  EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
+
+  SignalChildren(kSignalFileSlow);
+  exit_code = 42;
+  base::TerminationStatus status =
+      WaitForChildTermination(handle, &exit_code);
+  EXPECT_EQ(base::TERMINATION_STATUS_NORMAL_TERMINATION, status);
+  EXPECT_EQ(0, exit_code);
+  base::CloseProcessHandle(handle);
+  remove(kSignalFileSlow);
+}
 
-  SignalChildren("SlowChildProcess.die");
-  EXPECT_TRUE(base::WaitForSingleProcess(handle, 5000));
+#if !defined(OS_MACOSX)
+// This test is disabled on Mac, since it's flaky due to ReportCrash
+// taking a variable amount of time to parse and load the debug and
+// symbol data for this unit test's executable before firing the
+// signal handler.
+//
+// TODO(gspencer): turn this test process into a very small program
+// with no symbols (instead of using the multiprocess testing
+// framework) to reduce the ReportCrash overhead.
+
+MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
+  WaitToDie(kSignalFileCrash);
+#if defined(OS_POSIX)
+  // Have to disable to signal handler for segv so we can get a crash
+  // instead of an abnormal termination through the crash dump handler.
+  ::signal(SIGSEGV, SIG_DFL);
+#endif
+  // Make this process have a segmentation fault.
+  int* oops = NULL;
+  *oops = 0xDEAD;
+  return 1;
+}
+
+TEST_F(ProcessUtilTest, GetTerminationStatusCrash) {
+  remove(kSignalFileCrash);
+  base::ProcessHandle handle = this->SpawnChild("CrashingChildProcess",
+                                                false);
+  ASSERT_NE(base::kNullProcessHandle, handle);
 
-  EXPECT_FALSE(base::DidProcessCrash(&child_exited, handle));
+  int exit_code = 42;
+  EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
+            base::GetTerminationStatus(handle, &exit_code));
+  EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
+
+  SignalChildren(kSignalFileCrash);
+  exit_code = 42;
+  base::TerminationStatus status =
+      WaitForChildTermination(handle, &exit_code);
+  EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_CRASHED, status);
+
+#if defined(OS_WIN)
+  EXPECT_EQ(0xc0000005, exit_code);
+#elif defined(OS_POSIX)
+  int signaled = WIFSIGNALED(exit_code);
+  EXPECT_NE(0, signaled);
+  int signal = WTERMSIG(exit_code);
+  EXPECT_EQ(SIGSEGV, signal);
+#endif
+  base::CloseProcessHandle(handle);
+
+  // Reset signal handlers back to "normal".
+  base::EnableInProcessStackDumping();
+  remove(kSignalFileCrash);
+}
+#endif // !defined(OS_MACOSX)
+
+MULTIPROCESS_TEST_MAIN(KilledChildProcess) {
+  WaitToDie(kSignalFileKill);
+#if defined(OS_WIN)
+  // Kill ourselves.
+  HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId());
+  ::TerminateProcess(handle, kExpectedKilledExitCode);
+#elif defined(OS_POSIX)
+  // Send a SIGKILL to this process, just like the OOM killer would.
+  ::kill(getpid(), SIGKILL);
+#endif
+  return 1;
+}
+
+TEST_F(ProcessUtilTest, GetTerminationStatusKill) {
+  remove(kSignalFileKill);
+  base::ProcessHandle handle = this->SpawnChild("KilledChildProcess",
+                                                false);
+  ASSERT_NE(base::kNullProcessHandle, handle);
+
+  int exit_code = 42;
+  EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
+            base::GetTerminationStatus(handle, &exit_code));
+  EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
+
+  SignalChildren(kSignalFileKill);
+  exit_code = 42;
+  base::TerminationStatus status =
+      WaitForChildTermination(handle, &exit_code);
+  EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED, status);
+#if defined(OS_WIN)
+  EXPECT_EQ(kExpectedKilledExitCode, exit_code);
+#elif defined(OS_POSIX)
+  int signaled = WIFSIGNALED(exit_code);
+  EXPECT_NE(0, signaled);
+  int signal = WTERMSIG(exit_code);
+  EXPECT_EQ(SIGKILL, signal);
+#endif
   base::CloseProcessHandle(handle);
-  remove("SlowChildProcess.die");
+  remove(kSignalFileKill);
 }
 
 // Ensure that the priority of a process is restored correctly after
diff --git a/base/process_util_win.cc b/base/process_util_win.cc
index 097888e86e07447d7b0887b8c73cb427fdffbf6f..71f0a1a996c756affd03d41876438f1c4ffddadc 100644
--- a/base/process_util_win.cc
+++ b/base/process_util_win.cc
@@ -30,6 +30,20 @@ namespace {
 // System pagesize. This value remains constant on x86/64 architectures.
 const int PAGESIZE_KB = 4;
 
+// Exit codes with special meanings on Windows.
+const DWORD kNormalTerminationExitCode = 0;
+const DWORD kDebuggerInactiveExitCode = 0xC0000354;
+const DWORD kKeyboardInterruptExitCode = 0xC000013A;
+const DWORD kDebuggerTerminatedExitCode = 0x40010004;
+
+// This exit code is used by the Windows task manager when it kills a
+// process.  It's value is obviously not that unique, and it's
+// surprising to me that the task manager uses this value, but it
+// seems to be common practice on Windows to test for it as an
+// indication that the task manager has killed something if the
+// process goes away.
+const DWORD kProcessKilledExitCode = 1;
+
 // HeapSetInformation function pointer.
 typedef BOOL (WINAPI* HeapSetFn)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T);
 
@@ -105,10 +119,10 @@ bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
 
 bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) {
   ProcessHandle result = OpenProcess(PROCESS_DUP_HANDLE |
-                                         PROCESS_TERMINATE |
-                                         PROCESS_QUERY_INFORMATION |
-                                         PROCESS_VM_READ |
-                                         SYNCHRONIZE,
+                                     PROCESS_TERMINATE |
+                                     PROCESS_QUERY_INFORMATION |
+                                     PROCESS_VM_READ |
+                                     SYNCHRONIZE,
                                      FALSE, pid);
 
   if (result == INVALID_HANDLE_VALUE)
@@ -394,22 +408,33 @@ bool KillProcess(ProcessHandle process, int exit_code, bool wait) {
   return result;
 }
 
-bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
-  DWORD exitcode = 0;
+TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
+  DWORD tmp_exit_code = 0;
 
-  if (!::GetExitCodeProcess(handle, &exitcode)) {
+  if (!::GetExitCodeProcess(handle, &tmp_exit_code)) {
     NOTREACHED();
-    // Assume the child has exited.
-    if (child_exited)
-      *child_exited = true;
-    return false;
+    if (exit_code) {
+      // This really is a random number.  We haven't received any
+      // information about the exit code, presumably because this
+      // process doesn't have permission to get the exit code, or
+      // because of some other cause for GetExitCodeProcess to fail
+      // (MSDN docs don't give the possible failure error codes for
+      // this function, so it could be anything).  But we don't want
+      // to leave exit_code uninitialized, since that could cause
+      // random interpretations of the exit code.  So we assume it
+      // terminated "normally" in this case.
+      *exit_code = kNormalTerminationExitCode;
+    }
+    // Assume the child has exited normally if we can't get the exit
+    // code.
+    return TERMINATION_STATUS_NORMAL_TERMINATION;
   }
-  if (exitcode == STILL_ACTIVE) {
+  if (tmp_exit_code == STILL_ACTIVE) {
     DWORD wait_result = WaitForSingleObject(handle, 0);
     if (wait_result == WAIT_TIMEOUT) {
-      if (child_exited)
-        *child_exited = false;
-      return false;
+      if (exit_code)
+        *exit_code = wait_result;
+      return TERMINATION_STATUS_STILL_RUNNING;
     }
 
     DCHECK_EQ(WAIT_OBJECT_0, wait_result);
@@ -417,27 +442,24 @@ bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
     // Strange, the process used 0x103 (STILL_ACTIVE) as exit code.
     NOTREACHED();
 
-    return false;
+    return TERMINATION_STATUS_ABNORMAL_TERMINATION;
   }
 
-  // We're sure the child has exited.
-  if (child_exited)
-    *child_exited = true;
+  if (exit_code)
+    *exit_code = tmp_exit_code;
 
-  // Warning, this is not generic code; it heavily depends on the way
-  // the rest of the code kills a process.
-
-  if (exitcode == PROCESS_END_NORMAL_TERMINATION ||
-      exitcode == PROCESS_END_KILLED_BY_USER ||
-      exitcode == PROCESS_END_PROCESS_WAS_HUNG ||
-      exitcode == 0xC0000354 ||     // STATUS_DEBUGGER_INACTIVE.
-      exitcode == 0xC000013A ||     // Control-C/end session.
-      exitcode == 0x40010004) {     // Debugger terminated process/end session.
-    return false;
+  switch (tmp_exit_code) {
+    case kNormalTerminationExitCode:
+      return TERMINATION_STATUS_NORMAL_TERMINATION;
+    case kDebuggerInactiveExitCode:  // STATUS_DEBUGGER_INACTIVE.
+    case kKeyboardInterruptExitCode:  // Control-C/end session.
+    case kDebuggerTerminatedExitCode:  // Debugger terminated process.
+    case kProcessKilledExitCode:  // Task manager kill.
+      return TERMINATION_STATUS_PROCESS_WAS_KILLED;
+    default:
+      // All other exit codes indicate crashes.
+      return TERMINATION_STATUS_PROCESS_CRASHED;
   }
-
-  // All other exit codes indicate crashes.
-  return true;
 }
 
 bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
diff --git a/chrome/browser/browser_child_process_host.cc b/chrome/browser/browser_child_process_host.cc
index 6ad0c44167d4ff1c39b0e94ee88192e360be894a..6b7d47b6a8467d6a04615cd827e9f9bd1869ca88 100644
--- a/chrome/browser/browser_child_process_host.cc
+++ b/chrome/browser/browser_child_process_host.cc
@@ -141,18 +141,34 @@ void BrowserChildProcessHost::Notify(NotificationType type) {
       BrowserThread::UI, FROM_HERE, new ChildNotificationTask(type, this));
 }
 
-bool BrowserChildProcessHost::DidChildCrash() {
-  return child_process_->DidProcessCrash();
+base::TerminationStatus BrowserChildProcessHost::GetChildTerminationStatus(
+    int* exit_code) {
+  return child_process_->GetChildTerminationStatus(exit_code);
 }
 
 void BrowserChildProcessHost::OnChildDied() {
   if (handle() != base::kNullProcessHandle) {
-    bool did_crash = DidChildCrash();
-    if (did_crash) {
-      OnProcessCrashed();
-      // Report that this child process crashed.
-      Notify(NotificationType::CHILD_PROCESS_CRASHED);
-      UMA_HISTOGRAM_COUNTS("ChildProcess.Crashes", this->type());
+    int exit_code;
+    base::TerminationStatus status = GetChildTerminationStatus(&exit_code);
+    switch (status) {
+      case base::TERMINATION_STATUS_PROCESS_CRASHED: {
+        OnProcessCrashed(exit_code);
+
+        // Report that this child process crashed.
+        Notify(NotificationType::CHILD_PROCESS_CRASHED);
+        UMA_HISTOGRAM_COUNTS("ChildProcess.Crashes", this->type());
+        break;
+      }
+      case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
+        OnProcessWasKilled(exit_code);
+
+        // Report that this child process was killed.
+        Notify(NotificationType::CHILD_PROCESS_WAS_KILLED);
+        UMA_HISTOGRAM_COUNTS("ChildProcess.Kills", this->type());
+        break;
+      }
+      default:
+        break;
     }
     // Notify in the main loop of the disconnection.
     Notify(NotificationType::CHILD_PROCESS_HOST_DISCONNECTED);
diff --git a/chrome/browser/browser_child_process_host.h b/chrome/browser/browser_child_process_host.h
index f70c035a01784959bf71a7d6572ef318656a4ebc..b7bd39a5ca98fc6ab136a7f8a8a62248efbab1bf 100644
--- a/chrome/browser/browser_child_process_host.h
+++ b/chrome/browser/browser_child_process_host.h
@@ -78,12 +78,25 @@ class BrowserChildProcessHost : public ResourceDispatcherHost::Receiver,
   base::ProcessHandle GetChildProcessHandle() const;
 
   // ChildProcessLauncher::Client implementation.
-  virtual void OnProcessLaunched() { }
+  virtual void OnProcessLaunched() {}
 
   // Derived classes can override this to know if the process crashed.
-  virtual void OnProcessCrashed() {}
-
-  virtual bool DidChildCrash();
+  // |exit_code| is the status returned when the process crashed (for
+  // posix, as returned from waitpid(), for Windows, as returned from
+  // GetExitCodeProcess()).
+  virtual void OnProcessCrashed(int exit_code) {}
+
+  // Derived classes can override this to know if the process was
+  // killed.  |exit_code| is the status returned when the process
+  // was killed (for posix, as returned from waitpid(), for Windows,
+  // as returned from GetExitCodeProcess()).
+  virtual void OnProcessWasKilled(int exit_code) {}
+
+  // Returns the termination status of a child.  |exit_code| is the
+  // status returned when the process exited (for posix, as returned
+  // from waitpid(), for Windows, as returned from
+  // GetExitCodeProcess()).  |exit_code| may be NULL.
+  virtual base::TerminationStatus GetChildTerminationStatus(int* exit_code);
 
   // Overrides from ChildProcessHost
   virtual void OnChildDied();
@@ -111,4 +124,3 @@ class BrowserChildProcessHost : public ResourceDispatcherHost::Receiver,
 };
 
 #endif  // CHROME_BROWSER_BROWSER_CHILD_PROCESS_HOST_H_
-
diff --git a/chrome/browser/child_process_launcher.cc b/chrome/browser/child_process_launcher.cc
index a4a610af8deb65ea628208c7922c0ccc57b8b016..8ba6941485bc10d9a891e4317b708ff273489713 100644
--- a/chrome/browser/child_process_launcher.cc
+++ b/chrome/browser/child_process_launcher.cc
@@ -311,28 +311,29 @@ base::ProcessHandle ChildProcessLauncher::GetHandle() {
   return context_->process_.handle();
 }
 
-bool ChildProcessLauncher::DidProcessCrash() {
-  bool did_crash, child_exited;
+base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
+    int* exit_code) {
+  base::TerminationStatus status;
   base::ProcessHandle handle = context_->process_.handle();
 #if defined(OS_LINUX)
   if (context_->zygote_) {
-    did_crash = ZygoteHost::GetInstance()->DidProcessCrash(handle,
-                                                           &child_exited);
+    status = ZygoteHost::GetInstance()->GetTerminationStatus(handle, exit_code);
   } else
 #endif
   {
-    did_crash = base::DidProcessCrash(&child_exited, handle);
+    status = base::GetTerminationStatus(handle, exit_code);
   }
 
-  // POSIX: If the process crashed, then the kernel closed the socket for it
-  // and so the child has already died by the time we get here. Since
-  // DidProcessCrash called waitpid with WNOHANG, it'll reap the process.
-  // However, if DidProcessCrash didn't reap the child, we'll need to in
+  // POSIX: If the process crashed, then the kernel closed the socket
+  // for it and so the child has already died by the time we get
+  // here. Since GetTerminationStatus called waitpid with WNOHANG,
+  // it'll reap the process.  However, if GetTerminationStatus didn't
+  // reap the child (because it was still running), we'll need to
   // Terminate via ProcessWatcher. So we can't close the handle here.
-  if (child_exited)
+  if (status != base::TERMINATION_STATUS_STILL_RUNNING)
     context_->process_.Close();
 
-  return did_crash;
+  return status;
 }
 
 void ChildProcessLauncher::SetProcessBackgrounded(bool background) {
diff --git a/chrome/browser/child_process_launcher.h b/chrome/browser/child_process_launcher.h
index 95fb6ea32d95b298bc1dfb2aa6c87ef7d4b65b59..a3add53715020288958b425ae2339db1fa4d4ee5 100644
--- a/chrome/browser/child_process_launcher.h
+++ b/chrome/browser/child_process_launcher.h
@@ -50,8 +50,11 @@ class ChildProcessLauncher {
   // Getter for the process handle.  Only call after the process has started.
   base::ProcessHandle GetHandle();
 
-  // Call this when the process exits to know if a process crashed or not.
-  bool DidProcessCrash();
+  // Call this when the child process exits to know what happened to
+  // it.  |exit_code| is the exit code of the process if it exited
+  // (e.g. status from waitpid if on posix, from GetExitCodeProcess on
+  // Windows). |exit_code| may be NULL.
+  base::TerminationStatus GetChildTerminationStatus(int* exit_code);
 
   // Changes whether the process runs in the background or not.  Only call
   // this after the process has started.
diff --git a/chrome/browser/child_process_security_policy_browsertest.cc b/chrome/browser/child_process_security_policy_browsertest.cc
index bedac819d2443da75fc28b9d2450d5e17c56593c..4bcd3dce577fced8781da62c45c363d0a0e3dcf3 100644
--- a/chrome/browser/child_process_security_policy_browsertest.cc
+++ b/chrome/browser/child_process_security_policy_browsertest.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/common/result_codes.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -43,7 +44,7 @@ IN_PROC_BROWSER_TEST_F(ChildProcessSecurityPolicyInProcessBrowserTest, NoLeak) {
   TabContents* tab = browser()->GetTabContentsAt(0);
   ASSERT_TRUE(tab != NULL);
   base::KillProcess(tab->GetRenderProcessHost()->GetHandle(),
-                    base::PROCESS_END_KILLED_BY_USER, true);
+                    ResultCodes::KILLED, true);
 
   tab->controller().Reload(true);
   EXPECT_EQ(
diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
index 50144e1589e0617106f1101e3e15b84e68b9d763..1914ec7a8a80ea9d8e4ce5ad024c6352584f5e16 100644
--- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
+++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/tab_contents/infobar_delegate.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/common/result_codes.h"
 #include "chrome/test/ui_test_utils.h"
 
 class ExtensionCrashRecoveryTest : public ExtensionBrowserTest {
@@ -61,8 +62,7 @@ class ExtensionCrashRecoveryTest : public ExtensionBrowserTest {
 
     RenderProcessHost* extension_rph =
         extension_host->render_view_host()->process();
-    base::KillProcess(extension_rph->GetHandle(),
-                      base::PROCESS_END_KILLED_BY_USER, false);
+    base::KillProcess(extension_rph->GetHandle(), ResultCodes::KILLED, false);
     ASSERT_TRUE(WaitForExtensionCrash(extension_id));
     ASSERT_FALSE(
         GetExtensionProcessManager()->GetBackgroundHostForExtension(extension));
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index cb6bd6b4f2227de3dfa11fcd7f6051b858b84365..1051399fd6aaf7b0d63133f7d0c5a5901df782a8 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -288,7 +288,9 @@ void ExtensionHost::ClearInspectorSettings() {
   RenderViewHostDelegateHelper::ClearInspectorSettings(profile());
 }
 
-void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host) {
+void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host,
+                                   base::TerminationStatus status,
+                                   int error_code) {
   // During browser shutdown, we may use sudden termination on an extension
   // process, so it is expected to lose our connection to the render view.
   // Do nothing.
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 935b76c2ce3c1bb8e85c31f1b0de8627be2c1832..801bdab3dee85b0fc086dea073f8834ffba2c81b 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -112,7 +112,9 @@ class ExtensionHost : public RenderViewHostDelegate,
   virtual ViewType::Type GetRenderViewType() const;
   virtual FileSelect* GetFileSelectDelegate();
   virtual int GetBrowserWindowID() const;
-  virtual void RenderViewGone(RenderViewHost* render_view_host);
+  virtual void RenderViewGone(RenderViewHost* render_view_host,
+                              base::TerminationStatus status,
+                              int error_code);
   virtual void DidNavigate(RenderViewHost* render_view_host,
                            const ViewHostMsg_FrameNavigate_Params& params);
   virtual void DidStopLoading();
diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker.cc b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
index faf236b1fe09b67b0a135d74118193ff096190e3..fc01884bce29c0e2181d12da8e5174029ffcca69 100644
--- a/chrome/browser/extensions/sandboxed_extension_unpacker.cc
+++ b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
@@ -181,7 +181,7 @@ void SandboxedExtensionUnpacker::OnUnpackExtensionFailed(
   ReportFailure(error);
 }
 
-void SandboxedExtensionUnpacker::OnProcessCrashed() {
+void SandboxedExtensionUnpacker::OnProcessCrashed(int exit_code) {
   // Don't report crashes if they happen after we got a response.
   if (got_response_)
     return;
diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker.h b/chrome/browser/extensions/sandboxed_extension_unpacker.h
index acb408109ceae5884f2a1b69f1b8c7a1eec17b0e..e47b26c513abe87fe844ad601e40337296850d2b 100644
--- a/chrome/browser/extensions/sandboxed_extension_unpacker.h
+++ b/chrome/browser/extensions/sandboxed_extension_unpacker.h
@@ -124,7 +124,7 @@ class SandboxedExtensionUnpacker : public UtilityProcessHost::Client {
   // SandboxedExtensionUnpacker
   virtual void OnUnpackExtensionSucceeded(const DictionaryValue& manifest);
   virtual void OnUnpackExtensionFailed(const std::string& error_message);
-  virtual void OnProcessCrashed();
+  virtual void OnProcessCrashed(int exit_code);
 
   void ReportFailure(const std::string& message);
   void ReportSuccess();
diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc
index af4229a0921040c3556a03b2f3b5bdbab28897eb..7ddbdf1b310a0d1bbb6b5fd6c6559b873338a7f6 100644
--- a/chrome/browser/gpu_process_host.cc
+++ b/chrome/browser/gpu_process_host.cc
@@ -495,12 +495,12 @@ void GpuProcessHost::OnChildDied() {
   BrowserChildProcessHost::OnChildDied();
 }
 
-void GpuProcessHost::OnProcessCrashed() {
+void GpuProcessHost::OnProcessCrashed(int exit_code) {
   if (++g_gpu_crash_count >= kGpuMaxCrashCount) {
     // The gpu process is too unstable to use. Disable it for current session.
     RenderViewHostDelegateHelper::set_gpu_enabled(false);
   }
-  BrowserChildProcessHost::OnProcessCrashed();
+  BrowserChildProcessHost::OnProcessCrashed(exit_code);
 }
 
 bool GpuProcessHost::CanLaunchGpuProcess() const {
diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h
index a2b3c9ef0ced55c55952cdbd93c9d66cdb1c0057..c60c307afc6aa2be36e8c751de52867a96f5f202 100644
--- a/chrome/browser/gpu_process_host.h
+++ b/chrome/browser/gpu_process_host.h
@@ -113,7 +113,7 @@ class GpuProcessHost : public BrowserChildProcessHost, public NonThreadSafe {
 
   virtual bool CanShutdown();
   virtual void OnChildDied();
-  virtual void OnProcessCrashed();
+  virtual void OnProcessCrashed(int exit_code);
 
   bool CanLaunchGpuProcess() const;
   bool LaunchGpuProcess();
diff --git a/chrome/browser/importer/importer.cc b/chrome/browser/importer/importer.cc
index 861db31ad1ec93328e006235399684592fd3f3d5..6cf596b39b56a7128de232067c7e7b23f7aa4463 100644
--- a/chrome/browser/importer/importer.cc
+++ b/chrome/browser/importer/importer.cc
@@ -460,7 +460,7 @@ void ExternalProcessImporterClient::NotifyItemFinishedOnIOThread(
   profile_import_process_host_->ReportImportItemFinished(import_item);
 }
 
-void ExternalProcessImporterClient::OnProcessCrashed() {
+void ExternalProcessImporterClient::OnProcessCrashed(int exit_code) {
   if (cancelled_)
     return;
 
diff --git a/chrome/browser/importer/importer.h b/chrome/browser/importer/importer.h
index 515c58c72386974629cdab8224031b30e74123db..bc258506fb5853513e83628060fbdcb2ebd2d497 100644
--- a/chrome/browser/importer/importer.h
+++ b/chrome/browser/importer/importer.h
@@ -344,7 +344,7 @@ class ExternalProcessImporterClient
   void NotifyItemFinishedOnIOThread(importer::ImportItem import_item);
 
   // Cancel import on process crash.
-  virtual void OnProcessCrashed();
+  virtual void OnProcessCrashed(int exit_code);
 
   // Notifies the importerhost that import has finished, and calls Release().
   void Cleanup();
diff --git a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
index 920da34b6b5f8d7b2595c5bc29f30ad7ec775b20..e287c2c51199a1e0ed3f10bba41f36af26141ec6 100644
--- a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
+++ b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
@@ -148,7 +148,7 @@ IndexedDBKeyUtilityClient::Client::Client(IndexedDBKeyUtilityClient* parent)
     : parent_(parent) {
 }
 
-void IndexedDBKeyUtilityClient::Client::OnProcessCrashed() {
+void IndexedDBKeyUtilityClient::Client::OnProcessCrashed(int exit_code) {
   if (parent_->state_ == STATE_CREATING_KEYS)
     parent_->FinishCreatingKeys();
 }
diff --git a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
index ee03ed9bdf6debfe8a55f25cf348f4749dea278f..6b8aec121512bb943c58775b0f09cfe161c6e5a2 100644
--- a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
+++ b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
@@ -45,7 +45,7 @@ class IndexedDBKeyUtilityClient
     explicit Client(IndexedDBKeyUtilityClient* parent);
 
     // UtilityProcessHost::Client
-    virtual void OnProcessCrashed();
+    virtual void OnProcessCrashed(int exit_code);
     virtual void OnIDBKeysFromValuesAndKeyPathSucceeded(
         int id, const std::vector<IndexedDBKey>& keys);
     virtual void OnIDBKeysFromValuesAndKeyPathFailed(int id);
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index 092548ba976fd4e5381d04af5eea3488c89f6e16..30415493d989f463cd2dc47679bc85b1de93fc92 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -606,11 +606,13 @@ void MetricsService::Observe(NotificationType type,
       LogLoadStarted();
       break;
 
-    case NotificationType::RENDERER_PROCESS_CLOSED:
-      {
+    case NotificationType::RENDERER_PROCESS_CLOSED: {
         RenderProcessHost::RendererClosedDetails* process_details =
             Details<RenderProcessHost::RendererClosedDetails>(details).ptr();
-        if (process_details->did_crash) {
+        if (process_details->status ==
+            base::TERMINATION_STATUS_PROCESS_CRASHED ||
+            process_details->status ==
+            base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
           if (process_details->was_extension_renderer) {
             LogExtensionRendererCrash();
           } else {
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc
index ded73905ce6a24d5f2acdaa29d65b9a495a3cdae..df661e48e76ee22961a8a207989d5706ef6272e8 100644
--- a/chrome/browser/nacl_host/nacl_process_host.cc
+++ b/chrome/browser/nacl_host/nacl_process_host.cc
@@ -163,10 +163,11 @@ void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) {
   OnProcessLaunched();
 }
 
-bool NaClProcessHost::DidChildCrash() {
+base::TerminationStatus NaClProcessHost::GetChildTerminationStatus(
+    int* exit_code) {
   if (running_on_wow64_)
-    return base::DidProcessCrash(NULL, handle());
-  return BrowserChildProcessHost::DidChildCrash();
+    return base::GetTerminationStatus(handle(), exit_code);
+  return BrowserChildProcessHost::GetChildTerminationStatus(exit_code);
 }
 
 void NaClProcessHost::OnChildDied() {
diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h
index 3b35bf757854fe3c31b70442296cd9719bb06547..5d6cc35899e47c788a5e55d4f2cd52ddcb5ae7c3 100644
--- a/chrome/browser/nacl_host/nacl_process_host.h
+++ b/chrome/browser/nacl_host/nacl_process_host.h
@@ -37,7 +37,7 @@ class NaClProcessHost : public BrowserChildProcessHost {
   void OnProcessLaunchedByBroker(base::ProcessHandle handle);
 
  protected:
-  virtual bool DidChildCrash();
+  virtual base::TerminationStatus GetChildTerminationStatus(int* exit_code);
   virtual void OnChildDied();
 
  private:
diff --git a/chrome/browser/notifications/balloon_host.cc b/chrome/browser/notifications/balloon_host.cc
index 8c778d084ef93902a1f339273bddfc9c441e5a32..13b092f85ca0e598a7a28368e9972f654b30f41d 100644
--- a/chrome/browser/notifications/balloon_host.cc
+++ b/chrome/browser/notifications/balloon_host.cc
@@ -91,7 +91,8 @@ const string16& BalloonHost::GetSource() const {
 
 WebPreferences BalloonHost::GetWebkitPrefs() {
   WebPreferences web_prefs =
-      RenderViewHostDelegateHelper::GetWebkitPrefs(GetProfile(), enable_dom_ui_);
+      RenderViewHostDelegateHelper::GetWebkitPrefs(GetProfile(),
+                                                   enable_dom_ui_);
   web_prefs.allow_scripts_to_close_windows = true;
   return web_prefs;
 }
@@ -132,7 +133,9 @@ void BalloonHost::RenderViewReady(RenderViewHost* render_view_host) {
       Source<BalloonHost>(this), NotificationService::NoDetails());
 }
 
-void BalloonHost::RenderViewGone(RenderViewHost* render_view_host) {
+void BalloonHost::RenderViewGone(RenderViewHost* render_view_host,
+                                 base::TerminationStatus status,
+                                 int error_code) {
   Close(render_view_host);
 }
 
diff --git a/chrome/browser/notifications/balloon_host.h b/chrome/browser/notifications/balloon_host.h
index c5a88e760c6df3c4677576a7ccf63fa339460823..c3c058be1182611113d59fbb973ee54331491a78 100644
--- a/chrome/browser/notifications/balloon_host.h
+++ b/chrome/browser/notifications/balloon_host.h
@@ -49,7 +49,9 @@ class BalloonHost : public RenderViewHostDelegate,
   virtual void Close(RenderViewHost* render_view_host);
   virtual void RenderViewCreated(RenderViewHost* render_view_host);
   virtual void RenderViewReady(RenderViewHost* render_view_host);
-  virtual void RenderViewGone(RenderViewHost* render_view_host);
+  virtual void RenderViewGone(RenderViewHost* render_view_host,
+                              base::TerminationStatus status,
+                              int error_code);
   virtual void UpdateTitle(RenderViewHost* render_view_host,
                            int32 page_id, const std::wstring& title) {}
   virtual int GetBrowserWindowID() const;
diff --git a/chrome/browser/profile_import_process_host.cc b/chrome/browser/profile_import_process_host.cc
index 26e4ec16eb27f63db3079ffaa5e1115213bbef9c..45ec4f69efbf445747b5b4765ced5a6be986b491 100644
--- a/chrome/browser/profile_import_process_host.cc
+++ b/chrome/browser/profile_import_process_host.cc
@@ -127,12 +127,13 @@ void ProfileImportProcessHost::OnMessageReceived(const IPC::Message& message) {
                         message));
 }
 
-void ProfileImportProcessHost::OnProcessCrashed() {
+void ProfileImportProcessHost::OnProcessCrashed(int exit_code) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   BrowserThread::PostTask(
       thread_id_, FROM_HERE,
       NewRunnableMethod(import_process_client_.get(),
-                        &ImportProcessClient::OnProcessCrashed));
+                        &ImportProcessClient::OnProcessCrashed,
+                        exit_code));
 }
 
 bool ProfileImportProcessHost::CanShutdown() {
diff --git a/chrome/browser/profile_import_process_host.h b/chrome/browser/profile_import_process_host.h
index a6129a159519ca64d12c0c423fd6c88c47f233f0..fabb947b54b6c8f85c7bc0e5ebf0d40abda5a5c0 100644
--- a/chrome/browser/profile_import_process_host.h
+++ b/chrome/browser/profile_import_process_host.h
@@ -40,7 +40,7 @@ class ProfileImportProcessHost : public BrowserChildProcessHost {
     // These methods are used by the ProfileImportProcessHost to pass messages
     // received from the external process back to the ImportProcessClient in
     // ImporterHost.
-    virtual void OnProcessCrashed() {}
+    virtual void OnProcessCrashed(int exit_status) {}
     virtual void OnImportStart() {}
     virtual void OnImportFinished(bool succeeded, std::string error_msg) {}
     virtual void OnImportItemStart(int item) {}
@@ -126,7 +126,7 @@ class ProfileImportProcessHost : public BrowserChildProcessHost {
   virtual void OnMessageReceived(const IPC::Message& message);
 
   // Overridden from BrowserChildProcessHost:
-  virtual void OnProcessCrashed();
+  virtual void OnProcessCrashed(int exit_code);
   virtual bool CanShutdown();
   virtual URLRequestContext* GetRequestContext(
       uint32 request_id,
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 98b642b32bd0349ce1147dddcff206ecb188ae3e..e2c87805871ec4fc51b2326188a0007afa6f8949 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -989,16 +989,26 @@ void BrowserRenderProcessHost::OnChannelError() {
   if (!channel_.get())
     return;
 
-  // NULL in single process mode or if fast termination happened.
-  bool did_crash =
-      child_process_.get() ? child_process_->DidProcessCrash() : false;
-
-  if (did_crash) {
+  // child_process_ can be NULL in single process mode or if fast
+  // termination happened.
+  int exit_code = 0;
+  base::TerminationStatus status =
+      child_process_.get() ?
+      child_process_->GetChildTerminationStatus(&exit_code) :
+      base::TERMINATION_STATUS_NORMAL_TERMINATION;
+
+  if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
+      status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
     UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes",
                              extension_process_ ? 2 : 1);
   }
 
-  RendererClosedDetails details(did_crash, extension_process_);
+  if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
+    UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills",
+                             extension_process_ ? 2 : 1);
+  }
+
+  RendererClosedDetails details(status, exit_code, extension_process_);
   NotificationService::current()->Notify(
       NotificationType::RENDERER_PROCESS_CLOSED,
       Source<RenderProcessHost>(this),
@@ -1011,7 +1021,9 @@ void BrowserRenderProcessHost::OnChannelError() {
   IDMap<IPC::Channel::Listener>::iterator iter(&listeners_);
   while (!iter.IsAtEnd()) {
     iter.GetCurrentValue()->OnMessageReceived(
-        ViewHostMsg_RenderViewGone(iter.GetCurrentKey()));
+        ViewHostMsg_RenderViewGone(iter.GetCurrentKey(),
+                                   static_cast<int>(status),
+                                   exit_code));
     iter.Advance();
   }
 
diff --git a/chrome/browser/renderer_host/render_process_host.h b/chrome/browser/renderer_host/render_process_host.h
index a5fd378259468165ea9cb709f22d702553e016ac..c9a8abc463629e435686d25d87e893f8f70a20bf 100644
--- a/chrome/browser/renderer_host/render_process_host.h
+++ b/chrome/browser/renderer_host/render_process_host.h
@@ -11,6 +11,7 @@
 #include "app/surface/transport_dib.h"
 #include "base/id_map.h"
 #include "base/process.h"
+#include "base/process_util.h"
 #include "base/scoped_ptr.h"
 #include "base/time.h"
 #include "chrome/common/visitedlink_common.h"
@@ -48,11 +49,15 @@ class RenderProcessHost : public IPC::Channel::Sender,
 
   // Details for RENDERER_PROCESS_CLOSED notifications.
   struct RendererClosedDetails {
-    RendererClosedDetails(bool did_crash, bool was_extension_renderer) {
-      this->did_crash = did_crash;
+    RendererClosedDetails(base::TerminationStatus status,
+                          int exit_code,
+                          bool was_extension_renderer) {
+      this->status = status;
+      this->exit_code = exit_code;
       this->was_extension_renderer = was_extension_renderer;
     }
-    bool did_crash;
+    base::TerminationStatus status;
+    int exit_code;
     bool was_extension_renderer;
   };
 
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 1b1cf0bd517dbb9319247a96e8001ba072742fc5..dc358b6944541f111ff01f5c4797bb790df29b42 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -140,7 +140,8 @@ RenderViewHost::RenderViewHost(SiteInstance* instance,
       session_storage_namespace_(session_storage),
       is_extension_process_(false),
       autofill_query_id_(0),
-      save_accessibility_tree_for_testing_(false) {
+      save_accessibility_tree_for_testing_(false),
+      render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) {
   if (!session_storage_namespace_) {
     session_storage_namespace_ =
         new SessionStorageNamespace(process()->profile());
@@ -998,15 +999,23 @@ void RenderViewHost::OnMsgRunModal(IPC::Message* reply_msg) {
 }
 
 void RenderViewHost::OnMsgRenderViewReady() {
+  render_view_termination_status_ = base::TERMINATION_STATUS_STILL_RUNNING;
   WasResized();
   delegate_->RenderViewReady(this);
 }
 
-void RenderViewHost::OnMsgRenderViewGone() {
+void RenderViewHost::OnMsgRenderViewGone(int status, int exit_code) {
+  // Keep the termination status so we can get at it later when we
+  // need to know why it died.
+  render_view_termination_status_ =
+      static_cast<base::TerminationStatus>(status);
+
   // Our base class RenderWidgetHost needs to reset some stuff.
-  RendererExited();
+  RendererExited(render_view_termination_status_, exit_code);
 
-  delegate_->RenderViewGone(this);
+  delegate_->RenderViewGone(this,
+                            static_cast<base::TerminationStatus>(status),
+                            exit_code);
 }
 
 // Called when the renderer navigates.  For every frame loaded, we'll get this
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index b5399bf91cb84f2e5a6848e65505fa73523418cc..81223eaa722b9b0ff4e667c435f150287c22e9b2 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include "base/process_util.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/renderer_host/render_widget_host.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
@@ -127,6 +128,10 @@ class RenderViewHost : public RenderWidgetHost {
   // because it is overridden by TestRenderViewHost.
   virtual bool IsRenderViewLive() const;
 
+  base::TerminationStatus render_view_termination_status() const {
+    return render_view_termination_status_;
+  }
+
   // Send the renderer process the current preferences supplied by the
   // RenderViewHostDelegate.
   void SyncRendererPrefs();
@@ -550,7 +555,7 @@ class RenderViewHost : public RenderWidgetHost {
   void OnMsgShowFullscreenWidget(int route_id);
   void OnMsgRunModal(IPC::Message* reply_msg);
   void OnMsgRenderViewReady();
-  void OnMsgRenderViewGone();
+  void OnMsgRenderViewGone(int status, int error_code);
   void OnMsgNavigate(const IPC::Message& msg);
   void OnMsgUpdateState(int32 page_id,
                         const std::string& state);
@@ -819,6 +824,9 @@ class RenderViewHost : public RenderWidgetHost {
   // The most recently received accessibility tree - for unit testing only.
   webkit_glue::WebAccessibility accessibility_tree_;
 
+  // The termination status of the last render view that terminated.
+  base::TerminationStatus render_view_termination_status_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderViewHost);
 };
 
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index a566062e94fdff9a3327cf9c180c9fade079cc34..89f7d94d4da9002c8da5f250db6f4ce48e25561f 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
+#include "base/process_util.h"
 #include "base/ref_counted.h"
 #include "base/string16.h"
 #include "chrome/common/content_settings_types.h"
@@ -711,7 +712,9 @@ class RenderViewHostDelegate {
   virtual void RenderViewReady(RenderViewHost* render_view_host) {}
 
   // The RenderView died somehow (crashed or was killed by the user).
-  virtual void RenderViewGone(RenderViewHost* render_view_host) {}
+  virtual void RenderViewGone(RenderViewHost* render_view_host,
+                              base::TerminationStatus status,
+                              int error_code) {}
 
   // The RenderView is going to be deleted. This is called when each
   // RenderView is going to be destroyed
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index 3fa5610a0a886d317ddef36b1fd6d0dbbfc7c0f7..3c71440b7c9296ac8709d9bf52e992f1155c1e1e 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -643,7 +643,8 @@ void RenderWidgetHost::ForwardTouchEvent(
 }
 #endif
 
-void RenderWidgetHost::RendererExited() {
+void RenderWidgetHost::RendererExited(base::TerminationStatus status,
+                                      int exit_code) {
   // Clearing this flag causes us to re-create the renderer when recovering
   // from a crashed renderer.
   renderer_initialized_ = false;
@@ -671,7 +672,7 @@ void RenderWidgetHost::RendererExited() {
   is_accelerated_compositing_active_ = false;
 
   if (view_) {
-    view_->RenderViewGone();
+    view_->RenderViewGone(status, exit_code);
     view_ = NULL;  // The View should be deleted by RenderViewGone.
   }
 
@@ -777,7 +778,7 @@ void RenderWidgetHost::OnMsgRenderViewReady() {
   WasResized();
 }
 
-void RenderWidgetHost::OnMsgRenderViewGone() {
+void RenderWidgetHost::OnMsgRenderViewGone(int status, int exit_code) {
   // TODO(evanm): This synchronously ends up calling "delete this".
   // Is that really what we want in response to this message?  I'm matching
   // previous behavior of the code here.
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index b0192a478c5cb09cd0e3f6e1d2fb702fd5d25fea..90204aa36eee52fa27e5909571fda1b4a6f5e393 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -12,6 +12,7 @@
 
 #include "app/surface/transport_dib.h"
 #include "base/gtest_prod_util.h"
+#include "base/process_util.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
 #include "base/timer.h"
@@ -415,7 +416,7 @@ class RenderWidgetHost : public IPC::Channel::Listener,
   // Called when we receive a notification indicating that the renderer
   // process has gone. This will reset our state so that our state will be
   // consistent if a new renderer is created.
-  void RendererExited();
+  void RendererExited(base::TerminationStatus status, int exit_code);
 
   // Retrieves an id the renderer can use to refer to its view.
   // This is used for various IPC messages, including plugins.
@@ -473,7 +474,7 @@ class RenderWidgetHost : public IPC::Channel::Listener,
 
   // IPC message handlers
   void OnMsgRenderViewReady();
-  void OnMsgRenderViewGone();
+  void OnMsgRenderViewGone(int status, int error_code);
   void OnMsgClose();
   void OnMsgRequestMove(const gfx::Rect& pos);
   void OnMsgPaintAtSizeAck(int tag, const gfx::Size& size);
diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc
index 72495d3fb9cd5c1384ecf71d98f9fbb2ea3072ed..758a5bd714916e5a8887f44bbaafaf0b8bf4f9e4 100644
--- a/chrome/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chrome/browser/renderer_host/render_widget_host_unittest.cc
@@ -397,7 +397,7 @@ TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
   // resize ack logic is cleared.  Must clear the view first so it doesn't get
   // deleted.
   host_->set_view(NULL);
-  host_->RendererExited();
+  host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
   EXPECT_FALSE(host_->resize_ack_pending_);
   EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
 
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h
index af6300e5cda2019bd3e1da32e29b011e9f7cd64f..14cf129cdc0996c5e6b5a9c0a1107e8f49d38881 100644
--- a/chrome/browser/renderer_host/render_widget_host_view.h
+++ b/chrome/browser/renderer_host/render_widget_host_view.h
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "app/surface/transport_dib.h"
+#include "base/process_util.h"
 #include "gfx/native_widget_types.h"
 #include "gfx/rect.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -152,7 +153,8 @@ class RenderWidgetHostView {
       const std::vector<gfx::Rect>& copy_rects) = 0;
 
   // Notifies the View that the renderer has ceased to exist.
-  virtual void RenderViewGone() = 0;
+  virtual void RenderViewGone(base::TerminationStatus status,
+                              int error_code) = 0;
 
   // Notifies the View that the renderer will be delete soon.
   virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) = 0;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index 78b26e2ac7c9ee08fc4fa6ef3dd19c4398161697..cf3418a28943fb35fa878ccaaa915e5b3f283c8f 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -681,7 +681,8 @@ void RenderWidgetHostViewGtk::DidUpdateBackingStore(
   }
 }
 
-void RenderWidgetHostViewGtk::RenderViewGone() {
+void RenderWidgetHostViewGtk::RenderViewGone(base::TerminationStatus status,
+                                             int error_code) {
   Destroy();
   plugin_container_manager_.set_host_widget(NULL);
 }
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
index cd89ddbc6a654a868d68dd850a46321ca79a4f9c..7af66f8527dcd0facdb444a41b69d9fdcc2c904c 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
@@ -77,7 +77,8 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView,
   virtual void DidUpdateBackingStore(
       const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
       const std::vector<gfx::Rect>& copy_rects);
-  virtual void RenderViewGone();
+  virtual void RenderViewGone(base::TerminationStatus status,
+                              int error_code);
   virtual void Destroy();
   virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {}
   virtual void SetTooltipText(const std::wstring& tooltip_text);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index f4dfd25ea5187ee846c1f9f06452607f52406649..46efeeedf74c981311eb0cc52cf76889b5935baf 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -200,7 +200,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
   virtual void DidUpdateBackingStore(
       const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
       const std::vector<gfx::Rect>& copy_rects);
-  virtual void RenderViewGone();
+  virtual void RenderViewGone(base::TerminationStatus status,
+                              int error_code);
   virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {};
   virtual void Destroy();
   virtual void SetTooltipText(const std::wstring& tooltip_text);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index f88025eb7e30d4bb8484fe0e10c2836bd1cf0fd8..842bf9aeefd2c0c4a4271d6da2bea2ac845ba9ff 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -794,7 +794,8 @@ void RenderWidgetHostViewMac::DidUpdateBackingStore(
     HandleDelayedGpuViewHiding();
 }
 
-void RenderWidgetHostViewMac::RenderViewGone() {
+void RenderWidgetHostViewMac::RenderViewGone(base::TerminationStatus status,
+                                             int error_code) {
   // TODO(darin): keep this around, and draw sad-tab into it.
   UpdateCursorIfOverSelf();
   Destroy();
diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.cc b/chrome/browser/renderer_host/render_widget_host_view_views.cc
index cdc2e380cca979debad8e2e46c09482ffe9860d9..ea808f0f6871ba547312aadfed6b6c196d2a7909 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_views.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_views.cc
@@ -131,7 +131,8 @@ RenderWidgetHostViewViews::RenderWidgetHostViewViews(RenderWidgetHost* host)
 }
 
 RenderWidgetHostViewViews::~RenderWidgetHostViewViews() {
-  RenderViewGone();
+  RenderViewGone(base::TERMINATION_STATUS_NORMAL_TERMINATION,
+                 ResultCodes::NORMAL_EXIT);
 }
 
 void RenderWidgetHostViewViews::InitAsChild() {
@@ -286,7 +287,8 @@ void RenderWidgetHostViewViews::DidUpdateBackingStore(
   }
 }
 
-void RenderWidgetHostViewViews::RenderViewGone() {
+void RenderWidgetHostViewViews::RenderViewGone(base::TerminationStatus status,
+                                               int error_code) {
   GetRenderWidgetHost()->ViewDestroyed();
   Destroy();
 }
diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.h b/chrome/browser/renderer_host/render_widget_host_view_views.h
index a9a918f9e36b24fafd58b34afcb40b9512809ebb..9c5c8cb0465301f92e18b15df7f69ff7ab38d908 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_views.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_views.h
@@ -60,7 +60,8 @@ class RenderWidgetHostViewViews : public RenderWidgetHostView,
   virtual void DidUpdateBackingStore(
       const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
       const std::vector<gfx::Rect>& copy_rects);
-  virtual void RenderViewGone();
+  virtual void RenderViewGone(base::TerminationStatus status,
+                              int error_code);
   virtual void Destroy();
   virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {}
   virtual void SetTooltipText(const std::wstring& tooltip_text);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index a6657947449df54cbe78052f10b7f9bce12997f7..f5afe70cfecd3e929f324f5e4e8a62d0b34600d6 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -722,7 +722,8 @@ void RenderWidgetHostViewWin::DidUpdateBackingStore(
     Redraw();
 }
 
-void RenderWidgetHostViewWin::RenderViewGone() {
+void RenderWidgetHostViewWin::RenderViewGone(base::TerminationStatus status,
+                                             int error_code) {
   // TODO(darin): keep this around, and draw sad-tab into it.
   UpdateCursorIfOverSelf();
   being_destroyed_ = true;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h
index 282dfe95747538d59879732167641bb2099f9cec..1f6781421b199a9f4da3fcaaf961b6b9688627ec 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.h
@@ -148,7 +148,8 @@ class RenderWidgetHostViewWin
   virtual void DidUpdateBackingStore(
       const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
       const std::vector<gfx::Rect>& copy_rects);
-  virtual void RenderViewGone();
+  virtual void RenderViewGone(base::TerminationStatus status,
+                              int error_code);
   virtual void WillWmDestroy();  // called by TabContents before DestroyWindow
   virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh);
   virtual void Destroy();
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h
index a2ff8f7f50950204309bc0e3b5b38294578f87b2..7aa9638d8f872f8964d5b178193df174310c36e4 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.h
+++ b/chrome/browser/renderer_host/test/test_render_view_host.h
@@ -83,7 +83,8 @@ class TestRenderWidgetHostView : public RenderWidgetHostView {
   virtual void DidUpdateBackingStore(
       const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
       const std::vector<gfx::Rect>& rects) {}
-  virtual void RenderViewGone() { delete this; }
+  virtual void RenderViewGone(base::TerminationStatus status,
+                              int error_code) { delete this; }
   virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) { }
   virtual void Destroy() {}
   virtual void PrepareToDestroy() {}
diff --git a/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc b/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc
index 06ce085c40015179a67a5e132622e828d75a6206..3681c7001e22e650971a36e1b1a0ad7c4cfa550f 100644
--- a/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc
+++ b/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/renderer_host/web_cache_manager.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/common/result_codes.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -33,7 +34,7 @@ IN_PROC_BROWSER_TEST_F(WebCacheManagerBrowserTest, FLAKY_CrashOnceOnly) {
   TabContents* tab = browser()->GetTabContentsAt(0);
   ASSERT_TRUE(tab != NULL);
   base::KillProcess(tab->GetRenderProcessHost()->GetHandle(),
-                    base::PROCESS_END_KILLED_BY_USER, true);
+                    ResultCodes::KILLED, true);
 
   browser()->SelectTabContentsAt(0, true);
   browser()->NewTab();
diff --git a/chrome/browser/tab_contents/interstitial_page.cc b/chrome/browser/tab_contents/interstitial_page.cc
index d3c04298ad7a50b09cd0844ec4a639c807d4dfb3..bc9920b738c3eccacdc2af118c76393402b35b48 100644
--- a/chrome/browser/tab_contents/interstitial_page.cc
+++ b/chrome/browser/tab_contents/interstitial_page.cc
@@ -333,7 +333,9 @@ const GURL& InterstitialPage::GetURL() const {
   return url_;
 }
 
-void InterstitialPage::RenderViewGone(RenderViewHost* render_view_host) {
+void InterstitialPage::RenderViewGone(RenderViewHost* render_view_host,
+                                      base::TerminationStatus status,
+                                      int error_code) {
   // Our renderer died. This should not happen in normal cases.
   // Just dismiss the interstitial.
   DontProceed();
diff --git a/chrome/browser/tab_contents/interstitial_page.h b/chrome/browser/tab_contents/interstitial_page.h
index 50ede04443e8e8e4334d74c53b7ab07993e3e6e0..2faad773eda85e3e3f894332dd03a98da7298386 100644
--- a/chrome/browser/tab_contents/interstitial_page.h
+++ b/chrome/browser/tab_contents/interstitial_page.h
@@ -9,6 +9,7 @@
 #include <map>
 #include <string>
 
+#include "base/process_util.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
 #include "chrome/common/notification_observer.h"
@@ -124,7 +125,9 @@ class InterstitialPage : public NotificationObserver,
   // RenderViewHostDelegate implementation:
   virtual View* GetViewDelegate();
   virtual const GURL& GetURL() const;
-  virtual void RenderViewGone(RenderViewHost* render_view_host);
+  virtual void RenderViewGone(RenderViewHost* render_view_host,
+                              base::TerminationStatus status,
+                              int error_code);
   virtual void DidNavigate(RenderViewHost* render_view_host,
                            const ViewHostMsg_FrameNavigate_Params& params);
   virtual void UpdateTitle(RenderViewHost* render_view_host,
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 34ec8923ebe4eb9d6ed03c99f62a91d245e7d5d8..f95634f987a4a56b5e345d1ae49049cdc27f80f2 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -336,7 +336,8 @@ TabContents::TabContents(Profile* profile,
       bookmark_drag_(NULL),
       ALLOW_THIS_IN_INITIALIZER_LIST(fav_icon_helper_(this)),
       is_loading_(false),
-      is_crashed_(false),
+      crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
+      crashed_error_code_(0),
       waiting_for_response_(false),
       max_page_id_(-1),
       current_load_start_(),
@@ -767,11 +768,12 @@ void TabContents::RemoveNavigationObserver(WebNavigationObserver* observer) {
   web_navigation_observers_.RemoveObserver(observer);
 }
 
-void TabContents::SetIsCrashed(bool state) {
-  if (state == is_crashed_)
+void TabContents::SetIsCrashed(base::TerminationStatus status, int error_code) {
+  if (status == crashed_status_)
     return;
 
-  is_crashed_ = state;
+  crashed_status_ = status;
+  crashed_error_code_ = error_code;
   NotifyNavigationStateChanged(INVALIDATE_TAB);
 }
 
@@ -2423,7 +2425,7 @@ void TabContents::RenderViewReady(RenderViewHost* rvh) {
 
   NotifyConnected();
   bool was_crashed = is_crashed();
-  SetIsCrashed(false);
+  SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0);
 
   // Restore the focus to the tab (otherwise the focus will be on the top
   // window).
@@ -2433,7 +2435,9 @@ void TabContents::RenderViewReady(RenderViewHost* rvh) {
   }
 }
 
-void TabContents::RenderViewGone(RenderViewHost* rvh) {
+void TabContents::RenderViewGone(RenderViewHost* rvh,
+                                 base::TerminationStatus status,
+                                 int error_code) {
   // Ask the print preview if this renderer was valuable.
   if (!printing_->OnRenderViewGone(rvh))
     return;
@@ -2444,7 +2448,7 @@ void TabContents::RenderViewGone(RenderViewHost* rvh) {
 
   SetIsLoading(false, NULL);
   NotifyDisconnected();
-  SetIsCrashed(true);
+  SetIsCrashed(status, error_code);
 
   // Remove all infobars.
   for (int i = infobar_delegate_count() - 1; i >=0 ; --i)
@@ -3087,7 +3091,8 @@ void TabContents::DidStartLoadingFromRenderManager(
 
 void TabContents::RenderViewGoneFromRenderManager(
     RenderViewHost* render_view_host) {
-  RenderViewGone(render_view_host);
+  DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING);
+  RenderViewGone(render_view_host, crashed_status_, crashed_error_code_);
 }
 
 void TabContents::UpdateRenderViewSizeForRenderManager() {
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 122380a7b66ef8cfcbf9290d77d364b14ee0d07f..7800ee9c968463a4cd10b0db3541fd135a59cb6d 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -308,8 +308,14 @@ class TabContents : public PageNavigator,
 
   // Indicates whether this tab should be considered crashed. The setter will
   // also notify the delegate when the flag is changed.
-  bool is_crashed() const { return is_crashed_; }
-  void SetIsCrashed(bool state);
+  bool is_crashed() const {
+    return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
+            crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
+            crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
+  }
+  base::TerminationStatus crashed_status() const { return crashed_status_; }
+  int crashed_error_code() const { return crashed_error_code_; }
+  void SetIsCrashed(base::TerminationStatus status, int error_code);
 
   // Call this after updating a page action to notify clients about the changes.
   void PageActionStateChanged();
@@ -958,7 +964,9 @@ class TabContents : public PageNavigator,
   virtual int GetBrowserWindowID() const;
   virtual void RenderViewCreated(RenderViewHost* render_view_host);
   virtual void RenderViewReady(RenderViewHost* render_view_host);
-  virtual void RenderViewGone(RenderViewHost* render_view_host);
+  virtual void RenderViewGone(RenderViewHost* render_view_host,
+                              base::TerminationStatus status,
+                              int error_code);
   virtual void RenderViewDeleted(RenderViewHost* render_view_host);
   virtual void DidNavigate(RenderViewHost* render_view_host,
                            const ViewHostMsg_FrameNavigate_Params& params);
@@ -1146,7 +1154,8 @@ class TabContents : public PageNavigator,
   bool is_loading_;
 
   // Indicates if the tab is considered crashed.
-  bool is_crashed_;
+  base::TerminationStatus crashed_status_;
+  int crashed_error_code_;
 
   // See waiting_for_response() above.
   bool waiting_for_response_;
diff --git a/chrome/browser/tab_contents/web_contents_unittest.cc b/chrome/browser/tab_contents/web_contents_unittest.cc
index abb1578ccf0f678384057886c6cfa55ad780ee27..67d93a376eea9b068c67fdf8bd4768586f14494e 100644
--- a/chrome/browser/tab_contents/web_contents_unittest.cc
+++ b/chrome/browser/tab_contents/web_contents_unittest.cc
@@ -120,8 +120,8 @@ class TestInterstitialPage : public InterstitialPage {
     DidNavigate(render_view_host(), params);
   }
 
-  void TestRenderViewGone() {
-    RenderViewGone(render_view_host());
+  void TestRenderViewGone(base::TerminationStatus status, int error_code) {
+    RenderViewGone(render_view_host(), status, error_code);
   }
 
   bool is_showing() const {
@@ -1151,7 +1151,9 @@ TEST_F(TabContentsTest, ShowInterstitialCrashRendererThenGoBack) {
   interstitial->TestDidNavigate(2, interstitial_url);
 
   // Crash the renderer
-  rvh()->TestOnMessageReceived(ViewHostMsg_RenderViewGone(0));
+  rvh()->TestOnMessageReceived(
+      ViewHostMsg_RenderViewGone(
+          0, base::TERMINATION_STATUS_PROCESS_CRASHED, -1));
 
   // While the interstitial is showing, go back.
   controller().GoBack();
@@ -1186,7 +1188,9 @@ TEST_F(TabContentsTest, ShowInterstitialCrashRendererThenNavigate) {
   interstitial->Show();
 
   // Crash the renderer
-  rvh()->TestOnMessageReceived(ViewHostMsg_RenderViewGone(0));
+  rvh()->TestOnMessageReceived(
+      ViewHostMsg_RenderViewGone(
+          0, base::TERMINATION_STATUS_PROCESS_CRASHED, -1));
 
   interstitial->TestDidNavigate(2, interstitial_url);
 }
@@ -1429,7 +1433,8 @@ TEST_F(TabContentsTest, InterstitialCrasher) {
   TestInterstitialPageStateGuard state_guard(interstitial);
   interstitial->Show();
   // Simulate a renderer crash before the interstitial is shown.
-  interstitial->TestRenderViewGone();
+  interstitial->TestRenderViewGone(
+      base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
   // The interstitial should have been dismissed.
   EXPECT_TRUE(deleted);
   EXPECT_EQ(TestInterstitialPage::CANCELED, state);
@@ -1440,7 +1445,8 @@ TEST_F(TabContentsTest, InterstitialCrasher) {
   interstitial->Show();
   interstitial->TestDidNavigate(1, url);
   // Simulate a renderer crash.
-  interstitial->TestRenderViewGone();
+  interstitial->TestRenderViewGone(
+      base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
   // The interstitial should have been dismissed.
   EXPECT_TRUE(deleted);
   EXPECT_EQ(TestInterstitialPage::CANCELED, state);
diff --git a/chrome/browser/task_manager/task_manager.cc b/chrome/browser/task_manager/task_manager.cc
index 2dc5029e16e3444fe565b4139a056b7a93bbd771..da19fda767b19d2d42c27cddd37a23a62efeb84d 100644
--- a/chrome/browser/task_manager/task_manager.cc
+++ b/chrome/browser/task_manager/task_manager.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/task_manager/task_manager_resource_providers.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/result_codes.h"
 #include "chrome/common/url_constants.h"
 #include "grit/app_resources.h"
 #include "grit/chromium_strings.h"
@@ -944,7 +945,7 @@ void TaskManager::KillProcess(int index) {
   base::ProcessHandle process = model_->GetResourceProcessHandle(index);
   DCHECK(process);
   if (process != base::GetCurrentProcessHandle())
-    base::KillProcess(process, base::PROCESS_END_KILLED_BY_USER, false);
+    base::KillProcess(process, ResultCodes::KILLED, false);
 }
 
 void TaskManager::ActivateProcess(int index) {
diff --git a/chrome/browser/utility_process_host.cc b/chrome/browser/utility_process_host.cc
index 1756d3e06e536f39b7b4271d623fdefe4ca241d2..b8d6a77dca8e75b04a1d0d312e600ab3056cee5b 100644
--- a/chrome/browser/utility_process_host.cc
+++ b/chrome/browser/utility_process_host.cc
@@ -159,10 +159,10 @@ void UtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
       NewRunnableMethod(client_.get(), &Client::OnMessageReceived, message));
 }
 
-void UtilityProcessHost::OnProcessCrashed() {
+void UtilityProcessHost::OnProcessCrashed(int exit_code) {
   BrowserThread::PostTask(
       client_thread_id_, FROM_HERE,
-      NewRunnableMethod(client_.get(), &Client::OnProcessCrashed));
+      NewRunnableMethod(client_.get(), &Client::OnProcessCrashed, exit_code));
 }
 
 bool UtilityProcessHost::CanShutdown() {
diff --git a/chrome/browser/utility_process_host.h b/chrome/browser/utility_process_host.h
index 559f39e638aac8fe9fa0983935014464df174c35..96879a8db55991a6d24fa9a9af0fa88af47bb030 100644
--- a/chrome/browser/utility_process_host.h
+++ b/chrome/browser/utility_process_host.h
@@ -39,7 +39,7 @@ class UtilityProcessHost : public BrowserChildProcessHost {
     Client() {}
 
     // Called when the process has crashed.
-    virtual void OnProcessCrashed() {}
+    virtual void OnProcessCrashed(int exit_code) {}
 
     // Called when the extension has unpacked successfully.  |manifest| is the
     // parsed manifest.json file.  |catalogs| contains list of all parsed
@@ -153,7 +153,7 @@ class UtilityProcessHost : public BrowserChildProcessHost {
   virtual void OnMessageReceived(const IPC::Message& message);
 
   // BrowserChildProcessHost:
-  virtual void OnProcessCrashed();
+  virtual void OnProcessCrashed(int exit_code);
   virtual bool CanShutdown();
   virtual URLRequestContext* GetRequestContext(
       uint32 request_id,
diff --git a/chrome/browser/web_resource/web_resource_service.cc b/chrome/browser/web_resource/web_resource_service.cc
index ab557f5301867e8c0106e7693867c68d5defd9a5..e1de48ab13069c814b2ffd385341b96ba6d9a5fc 100644
--- a/chrome/browser/web_resource/web_resource_service.cc
+++ b/chrome/browser/web_resource/web_resource_service.cc
@@ -157,7 +157,7 @@ class WebResourceService::UnpackerClient
   ~UnpackerClient() {}
 
   // UtilityProcessHost::Client
-  virtual void OnProcessCrashed() {
+  virtual void OnProcessCrashed(int exit_code) {
     if (got_response_)
       return;
 
diff --git a/chrome/browser/zygote_host_linux.cc b/chrome/browser/zygote_host_linux.cc
index 74b68529700229315a599a02bf1c4135a44e506d..e4e7ce3da4f8f4570b79777ab34465e696af494b 100644
--- a/chrome/browser/zygote_host_linux.cc
+++ b/chrome/browser/zygote_host_linux.cc
@@ -27,6 +27,7 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/process_watcher.h"
+#include "chrome/common/result_codes.h"
 
 #include "sandbox/linux/suid/suid_unsafe_environment_variables.h"
 
@@ -316,13 +317,18 @@ void ZygoteHost::EnsureProcessTerminated(pid_t process) {
     PLOG(ERROR) << "write";
 }
 
-bool ZygoteHost::DidProcessCrash(base::ProcessHandle handle,
-                                 bool* child_exited) {
+base::TerminationStatus ZygoteHost::GetTerminationStatus(
+    base::ProcessHandle handle,
+    int* exit_code) {
   DCHECK(init_);
   Pickle pickle;
-  pickle.WriteInt(kCmdDidProcessCrash);
+  pickle.WriteInt(kCmdGetTerminationStatus);
   pickle.WriteInt(handle);
 
+  // Set this now to handle the early termination cases.
+  if (exit_code)
+    *exit_code = ResultCodes::NORMAL_EXIT;
+
   static const unsigned kMaxMessageLength = 128;
   char buf[kMaxMessageLength];
   ssize_t len;
@@ -336,23 +342,23 @@ bool ZygoteHost::DidProcessCrash(base::ProcessHandle handle,
 
   if (len == -1) {
     LOG(WARNING) << "Error reading message from zygote: " << errno;
-    return false;
+    return base::TERMINATION_STATUS_NORMAL_TERMINATION;
   } else if (len == 0) {
     LOG(WARNING) << "Socket closed prematurely.";
-    return false;
+    return base::TERMINATION_STATUS_NORMAL_TERMINATION;
   }
 
   Pickle read_pickle(buf, len);
-  bool did_crash, tmp_child_exited;
+  int status, tmp_exit_code;
   void* iter = NULL;
-  if (!read_pickle.ReadBool(&iter, &did_crash) ||
-      !read_pickle.ReadBool(&iter, &tmp_child_exited)) {
-    LOG(WARNING) << "Error parsing DidProcessCrash response from zygote.";
-    return false;
+  if (!read_pickle.ReadInt(&iter, &status) ||
+      !read_pickle.ReadInt(&iter, &tmp_exit_code)) {
+    LOG(WARNING) << "Error parsing GetTerminationStatus response from zygote.";
+    return base::TERMINATION_STATUS_NORMAL_TERMINATION;
   }
 
-  if (child_exited)
-    *child_exited = tmp_child_exited;
+  if (exit_code)
+    *exit_code = tmp_exit_code;
 
-  return did_crash;
+  return static_cast<base::TerminationStatus>(status);
 }
diff --git a/chrome/browser/zygote_host_linux.h b/chrome/browser/zygote_host_linux.h
index 01a64435cf86ead1be5800da5d838ec80b75b693..e13f1b4627dec5baf8594a8cc813a82e95905b60 100644
--- a/chrome/browser/zygote_host_linux.h
+++ b/chrome/browser/zygote_host_linux.h
@@ -14,6 +14,7 @@
 #include "base/global_descriptors_posix.h"
 #include "base/lock.h"
 #include "base/process.h"
+#include "base/process_util.h"
 
 template<typename Type>
 struct DefaultSingletonTraits;
@@ -37,26 +38,27 @@ class ZygoteHost {
                      const base::GlobalDescriptors::Mapping& mapping);
   void EnsureProcessTerminated(pid_t process);
 
-  // Get the termination status (exit code) of the process and return true if
-  // the status indicates the process crashed. |child_exited| is set to true
-  // iff the child process has terminated. (|child_exited| may be NULL.)
-  bool DidProcessCrash(base::ProcessHandle handle, bool* child_exited);
+  // Get the termination status (and, optionally, the exit code) of
+  // the process. |exit_code| is set to the exit code of the child
+  // process. (|exit_code| may be NULL.)
+  base::TerminationStatus GetTerminationStatus(base::ProcessHandle handle,
+                                               int* exit_code);
 
   // These are the command codes used on the wire between the browser and the
   // zygote.
   enum {
-    kCmdFork = 0,             // Fork off a new renderer.
-    kCmdReap = 1,             // Reap a renderer child.
-    kCmdDidProcessCrash = 2,  // Check if child process crashed.
-    kCmdGetSandboxStatus = 3, // Read a bitmask of kSandbox*
+    kCmdFork = 0,                  // Fork off a new renderer.
+    kCmdReap = 1,                  // Reap a renderer child.
+    kCmdGetTerminationStatus = 2,  // Check what happend to a child process.
+    kCmdGetSandboxStatus = 3,      // Read a bitmask of kSandbox*
   };
 
   // These form a bitmask which describes the conditions of the sandbox that
   // the zygote finds itself in.
   enum {
-    kSandboxSUID = 1 << 0,  // SUID sandbox active
-    kSandboxPIDNS = 1 << 1,  // SUID sandbox is using the PID namespace
-    kSandboxNetNS = 1 << 2,  // SUID sandbox is using the network namespace
+    kSandboxSUID = 1 << 0,     // SUID sandbox active
+    kSandboxPIDNS = 1 << 1,    // SUID sandbox is using the PID namespace
+    kSandboxNetNS = 1 << 2,    // SUID sandbox is using the network namespace
     kSandboxSeccomp = 1 << 3,  // seccomp sandbox active.
   };
 
diff --git a/chrome/browser/zygote_main_linux.cc b/chrome/browser/zygote_main_linux.cc
index 5943d11097d12cef3c3c3c27719afb53db02f615..1b26a6b4980b145bae224042aa18404d1bbdecee 100644
--- a/chrome/browser/zygote_main_linux.cc
+++ b/chrome/browser/zygote_main_linux.cc
@@ -41,6 +41,7 @@
 #include "chrome/common/main_function_params.h"
 #include "chrome/common/pepper_plugin_registry.h"
 #include "chrome/common/process_watcher.h"
+#include "chrome/common/result_codes.h"
 #include "chrome/common/sandbox_methods_linux.h"
 
 #include "media/base/media.h"
@@ -167,10 +168,10 @@ class Zygote {
             break;
           HandleReapRequest(fd, pickle, iter);
           return false;
-        case ZygoteHost::kCmdDidProcessCrash:
+        case ZygoteHost::kCmdGetTerminationStatus:
           if (!fds.empty())
             break;
-          HandleDidProcessCrash(fd, pickle, iter);
+          HandleGetTerminationStatus(fd, pickle, iter);
           return false;
         case ZygoteHost::kCmdGetSandboxStatus:
           HandleGetSandboxStatus(fd, pickle, iter);
@@ -209,26 +210,31 @@ class Zygote {
     ProcessWatcher::EnsureProcessTerminated(actual_child);
   }
 
-  void HandleDidProcessCrash(int fd, const Pickle& pickle, void* iter) {
+  void HandleGetTerminationStatus(int fd, const Pickle& pickle, void* iter) {
     base::ProcessHandle child;
 
     if (!pickle.ReadInt(&iter, &child)) {
-      LOG(WARNING) << "Error parsing DidProcessCrash request from browser";
+      LOG(WARNING) << "Error parsing GetTerminationStatus request "
+                   << "from browser";
       return;
     }
 
-    bool child_exited;
-    bool did_crash;
+    base::TerminationStatus status;
+    int exit_code;
     if (g_suid_sandbox_active)
       child = real_pids_to_sandbox_pids[child];
-    if (child)
-      did_crash = base::DidProcessCrash(&child_exited, child);
-    else
-      did_crash = child_exited = false;
+    if (child) {
+      status = base::GetTerminationStatus(child, &exit_code);
+    } else {
+      // Assume that if we can't find the child in the sandbox, then
+      // it terminated normally.
+      status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
+      exit_code = ResultCodes::NORMAL_EXIT;
+    }
 
     Pickle write_pickle;
-    write_pickle.WriteBool(did_crash);
-    write_pickle.WriteBool(child_exited);
+    write_pickle.WriteInt(static_cast<int>(status));
+    write_pickle.WriteInt(exit_code);
     if (HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())) !=
         write_pickle.size()) {
       PLOG(ERROR) << "write";
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 5bd1e96c3b9db2d75451f6d79cb46fddd1864287..2ea5c9a7f15672a18a59407ce912ff8fc43412c5 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -549,12 +549,20 @@ class NotificationType {
     // The details are in a Details<ChildProcessInfo>.
     CHILD_PROCESS_HOST_DISCONNECTED,
 
-    // This message is sent when a child process disappears unexpectedly.
-    // There is no usable source, since it is sent from an ephemeral task;
-    // register for AllSources() to receive this notification.  The details are
-    // in a Details<ChildProcessInfo>.
+    // This message is sent when a child process disappears
+    // unexpectedly as a result of a crash.  There is no usable
+    // source, since it is sent from an ephemeral task; register for
+    // AllSources() to receive this notification.  The details are in
+    // a Details<ChildProcessInfo>.
     CHILD_PROCESS_CRASHED,
 
+    // This message is sent when a child process disappears
+    // unexpectedly as a result of a termination signal.  There is no
+    // usable source, since it is sent from an ephemeral task;
+    // register for AllSources() to receive this notification.  The
+    // details are in a Details<ChildProcessInfo>.
+    CHILD_PROCESS_WAS_KILLED,
+
     // This message indicates that an instance of a particular child was
     // created in a page.  (If one page contains several regions rendered by
     // the same child, this notification will occur once for each region
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 304dcae42cbe9e881f521a33fcfeb29c69e9e55a..2479c5a7a0a156a47ae045174cea99f8dc3882bf 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1138,9 +1138,12 @@ IPC_MESSAGE_CONTROL1(ViewHostMsg_UpdatedCacheStats,
 // a ViewMsg_CreatingNew_ACK.
 IPC_MESSAGE_ROUTED0(ViewHostMsg_RenderViewReady)
 
+
 // Indicates the renderer process is gone.  This actually is sent by the
 // browser process to itself, but keeps the interface cleaner.
-IPC_MESSAGE_ROUTED0(ViewHostMsg_RenderViewGone)
+IPC_MESSAGE_ROUTED2(ViewHostMsg_RenderViewGone,
+                    int, /* this really is base::TerminationStatus */
+                    int /* exit_code */)
 
 // Sent by the renderer process to request that the browser close the view.
 // This corresponds to the window.close() API, and the browser may ignore
diff --git a/chrome/common/result_codes.h b/chrome/common/result_codes.h
index 38fe54df7d343964330f3f4da218a2f36fc5ee67..ae842bbb0a63676c5b75125753066ce78076c50a 100644
--- a/chrome/common/result_codes.h
+++ b/chrome/common/result_codes.h
@@ -21,9 +21,9 @@
 class ResultCodes {
  public:
   enum ExitCode {
-    NORMAL_EXIT = base::PROCESS_END_NORMAL_TERMINATION,
-    TASKMAN_KILL = base::PROCESS_END_KILLED_BY_USER,
-    HUNG = base::PROCESS_END_PROCESS_WAS_HUNG,
+    NORMAL_EXIT = 0,            // Process terminated normally.
+    KILLED = 1,                 // Process was killed by user or system.
+    HUNG = 2,                   // Process hung.
     INVALID_CMDLINE_URL,        // An invalid command line url was given.
     SBOX_INIT_FAILED,           // The sandbox could not be initialized.
     GOOGLE_UPDATE_INIT_FAILED,  // The Google Update client stub init failed.
diff --git a/chrome/test/chrome_process_util.cc b/chrome/test/chrome_process_util.cc
index 11228e2004fd4fb4e588a0193241f4ddb3c1f155..7de99084b4ae82e6c7871ebf430fe65a4a60f96a 100644
--- a/chrome/test/chrome_process_util.cc
+++ b/chrome/test/chrome_process_util.cc
@@ -27,7 +27,7 @@ void TerminateAllChromeProcesses(base::ProcessId browser_pid) {
       continue;
     }
 
-    base::KillProcess(handle, ResultCodes::TASKMAN_KILL, true);
+    base::KillProcess(handle, ResultCodes::KILLED, true);
     base::CloseProcessHandle(handle);
   }
 }
@@ -117,4 +117,3 @@ ChromeTestProcessMetrics::ChromeTestProcessMetrics(
 #endif
   process_handle_ = process;
 }
-