summaryrefslogtreecommitdiffstats
path: root/chrome/nacl
diff options
context:
space:
mode:
authorgregoryd@google.com <gregoryd@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-18 01:46:27 +0000
committergregoryd@google.com <gregoryd@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-18 01:46:27 +0000
commitea5ac0e47d18753dbe971a35cce7f657ba64bae8 (patch)
tree54713ad26e136bbb9b0bf0062229092c537df533 /chrome/nacl
parenteb4035b0048a7c9e3eeae7e189161f0cfbf3db22 (diff)
downloadchromium_src-ea5ac0e47d18753dbe971a35cce7f657ba64bae8.zip
chromium_src-ea5ac0e47d18753dbe971a35cce7f657ba64bae8.tar.gz
chromium_src-ea5ac0e47d18753dbe971a35cce7f657ba64bae8.tar.bz2
This is a copy of http://codereview.chromium.org/153002/show
First step towards NaCl-Chrome integration:1. NaCl plugin becomes a built-in plugin in Chrome and runs in the renderer process.2. Most of the changes are related to launching the NaCl process (that loads and runs the NaCl module) and establishing the initial communication between that process and the NaCl plugin.3. This CL relies on another CL that contains the changes on the Native Client side: http://codereview.chromium.org/1501904. Command line flag "--internal-nacl" is required to enable the built-in NaCl plugin.5. NaCl still cannot run in Chrome sandbox, so the "--no-sandbox" flag is also required TBR=bradnelson Review URL: http://codereview.chromium.org/207025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26540 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/nacl')
-rw-r--r--chrome/nacl/nacl_main.cc75
-rw-r--r--chrome/nacl/nacl_thread.cc33
-rw-r--r--chrome/nacl/nacl_thread.h35
-rw-r--r--chrome/nacl/sel_main.cc210
4 files changed, 353 insertions, 0 deletions
diff --git a/chrome/nacl/nacl_main.cc b/chrome/nacl/nacl_main.cc
new file mode 100644
index 0000000..2d583b1
--- /dev/null
+++ b/chrome/nacl/nacl_main.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2006-2009 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 "build/build_config.h"
+
+#if defined(OS_WIN)
+#include "app/win_util.h"
+#endif
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "base/system_monitor.h"
+#include "chrome/common/child_process.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/logging_chrome.h"
+#include "chrome/common/main_function_params.h"
+#include "chrome/nacl/nacl_thread.h"
+
+#if defined(OS_WIN)
+#include "chrome/test/injection_test_dll.h"
+#include "sandbox/src/sandbox.h"
+#endif
+
+// main() routine for running as the sel_ldr process.
+int NaClMain(const MainFunctionParams& parameters) {
+ // The main thread of the plugin services IO.
+ MessageLoopForIO main_message_loop;
+ std::wstring app_name = chrome::kBrowserAppName;
+ PlatformThread::SetName(WideToASCII(app_name + L"_NaClMain").c_str());
+
+ // Initialize the SystemMonitor
+ base::SystemMonitor::Start();
+
+#if defined(OS_WIN)
+ const CommandLine& parsed_command_line = parameters.command_line_;
+
+ sandbox::TargetServices* target_services =
+ parameters.sandbox_info_.TargetServices();
+
+ DLOG(INFO) << "Started plugin with " <<
+ parsed_command_line.command_line_string();
+
+ HMODULE sandbox_test_module = NULL;
+ bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox);
+ if (target_services && !no_sandbox) {
+ // The command line might specify a test plugin to load.
+ if (parsed_command_line.HasSwitch(switches::kTestSandbox)) {
+ std::wstring test_plugin_name =
+ parsed_command_line.GetSwitchValue(switches::kTestSandbox);
+ sandbox_test_module = LoadLibrary(test_plugin_name.c_str());
+ DCHECK(sandbox_test_module);
+ }
+ }
+
+#else
+ NOTIMPLEMENTED() << " non-windows startup, plugin startup dialog etc.";
+#endif
+
+ {
+ ChildProcess nacl_process;
+ nacl_process.set_main_thread(new NaClThread());
+#if defined(OS_WIN)
+ if (!no_sandbox && target_services)
+ target_services->LowerToken();
+#endif
+
+ MessageLoop::current()->Run();
+ }
+
+ return 0;
+}
+
+
diff --git a/chrome/nacl/nacl_thread.cc b/chrome/nacl/nacl_thread.cc
new file mode 100644
index 0000000..0b669f0
--- /dev/null
+++ b/chrome/nacl/nacl_thread.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2006-2009 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/nacl/nacl_thread.h"
+
+#include "build/build_config.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/nacl_messages.h"
+#include "native_client/src/trusted/service_runtime/include/sys/nacl_imc_api.h"
+
+int SelMain(const int desc, const NaClHandle handle);
+
+NaClThread::NaClThread() {
+}
+
+NaClThread::~NaClThread() {
+}
+
+NaClThread* NaClThread::current() {
+ return static_cast<NaClThread*>(ChildThread::current());
+}
+
+void NaClThread::OnControlMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(NaClThread, msg)
+ IPC_MESSAGE_HANDLER(NaClProcessMsg_StartSelLdr, OnStartSelLdr)
+ IPC_END_MESSAGE_MAP()
+}
+
+void NaClThread::OnStartSelLdr(const int channel_descriptor,
+ const nacl::FileDescriptor handle) {
+ SelMain(channel_descriptor, NATIVE_HANDLE(handle));
+}
diff --git a/chrome/nacl/nacl_thread.h b/chrome/nacl/nacl_thread.h
new file mode 100644
index 0000000..a69ce3a
--- /dev/null
+++ b/chrome/nacl/nacl_thread.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2009 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_NACL_NACL_THREAD_H_
+#define CHROME_NACL_NACL_THREAD_H_
+
+#include "base/file_path.h"
+#include "base/native_library.h"
+#include "chrome/common/child_thread.h"
+#include "chrome/common/nacl_types.h"
+
+class NotificationService;
+
+// The NaClThread class represents a background thread where NaCl app gets
+// started.
+class NaClThread : public ChildThread {
+ public:
+ NaClThread();
+ ~NaClThread();
+ // Returns the one NaCl thread.
+ static NaClThread* current();
+
+ private:
+ virtual void OnControlMessageReceived(const IPC::Message& msg);
+ void OnStartSelLdr(const int channel_descriptor,
+ const nacl::FileDescriptor handle);
+ // TODO(gregoryd): do we need to override Cleanup as in PluginThread?
+
+ scoped_ptr<NotificationService> notification_service_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(NaClThread);
+};
+
+#endif // CHROME_NACL_NACL_THREAD_H_
diff --git a/chrome/nacl/sel_main.cc b/chrome/nacl/sel_main.cc
new file mode 100644
index 0000000..7174706
--- /dev/null
+++ b/chrome/nacl/sel_main.cc
@@ -0,0 +1,210 @@
+// Copyright (c) 2006-2009 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 "build/build_config.h"
+
+#include "native_client/src/include/portability.h"
+
+#if NACL_OSX
+#include <crt_externs.h>
+#endif
+
+EXTERN_C_BEGIN
+#include "native_client/src/shared/platform/nacl_sync.h"
+#include "native_client/src/shared/platform/nacl_sync_checked.h"
+#include "native_client/src/trusted/service_runtime/nacl_globals.h"
+#include "native_client/src/trusted/service_runtime/expiration.h"
+#include "native_client/src/trusted/service_runtime/nacl_app.h"
+#include "native_client/src/trusted/service_runtime/nacl_all_modules.h"
+#include "native_client/src/trusted/service_runtime/sel_ldr.h"
+#include "native_client/src/trusted/platform_qualify/nacl_os_qualify.h"
+EXTERN_C_END
+
+int verbosity = 0;
+
+#ifdef __GNUC__
+
+/*
+ * GDB's canonical overlay managment routine.
+ * We need its symbol in the symbol table so don't inline it.
+ * TODO(dje): add some explanation for the non-GDB person.
+ */
+
+static void __attribute__ ((noinline)) _ovly_debug_event (void) {
+ /*
+ * The asm volatile is here as instructed by the GCC docs.
+ * It's not enough to declare a function noinline.
+ * GCC will still look inside the function to see if it's worth calling.
+ */
+ asm volatile ("");
+}
+
+#endif
+
+static void StopForDebuggerInit (const struct NaClApp *state) {
+ /* Put xlate_base in a place where gdb can find it. */
+ nacl_global_xlate_base = state->xlate_base;
+
+#ifdef __GNUC__
+ _ovly_debug_event ();
+#endif
+}
+
+int SelMain(const int desc, const NaClHandle handle) {
+ char *av[1];
+ int ac = 1;
+
+ char **envp;
+ struct NaClApp state;
+ char *nacl_file = 0;
+ int main_thread_only = 1;
+ int export_addr_to = -2;
+
+ struct NaClApp *nap;
+
+ NaClErrorCode errcode;
+
+ int ret_code = 1;
+#if NACL_OSX
+ // Mac dynamic libraries cannot access the environ variable directly.
+ envp = *_NSGetEnviron();
+#else
+ extern char **environ;
+ envp = environ;
+#endif
+
+
+ if (NaClHasExpired()) {
+ // TODO(gregoryd): report error to browser?
+ fprintf(stderr, "This version of Native Client has expired.\n");
+ fprintf(stderr, "Please visit: http://code.google.com/p/nativeclient/\n");
+ exit(-1);
+ }
+
+ NaClAllModulesInit();
+
+ /* used to be -P */
+ NaClSrpcFileDescriptor = desc;
+ /* used to be -X */
+ export_addr_to = desc;
+
+ /* to be passed to NaClMain, eventually... */
+ av[0] = const_cast<char*>("NaClMain");
+
+ if (!NaClAppCtor(&state)) {
+ fprintf(stderr, "Error while constructing app state\n");
+ goto done_file_dtor;
+ }
+
+ state.restrict_to_main_thread = main_thread_only;
+
+ nap = &state;
+ errcode = LOAD_OK;
+
+ /* import IMC handle - used to be "-i" */
+ NaClAddImcHandle(nap, handle, desc);
+
+ /*
+ * in order to report load error to the browser plugin through the
+ * secure command channel, we do not immediate jump to cleanup code
+ * on error. rather, we continue processing (assuming earlier
+ * errors do not make it inappropriate) until the secure command
+ * channel is set up, and then bail out.
+ */
+
+ /*
+ * Ensure this operating system platform is supported.
+ */
+ if (!NaClOsIsSupported()) {
+ errcode = LOAD_UNSUPPORTED_OS_PLATFORM;
+ nap->module_load_status = errcode;
+ fprintf(stderr, "Error while loading \"%s\": %s\n",
+ nacl_file,
+ NaClErrorString(errcode));
+ }
+
+ /* Give debuggers a well known point at which xlate_base is known. */
+ StopForDebuggerInit(&state);
+
+ /*
+ * If export_addr_to is set to a non-negative integer, we create a
+ * bound socket and socket address pair and bind the former to
+ * descriptor 3 and the latter to descriptor 4. The socket address
+ * is written out to the export_addr_to descriptor.
+ *
+ * The service runtime also accepts a connection on the bound socket
+ * and spawns a secure command channel thread to service it.
+ *
+ * If export_addr_to is -1, we only create the bound socket and
+ * socket address pair, and we do not export to an IMC socket. This
+ * use case is typically only used in testing, where we only "dump"
+ * the socket address to stdout or similar channel.
+ */
+ if (-2 < export_addr_to) {
+ NaClCreateServiceSocket(nap);
+ if (0 <= export_addr_to) {
+ NaClSendServiceAddressTo(nap, export_addr_to);
+ /*
+ * NB: spawns a thread that uses the command channel. we do
+ * this after NaClAppLoadFile so that NaClApp object is more
+ * fully populated. Hereafter any changes to nap should be done
+ * while holding locks.
+ */
+ NaClSecureCommandChannel(nap);
+ }
+ }
+
+ NaClXMutexLock(&nap->mu);
+ nap->module_load_status = LOAD_OK;
+ NaClXCondVarBroadcast(&nap->cv);
+ NaClXMutexUnlock(&nap->mu);
+
+ if (NULL != nap->secure_channel) {
+ /*
+ * wait for start_module RPC call on secure channel thread.
+ */
+ NaClWaitForModuleStartStatusCall(nap);
+ }
+
+ /*
+ * error reporting done; can quit now if there was an error earlier.
+ */
+ if (LOAD_OK != errcode) {
+ goto done;
+ }
+
+ /*
+ * only nap->ehdrs.e_entry is usable, no symbol table is
+ * available.
+ */
+ if (!NaClCreateMainThread(nap,
+ ac,
+ av,
+ envp)) {
+ fprintf(stderr, "creating main thread failed\n");
+ goto done;
+ }
+
+ ret_code = NaClWaitForMainThreadToExit(nap);
+
+ /*
+ * exit_group or equiv kills any still running threads while module
+ * addr space is still valid. otherwise we'd have to kill threads
+ * before we clean up the address space.
+ */
+ return ret_code;
+
+ done:
+ fflush(stdout);
+
+ NaClAppDtor(&state);
+
+ done_file_dtor:
+ fflush(stdout);
+
+ NaClAllModulesFini();
+
+ return ret_code;
+}
+