Index: components/nacl/loader/sfi_listener_delegate.cc |
diff --git a/components/nacl/loader/nacl_listener.cc b/components/nacl/loader/sfi_listener_delegate.cc |
similarity index 54% |
copy from components/nacl/loader/nacl_listener.cc |
copy to components/nacl/loader/sfi_listener_delegate.cc |
index 433d9417d2abd291e532156de13b676ba6c57a4c..33ce605f976c6001c06128e6970077643048bf15 100644 |
--- a/components/nacl/loader/nacl_listener.cc |
+++ b/components/nacl/loader/sfi_listener_delegate.cc |
@@ -1,54 +1,51 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Copyright 2014 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 "components/nacl/loader/nacl_listener.h" |
+#include "components/nacl/loader/sfi_listener_delegate.h" |
-#include <errno.h> |
-#include <fcntl.h> |
-#include <stdlib.h> |
- |
-#if defined(OS_POSIX) |
-#include <unistd.h> |
-#endif |
- |
-#include "base/command_line.h" |
#include "base/logging.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/rand_util.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/message_loop/message_loop_proxy.h" |
#include "components/nacl/common/nacl_messages.h" |
+#include "components/nacl/common/nacl_types.h" |
#include "components/nacl/loader/nacl_ipc_adapter.h" |
#include "components/nacl/loader/nacl_validation_db.h" |
#include "components/nacl/loader/nacl_validation_query.h" |
+#include "ipc/ipc_channel.h" |
#include "ipc/ipc_channel_handle.h" |
-#include "ipc/ipc_switches.h" |
-#include "ipc/ipc_sync_channel.h" |
-#include "ipc/ipc_sync_message_filter.h" |
+#include "ipc/ipc_sender.h" |
#include "native_client/src/public/chrome_main.h" |
#include "native_client/src/public/nacl_app.h" |
#include "native_client/src/public/nacl_file_info.h" |
#include "native_client/src/trusted/service_runtime/include/sys/fcntl.h" |
+#if defined(OS_WIN) |
+#include <fcntl.h> |
+#include <io.h> |
+#include "content/public/common/sandbox_init.h" |
+#endif // OS_WIN |
+ |
#if defined(OS_POSIX) |
+#include <unistd.h> |
#include "base/file_descriptor_posix.h" |
-#endif |
+#include "base/rand_util.h" |
+#endif // OS_POSIX |
+ |
+#if defined(OS_MACOSX) |
+#include <errno.h> |
+#include <sys/types.h> |
+#include "base/atomicops.h" |
+#endif // OS_MACOSX |
#if defined(OS_LINUX) |
-#include "components/nacl/loader/nonsfi/irt_random.h" |
-#include "components/nacl/loader/nonsfi/nonsfi_main.h" |
#include "content/public/common/child_process_sandbox_support_linux.h" |
-#include "ppapi/nacl_irt/plugin_startup.h" |
-#endif |
+#endif // OS_LINUX |
-#if defined(OS_WIN) |
-#include <fcntl.h> |
-#include <io.h> |
- |
-#include "content/public/common/sandbox_init.h" |
-#endif |
+namespace nacl { |
namespace { |
+ |
#if defined(OS_MACOSX) |
// On Mac OS X, shm_open() works in the sandbox but does not give us |
@@ -89,7 +86,7 @@ int CreateMemoryObject(size_t size, int executable) { |
#elif defined(OS_WIN) |
-NaClListener* g_listener; |
+IPC::Sender* g_sender; |
// We wrap the function to convert the bool return value to an int. |
int BrokerDuplicateHandle(NaClHandle source_handle, |
@@ -105,14 +102,14 @@ int BrokerDuplicateHandle(NaClHandle source_handle, |
int AttachDebugExceptionHandler(const void* info, size_t info_size) { |
std::string info_string(reinterpret_cast<const char*>(info), info_size); |
bool result = false; |
- if (!g_listener->Send(new NaClProcessMsg_AttachDebugExceptionHandler( |
+ if (!g_sender->Send(new NaClProcessMsg_AttachDebugExceptionHandler( |
info_string, &result))) |
return false; |
return result; |
} |
void DebugStubPortSelectedHandler(uint16_t port) { |
- g_listener->Send(new NaClProcessHostMsg_DebugStubPortSelected(port)); |
+ g_sender->Send(new NaClProcessHostMsg_DebugStubPortSelected(port)); |
} |
#endif |
@@ -139,12 +136,10 @@ void SetUpIPCAdapter(IPC::ChannelHandle* handle, |
NaClAppSetDesc(nap, nacl_fd, ipc_adapter->MakeNaClDesc()); |
} |
-} // namespace |
- |
class BrowserValidationDBProxy : public NaClValidationDB { |
public: |
- explicit BrowserValidationDBProxy(NaClListener* listener) |
- : listener_(listener) { |
+ explicit BrowserValidationDBProxy(IPC::Sender* sender) |
+ : sender_(sender) { |
} |
virtual bool QueryKnownToValidate(const std::string& signature) OVERRIDE { |
@@ -152,8 +147,8 @@ class BrowserValidationDBProxy : public NaClValidationDB { |
// value we're safe. For example if the message is (for some reason) |
// dispatched as an async message the return parameter will not be written. |
bool result = false; |
- if (!listener_->Send(new NaClProcessMsg_QueryKnownToValidate(signature, |
- &result))) { |
+ if (!sender_->Send(new NaClProcessMsg_QueryKnownToValidate(signature, |
+ &result))) { |
LOG(ERROR) << "Failed to query NaCl validation cache."; |
result = false; |
} |
@@ -162,7 +157,7 @@ class BrowserValidationDBProxy : public NaClValidationDB { |
virtual void SetKnownToValidate(const std::string& signature) OVERRIDE { |
// Caching is optional: NaCl will still work correctly if the IPC fails. |
- if (!listener_->Send(new NaClProcessMsg_SetKnownToValidate(signature))) { |
+ if (!sender_->Send(new NaClProcessMsg_SetKnownToValidate(signature))) { |
LOG(ERROR) << "Failed to update NaCl validation cache."; |
} |
} |
@@ -176,10 +171,10 @@ class BrowserValidationDBProxy : public NaClValidationDB { |
} |
IPC::PlatformFileForTransit ipc_fd = IPC::InvalidPlatformFileForTransit(); |
base::FilePath ipc_path; |
- if (!listener_->Send(new NaClProcessMsg_ResolveFileToken(file_token->lo, |
- file_token->hi, |
- &ipc_fd, |
- &ipc_path))) { |
+ if (!sender_->Send(new NaClProcessMsg_ResolveFileToken(file_token->lo, |
+ file_token->hi, |
+ &ipc_fd, |
+ &ipc_path))) { |
return false; |
} |
if (ipc_fd == IPC::InvalidPlatformFileForTransit()) { |
@@ -200,75 +195,41 @@ class BrowserValidationDBProxy : public NaClValidationDB { |
} |
private: |
- // The listener never dies, otherwise this might be a dangling reference. |
- NaClListener* listener_; |
+ // Do not own the sender. Practically, this is pointing to NaClListener |
+ // instance, which will be alive while the plugin is running. |
+ IPC::Sender* sender_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(BrowserValidationDBProxy); |
}; |
+} // namespace |
+ |
-NaClListener::NaClListener() : shutdown_event_(true, false), |
- io_thread_("NaCl_IOThread"), |
- uses_nonsfi_mode_(false), |
+SfiListenerDelegate::SfiListenerDelegate() |
+#if defined(OS_POSIX) |
+ : |
+#endif // OS_POSIX |
#if defined(OS_LINUX) |
- prereserved_sandbox_size_(0), |
-#endif |
+ prereserved_sandbox_size_(0), |
+#endif // OS_LINUX |
#if defined(OS_POSIX) |
- number_of_cores_(-1), // unknown/error |
-#endif |
- main_loop_(NULL) { |
- io_thread_.StartWithOptions( |
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
-#if defined(OS_WIN) |
- DCHECK(g_listener == NULL); |
- g_listener = this; |
-#endif |
+ number_of_cores_(-1) |
+#endif // OS_POSIX |
+{ |
} |
-NaClListener::~NaClListener() { |
- NOTREACHED(); |
- shutdown_event_.Signal(); |
-#if defined(OS_WIN) |
- g_listener = NULL; |
-#endif |
+SfiListenerDelegate::~SfiListenerDelegate() { |
} |
-bool NaClListener::Send(IPC::Message* msg) { |
- DCHECK(main_loop_ != NULL); |
- if (base::MessageLoop::current() == main_loop_) { |
- // This thread owns the channel. |
- return channel_->Send(msg); |
- } else { |
- // This thread does not own the channel. |
- return filter_->Send(msg); |
- } |
-} |
- |
-void NaClListener::Listen() { |
- std::string channel_name = |
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
- switches::kProcessChannelID); |
- channel_ = IPC::SyncChannel::Create( |
- this, io_thread_.message_loop_proxy().get(), &shutdown_event_); |
- filter_ = new IPC::SyncMessageFilter(&shutdown_event_); |
- channel_->AddFilter(filter_.get()); |
- channel_->Init(channel_name, IPC::Channel::MODE_CLIENT, true); |
- main_loop_ = base::MessageLoop::current(); |
- main_loop_->Run(); |
-} |
- |
-bool NaClListener::OnMessageReceived(const IPC::Message& msg) { |
- bool handled = true; |
- IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) |
- IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) |
- IPC_MESSAGE_UNHANDLED(handled = false) |
- IPC_END_MESSAGE_MAP() |
- return handled; |
-} |
- |
-void NaClListener::OnStart(const nacl::NaClStartParams& params) { |
- if (uses_nonsfi_mode_) { |
- StartNonSfi(params); |
- return; |
- } |
+void SfiListenerDelegate::Start( |
+ const nacl::NaClStartParams& params, |
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy, |
+ IPC::ChannelHandle trusted_channel_handle, |
+ IPC::Sender* sender) { |
+#if defined(OS_WIN) |
+ DCHECK(g_sender == NULL); |
+ g_sender = sender; |
+#endif |
#if defined(OS_LINUX) || defined(OS_MACOSX) |
int urandom_fd = dup(base::GetUrandomFD()); |
@@ -287,27 +248,25 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) { |
return; |
} |
- IPC::ChannelHandle browser_handle; |
+ IPC::ChannelHandle ppapi_browser_handle; |
IPC::ChannelHandle ppapi_renderer_handle; |
if (params.enable_ipc_proxy) { |
- browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
+ ppapi_browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
// Create the PPAPI IPC channels between the NaCl IRT and the host |
// (browser/renderer) processes. The IRT uses these channels to |
// communicate with the host and to initialize the IPC dispatchers. |
- SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), |
+ SetUpIPCAdapter(&ppapi_browser_handle, io_message_loop_proxy, |
nap, NACL_CHROME_DESC_BASE); |
- SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.message_loop_proxy(), |
+ SetUpIPCAdapter(&ppapi_renderer_handle, io_message_loop_proxy, |
nap, NACL_CHROME_DESC_BASE + 1); |
} |
- IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener( |
- io_thread_.message_loop_proxy(), &shutdown_event_); |
- if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( |
- browser_handle, ppapi_renderer_handle, |
- trusted_renderer_handle, IPC::ChannelHandle()))) |
+ if (!sender->Send(new NaClProcessHostMsg_PpapiChannelsCreated( |
+ ppapi_browser_handle, ppapi_renderer_handle, |
+ trusted_channel_handle, IPC::ChannelHandle()))) |
LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; |
std::vector<nacl::FileDescriptor> handles = params.handles; |
@@ -352,7 +311,7 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) { |
CHECK_EQ(params.validation_cache_key.length(), (size_t) 64); |
// The cache structure is not freed and exists until the NaCl process exits. |
args->validation_cache = CreateValidationCache( |
- new BrowserValidationDBProxy(this), params.validation_cache_key, |
+ new BrowserValidationDBProxy(sender), params.validation_cache_key, |
params.version); |
} |
@@ -409,105 +368,4 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) { |
NaClChromeMainStartApp(nap, args); |
} |
-void NaClListener::StartNonSfi(const nacl::NaClStartParams& params) { |
-#if !defined(OS_LINUX) |
- NOTREACHED() << "Non-SFI NaCl is only supported on Linux"; |
-#else |
- // Random number source initialization. |
- nacl::nonsfi::SetUrandomFd(base::GetUrandomFD()); |
- |
- IPC::ChannelHandle browser_handle; |
- IPC::ChannelHandle ppapi_renderer_handle; |
- IPC::ChannelHandle manifest_service_handle; |
- |
- if (params.enable_ipc_proxy) { |
- browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
- ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
- manifest_service_handle = |
- IPC::Channel::GenerateVerifiedChannelID("nacl"); |
- |
- // In non-SFI mode, we neither intercept nor rewrite the message using |
- // NaClIPCAdapter, and the channels are connected between the plugin and |
- // the hosts directly. So, the IPC::Channel instances will be created in |
- // the plugin side, because the IPC::Listener needs to live on the |
- // plugin's main thread. However, on initialization (i.e. before loading |
- // the plugin binary), the FD needs to be passed to the hosts. So, here |
- // we create raw FD pairs, and pass the client side FDs to the hosts, |
- // and the server side FDs to the plugin. |
- int browser_server_ppapi_fd; |
- int browser_client_ppapi_fd; |
- int renderer_server_ppapi_fd; |
- int renderer_client_ppapi_fd; |
- int manifest_service_server_fd; |
- int manifest_service_client_fd; |
- if (!IPC::SocketPair( |
- &browser_server_ppapi_fd, &browser_client_ppapi_fd) || |
- !IPC::SocketPair( |
- &renderer_server_ppapi_fd, &renderer_client_ppapi_fd) || |
- !IPC::SocketPair( |
- &manifest_service_server_fd, &manifest_service_client_fd)) { |
- LOG(ERROR) << "Failed to create sockets for IPC."; |
- return; |
- } |
- |
- // Set the plugin IPC channel FDs. |
- ppapi::SetIPCFileDescriptors(browser_server_ppapi_fd, |
- renderer_server_ppapi_fd, |
- manifest_service_server_fd); |
- ppapi::StartUpPlugin(); |
- |
- // Send back to the client side IPC channel FD to the host. |
- browser_handle.socket = |
- base::FileDescriptor(browser_client_ppapi_fd, true); |
- ppapi_renderer_handle.socket = |
- base::FileDescriptor(renderer_client_ppapi_fd, true); |
- manifest_service_handle.socket = |
- base::FileDescriptor(manifest_service_client_fd, true); |
- } |
- |
- // TODO(teravest): Do we plan on using this renderer handle for nexe loading |
- // for non-SFI? Right now, passing an empty channel handle instead causes |
- // hangs, so we'll keep it. |
- IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener( |
- io_thread_.message_loop_proxy(), &shutdown_event_); |
- if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( |
- browser_handle, ppapi_renderer_handle, |
- trusted_renderer_handle, manifest_service_handle))) |
- LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; |
- |
- // Ensure that the validation cache key (used as an extra input to the |
- // validation cache's hashing) isn't exposed accidentally. |
- CHECK(!params.validation_cache_enabled); |
- CHECK(params.validation_cache_key.size() == 0); |
- CHECK(params.version.size() == 0); |
- // Ensure that a debug stub FD isn't passed through accidentally. |
- CHECK(!params.enable_debug_stub); |
- CHECK(params.debug_stub_server_bound_socket.fd == -1); |
- |
- CHECK(!params.uses_irt); |
- CHECK(params.handles.empty()); |
- |
- CHECK(params.nexe_file != IPC::InvalidPlatformFileForTransit()); |
- CHECK(params.nexe_token_lo == 0); |
- CHECK(params.nexe_token_hi == 0); |
- nacl::nonsfi::MainStart( |
- IPC::PlatformFileForTransitToPlatformFile(params.nexe_file)); |
-#endif // defined(OS_LINUX) |
-} |
- |
-IPC::ChannelHandle NaClListener::CreateTrustedListener( |
- base::MessageLoopProxy* message_loop_proxy, |
- base::WaitableEvent* shutdown_event) { |
- // The argument passed to GenerateVerifiedChannelID() here MUST be "nacl". |
- // Using an alternate channel name prevents the pipe from being created on |
- // Windows when the sandbox is enabled. |
- IPC::ChannelHandle trusted_renderer_handle = |
- IPC::Channel::GenerateVerifiedChannelID("nacl"); |
- trusted_listener_ = new NaClTrustedListener( |
- trusted_renderer_handle, io_thread_.message_loop_proxy().get()); |
-#if defined(OS_POSIX) |
- trusted_renderer_handle.socket = base::FileDescriptor( |
- trusted_listener_->TakeClientFileDescriptor(), true); |
-#endif |
- return trusted_renderer_handle; |
-} |
+} // namespace nacl |