15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/child_process_launcher.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>  // For std::pair.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/scoped_file.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
1658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/content_browser_client.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_descriptors.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/result_codes.h"
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/common/sandboxed_process_launcher_delegate.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/sandbox_win.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/sandbox_init.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/browser/bootstrap_sandbox_mac.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/mach_broker_mac.h"
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "sandbox/mac/bootstrap_sandbox.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/jni_android.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/android/child_process_launcher_android.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/memory/shared_memory.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_sandbox_host_linux.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/zygote_host/zygote_host_impl_linux.h"
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/common/child_process_sandbox_support_impl_linux.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/metrics/stats_table.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/posix/global_descriptors.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Having the functionality of ChildProcessLauncher be in an internal
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ref counted object allows us to automatically terminate the process when the
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parent class destructs, while still holding on to state that we need.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChildProcessLauncher::Context
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCountedThreadSafe<ChildProcessLauncher::Context> {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Context()
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : client_(NULL),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        client_thread_id_(BrowserThread::UI),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exit_code_(RESULT_CODE_NORMAL_EXIT),
63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        starting_(true),
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        // TODO(earthdok): Re-enable on CrOS http://crbug.com/360622
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if (defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    defined(THREAD_SANITIZER)) && !defined(OS_CHROMEOS)
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        terminate_child_on_shutdown_(false)
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#else
69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        terminate_child_on_shutdown_(true)
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        , zygote_(false)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Launch(
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SandboxedProcessLauncherDelegate* delegate,
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::CommandLine* cmd_line,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int child_process_id,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Client* client) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_ = client;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to close the client end of the IPC channel to reliably detect
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // child termination. We will close this fd after we create the child
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // process which is asynchronous on Android.
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ipcfd_ = delegate->GetIpcFd();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            &Context::LaunchInternal,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            make_scoped_refptr(this),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            client_thread_id_,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            child_process_id,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            delegate,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            cmd_line));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void OnChildProcessStarted(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |this_object| is NOT thread safe. Only use it to post a task back.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<Context> this_object,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::ID client_thread_id,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::TimeTicks begin_launch_time,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ProcessHandle handle) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RecordHistograms(begin_launch_time);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (BrowserThread::CurrentlyOn(client_thread_id)) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is always invoked on the UI thread which is commonly the
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |client_thread_id| so we can shortcut one PostTask.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this_object->Notify(handle);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::PostTask(
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          client_thread_id, FROM_HERE,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &ChildProcessLauncher::Context::Notify,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              this_object,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              handle));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetClient() {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No need for locking as this function gets called on the same thread that
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // client_ would be used.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(BrowserThread::CurrentlyOn(client_thread_id_));
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_ = NULL;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_terminate_child_on_shutdown(bool terminate_on_shutdown) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    terminate_child_on_shutdown_ = terminate_on_shutdown;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class ChildProcessLauncher;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Context() {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Terminate();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void RecordHistograms(const base::TimeTicks begin_launch_time) {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER)) {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RecordLaunchHistograms(launch_time);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::PostTask(
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&ChildProcessLauncher::Context::RecordLaunchHistograms,
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     launch_time));
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void RecordLaunchHistograms(const base::TimeDelta launch_time) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Log the launch time, separating out the first one (which will likely be
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // slower due to the rest of the browser initializing at the same time).
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static bool done_first_launch = false;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (done_first_launch) {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchFirst", launch_time);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      done_first_launch = true;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void LaunchInternal(
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |this_object| is NOT thread safe. Only use it to post a task back.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<Context> this_object,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::ID client_thread_id,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int child_process_id,
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SandboxedProcessLauncherDelegate* delegate,
1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::CommandLine* cmd_line) {
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN)
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool launch_elevated = delegate->ShouldLaunchElevated();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int ipcfd = delegate->GetIpcFd();
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_MACOSX)
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::EnvironmentMap env = delegate->GetEnvironment();
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int ipcfd = delegate->GetIpcFd();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool use_zygote = delegate->ShouldUseZygote();
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::EnvironmentMap env = delegate->GetEnvironment();
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int ipcfd = delegate->GetIpcFd();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<base::CommandLine> cmd_line_deleter(cmd_line);
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeTicks begin_launch_time = base::TimeTicks::Now();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ProcessHandle handle = base::kNullProcessHandle;
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (launch_elevated) {
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::LaunchOptions options;
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      options.start_hidden = true;
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::LaunchElevatedProcess(*cmd_line, options, &handle);
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      handle = StartSandboxedProcess(delegate, cmd_line);
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#elif defined(OS_POSIX)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string process_type =
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cmd_line->GetSwitchValueASCII(switches::kProcessType);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<FileDescriptorInfo> files_to_register;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    files_to_register.push_back(
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileDescriptorInfo(kPrimaryIPCChannel,
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           base::FileDescriptor(ipcfd, false)));
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::StatsTable* stats_table = base::StatsTable::current();
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (stats_table &&
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::SharedMemory::IsHandleValid(
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            stats_table->GetSharedMemoryHandle())) {
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      files_to_register.push_back(
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          FileDescriptorInfo(kStatsTableSharedMemFd,
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             stats_table->GetSharedMemoryHandle()));
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if defined(OS_ANDROID)
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Android WebView runs in single process, ensure that we never get here
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // when running in single process mode.
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetContentClient()->browser()->
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                &files_to_register);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2274ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    StartChildProcess(cmd_line->argv(), child_process_id, files_to_register,
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&ChildProcessLauncher::Context::OnChildProcessStarted,
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   this_object, client_thread_id, begin_launch_time));
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ProcessHandle handle = base::kNullProcessHandle;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to close the client end of the IPC channel to reliably detect
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // child termination.
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::ScopedFD ipcfd_closer(ipcfd);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetContentClient()->browser()->
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                &files_to_register);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_zygote) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(),
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          files_to_register,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          process_type);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Fall through to the normal posix case below when we're not zygoting.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Convert FD mapping to FileHandleMappingVector
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::FileHandleMappingVector fds_to_map;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < files_to_register.size(); ++i) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fds_to_map.push_back(std::make_pair(
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            files_to_register[i].fd.fd,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            files_to_register[i].id +
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                base::GlobalDescriptors::kBaseDescriptor));
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (process_type == switches::kRendererProcess) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const int sandbox_fd =
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fds_to_map.push_back(std::make_pair(
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sandbox_fd,
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            GetSandboxFD()));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Actually launch the app.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::LaunchOptions options;
27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      options.environ = env;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      options.fds_to_remap = &fds_to_map;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Hold the MachBroker lock for the duration of LaunchProcess. The child
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // will send its task port to the parent almost immediately after startup.
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // The Mach message will be delivered to the parent, but updating the
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // record of the launch will wait until after the placeholder PID is
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // inserted below. This ensures that while the child process may send its
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // port to the parent prior to the parent leaving LaunchProcess, the
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // order in which the record in MachBroker is updated is correct.
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      MachBroker* broker = MachBroker::GetInstance();
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      broker->GetLock().Acquire();
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Make sure the MachBroker is running, and inform it to expect a
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // check-in from the new process.
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      broker->EnsureRunning();
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      const int bootstrap_sandbox_policy = delegate->GetSandboxType();
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (ShouldEnableBootstrapSandbox() &&
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          bootstrap_sandbox_policy != SANDBOX_TYPE_INVALID) {
2916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        options.replacement_bootstrap_name =
2926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            GetBootstrapSandbox()->server_bootstrap_name();
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        GetBootstrapSandbox()->PrepareToForkWithPolicy(
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            bootstrap_sandbox_policy);
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool launched = base::LaunchProcess(*cmd_line, options, &handle);
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (!launched)
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        handle = base::kNullProcessHandle;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (ShouldEnableBootstrapSandbox() &&
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          bootstrap_sandbox_policy != SANDBOX_TYPE_INVALID) {
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        GetBootstrapSandbox()->FinishedFork(handle);
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (launched)
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        broker->AddPlaceholderForPid(handle);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // After updating the broker, release the lock and let the child's
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // messasge be processed on the broker's thread.
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      broker->GetLock().Release();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // else defined(OS_POSIX)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (handle)
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RecordHistograms(begin_launch_time);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_thread_id, FROM_HERE,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &Context::Notify,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this_object.get(),
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          use_zygote,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          handle));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_ANDROID)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Notify(
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool zygote,
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ProcessHandle handle) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Finally close the ipcfd
339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::ScopedFD ipcfd_closer(ipcfd_);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    starting_ = false;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process_.set_handle(handle);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!handle)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to launch child process";
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zygote_ = zygote;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (client_) {
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (handle) {
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        client_->OnProcessLaunched();
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        client_->OnProcessLaunchFailed();
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Terminate();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Terminate() {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!process_.handle())
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!terminate_child_on_shutdown_)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep!  So
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // don't this on the UI/IO threads.
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            &Context::TerminateInternal,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            zygote_,
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            process_.handle()));
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process_.set_handle(base::kNullProcessHandle);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void SetProcessBackgrounded(base::ProcessHandle handle,
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     bool background) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Process process(handle);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process.SetProcessBackgrounded(background);
384a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#if defined(OS_ANDROID)
385a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    SetChildProcessInForeground(handle, !background);
386a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#endif
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void TerminateInternal(
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool zygote,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ProcessHandle handle) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(0) << "ChromeProcess: Stopping process with handle " << handle;
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StopChildProcess(handle);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Process process(handle);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     // Client has gone away, so just kill the process.  Using exit code 0
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // means that UMA won't treat this as a crash.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process.Terminate(RESULT_CODE_NORMAL_EXIT);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On POSIX, we must additionally reap the child.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (zygote) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If the renderer was created via a zygote, we have to proxy the reaping
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // through the zygote process.
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(handle);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !OS_MACOSX
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::EnsureProcessTerminated(handle);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_POSIX
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process.Close();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_ANDROID)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Client* client_;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::ID client_thread_id_;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Process process_;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TerminationStatus termination_status_;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int exit_code_;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool starting_;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Controls whether the child process should be terminated on browser
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shutdown. Default behavior is to terminate the child.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool terminate_child_on_shutdown_;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The fd to close after creating the process.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ipcfd_;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) && !defined(OS_MACOSX)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool zygote_;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChildProcessLauncher::ChildProcessLauncher(
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SandboxedProcessLauncherDelegate* delegate,
4396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    base::CommandLine* cmd_line,
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int child_process_id,
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Client* client) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_ = new Context();
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_->Launch(
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delegate,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmd_line,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      child_process_id,
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChildProcessLauncher::~ChildProcessLauncher() {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_->ResetClient();
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChildProcessLauncher::IsStarting() {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context_->starting_;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle ChildProcessLauncher::GetHandle() {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!context_->starting_);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context_->process_.handle();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool known_dead,
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* exit_code) {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ProcessHandle handle = context_->process_.handle();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (handle == base::kNullProcessHandle) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Process is already gone, so return the cached termination status.
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (exit_code)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *exit_code = context_->exit_code_;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return context_->termination_status_;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context_->zygote_) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_->termination_status_ = ZygoteHostImpl::GetInstance()->
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetTerminationStatus(handle, known_dead, &context_->exit_code_);
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (known_dead) {
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    context_->termination_status_ =
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
480f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
481d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#elif defined(OS_MACOSX)
482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (known_dead) {
483d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    context_->termination_status_ =
484d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
485f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#elif defined(OS_ANDROID)
487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (IsChildProcessOomProtected(handle)) {
488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      context_->termination_status_ = base::TERMINATION_STATUS_OOM_PROTECTED;
489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#else
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_->termination_status_ =
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::GetTerminationStatus(handle, &context_->exit_code_);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exit_code)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *exit_code = context_->exit_code_;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // POSIX: If the process crashed, then the kernel closed the socket
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for it and so the child has already died by the time we get
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here. Since GetTerminationStatus called waitpid with WNOHANG,
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it'll reap the process.  However, if GetTerminationStatus didn't
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reap the child (because it was still running), we'll need to
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Terminate via ProcessWatcher. So we can't close the handle here.
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context_->termination_status_ != base::TERMINATION_STATUS_STILL_RUNNING)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_->process_.Close();
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context_->termination_status_;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcessLauncher::SetProcessBackgrounded(bool background) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     base::Bind(
5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         &ChildProcessLauncher::Context::SetProcessBackgrounded,
5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         GetHandle(), background));
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcessLauncher::SetTerminateChildOnShutdown(
521effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    bool terminate_on_shutdown) {
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (context_.get())
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_->set_terminate_child_on_shutdown(terminate_on_shutdown);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
527