| Index: chrome/browser/child_process_context.cc
|
| ===================================================================
|
| --- chrome/browser/child_process_context.cc (revision 0)
|
| +++ chrome/browser/child_process_context.cc (revision 0)
|
| @@ -0,0 +1,225 @@
|
| +// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/child_process_context.h"
|
| +
|
| +#include "chrome/browser/chrome_thread.h"
|
| +#include "chrome/common/child_process_info.h"
|
| +#include "chrome/common/notification_type.h"
|
| +#include "chrome/common/result_codes.h"
|
| +#include "chrome/common/chrome_descriptors.h"
|
| +#include "chrome/common/chrome_switches.h"
|
| +#include "chrome/common/process_watcher.h"
|
| +
|
| +#if defined(OS_WIN)
|
| +#include "chrome/common/sandbox_policy.h"
|
| +#elif defined(OS_LINUX)
|
| +#include "base/singleton.h"
|
| +#include "chrome/browser/crash_handler_host_linux.h"
|
| +#include "chrome/browser/zygote_host_linux.h"
|
| +#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
|
| +#endif
|
| +
|
| +#if defined(OS_MACOSX)
|
| +#include "chrome/browser/mach_broker_mac.h"
|
| +#endif
|
| +
|
| +#if defined(OS_POSIX)
|
| +#include "base/global_descriptors_posix.h"
|
| +#endif
|
| +
|
| +// TODO(eroman): Debugging helper to make strings show up in mini-dumps.
|
| +// Remove after done investigating 40447.
|
| +class StackString {
|
| + public:
|
| + explicit StackString(const std::wstring& str) {
|
| + length_ = str.size();
|
| + memcpy(&buffer_[0], str.data(),
|
| + std::min(sizeof(wchar_t) * str.length(),
|
| + sizeof(buffer_)));
|
| + }
|
| +
|
| + std::wstring ToString() {
|
| + return std::wstring(buffer_, length_);
|
| + }
|
| +
|
| + ~StackString() {
|
| + // Hack to make sure compiler doesn't optimize us away.
|
| + if (ToString() != ToString())
|
| + LOG(INFO) << ToString();
|
| + }
|
| +
|
| + private:
|
| + wchar_t buffer_[128];
|
| + size_t length_;
|
| +};
|
| +
|
| +ChildProcessContext::ChildProcessContext() {
|
| +}
|
| +
|
| +int ChildProcessContext::GetBadMessageResultCode() {
|
| + return ResultCodes::KILLED_BAD_MESSAGE;
|
| +}
|
| +
|
| +int ChildProcessContext::GetNormalExitResultCode() {
|
| + return ResultCodes::NORMAL_EXIT;
|
| +}
|
| +
|
| +std::string ChildProcessContext::GenerateRandomChannelID(void* instance) {
|
| + return ChildProcessInfo::GenerateRandomChannelID(instance);
|
| +}
|
| +
|
| +bool ChildProcessContext::GetCurrentThreadIdentifier(int* identifier) {
|
| + ChromeThread::ID chrome_id;
|
| + if (ChromeThread::GetCurrentThreadIdentifier(&chrome_id)) {
|
| + *identifier = static_cast<int>(chrome_id);
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool ChildProcessContext::CurrentlyOnThread(int identifier) {
|
| + return ChromeThread::CurrentlyOn(static_cast<ChromeThread::ID>(identifier));
|
| +}
|
| +
|
| +bool ChildProcessContext::PostTask(int identifier,
|
| + const tracked_objects::Location& from_here,
|
| + Task* task) {
|
| + return ChromeThread::PostTask(static_cast<ChromeThread::ID>(identifier),
|
| + from_here, task);
|
| +}
|
| +
|
| +bool ChildProcessContext::PostProcessLauncherTask(
|
| + const tracked_objects::Location& from_here,
|
| + Task* task) {
|
| + return ChromeThread::PostTask(ChromeThread::PROCESS_LAUNCHER, from_here,
|
| + task);
|
| +}
|
| +
|
| +base::ProcessHandle ChildProcessContext::StartProcess(
|
| +#if defined(OS_WIN)
|
| + const FilePath& exposed_dir,
|
| +#elif defined(OS_POSIX)
|
| + bool use_zygote,
|
| + const base::environment_vector& environ,
|
| + int ipcfd,
|
| +#endif
|
| + CommandLine* cmd_line) {
|
| + base::ProcessHandle handle = base::kNullProcessHandle;
|
| +#if defined(OS_WIN)
|
| + // TODO(eroman): Remove after done investigating 40447.
|
| + StackString stack_command_line(cmd_line->command_line_string());
|
| + // This line might crash, since it calls the string copy-constructor:
|
| + StackString stack_program(cmd_line->program());
|
| +
|
| + handle = sandbox::StartProcessWithAccess(cmd_line, exposed_dir);
|
| +#elif defined(OS_POSIX)
|
| +
|
| +#if defined(OS_LINUX)
|
| + if (use_zygote) {
|
| + base::GlobalDescriptors::Mapping mapping;
|
| + mapping.push_back(std::pair<uint32_t, int>(kPrimaryIPCChannel, ipcfd));
|
| + const int crash_signal_fd =
|
| + Singleton<RendererCrashHandlerHostLinux>()->GetDeathSignalSocket();
|
| + if (crash_signal_fd >= 0) {
|
| + mapping.push_back(std::pair<uint32_t, int>(kCrashDumpSignal,
|
| + crash_signal_fd));
|
| + }
|
| + handle = Singleton<ZygoteHost>()->ForkRenderer(cmd_line->argv(), mapping);
|
| + } else
|
| + // Fall through to the normal posix case below when we're not zygoting.
|
| +#endif
|
| + {
|
| + base::file_handle_mapping_vector fds_to_map;
|
| + fds_to_map.push_back(std::make_pair(
|
| + ipcfd,
|
| + kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
|
| +
|
| +#if defined(OS_LINUX)
|
| + // On Linux, we need to add some extra file descriptors for crash handling
|
| + // and the sandbox.
|
| + bool is_renderer =
|
| + cmd_line->GetSwitchValueASCII(switches::kProcessType) ==
|
| + switches::kRendererProcess;
|
| + bool is_plugin =
|
| + cmd_line->GetSwitchValueASCII(switches::kProcessType) ==
|
| + switches::kPluginProcess;
|
| +
|
| + if (is_renderer || is_plugin) {
|
| + int crash_signal_fd;
|
| + if (is_renderer) {
|
| + crash_signal_fd = Singleton<RendererCrashHandlerHostLinux>()->
|
| + GetDeathSignalSocket();
|
| + } else {
|
| + crash_signal_fd = Singleton<PluginCrashHandlerHostLinux>()->
|
| + GetDeathSignalSocket();
|
| + }
|
| + if (crash_signal_fd >= 0) {
|
| + fds_to_map.push_back(std::make_pair(
|
| + crash_signal_fd,
|
| + kCrashDumpSignal + base::GlobalDescriptors::kBaseDescriptor));
|
| + }
|
| + }
|
| + if (is_renderer) {
|
| + const int sandbox_fd =
|
| + Singleton<RenderSandboxHostLinux>()->GetRendererSocket();
|
| + fds_to_map.push_back(std::make_pair(
|
| + sandbox_fd,
|
| + kSandboxIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
|
| + }
|
| +#endif // defined(OS_LINUX)
|
| +
|
| + // Actually launch the app.
|
| + bool launched;
|
| +#if defined(OS_MACOSX)
|
| + task_t child_task;
|
| + launched = base::LaunchAppAndGetTask(
|
| + cmd_line->argv(), env, fds_to_map, false, &child_task, &handle);
|
| + if (launched && child_task != MACH_PORT_NULL) {
|
| + MachBroker::instance()->RegisterPid(
|
| + handle,
|
| + MachBroker::MachInfo().SetTask(child_task));
|
| + }
|
| +#else
|
| + launched = base::LaunchApp(cmd_line->argv(), env, fds_to_map,
|
| + /* wait= */false, &handle);
|
| +#endif
|
| + if (!launched)
|
| + handle = base::kNullProcessHandle;
|
| + }
|
| +#endif // else defined(OS_POSIX)
|
| +
|
| + return handle;
|
| +}
|
| +
|
| +void ChildProcessContext::EnsureProcessTerminated(base::ProcessHandle) {
|
| + // On POSIX, we must additionally reap the child.
|
| +#if defined(OS_POSIX)
|
| +#if defined(OS_LINUX)
|
| + if (zygote) {
|
| + // If the renderer was created via a zygote, we have to proxy the reaping
|
| + // through the zygote process.
|
| + Singleton<ZygoteHost>()->EnsureProcessTerminated(handle);
|
| + } else
|
| +#endif // OS_LINUX
|
| + {
|
| + ProcessWatcher::EnsureProcessTerminated(handle);
|
| + }
|
| +#endif // OS_POSIX
|
| +}
|
| +
|
| +bool ChildProcessContext::CheckProcessCrash(bool* child_exited,
|
| +#if defined(OS_POSIX)
|
| + bool use_zygote,
|
| +#endif
|
| + base::ProcessHandle handle) {
|
| +#if defined(OS_LINUX)
|
| + if (use_zygote) {
|
| + return Singleton<ZygoteHost>()->DidProcessCrash(handle, child_exited);
|
| + } else
|
| +#endif
|
| + {
|
| + return base::DidProcessCrash(child_exited, handle);
|
| + }
|
| +}
|
|
|