Index: services/nacl/content_handler_main_nonsfi_pexe.cc |
diff --git a/services/nacl/content_handler_main_nonsfi_pexe.cc b/services/nacl/content_handler_main_nonsfi_pexe.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..46c40233b2000c296a3c70d91ab8dbda8aafe383 |
--- /dev/null |
+++ b/services/nacl/content_handler_main_nonsfi_pexe.cc |
@@ -0,0 +1,153 @@ |
+// 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 <fcntl.h> |
+ |
+#include "base/files/file_util.h" |
+#include "mojo/application/application_runner_chromium.h" |
+#include "mojo/application/content_handler_factory.h" |
+#include "mojo/data_pipe_utils/data_pipe_utils.h" |
+#include "mojo/message_pump/message_pump_mojo.h" |
+#include "mojo/nacl/nonsfi/nexe_launcher_nonsfi.h" |
+#include "mojo/public/c/system/main.h" |
+#include "mojo/public/cpp/application/application_impl.h" |
+#include "mojo/services/files/c/lib/template_util.h" |
+#include "services/nacl/pnacl_compile.mojom.h" |
+#include "services/nacl/pnacl_link.mojom.h" |
+ |
+namespace nacl { |
+namespace content_handler { |
+namespace { |
+ |
+class CompilerUI { |
+ public: |
+ explicit CompilerUI(mojo::ScopedMessagePipeHandle handle) { |
+ compiler_.Bind(mojo::InterfacePtrInfo<mojo::nacl::PexeCompiler>( |
+ handle.Pass(), 0u)); |
+ } |
+ |
+ // Synchronous method to compile pexe into object file. |
+ mojo::String CompilePexe(mojo::String pexe_file_path) { |
+ compiler_->PexeCompile(pexe_file_path, mojio::Capture(&output_)); |
Mark Seaborn
2015/10/28 18:31:43
output_ can now be a local variable instead of a c
Sean Klein
2015/10/28 21:39:59
Done.
|
+ if (!compiler_.WaitForIncomingResponse()) |
+ LOG(FATAL) << "Could not wait for pexe compiler"; |
Mark Seaborn
2015/10/28 18:31:43
Sounds impatient. :-) Maybe "Waiting for pexe com
Sean Klein
2015/10/28 21:39:59
Done.
|
+ return output_; |
+ } |
+ |
+ private: |
+ mojo::nacl::PexeCompilerPtr compiler_; |
+ mojo::String output_; |
+}; |
+ |
+class LinkerUI { |
+ public: |
+ explicit LinkerUI(mojo::ScopedMessagePipeHandle handle) { |
+ linker_.Bind(mojo::InterfacePtrInfo<mojo::nacl::PexeLinker>( |
+ handle.Pass(), 0u)); |
+ } |
+ |
+ // Synchronous method to link object file into nexe. |
+ mojo::String LinkPexe(mojo::String object_file_path) { |
+ linker_->PexeLink(object_file_path, mojio::Capture(&output_)); |
+ if (!linker_.WaitForIncomingResponse()) |
+ LOG(FATAL) << "Could not wait for pexe linker"; |
+ return output_; |
+ } |
+ |
+ private: |
+ mojo::nacl::PexeLinkerPtr linker_; |
+ mojo::String output_; |
+}; |
+ |
+} // namespace anonymous |
+ |
+class PexeContentHandler : public mojo::ApplicationDelegate, |
+ public mojo::ContentHandlerFactory::Delegate { |
+ public: |
+ PexeContentHandler() : content_handler_factory_(this) {} |
+ |
+ private: |
+ // Overridden from ApplicationDelegate: |
+ void Initialize(mojo::ApplicationImpl* app) override { |
+ app->ConnectToService("mojo:pnacl_compile", &compiler_init_); |
+ app->ConnectToService("mojo:pnacl_link", &linker_init_); |
+ } |
+ |
+ // Overridden from ApplicationDelegate: |
+ bool ConfigureIncomingConnection( |
+ mojo::ApplicationConnection* connection) override { |
+ connection->AddService(&content_handler_factory_); |
+ return true; |
+ } |
+ |
+ // Overridden from ContentHandlerFactory::ManagedDelegate: |
+ void RunApplication( |
+ mojo::InterfaceRequest<mojo::Application> application_request, |
+ mojo::URLResponsePtr response) override { |
+ // Needed to use Mojo interfaces on this thread. |
+ base::MessageLoop loop(mojo::common::MessagePumpMojo::Create()); |
+ // Create temporary file for pexe |
+ base::FilePath pexe_file_path; |
+ FILE* pexe_fp = CreateAndOpenTemporaryFile(&pexe_file_path); |
+ if (!pexe_fp) |
+ LOG(FATAL) << "Could not create temporary file for pexe"; |
+ // Acquire the pexe. |
+ if (!mojo::common::BlockingCopyToFile(response->body.Pass(), pexe_fp)) |
+ LOG(FATAL) << "Could not copy pexe to file"; |
+ if (fclose(pexe_fp)) |
+ LOG(FATAL) << "Could not close pexe file"; |
+ |
+ // Compile the pexe into an object file |
+ mojo::ScopedMessagePipeHandle parent_compile_pipe; |
+ mojo::ScopedMessagePipeHandle child_compile_pipe; |
+ if (CreateMessagePipe(nullptr, &parent_compile_pipe, &child_compile_pipe) != |
+ MOJO_RESULT_OK) |
+ LOG(FATAL) << "Could not create message pipe to compiler"; |
+ compiler_init_->PexeCompilerStart(child_compile_pipe.Pass()); |
+ |
+ // Communicate with the compiler using a mojom interface. |
+ CompilerUI compiler_ui(parent_compile_pipe.Pass()); |
+ mojo::String object_file = compiler_ui.CompilePexe(pexe_file_path.value()); |
+ |
+ // Link the object file into a nexe |
+ mojo::ScopedMessagePipeHandle parent_link_pipe; |
+ mojo::ScopedMessagePipeHandle child_link_pipe; |
+ if (CreateMessagePipe(nullptr, &parent_link_pipe, &child_link_pipe) != |
+ MOJO_RESULT_OK) |
+ LOG(FATAL) << "Could not create message pipe to linker"; |
+ linker_init_->PexeLinkerStart(child_link_pipe.Pass()); |
+ |
+ // Communicate with the linker using a mojom interface. |
+ LinkerUI linker_ui(parent_link_pipe.Pass()); |
+ mojo::String nexe_file = linker_ui.LinkPexe(object_file); |
+ |
+ // Open the nexe file and launch it (with our mojo handle) |
+ int nexe_fd = open(nexe_file.get().c_str(), O_RDONLY); |
+ if (unlink(nexe_file.get().c_str())) |
+ LOG(FATAL) << "Could not unlink temporary nexe file"; |
+ if (nexe_fd < 0) |
+ LOG(FATAL) << "Could not open nexe object file"; |
+ |
+ // Pass the handle connecting us with mojo_shell to the nexe. |
+ MojoHandle handle = application_request.PassMessagePipe().release().value(); |
+ ::nacl::MojoLaunchNexeNonsfi(nexe_fd, handle, |
+ false /* enable_translation_irt */); |
+ } |
+ |
+ private: |
+ mojo::ContentHandlerFactory content_handler_factory_; |
+ mojo::nacl::PexeCompilerInitPtr compiler_init_; |
+ mojo::nacl::PexeLinkerInitPtr linker_init_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(PexeContentHandler); |
+}; |
+ |
+} // namespace content_handler |
+} // namespace nacl |
+ |
+MojoResult MojoMain(MojoHandle application_request) { |
+ mojo::ApplicationRunnerChromium runner( |
+ new nacl::content_handler::PexeContentHandler()); |
+ return runner.Run(application_request); |
+} |