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}
This commit is contained in:
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP,
|
||||
"Link process could not reset object file");
|
||||
}
|
||||
ld_in_files.push_back((*obj_files_)[i]->read_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));
|
||||
}
|
||||
for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++)
|
||||
ld_in_files.push_back(invalid_desc_wrapper_);
|
||||
|
||||
nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper();
|
||||
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());
|
||||
if (!success) {
|
||||
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.");
|
||||
"link failed: reply not received from linker.");
|
||||
return;
|
||||
}
|
||||
if (!success) {
|
||||
TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL,
|
||||
"link failed: linker returned failure status.");
|
||||
return;
|
||||
}
|
||||
|
||||
GetNaClInterface()->LogTranslateTime(
|
||||
"NaCl.Perf.PNaClLoadTime.LinkTime",
|
||||
NaClGetTimeOfDayMicroseconds() - link_start_time);
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)) =
|
||||
|
@ -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;
|
||||
|
||||
if (obj_file_count < 1 || obj_file_count > kMaxObjectFiles) {
|
||||
NaClLog(LOG_FATAL, "Bad object file count (%i)\n", obj_file_count);
|
||||
}
|
||||
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;
|
||||
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());
|
||||
}
|
||||
|
||||
int result = g_func(nexe_fd, obj_file_fds, obj_file_count);
|
||||
// Needed for handling sync messages in OnMessageReceived().
|
||||
bool Send(IPC::Message* message) {
|
||||
return channel_->Send(message);
|
||||
}
|
||||
|
||||
rpc->result = result == 0 ? NACL_SRPC_RESULT_OK : NACL_SRPC_RESULT_APP_ERROR;
|
||||
done->Run(done);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
const struct NaClSrpcHandlerDesc kSrpcMethods[] = {
|
||||
{ "RunWithSplit:ihhhhhhhhhhhhhhhhh:", HandleLinkRequest },
|
||||
{ NULL, NULL },
|
||||
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());
|
||||
|
||||
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_;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
Reference in New Issue
Block a user