| 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 |