| // Copyright 2015 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 "base/macros.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| #include "build/build_config.h" |
| #include "ipc/ipc_listener.h" |
| #include "ipc/ipc_sync_channel.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 { |
| |
| class TranslatorCompileListener : public IPC::Listener { |
| public: |
| TranslatorCompileListener(const IPC::ChannelHandle& handle, |
| const struct nacl_irt_pnacl_compile_funcs* funcs) |
| : funcs_(funcs) { |
| channel_ = IPC::Channel::Create(handle, IPC::Channel::MODE_SERVER, this); |
| CHECK(channel_->Connect()); |
| } |
| |
| // Needed for handling sync messages in OnMessageReceived(). |
| bool Send(IPC::Message* message) { |
| return channel_->Send(message); |
| } |
| |
| virtual bool OnMessageReceived(const IPC::Message& msg) { |
| bool handled = false; |
| IPC_BEGIN_MESSAGE_MAP(TranslatorCompileListener, msg) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(PpapiMsg_PnaclTranslatorCompileInit, |
| OnPnaclTranslatorCompileInit) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(PpapiMsg_PnaclTranslatorCompileChunk, |
| OnPnaclTranslatorCompileChunk) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(PpapiMsg_PnaclTranslatorCompileEnd, |
| OnPnaclTranslatorCompileEnd) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled; |
| } |
| |
| private: |
| void OnPnaclTranslatorCompileInit( |
| int num_threads, |
| const std::vector<ppapi::proxy::SerializedHandle>& obj_files, |
| const std::vector<std::string>& cmd_flags, |
| IPC::Message* reply_msg) { |
| 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; |
| } |
| |
| std::vector<char*> cmd_flags_cstrings(cmd_flags.size()); |
| for (size_t i = 0; i < cmd_flags.size(); ++i) { |
| // It's OK to use const_cast here because the callee (the translator) |
| // is not supposed to modify the strings. (The interface definition |
| // should have used "const char* const*".) |
| cmd_flags_cstrings[i] = const_cast<char*>(cmd_flags[i].c_str()); |
| } |
| |
| char* error_cstr = funcs_->init_callback(num_threads, |
| obj_file_fds.data(), |
| obj_file_fds.size(), |
| cmd_flags_cstrings.data(), |
| cmd_flags_cstrings.size()); |
| bool success = !error_cstr; |
| std::string error_str(error_cstr ? error_cstr : ""); |
| PpapiMsg_PnaclTranslatorCompileInit::WriteReplyParams( |
| reply_msg, success, error_str); |
| Send(reply_msg); |
| } |
| |
| void OnPnaclTranslatorCompileChunk(const std::string& data_chunk, |
| IPC::Message* reply_msg) { |
| int result = funcs_->data_callback(data_chunk.data(), data_chunk.size()); |
| bool success = !result; |
| PpapiMsg_PnaclTranslatorCompileChunk::WriteReplyParams(reply_msg, success); |
| Send(reply_msg); |
| } |
| |
| void OnPnaclTranslatorCompileEnd(IPC::Message* reply_msg) { |
| char* error_cstr = funcs_->end_callback(); |
| bool success = !error_cstr; |
| std::string error_str(error_cstr ? error_cstr : ""); |
| PpapiMsg_PnaclTranslatorCompileEnd::WriteReplyParams( |
| reply_msg, success, error_str); |
| Send(reply_msg); |
| } |
| |
| std::unique_ptr<IPC::Channel> channel_; |
| const struct nacl_irt_pnacl_compile_funcs* funcs_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TranslatorCompileListener); |
| }; |
| |
| void ServeTranslateRequest(const struct nacl_irt_pnacl_compile_funcs* funcs) { |
| base::MessageLoop loop; |
| new TranslatorCompileListener(ppapi::GetRendererIPCChannelHandle(), funcs); |
| base::RunLoop().Run(); |
| } |
| |
| } |
| |
| const struct nacl_irt_private_pnacl_translator_compile |
| nacl_irt_private_pnacl_translator_compile = { |
| ServeTranslateRequest |
| }; |
| |
| #endif // !defined(OS_NACL_NONSFI) |