diff options
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/nacl_process_host.cc | 187 | ||||
-rw-r--r-- | chrome/browser/nacl_process_host.h | 55 | ||||
-rw-r--r-- | chrome/browser/plugin_service.cc | 3 | ||||
-rw-r--r-- | chrome/browser/renderer_host/browser_render_process_host.cc | 1 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.cc | 8 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.h | 3 | ||||
-rw-r--r-- | chrome/browser/sandbox_policy.cc | 8 |
7 files changed, 264 insertions, 1 deletions
diff --git a/chrome/browser/nacl_process_host.cc b/chrome/browser/nacl_process_host.cc new file mode 100644 index 0000000..72db561 --- /dev/null +++ b/chrome/browser/nacl_process_host.cc @@ -0,0 +1,187 @@ +// Copyright (c) 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 "chrome/browser/nacl_process_host.h" + +#if defined(OS_POSIX) +#include <fcntl.h> +#endif + +#if defined(OS_POSIX) +#include "base/global_descriptors_posix.h" +#endif +#include "base/path_service.h" +#include "base/process_util.h" +#include "chrome/browser/renderer_host/resource_message_filter.h" +#include "chrome/common/chrome_descriptors.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/logging_chrome.h" +#include "chrome/common/nacl_messages.h" +#include "ipc/ipc_switches.h" + +#if defined(OS_WIN) +#include "chrome/browser/sandbox_policy.h" +#endif + +#if defined(OS_POSIX) +#include "ipc/ipc_channel_posix.h" +#endif + +NaClProcessHost::NaClProcessHost( + ResourceDispatcherHost *resource_dispatcher_host) + : ChildProcessHost(NACL_PROCESS, resource_dispatcher_host), + resource_dispatcher_host_(resource_dispatcher_host) { +} + +bool NaClProcessHost::Launch(ResourceMessageFilter* renderer_msg_filter, + const int descriptor, + nacl::FileDescriptor* handle) { + nacl::Handle pair[2]; + bool success = false; + // Create a connected socket + if (nacl::SocketPair(pair) == -1) { + NATIVE_HANDLE(*handle) = nacl::kInvalidHandle; + return false; + } + + // Launch the process + success = LaunchSelLdr(renderer_msg_filter, descriptor, pair[1]); + + if (!success) { + nacl::Close(pair[0]); + NATIVE_HANDLE(*handle) = nacl::kInvalidHandle; + return false; + } + + nacl::Handle duplicate_handle = nacl::kInvalidHandle; +#if NACL_WINDOWS + DuplicateHandle(base::GetCurrentProcessHandle(), + reinterpret_cast<HANDLE>(pair[0]), + renderer_msg_filter->handle(), + reinterpret_cast<HANDLE*>(&duplicate_handle), + GENERIC_READ | GENERIC_WRITE, + FALSE, + DUPLICATE_CLOSE_SOURCE); + *handle = duplicate_handle; +#else + duplicate_handle = pair[0]; + int flags = fcntl(duplicate_handle, F_GETFD); + if (flags != -1) { + flags |= FD_CLOEXEC; + fcntl(duplicate_handle, F_SETFD, flags); + } + // No need to dup the handle - we don't pass it anywhere else so + // it cannot be closed. + handle->fd = duplicate_handle; + handle->auto_close = true; +#endif + + return true; +} + +bool NaClProcessHost::LaunchSelLdr(ResourceMessageFilter* renderer_msg_filter, + const int descriptor, + const nacl::Handle handle) { + if (!CreateChannel()) + return false; + + // Build command line for nacl. + const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); + std::wstring exe_path = + browser_command_line.GetSwitchValue(switches::kBrowserSubprocessPath); + if (exe_path.empty() && !PathService::Get(base::FILE_EXE, &exe_path)) + return false; + + CommandLine cmd_line(exe_path); + if (logging::DialogsAreSuppressed()) + cmd_line.AppendSwitch(switches::kNoErrorDialogs); + + // propagate the following switches to the plugin command line (along with + // any associated values) if present in the browser command line + // TODO(gregoryd): check which flags of those below can be supported. + static const wchar_t* const switch_names[] = { + switches::kNoSandbox, + switches::kTestSandbox, + switches::kDisableBreakpad, + switches::kFullMemoryCrashReport, + switches::kEnableLogging, + switches::kDisableLogging, + switches::kLoggingLevel, + switches::kEnableDCHECK, + switches::kSilentDumpOnDCHECK, + switches::kMemoryProfiling, + }; + + for (size_t i = 0; i < arraysize(switch_names); ++i) { + if (browser_command_line.HasSwitch(switch_names[i])) { + cmd_line.AppendSwitchWithValue( + switch_names[i], + browser_command_line.GetSwitchValue(switch_names[i])); + } + } + + cmd_line.AppendSwitchWithValue(switches::kProcessType, + switches::kNaClProcess); + + cmd_line.AppendSwitchWithValue(switches::kProcessChannelID, + ASCIIToWide(channel_id())); + + base::ProcessHandle process = 0; +#if defined(OS_WIN) + process = sandbox::StartProcess(&cmd_line); +#else + base::file_handle_mapping_vector fds_to_map; + const int ipcfd = channel().GetClientFileDescriptor(); + if (ipcfd > -1) + fds_to_map.push_back(std::pair<int, int>( + ipcfd, kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor)); + base::LaunchApp(cmd_line.argv(), fds_to_map, false, &process); +#endif + + if (!process) + return false; + SetHandle(process); + + // send a message with duplicated handle to sel_ldr + return SendStartMessage(process, descriptor, handle); +} + +bool NaClProcessHost::SendStartMessage(base::ProcessHandle process, + int descriptor, + nacl::Handle handle) { + nacl::FileDescriptor channel; +#if defined(OS_WIN) + if (!DuplicateHandle(GetCurrentProcess(), + reinterpret_cast<HANDLE>(handle), + process, + reinterpret_cast<HANDLE*>(&channel), + GENERIC_READ | GENERIC_WRITE, + FALSE, DUPLICATE_CLOSE_SOURCE)) { + return false; + } +#else + channel.fd = dup(handle); + channel.auto_close = true; +#endif + NaClProcessMsg_Start* msg = new NaClProcessMsg_Start(descriptor, + channel); + + if (!Send(msg)) { + return false; + } + return true; +} + +void NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { + NOTREACHED() << "Invalid message with type = " << msg.type(); +} + +URLRequestContext* NaClProcessHost::GetRequestContext( + uint32 request_id, + const ViewHostMsg_Resource_Request& request_data) { + return NULL; +} + diff --git a/chrome/browser/nacl_process_host.h b/chrome/browser/nacl_process_host.h new file mode 100644 index 0000000..59de526 --- /dev/null +++ b/chrome/browser/nacl_process_host.h @@ -0,0 +1,55 @@ +// Copyright (c) 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_BROWSER_NACL_PROCESS_HOST_H_ +#define CHROME_BROWSER_NACL_PROCESS_HOST_H_ + +#include "build/build_config.h" +#include "chrome/common/child_process_host.h" +#include "chrome/common/nacl_types.h" +#include "native_client/src/shared/imc/nacl_imc.h" + +class ResourceMessageFilter; + +// Represents the browser side of the browser <--> NaCl communication +// channel. There will be one NaClProcessHost per NaCl process +// The browser is responsible for starting the NaCl process +// when requested by the renderer. +// After that, most of the communication is directly between NaCl plugin +// running in the renderer and NaCl processes. +class NaClProcessHost : public ChildProcessHost { + public: + explicit NaClProcessHost(ResourceDispatcherHost *resource_dispatcher_host); + ~NaClProcessHost() {} + + // Initialize the new NaCl process, returning true on success. + bool Launch(ResourceMessageFilter* renderer_msg_filter, + const int descriptor, + nacl::FileDescriptor *handle); + + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + bool LaunchSelLdr(ResourceMessageFilter* renderer_msg_filter, + const int descriptor, + const nacl::Handle handle); + + bool SendStartMessage(base::ProcessHandle process, + int descriptor, + nacl::Handle handle); + + // ResourceDispatcherHost::Receiver implementation: + virtual URLRequestContext* GetRequestContext( + uint32 request_id, + const ViewHostMsg_Resource_Request& request_data); + + virtual bool CanShutdown() { return true; } + + private: + ResourceDispatcherHost* resource_dispatcher_host_; + + DISALLOW_COPY_AND_ASSIGN(NaClProcessHost); +}; + +#endif // CHROME_BROWSER_NACL_PROCESS_HOST_H_ diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc index 42a67e9..5c5a8bb 100644 --- a/chrome/browser/plugin_service.cc +++ b/chrome/browser/plugin_service.cc @@ -23,6 +23,7 @@ #include "chrome/common/notification_type.h" #include "chrome/common/notification_service.h" #include "chrome/common/render_messages.h" +#include "native_client/src/trusted/plugin/nacl_entry_points.h" #include "webkit/glue/plugins/plugin_constants_win.h" #include "webkit/glue/plugins/plugin_list.h" @@ -44,6 +45,8 @@ PluginService::PluginService() NPAPI::PluginList::Singleton()->AddExtraPluginPath( FilePath::FromWStringHack(path)); } + if (command_line->HasSwitch(switches::kInternalNaCl)) + RegisterInternalNaClPlugin(); #if defined(OS_WIN) hkcu_key_.Create( diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index fb91a80..43482f1 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -326,6 +326,7 @@ bool BrowserRenderProcessHost::Init() { switches::kDisableAudio, switches::kSimpleDataSource, switches::kEnableBenchmarking, + switches::kInternalNaCl, switches::kEnableDatabases, }; diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 0b8a923..3091033 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -15,6 +15,7 @@ #include "chrome/browser/chrome_thread.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h" +#include "chrome/browser/nacl_process_host.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/net/dns_global.h" #include "chrome/browser/plugin_service.h" @@ -295,6 +296,7 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) { OnReceiveContextMenuMsg(msg)) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, OnOpenChannelToPlugin) + IPC_MESSAGE_HANDLER(ViewHostMsg_LaunchNaCl, OnLaunchNaCl) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateDedicatedWorker, OnCreateDedicatedWorker) IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, @@ -585,6 +587,12 @@ void ResourceMessageFilter::OnOpenChannelToPlugin(const GURL& url, this, url, mime_type, locale, reply_msg); } +void ResourceMessageFilter::OnLaunchNaCl(int channel_descriptor, + nacl::FileDescriptor* handle) { + NaClProcessHost* nacl_host = new NaClProcessHost(resource_dispatcher_host_); + nacl_host->Launch(this, channel_descriptor, handle); +} + void ResourceMessageFilter::OnCreateDedicatedWorker(const GURL& url, int render_view_route_id, int* route_id) { diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 6b93eee..ca37294 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -25,6 +25,7 @@ #include "chrome/browser/renderer_host/render_widget_helper.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/common/modal_dialog_event.h" +#include "chrome/common/nacl_types.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/transport_dib.h" #include "ipc/ipc_channel_proxy.h" @@ -154,6 +155,8 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, const std::string& mime_type, const std::wstring& locale, IPC::Message* reply_msg); + void OnLaunchNaCl(int channel_descriptor, + nacl::FileDescriptor* handle); void OnCreateDedicatedWorker(const GURL& url, int render_view_route_id, int* route_id); diff --git a/chrome/browser/sandbox_policy.cc b/chrome/browser/sandbox_policy.cc index 13f4ee2..784e5a7 100644 --- a/chrome/browser/sandbox_policy.cc +++ b/chrome/browser/sandbox_policy.cc @@ -359,6 +359,8 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line, type = ChildProcessInfo::PLUGIN_PROCESS; } else if (type_str == switches::kWorkerProcess) { type = ChildProcessInfo::WORKER_PROCESS; + } else if (type_str == switches::kNaClProcess) { + type = ChildProcessInfo::NACL_PROCESS; } else if (type_str == switches::kUtilityProcess) { type = ChildProcessInfo::UTILITY_PROCESS; } else { @@ -371,8 +373,10 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line, (type != ChildProcessInfo::PLUGIN_PROCESS || browser_command_line.HasSwitch(switches::kSafePlugins)); #if !defined (GOOGLE_CHROME_BUILD) - if (browser_command_line.HasSwitch(switches::kInProcessPlugins)) { + if (browser_command_line.HasSwitch(switches::kInProcessPlugins) || + browser_command_line.HasSwitch(switches::kInternalNaCl)) { // In process plugins won't work if the sandbox is enabled. + // The internal NaCl plugin doesn't work in the sandbox for now. in_sandbox = false; } #endif @@ -394,6 +398,8 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line, sandbox::TargetPolicy* policy = broker_service->CreatePolicy(); bool on_sandbox_desktop = false; + // TODO(gregoryd): try locked-down policy for sel_ldr after we fix IMC. + // TODO(gregoryd): do we need a new desktop for sel_ldr? if (type == ChildProcessInfo::PLUGIN_PROCESS) { if (!AddPolicyForPlugin(cmd_line, policy)) return 0; |