OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <fcntl.h> |
| 6 |
| 7 #include "base/files/file_util.h" |
| 8 #include "mojo/application/application_runner_chromium.h" |
| 9 #include "mojo/application/content_handler_factory.h" |
| 10 #include "mojo/data_pipe_utils/data_pipe_utils.h" |
| 11 #include "mojo/message_pump/message_pump_mojo.h" |
| 12 #include "mojo/nacl/nonsfi/nexe_launcher_nonsfi.h" |
| 13 #include "mojo/public/c/system/main.h" |
| 14 #include "mojo/public/cpp/application/application_impl.h" |
| 15 #include "mojo/services/files/c/lib/template_util.h" |
| 16 #include "services/nacl/pnacl_compile.mojom.h" |
| 17 #include "services/nacl/pnacl_link.mojom.h" |
| 18 |
| 19 namespace nacl { |
| 20 namespace content_handler { |
| 21 namespace { |
| 22 |
| 23 class CompilerUI { |
| 24 public: |
| 25 explicit CompilerUI(mojo::ScopedMessagePipeHandle handle) { |
| 26 compiler_.Bind(mojo::InterfacePtrInfo<mojo::nacl::PexeCompiler>( |
| 27 handle.Pass(), 0u)); |
| 28 } |
| 29 |
| 30 // Synchronous method to compile pexe into object file. |
| 31 mojo::String CompilePexe(mojo::String pexe_file_path) { |
| 32 mojo::String output; |
| 33 compiler_->PexeCompile(pexe_file_path, mojio::Capture(&output)); |
| 34 if (!compiler_.WaitForIncomingResponse()) |
| 35 LOG(FATAL) << "Waiting for pexe compiler failed"; |
| 36 return output; |
| 37 } |
| 38 |
| 39 private: |
| 40 mojo::nacl::PexeCompilerPtr compiler_; |
| 41 }; |
| 42 |
| 43 class LinkerUI { |
| 44 public: |
| 45 explicit LinkerUI(mojo::ScopedMessagePipeHandle handle) { |
| 46 linker_.Bind(mojo::InterfacePtrInfo<mojo::nacl::PexeLinker>( |
| 47 handle.Pass(), 0u)); |
| 48 } |
| 49 |
| 50 // Synchronous method to link object file into nexe. |
| 51 mojo::String LinkPexe(mojo::String object_file_path) { |
| 52 mojo::String output; |
| 53 linker_->PexeLink(object_file_path, mojio::Capture(&output)); |
| 54 if (!linker_.WaitForIncomingResponse()) |
| 55 LOG(FATAL) << "Waiting for pexe linker failed"; |
| 56 return output; |
| 57 } |
| 58 |
| 59 private: |
| 60 mojo::nacl::PexeLinkerPtr linker_; |
| 61 }; |
| 62 |
| 63 } // namespace anonymous |
| 64 |
| 65 class PexeContentHandler : public mojo::ApplicationDelegate, |
| 66 public mojo::ContentHandlerFactory::Delegate { |
| 67 public: |
| 68 PexeContentHandler() : content_handler_factory_(this) {} |
| 69 |
| 70 private: |
| 71 // Overridden from ApplicationDelegate: |
| 72 void Initialize(mojo::ApplicationImpl* app) override { |
| 73 app->ConnectToService("mojo:pnacl_compile", &compiler_init_); |
| 74 app->ConnectToService("mojo:pnacl_link", &linker_init_); |
| 75 } |
| 76 |
| 77 // Overridden from ApplicationDelegate: |
| 78 bool ConfigureIncomingConnection( |
| 79 mojo::ApplicationConnection* connection) override { |
| 80 connection->AddService(&content_handler_factory_); |
| 81 return true; |
| 82 } |
| 83 |
| 84 // Overridden from ContentHandlerFactory::ManagedDelegate: |
| 85 void RunApplication( |
| 86 mojo::InterfaceRequest<mojo::Application> application_request, |
| 87 mojo::URLResponsePtr response) override { |
| 88 // Needed to use Mojo interfaces on this thread. |
| 89 base::MessageLoop loop(mojo::common::MessagePumpMojo::Create()); |
| 90 // Create temporary file for pexe |
| 91 base::FilePath pexe_file_path; |
| 92 FILE* pexe_fp = CreateAndOpenTemporaryFile(&pexe_file_path); |
| 93 if (!pexe_fp) |
| 94 LOG(FATAL) << "Could not create temporary file for pexe"; |
| 95 // Acquire the pexe. |
| 96 if (!mojo::common::BlockingCopyToFile(response->body.Pass(), pexe_fp)) |
| 97 LOG(FATAL) << "Could not copy pexe to file"; |
| 98 if (fclose(pexe_fp)) |
| 99 LOG(FATAL) << "Could not close pexe file"; |
| 100 |
| 101 // Compile the pexe into an object file |
| 102 mojo::ScopedMessagePipeHandle parent_compile_pipe; |
| 103 mojo::ScopedMessagePipeHandle child_compile_pipe; |
| 104 if (CreateMessagePipe(nullptr, &parent_compile_pipe, &child_compile_pipe) != |
| 105 MOJO_RESULT_OK) |
| 106 LOG(FATAL) << "Could not create message pipe to compiler"; |
| 107 compiler_init_->PexeCompilerStart(child_compile_pipe.Pass()); |
| 108 |
| 109 // Communicate with the compiler using a mojom interface. |
| 110 CompilerUI compiler_ui(parent_compile_pipe.Pass()); |
| 111 mojo::String object_file = compiler_ui.CompilePexe(pexe_file_path.value()); |
| 112 |
| 113 // Link the object file into a nexe |
| 114 mojo::ScopedMessagePipeHandle parent_link_pipe; |
| 115 mojo::ScopedMessagePipeHandle child_link_pipe; |
| 116 if (CreateMessagePipe(nullptr, &parent_link_pipe, &child_link_pipe) != |
| 117 MOJO_RESULT_OK) |
| 118 LOG(FATAL) << "Could not create message pipe to linker"; |
| 119 linker_init_->PexeLinkerStart(child_link_pipe.Pass()); |
| 120 |
| 121 // Communicate with the linker using a mojom interface. |
| 122 LinkerUI linker_ui(parent_link_pipe.Pass()); |
| 123 mojo::String nexe_file = linker_ui.LinkPexe(object_file); |
| 124 |
| 125 // Open the nexe file and launch it (with our mojo handle) |
| 126 int nexe_fd = open(nexe_file.get().c_str(), O_RDONLY); |
| 127 if (unlink(nexe_file.get().c_str())) |
| 128 LOG(FATAL) << "Could not unlink temporary nexe file"; |
| 129 if (nexe_fd < 0) |
| 130 LOG(FATAL) << "Could not open nexe object file"; |
| 131 |
| 132 // Pass the handle connecting us with mojo_shell to the nexe. |
| 133 MojoHandle handle = application_request.PassMessagePipe().release().value(); |
| 134 ::nacl::MojoLaunchNexeNonsfi(nexe_fd, handle, |
| 135 false /* enable_translation_irt */); |
| 136 } |
| 137 |
| 138 private: |
| 139 mojo::ContentHandlerFactory content_handler_factory_; |
| 140 mojo::nacl::PexeCompilerInitPtr compiler_init_; |
| 141 mojo::nacl::PexeLinkerInitPtr linker_init_; |
| 142 |
| 143 DISALLOW_COPY_AND_ASSIGN(PexeContentHandler); |
| 144 }; |
| 145 |
| 146 } // namespace content_handler |
| 147 } // namespace nacl |
| 148 |
| 149 MojoResult MojoMain(MojoHandle application_request) { |
| 150 mojo::ApplicationRunnerChromium runner( |
| 151 new nacl::content_handler::PexeContentHandler()); |
| 152 return runner.Run(application_request); |
| 153 } |
OLD | NEW |