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..7741bb9f5cc0c035a764636c8c1ba2b5b0ca3ae6 |
--- /dev/null |
+++ b/services/nacl/content_handler_main_nonsfi_pexe.cc |
@@ -0,0 +1,149 @@ |
+// 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 "services/nacl/pexe_linker.mojom.h" |
+#include "services/nacl/pexe_translator.mojom.h" |
+ |
+namespace nacl { |
+namespace content_handler { |
+namespace { |
+ |
+void WriteStringToHandle(MojoHandle handle, const char* str, uint32_t size) { |
+ MojoResult result; |
+ result = MojoWriteMessage(handle, str, size, nullptr, 0, |
+ MOJO_WRITE_MESSAGE_FLAG_NONE); |
+ if (result != MOJO_RESULT_OK) |
+ LOG(FATAL) << "Could not write message to handle"; |
+} |
+ |
+void ReadStringFromHandle(MojoHandle handle, char* str, uint32_t* size) { |
+ MojoResult result; |
+ do { |
+ result = MojoReadMessage(handle, str, size, nullptr, 0, |
+ MOJO_READ_MESSAGE_FLAG_NONE); |
+ if (result == MOJO_RESULT_SHOULD_WAIT) { |
+ result = MojoWait(handle, |
+ MOJO_HANDLE_SIGNAL_READABLE, |
+ MOJO_DEADLINE_INDEFINITE, |
+ nullptr); |
+ if (result != MOJO_RESULT_OK) |
+ LOG(FATAL) << "Error waiting for string"; |
+ } else { |
+ break; |
+ } |
+ } while (true); |
+ if (result != MOJO_RESULT_OK) |
+ LOG(FATAL) << "Could not read message from handle"; |
+ str[*size] = '\0'; |
+} |
+ |
+} // 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:pexe_translator_app", &translator_); |
Mark Seaborn
2015/10/20 22:28:58
I'm curious whether this could just be done in Run
Sean Klein
2015/10/22 21:50:00
I'm not entirely sure -- the ApplicationImpl point
|
+ app->ConnectToService("mojo:pexe_linker_app", &linker_); |
+ } |
+ |
+ // 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()); |
+ // Acquire the pexe. |
+ base::FilePath pexe_file_path = |
+ mojo::common::BlockingCopyToNewTempFile(response->body.Pass()); |
+ if (pexe_file_path.empty()) { |
+ LOG(FATAL) << "Could not redirect pexe to temp file"; |
+ } |
+ |
+ // Translate 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 translator"; |
+ translator_->PexeTranslate(child_compile_pipe.Pass()); |
+ |
+ // Write the name of the pexe to the translating service. |
+ WriteStringToHandle(parent_compile_pipe.get().value(), |
+ pexe_file_path.value().c_str(), |
+ pexe_file_path.value().size()); |
+ // Read the name of the output object from the translating service. |
+ char obj_file_name[PATH_MAX + 1]; |
+ uint32_t path_size = sizeof(obj_file_name); |
+ ReadStringFromHandle(parent_compile_pipe.get().value(), |
+ obj_file_name, &path_size); |
+ |
+ // 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_->PexeLink(child_link_pipe.Pass()); |
+ |
+ // Write the name of the object file to the linking service. |
+ WriteStringToHandle(parent_link_pipe.get().value(), |
+ obj_file_name, |
+ path_size); |
+ // Read the name of the output nexe from the linking service. |
+ char nexe_file_name[PATH_MAX + 1]; |
+ path_size = sizeof(nexe_file_name); |
+ ReadStringFromHandle(parent_link_pipe.get().value(), |
+ nexe_file_name, &path_size); |
+ |
+ // Open the nexe file and launch it (with our mojo handle) |
+ int nexe_fd = open(nexe_file_name, O_RDONLY); |
+ if (unlink(nexe_file_name)) |
+ 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); |
+ } |
+ |
+ private: |
+ mojo::ContentHandlerFactory content_handler_factory_; |
+ mojo::nacl::PexeTranslatorPtr translator_; |
+ mojo::nacl::PexeLinkerPtr linker_; |
+ |
+ 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); |
+} |