summaryrefslogtreecommitdiffstats
path: root/chrome/app
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-25 16:08:52 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-25 16:08:52 +0000
commitf8ba13ddfaf769ade709cf4ce205a009521a7c09 (patch)
treeec017792f84d8e59493e1a5f180b0c611f30619e /chrome/app
parent0981f86e200719979691ce48a93c8532d525c06b (diff)
downloadchromium_src-f8ba13ddfaf769ade709cf4ce205a009521a7c09.zip
chromium_src-f8ba13ddfaf769ade709cf4ce205a009521a7c09.tar.gz
chromium_src-f8ba13ddfaf769ade709cf4ce205a009521a7c09.tar.bz2
Move ZygoteForkDelegateLinux to content/public/common.
BUG=98716 Review URL: http://codereview.chromium.org/8381029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107128 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/app')
-rw-r--r--chrome/app/chrome_main_delegate.cc4
-rw-r--r--chrome/app/chrome_main_delegate.h2
-rw-r--r--chrome/app/nacl_fork_delegate_linux.cc150
-rw-r--r--chrome/app/nacl_fork_delegate_linux.h54
4 files changed, 207 insertions, 3 deletions
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index 776b989..93ce114 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -72,7 +72,7 @@
#endif
#if defined(OS_POSIX) && !defined(OS_MACOSX)
-#include "chrome/common/nacl_fork_delegate_linux.h"
+#include "chrome/app/nacl_fork_delegate_linux.h"
#endif
#if defined(OS_CHROMEOS)
@@ -704,7 +704,7 @@ bool ChromeMainDelegate::DelaySandboxInitialization(
process_type == switches::kRelauncherProcess;
}
#elif defined(OS_POSIX)
-ZygoteForkDelegate* ChromeMainDelegate::ZygoteStarting() {
+content::ZygoteForkDelegate* ChromeMainDelegate::ZygoteStarting() {
// Each Renderer we spawn will re-attempt initialization of the media
// libraries, at which point failure will be detected and handled, so
// we do not need to cope with initialization failures here.
diff --git a/chrome/app/chrome_main_delegate.h b/chrome/app/chrome_main_delegate.h
index f0a6fe9..064b561 100644
--- a/chrome/app/chrome_main_delegate.h
+++ b/chrome/app/chrome_main_delegate.h
@@ -38,7 +38,7 @@ class ChromeMainDelegate : public content::ContentMainDelegate {
virtual bool DelaySandboxInitialization(
const std::string& process_type) OVERRIDE;
#elif defined(OS_POSIX)
- virtual ZygoteForkDelegate* ZygoteStarting() OVERRIDE;
+ virtual content::ZygoteForkDelegate* ZygoteStarting() OVERRIDE;
virtual void ZygoteForked() OVERRIDE;
#endif
diff --git a/chrome/app/nacl_fork_delegate_linux.cc b/chrome/app/nacl_fork_delegate_linux.cc
new file mode 100644
index 0000000..a3723a3
--- /dev/null
+++ b/chrome/app/nacl_fork_delegate_linux.cc
@@ -0,0 +1,150 @@
+// Copyright (c) 2011 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/app/nacl_fork_delegate_linux.h"
+
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/eintr_wrapper.h"
+#include "base/logging.h"
+#include "base/file_path.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+#include "content/common/unix_domain_socket_posix.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/nacl_helper_linux.h"
+
+NaClForkDelegate::NaClForkDelegate()
+ : status_(kNaClHelperUnused),
+ sandboxed_(false),
+ fd_(-1) {}
+
+const char kNaClHelperAtZero[] = "--at-zero";
+
+void NaClForkDelegate::Init(const bool sandboxed,
+ const int browserdesc,
+ const int sandboxdesc) {
+ VLOG(1) << "NaClForkDelegate::Init()";
+ int fds[2];
+
+ sandboxed_ = sandboxed;
+ // Confirm a couple hard-wired assumptions.
+ // The NaCl constants are from chrome/nacl/nacl_linux_helper.h
+ DCHECK(kNaClBrowserDescriptor == browserdesc);
+ DCHECK(kNaClSandboxDescriptor == sandboxdesc);
+
+ CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
+ base::file_handle_mapping_vector fds_to_map;
+ fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor));
+ fds_to_map.push_back(std::make_pair(sandboxdesc, kNaClSandboxDescriptor));
+
+ status_ = kNaClHelperUnused;
+ FilePath helper_exe;
+ FilePath helper_bootstrap_exe;
+ if (!PathService::Get(chrome::FILE_NACL_HELPER, &helper_exe)) {
+ status_ = kNaClHelperMissing;
+ } else if (!PathService::Get(chrome::FILE_NACL_HELPER_BOOTSTRAP,
+ &helper_bootstrap_exe)) {
+ status_ = kNaClHelperBootstrapMissing;
+ } else if (RunningOnValgrind()) {
+ status_ = kNaClHelperValgrind;
+ } else {
+ CommandLine cmd_line(helper_bootstrap_exe);
+ cmd_line.AppendArgPath(helper_exe);
+ cmd_line.AppendArgNative(kNaClHelperAtZero);
+ base::LaunchOptions options;
+ options.fds_to_remap = &fds_to_map;
+ options.clone_flags = CLONE_FS | SIGCHLD;
+ if (!base::LaunchProcess(cmd_line.argv(), options, NULL))
+ status_ = kNaClHelperLaunchFailed;
+ // parent and error cases are handled below
+ }
+ if (HANDLE_EINTR(close(fds[1])) != 0)
+ LOG(ERROR) << "close(fds[1]) failed";
+ if (status_ == kNaClHelperUnused) {
+ const ssize_t kExpectedLength = strlen(kNaClHelperStartupAck);
+ char buf[kExpectedLength];
+
+ // Wait for ack from nacl_helper, indicating it is ready to help
+ const ssize_t nread = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
+ if (nread == kExpectedLength &&
+ memcmp(buf, kNaClHelperStartupAck, nread) == 0) {
+ // all is well
+ status_ = kNaClHelperSuccess;
+ fd_ = fds[0];
+ return;
+ }
+
+ status_ = kNaClHelperAckFailed;
+ LOG(ERROR) << "Bad NaCl helper startup ack (" << nread << " bytes)";
+ }
+ // TODO(bradchen): Make this LOG(ERROR) when the NaCl helper
+ // becomes the default.
+ fd_ = -1;
+ if (HANDLE_EINTR(close(fds[0])) != 0)
+ LOG(ERROR) << "close(fds[0]) failed";
+}
+
+void NaClForkDelegate::InitialUMA(std::string* uma_name,
+ int* uma_sample,
+ int* uma_boundary_value) {
+ *uma_name = "NaCl.Client.Helper.InitState";
+ *uma_sample = status_;
+ *uma_boundary_value = kNaClHelperStatusBoundary;
+}
+
+NaClForkDelegate::~NaClForkDelegate() {
+ // side effect of close: delegate process will terminate
+ if (status_ == kNaClHelperSuccess) {
+ if (HANDLE_EINTR(close(fd_)) != 0)
+ LOG(ERROR) << "close(fd_) failed";
+ }
+}
+
+bool NaClForkDelegate::CanHelp(const std::string& process_type,
+ std::string* uma_name,
+ int* uma_sample,
+ int* uma_boundary_value) {
+ if (process_type != switches::kNaClLoaderProcess)
+ return false;
+ *uma_name = "NaCl.Client.Helper.StateOnFork";
+ *uma_sample = status_;
+ *uma_boundary_value = kNaClHelperStatusBoundary;
+ return status_ == kNaClHelperSuccess;
+}
+
+pid_t NaClForkDelegate::Fork(const std::vector<int>& fds) {
+ base::ProcessId naclchild;
+ VLOG(1) << "NaClForkDelegate::Fork";
+
+ DCHECK(fds.size() == kNaClParentFDIndex + 1);
+ if (!UnixDomainSocket::SendMsg(fd_, kNaClForkRequest,
+ strlen(kNaClForkRequest), fds)) {
+ LOG(ERROR) << "NaClForkDelegate::Fork: SendMsg failed";
+ return -1;
+ }
+ int nread = HANDLE_EINTR(read(fd_, &naclchild, sizeof(naclchild)));
+ if (nread != sizeof(naclchild)) {
+ LOG(ERROR) << "NaClForkDelegate::Fork: read failed";
+ return -1;
+ }
+ VLOG(1) << "nacl_child is " << naclchild << " (" << nread << " bytes)";
+ return naclchild;
+}
+
+bool NaClForkDelegate::AckChild(const int fd,
+ const std::string& channel_switch) {
+ int nwritten = HANDLE_EINTR(write(fd, channel_switch.c_str(),
+ channel_switch.length()));
+ if (nwritten != static_cast<int>(channel_switch.length())) {
+ return false;
+ }
+ return true;
+}
diff --git a/chrome/app/nacl_fork_delegate_linux.h b/chrome/app/nacl_fork_delegate_linux.h
new file mode 100644
index 0000000..853df09
--- /dev/null
+++ b/chrome/app/nacl_fork_delegate_linux.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 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.
+
+#ifndef CHROME_APP_NACL_FORK_DELEGATE_LINUX_H_
+#define CHROME_APP_NACL_FORK_DELEGATE_LINUX_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "content/public/common/zygote_fork_delegate_linux.h"
+
+// The NaClForkDelegate is created during Chrome linux zygote
+// initialization, and provides "fork()" functionality with
+// NaCl specific process characteristics (specifically address
+// space layout) as an alternative to forking the zygote.
+// A new delegate is passed in as an argument to ZygoteMain().
+class NaClForkDelegate : public content::ZygoteForkDelegate {
+ public:
+ NaClForkDelegate();
+ virtual ~NaClForkDelegate();
+
+ virtual void Init(bool sandboxed,
+ int browserdesc,
+ int sandboxdesc) OVERRIDE;
+ virtual void InitialUMA(std::string* uma_name,
+ int* uma_sample,
+ int* uma_boundary_value) OVERRIDE;
+ virtual bool CanHelp(const std::string& process_type, std::string* uma_name,
+ int* uma_sample, int* uma_boundary_value) OVERRIDE;
+ virtual pid_t Fork(const std::vector<int>& fds) OVERRIDE;
+ virtual bool AckChild(int fd,
+ const std::string& channel_switch) OVERRIDE;
+
+ private:
+ // These values are reported via UMA and hence they become permanent
+ // constants. Old values cannot be reused, only new ones added.
+ enum NaClHelperStatus {
+ kNaClHelperUnused = 0,
+ kNaClHelperMissing = 1,
+ kNaClHelperBootstrapMissing = 2,
+ kNaClHelperValgrind = 3,
+ kNaClHelperLaunchFailed = 4,
+ kNaClHelperAckFailed = 5,
+ kNaClHelperSuccess = 6,
+ kNaClHelperStatusBoundary // Must be one greater than highest value used.
+ };
+
+ NaClHelperStatus status_;
+ bool sandboxed_;
+ int fd_;
+};
+
+#endif // CHROME_APP_NACL_FORK_DELEGATE_LINUX_H_