diff options
author | mseaborn <mseaborn@chromium.org> | 2016-01-04 13:14:13 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-04 21:15:29 +0000 |
commit | 3bedcdc7ad86115836141f91ffd7fa331d07e2a1 (patch) | |
tree | ab8614bf4f6dca588eb74aa22db7d36a2d7f461a | |
parent | 1baaf4eee10edab63f61206e0cabc34c0ee1e52c (diff) | |
download | chromium_src-3bedcdc7ad86115836141f91ffd7fa331d07e2a1.zip chromium_src-3bedcdc7ad86115836141f91ffd7fa331d07e2a1.tar.gz chromium_src-3bedcdc7ad86115836141f91ffd7fa331d07e2a1.tar.bz2 |
PNaCl: Use Chrome IPC to talk to the linker process, instead of SRPC
This is the second-to-last remaining use of SRPC.
* Change pnacl_translate_thread.cc to send its request using Chrome
IPC instead of SRPC. Similarly, change
irt_pnacl_translator_link.cc to receive its request this way.
* Add plumbing so that pnacl_translate_thread.cc can acquire a Chrome
IPC channel object. Change LaunchSelLdr() (in ppb_nacl_private.h)
to return this channel, and plumb it through service_runtime.h too.
* Extend nacl_message_scanner.cc to handle a couple of things our new
IPC message needs:
* File handles inside of std::vector<>s.
* File handles inside of sync messages. (Previously, only sync
replies were handled.)
* Change a BUILD.gn to account for #includes of
content/public/common/sandbox_init.h and
ppapi/proxy/{serialized_handle.h,ppapi_messages.h}.
BUG=302078
TEST=e.g. NaClBrowserTestPnacl.PPAPICore (tests PNaCl translation)
Review URL: https://codereview.chromium.org/1512733003
Cr-Commit-Position: refs/heads/master@{#367369}
-rw-r--r-- | components/nacl/renderer/plugin/BUILD.gn | 2 | ||||
-rw-r--r-- | components/nacl/renderer/plugin/pnacl_translate_thread.cc | 115 | ||||
-rw-r--r-- | components/nacl/renderer/plugin/pnacl_translate_thread.h | 13 | ||||
-rw-r--r-- | components/nacl/renderer/plugin/service_runtime.cc | 5 | ||||
-rw-r--r-- | components/nacl/renderer/plugin/service_runtime.h | 14 | ||||
-rw-r--r-- | components/nacl/renderer/plugin/temporary_file.cc | 6 | ||||
-rw-r--r-- | components/nacl/renderer/plugin/temporary_file.h | 5 | ||||
-rw-r--r-- | components/nacl/renderer/ppb_nacl_private.h | 7 | ||||
-rw-r--r-- | components/nacl/renderer/ppb_nacl_private_impl.cc | 32 | ||||
-rw-r--r-- | ppapi/nacl_irt/irt_pnacl_translator_link.cc | 91 | ||||
-rw-r--r-- | ppapi/proxy/nacl_message_scanner.cc | 38 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 12 |
12 files changed, 257 insertions, 83 deletions
diff --git a/components/nacl/renderer/plugin/BUILD.gn b/components/nacl/renderer/plugin/BUILD.gn index f4d2a82..5c3d22e 100644 --- a/components/nacl/renderer/plugin/BUILD.gn +++ b/components/nacl/renderer/plugin/BUILD.gn @@ -21,6 +21,7 @@ source_set("nacl_trusted_plugin") { deps = [ "//base", + "//content/public/common", "//media:shared_memory_support", "//native_client/src/shared/gio", "//native_client/src/shared/imc", @@ -33,6 +34,7 @@ source_set("nacl_trusted_plugin") { "//ppapi/c", "//ppapi/cpp:objects", "//ppapi/cpp/private:internal_module", + "//ppapi/proxy:ipc", ] if (is_linux) { diff --git a/components/nacl/renderer/plugin/pnacl_translate_thread.cc b/components/nacl/renderer/plugin/pnacl_translate_thread.cc index af71b69..85a5b88 100644 --- a/components/nacl/renderer/plugin/pnacl_translate_thread.cc +++ b/components/nacl/renderer/plugin/pnacl_translate_thread.cc @@ -15,9 +15,12 @@ #include "components/nacl/renderer/plugin/srpc_params.h" #include "components/nacl/renderer/plugin/temporary_file.h" #include "components/nacl/renderer/plugin/utility.h" +#include "content/public/common/sandbox_init.h" #include "native_client/src/shared/platform/nacl_sync_raii.h" #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" +#include "ppapi/c/ppb_file_io.h" #include "ppapi/cpp/var.h" +#include "ppapi/proxy/ppapi_messages.h" namespace plugin { namespace { @@ -86,7 +89,8 @@ PnaclTranslateThread::PnaclTranslateThread() num_threads_(0), nexe_file_(NULL), coordinator_error_info_(NULL), - coordinator_(NULL) { + coordinator_(NULL), + ld_channel_peer_pid_(base::kNullProcessId) { NaClXMutexCtor(&subprocess_mu_); NaClXMutexCtor(&cond_mu_); NaClXCondVarCtor(&buffer_cond_); @@ -126,6 +130,13 @@ void PnaclTranslateThread::RunCompile( DCHECK(compiler_subprocess_->service_runtime()); compiler_subprocess_active_ = true; + // Free this IPC channel now to make sure that it does not get freed on + // the child thread when the child thread calls Shutdown(). + // TODO(mseaborn): Convert DoCompile() to using Chrome IPC instead of SRPC, + // the same way DoLink() has been converted. Then we will use this IPC + // channel instead of just freeing it here. + compiler_subprocess_->service_runtime()->TakeTranslatorChannel(); + compile_finished_callback_ = compile_finished_callback; translate_thread_.reset(new NaClThread); if (translate_thread_ == NULL) { @@ -148,6 +159,17 @@ void PnaclTranslateThread::RunLink() { DCHECK(ld_subprocess_->service_runtime()); ld_subprocess_active_ = true; + // Take ownership of this IPC channel to make sure that it does not get + // freed on the child thread when the child thread calls Shutdown(). + ld_channel_ = ld_subprocess_->service_runtime()->TakeTranslatorChannel(); + // ld_channel_ is a IPC::SyncChannel, which is not thread-safe and cannot be + // used directly by the child thread, so create a SyncMessageFilter which + // can be used by the child thread. + ld_channel_filter_ = ld_channel_->CreateSyncMessageFilter(); + // Make a copy of the process ID, again to avoid any thread-safety issues + // involved in accessing ld_subprocess_ on the child thread. + ld_channel_peer_pid_ = ld_subprocess_->service_runtime()->get_process_id(); + // Tear down the previous thread. // TODO(jvoung): Use base/threading or something where we can have a // persistent thread and easily post tasks to that persistent thread. @@ -186,6 +208,31 @@ void PnaclTranslateThread::EndStream() { NaClXMutexUnlock(&cond_mu_); } +ppapi::proxy::SerializedHandle PnaclTranslateThread::GetHandleForSubprocess( + TempFile* file, int32_t open_flags) { + IPC::PlatformFileForTransit file_for_transit; + +#if defined(OS_WIN) + if (!content::BrokerDuplicateHandle( + file->GetFileHandle(), + ld_channel_peer_pid_, + &file_for_transit, + 0, // desired_access is 0 since we're using DUPLICATE_SAME_ACCESS. + DUPLICATE_SAME_ACCESS)) { + return ppapi::proxy::SerializedHandle(); + } +#else + file_for_transit = base::FileDescriptor(dup(file->GetFileHandle()), true); +#endif + + // Using 0 disables any use of quota enforcement for this file handle. + PP_Resource file_io = 0; + + ppapi::proxy::SerializedHandle handle; + handle.set_file_handle(file_for_transit, open_flags, file_io); + return handle; +} + void WINAPI PnaclTranslateThread::DoCompileThread(void* arg) { PnaclTranslateThread* translator = reinterpret_cast<PnaclTranslateThread*>(arg); @@ -348,60 +395,42 @@ void PnaclTranslateThread::DoLink() { // and now, just leave now. if (!ld_subprocess_active_) return; - // Now that we are in helper thread, we can do the the blocking - // StartSrpcServices operation. - if (!ld_subprocess_->StartSrpcServices()) { - TranslateFailed( - PP_NACL_ERROR_SRPC_CONNECTION_FAIL, - "SRPC connection failure for " + ld_subprocess_->description()); - return; - } } - SrpcParams params; - std::vector<nacl::DescWrapper*> ld_in_files; - size_t i; - for (i = 0; i < obj_files_->size(); i++) { - // Reset object file for reading first. - if (!(*obj_files_)[i]->Reset()) { + // Reset object files for reading first. We do this before duplicating + // handles/FDs to prevent any handle/FD leaks in case any of the Reset() + // calls fail. + for (TempFile* obj_file : *obj_files_) { + if (!obj_file->Reset()) { TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, "Link process could not reset object file"); + return; } - ld_in_files.push_back((*obj_files_)[i]->read_wrapper()); } - for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) - ld_in_files.push_back(invalid_desc_wrapper_); - nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); + ppapi::proxy::SerializedHandle nexe_file = + GetHandleForSubprocess(nexe_file_, PP_FILEOPENFLAG_WRITE); + std::vector<ppapi::proxy::SerializedHandle> ld_input_files; + for (TempFile* obj_file : *obj_files_) { + ld_input_files.push_back( + GetHandleForSubprocess(obj_file, PP_FILEOPENFLAG_READ)); + } + int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); - // Run LD. - bool success = ld_subprocess_->InvokeSrpcMethod( - "RunWithSplit", - "ihhhhhhhhhhhhhhhhh", - ¶ms, - static_cast<int>(obj_files_->size()), - ld_in_files[0]->desc(), - ld_in_files[1]->desc(), - ld_in_files[2]->desc(), - ld_in_files[3]->desc(), - ld_in_files[4]->desc(), - ld_in_files[5]->desc(), - ld_in_files[6]->desc(), - ld_in_files[7]->desc(), - ld_in_files[8]->desc(), - ld_in_files[9]->desc(), - ld_in_files[10]->desc(), - ld_in_files[11]->desc(), - ld_in_files[12]->desc(), - ld_in_files[13]->desc(), - ld_in_files[14]->desc(), - ld_in_files[15]->desc(), - ld_out_file->desc()); + bool success = false; + bool sent = ld_channel_filter_->Send( + new PpapiMsg_PnaclTranslatorLink(ld_input_files, nexe_file, &success)); + if (!sent) { + TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, + "link failed: reply not received from linker."); + return; + } if (!success) { TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, - "link failed."); + "link failed: linker returned failure status."); return; } + GetNaClInterface()->LogTranslateTime( "NaCl.Perf.PNaClLoadTime.LinkTime", NaClGetTimeOfDayMicroseconds() - link_start_time); diff --git a/components/nacl/renderer/plugin/pnacl_translate_thread.h b/components/nacl/renderer/plugin/pnacl_translate_thread.h index 7db7e7d..cbb0ed0 100644 --- a/components/nacl/renderer/plugin/pnacl_translate_thread.h +++ b/components/nacl/renderer/plugin/pnacl_translate_thread.h @@ -17,6 +17,7 @@ #include "native_client/src/shared/platform/nacl_sync_checked.h" #include "native_client/src/shared/platform/nacl_threads.h" #include "ppapi/cpp/completion_callback.h" +#include "ppapi/proxy/serialized_handle.h" struct PP_PNaClOptions; @@ -84,6 +85,9 @@ class PnaclTranslateThread { bool started() const { return coordinator_ != NULL; } private: + ppapi::proxy::SerializedHandle GetHandleForSubprocess(TempFile* file, + int32_t open_flags); + // Helper thread entry point for compilation. Takes a pointer to // PnaclTranslateThread and calls DoCompile(). static void WINAPI DoCompileThread(void* arg); @@ -149,6 +153,15 @@ class PnaclTranslateThread { PP_PNaClOptions* pnacl_options_; std::string architecture_attributes_; PnaclCoordinator* coordinator_; + + // This IPC::SyncChannel can only be used and freed by the parent thread. + scoped_ptr<IPC::SyncChannel> ld_channel_; + // This IPC::SyncMessageFilter can be used by the child thread. + scoped_refptr<IPC::SyncMessageFilter> ld_channel_filter_; + // PID of the subprocess, needed for copying handles to the subprocess on + // Windows. This is used by the child thread. + base::ProcessId ld_channel_peer_pid_; + private: NACL_DISALLOW_COPY_AND_ASSIGN(PnaclTranslateThread); }; diff --git a/components/nacl/renderer/plugin/service_runtime.cc b/components/nacl/renderer/plugin/service_runtime.cc index 9c4e2b4..81479d3 100644 --- a/components/nacl/renderer/plugin/service_runtime.cc +++ b/components/nacl/renderer/plugin/service_runtime.cc @@ -38,7 +38,8 @@ ServiceRuntime::ServiceRuntime(Plugin* plugin, pp_instance_(pp_instance), main_service_runtime_(main_service_runtime), uses_nonsfi_mode_(uses_nonsfi_mode), - bootstrap_channel_(NACL_INVALID_HANDLE) { + bootstrap_channel_(NACL_INVALID_HANDLE), + process_id_(base::kNullProcessId) { } bool ServiceRuntime::SetupCommandChannel() { @@ -91,6 +92,8 @@ void ServiceRuntime::StartSelLdr(const SelLdrStartParams& params, PP_FromBool(uses_nonsfi_mode_), params.process_type, &bootstrap_channel_, + &translator_channel_, + &process_id_, callback.pp_completion_callback()); subprocess_.reset(tmp_subprocess.release()); } diff --git a/components/nacl/renderer/plugin/service_runtime.h b/components/nacl/renderer/plugin/service_runtime.h index c3a659c..cc966a4 100644 --- a/components/nacl/renderer/plugin/service_runtime.h +++ b/components/nacl/renderer/plugin/service_runtime.h @@ -12,7 +12,10 @@ #define COMPONENTS_NACL_RENDERER_PLUGIN_SERVICE_RUNTIME_H_ #include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/process/process_handle.h" #include "components/nacl/renderer/plugin/utility.h" +#include "ipc/ipc_sync_channel.h" #include "native_client/src/include/nacl_macros.h" #include "native_client/src/include/nacl_scoped_ptr.h" #include "native_client/src/public/imc_types.h" @@ -70,6 +73,14 @@ class ServiceRuntime { bool main_service_runtime() const { return main_service_runtime_; } + scoped_ptr<IPC::SyncChannel> TakeTranslatorChannel() { + return scoped_ptr<IPC::SyncChannel>(translator_channel_.release()); + } + + // Returns the PID of the subprocess. This PID is needed for copying + // handles to the subprocess on Windows. + base::ProcessId get_process_id() { return process_id_; } + private: NACL_DISALLOW_COPY_AND_ASSIGN(ServiceRuntime); @@ -84,6 +95,9 @@ class ServiceRuntime { nacl::scoped_ptr<SelLdrLauncherChrome> subprocess_; NaClHandle bootstrap_channel_; + + scoped_ptr<IPC::SyncChannel> translator_channel_; + base::ProcessId process_id_; }; } // namespace plugin diff --git a/components/nacl/renderer/plugin/temporary_file.cc b/components/nacl/renderer/plugin/temporary_file.cc index 10502ea..bd942c5 100644 --- a/components/nacl/renderer/plugin/temporary_file.cc +++ b/components/nacl/renderer/plugin/temporary_file.cc @@ -62,7 +62,13 @@ bool TempFile::Reset() { } PP_FileHandle TempFile::TakeFileHandle() { + DCHECK(file_handle_.IsValid()); return file_handle_.TakePlatformFile(); } +PP_FileHandle TempFile::GetFileHandle() { + DCHECK(file_handle_.IsValid()); + return file_handle_.GetPlatformFile(); +} + } // namespace plugin diff --git a/components/nacl/renderer/plugin/temporary_file.h b/components/nacl/renderer/plugin/temporary_file.h index 4941e98..4e4e9af 100644 --- a/components/nacl/renderer/plugin/temporary_file.h +++ b/components/nacl/renderer/plugin/temporary_file.h @@ -61,6 +61,11 @@ class TempFile { // valid after TakeFileHandle() is called. PP_FileHandle TakeFileHandle(); + // Returns a handle to the file, without transferring ownership of it. + // This handle remains valid until the TempFile object is destroyed or + // TakeFileHandle() is called. + PP_FileHandle GetFileHandle(); + private: NACL_DISALLOW_COPY_AND_ASSIGN(TempFile); diff --git a/components/nacl/renderer/ppb_nacl_private.h b/components/nacl/renderer/ppb_nacl_private.h index 2683652..26ec98e 100644 --- a/components/nacl/renderer/ppb_nacl_private.h +++ b/components/nacl/renderer/ppb_nacl_private.h @@ -5,6 +5,9 @@ #ifndef COMPONENTS_NACL_RENDERER_PPB_NACL_PRIVATE_H_ #define COMPONENTS_NACL_RENDERER_PPB_NACL_PRIVATE_H_ +#include "base/memory/scoped_ptr.h" +#include "base/process/process_handle.h" +#include "ipc/ipc_sync_channel.h" #include "ppapi/c/pp_bool.h" #include "ppapi/c/pp_completion_callback.h" #include "ppapi/c/pp_instance.h" @@ -214,6 +217,8 @@ struct PPB_NaCl_Private { * LaunchSelLdr takes the ownership of the file handle. * The |uses_nonsfi_mode| flag indicates whether or not nonsfi-mode should * be used with the binary pointed by the url. + * |translator_channel| and |process_id| are filled out when launching PNaCl + * translator processes. */ void (*LaunchSelLdr)(PP_Instance instance, PP_Bool main_service_runtime, @@ -222,6 +227,8 @@ struct PPB_NaCl_Private { PP_Bool uses_nonsfi_mode, PP_NaClAppProcessType process_type, void* imc_handle, + scoped_ptr<IPC::SyncChannel>* translator_channel, + base::ProcessId* process_id, struct PP_CompletionCallback callback); /* On POSIX systems, this function returns the file descriptor of * /dev/urandom. On non-POSIX systems, this function returns 0. diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc index 6cbdfe4..7f87ddc 100644 --- a/components/nacl/renderer/ppb_nacl_private_impl.cc +++ b/components/nacl/renderer/ppb_nacl_private_impl.cc @@ -389,6 +389,16 @@ NaClAppProcessType PP_ToNaClAppProcessType( return static_cast<NaClAppProcessType>(pp_process_type); } +// A dummy IPC::Listener object with a no-op message handler. We use +// this with an IPC::SyncChannel where we only send synchronous +// messages and don't need to handle any messages other than sync +// replies. +class NoOpListener : public IPC::Listener { + public: + bool OnMessageReceived(const IPC::Message& message) override { return false; } + void OnChannelError() override {} +}; + // Launch NaCl's sel_ldr process. void LaunchSelLdr(PP_Instance instance, PP_Bool main_service_runtime, @@ -397,6 +407,8 @@ void LaunchSelLdr(PP_Instance instance, PP_Bool uses_nonsfi_mode, PP_NaClAppProcessType pp_process_type, void* imc_handle, + scoped_ptr<IPC::SyncChannel>* translator_channel, + base::ProcessId* process_id, PP_CompletionCallback callback) { CHECK(ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()-> BelongsToCurrentThread()); @@ -516,8 +528,24 @@ void LaunchSelLdr(PP_Instance instance, // Don't save instance_info if channel handle is invalid. if (IsValidChannelHandle(instance_info.channel_handle)) { - NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); - nacl_plugin_instance->instance_info.reset(new InstanceInfo(instance_info)); + if (process_type == kPNaClTranslatorProcessType) { + // Return an IPC channel which allows communicating with a PNaCl + // translator process. + *translator_channel = IPC::SyncChannel::Create( + instance_info.channel_handle, + IPC::Channel::MODE_CLIENT, + new NoOpListener, + content::RenderThread::Get()->GetIOMessageLoopProxy(), + true, + content::RenderThread::Get()->GetShutdownEvent()); + *process_id = launch_result.plugin_pid; + } else { + // Save the channel handle for when StartPpapiProxy() is called. + NaClPluginInstance* nacl_plugin_instance = + GetNaClPluginInstance(instance); + nacl_plugin_instance->instance_info.reset( + new InstanceInfo(instance_info)); + } } *(static_cast<NaClHandle*>(imc_handle)) = diff --git a/ppapi/nacl_irt/irt_pnacl_translator_link.cc b/ppapi/nacl_irt/irt_pnacl_translator_link.cc index af31fd4..b3e13ec 100644 --- a/ppapi/nacl_irt/irt_pnacl_translator_link.cc +++ b/ppapi/nacl_irt/irt_pnacl_translator_link.cc @@ -2,58 +2,79 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/macros.h" #include "build/build_config.h" -#include "native_client/src/shared/platform/nacl_log.h" -#include "native_client/src/shared/srpc/nacl_srpc.h" +#include "ipc/ipc_listener.h" +#include "ipc/ipc_sync_channel.h" +#include "native_client/src/public/chrome_main.h" #include "native_client/src/untrusted/irt/irt_dev.h" #include "ppapi/nacl_irt/irt_interfaces.h" +#include "ppapi/nacl_irt/plugin_startup.h" +#include "ppapi/proxy/ppapi_messages.h" #if !defined(OS_NACL_NONSFI) namespace { -const int kMaxObjectFiles = 16; +typedef int (*CallbackFunc)(int nexe_fd, + const int* obj_file_fds, + int obj_file_fd_count); -int (*g_func)(int nexe_fd, - const int* obj_file_fds, - int obj_file_fd_count); - -void HandleLinkRequest(NaClSrpcRpc* rpc, - NaClSrpcArg** in_args, - NaClSrpcArg** out_args, - NaClSrpcClosure* done) { - int obj_file_count = in_args[0]->u.ival; - int nexe_fd = in_args[kMaxObjectFiles + 1]->u.hval; +class TranslatorLinkListener : public IPC::Listener { + public: + TranslatorLinkListener(const IPC::ChannelHandle& handle, CallbackFunc func) + : func_(func) { + channel_ = IPC::Channel::Create(handle, IPC::Channel::MODE_SERVER, this); + CHECK(channel_->Connect()); + } - if (obj_file_count < 1 || obj_file_count > kMaxObjectFiles) { - NaClLog(LOG_FATAL, "Bad object file count (%i)\n", obj_file_count); + // Needed for handling sync messages in OnMessageReceived(). + bool Send(IPC::Message* message) { + return channel_->Send(message); } - int obj_file_fds[obj_file_count]; - for (int i = 0; i < obj_file_count; i++) { - obj_file_fds[i] = in_args[i + 1]->u.hval; + + virtual bool OnMessageReceived(const IPC::Message& msg) { + bool handled = false; + IPC_BEGIN_MESSAGE_MAP(TranslatorLinkListener, msg) + IPC_MESSAGE_HANDLER_DELAY_REPLY(PpapiMsg_PnaclTranslatorLink, + OnPnaclTranslatorLink) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; } - int result = g_func(nexe_fd, obj_file_fds, obj_file_count); + private: + void OnPnaclTranslatorLink( + const std::vector<ppapi::proxy::SerializedHandle>& obj_files, + ppapi::proxy::SerializedHandle nexe_file, + IPC::Message* reply_msg) { + CHECK(nexe_file.is_file()); - rpc->result = result == 0 ? NACL_SRPC_RESULT_OK : NACL_SRPC_RESULT_APP_ERROR; - done->Run(done); -} + std::vector<int> obj_file_fds(obj_files.size()); + for (size_t i = 0; i < obj_files.size(); ++i) { + CHECK(obj_files[i].is_file()); + obj_file_fds[i] = obj_files[i].descriptor().fd; + } + int result = func_(nexe_file.descriptor().fd, + obj_file_fds.data(), + obj_file_fds.size()); + bool success = (result == 0); + PpapiMsg_PnaclTranslatorLink::WriteReplyParams(reply_msg, success); + Send(reply_msg); + } + + scoped_ptr<IPC::Channel> channel_; + CallbackFunc func_; -const struct NaClSrpcHandlerDesc kSrpcMethods[] = { - { "RunWithSplit:ihhhhhhhhhhhhhhhhh:", HandleLinkRequest }, - { NULL, NULL }, + DISALLOW_COPY_AND_ASSIGN(TranslatorLinkListener); }; -void ServeLinkRequest(int (*func)(int nexe_fd, - const int* obj_file_fds, - int obj_file_fd_count)) { - g_func = func; - if (!NaClSrpcModuleInit()) { - NaClLog(LOG_FATAL, "NaClSrpcModuleInit() failed\n"); - } - if (!NaClSrpcAcceptClientConnection(kSrpcMethods)) { - NaClLog(LOG_FATAL, "NaClSrpcAcceptClientConnection() failed\n"); - } +void ServeLinkRequest(CallbackFunc func) { + base::MessageLoop loop; + int fd = ppapi::GetRendererIPCFileDescriptor(); + IPC::ChannelHandle handle("NaCl IPC", base::FileDescriptor(fd, false)); + new TranslatorLinkListener(handle, func); + loop.Run(); } } diff --git a/ppapi/proxy/nacl_message_scanner.cc b/ppapi/proxy/nacl_message_scanner.cc index c95287e..5011501 100644 --- a/ppapi/proxy/nacl_message_scanner.cc +++ b/ppapi/proxy/nacl_message_scanner.cc @@ -143,6 +143,15 @@ void ScanParam(const IPC::Message& param, ScanningResults* results) { IPC::WriteParam(results->new_msg.get(), param); } +template <class T> +void ScanParam(const std::vector<T>& vec, ScanningResults* results) { + if (results->new_msg) + IPC::WriteParam(results->new_msg.get(), static_cast<int>(vec.size())); + for (const T& element : vec) { + ScanParam(element, results); + } +} + // Overload to match all other types. If we need to rewrite the message, write // the parameter. template <class T> @@ -192,6 +201,21 @@ class MessageScannerImpl { return true; } + bool ScanSyncMessage(ScanningResults* results) { + typename base::TupleTypes<typename MessageType::Schema::SendParam> + ::ValueTuple params; + if (!MessageType::ReadSendParam(msg_, ¶ms)) + return false; + // If we need to rewrite the message, write the message id first. + if (results->new_msg) { + results->new_msg->set_sync(); + int id = IPC::SyncMessage::GetMessageId(*msg_); + results->new_msg->WriteInt(id); + } + ScanTuple(params, results); + return true; + } + bool ScanReply(ScanningResults* results) { typename base::TupleTypes<typename MessageType::Schema::ReplyParam> ::ValueTuple params; @@ -206,8 +230,6 @@ class MessageScannerImpl { ScanTuple(params, results); return true; } - // TODO(dmichael): Add ScanSyncMessage for outgoing sync messages, if we ever - // need to scan those. private: const MessageType* msg_; @@ -226,6 +248,17 @@ class MessageScannerImpl { return false; \ break; \ } +#define CASE_FOR_SYNC_MESSAGE(MESSAGE_TYPE) \ + case MESSAGE_TYPE::ID: { \ + MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \ + if (rewrite_msg) \ + results.new_msg.reset( \ + new IPC::Message(msg.routing_id(), msg.type(), \ + IPC::Message::PRIORITY_NORMAL)); \ + if (!scanner.ScanSyncMessage(&results)) \ + return false; \ + break; \ + } #define CASE_FOR_REPLY(MESSAGE_TYPE) \ case MESSAGE_TYPE::ID: { \ MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \ @@ -331,6 +364,7 @@ bool NaClMessageScanner::ScanMessage( CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated) CASE_FOR_MESSAGE(PpapiMsg_PPPMessaging_HandleMessage) CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply) + CASE_FOR_SYNC_MESSAGE(PpapiMsg_PnaclTranslatorLink) CASE_FOR_REPLY(PpapiHostMsg_OpenResource) CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_Create) CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer) diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 2a59a7a..41be9a4 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -871,6 +871,18 @@ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPInstancePrivate_GetInstanceObject, #endif // !defined(OS_NACL) && !defined(NACL_WIN64) +// This message is sent from the renderer to the PNaCl linker process +// (NaCl untrusted code -- a nexe). This message tells the PNaCl +// linker to link the given object files together to produce a nexe +// file, writing the output to the given file handle. +IPC_SYNC_MESSAGE_CONTROL2_1(PpapiMsg_PnaclTranslatorLink, + /* object file FDs for inputs */ + std::vector<ppapi::proxy::SerializedHandle>, + /* nexe file FD for output */ + ppapi::proxy::SerializedHandle, + /* success status result */ + bool) + // Reports to the browser that a plugin has been active. IPC_MESSAGE_CONTROL0(PpapiHostMsg_Keepalive) |