Chromium Code Reviews| 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 "services/nacl/pnacl_compile.mojom.h" | |
| 16 #include "services/nacl/pnacl_link.mojom.h" | |
| 17 | |
| 18 namespace nacl { | |
| 19 namespace content_handler { | |
| 20 namespace { | |
| 21 | |
| 22 // RunnableImpl and MakeRunnable lifted from | |
|
Mark Seaborn
2015/10/27 17:30:21
Is this different from base::Bind() (from base/bin
Sean Klein
2015/10/28 17:02:41
Nope -- Removed. Now I know what base::Bind() does
| |
| 23 // mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc. | |
| 24 // They are used to turn functions into callbacks easily. | |
| 25 template <typename Method, typename Class> | |
| 26 class RunnableImpl { | |
| 27 public: | |
| 28 RunnableImpl(Method method, Class instance) | |
| 29 : method_(method), instance_(instance) {} | |
| 30 template <typename... Args> | |
| 31 void Run(Args... args) const { | |
| 32 (instance_->*method_)(args...); | |
| 33 } | |
| 34 | |
| 35 private: | |
| 36 Method method_; | |
| 37 Class instance_; | |
| 38 }; | |
| 39 | |
| 40 template <typename Method, typename Class> | |
| 41 RunnableImpl<Method, Class> MakeRunnable(Method method, Class object) { | |
| 42 return RunnableImpl<Method, Class>(method, object); | |
| 43 } | |
| 44 | |
| 45 class CompilerUI { | |
|
Mark Seaborn
2015/10/27 17:30:21
Does "UI" mean "user interface" here?
Sean Klein
2015/10/28 17:02:41
Yeah, I used this naming scheme (https://cs.corp.g
| |
| 46 public: | |
| 47 explicit CompilerUI(mojo::ScopedMessagePipeHandle handle) | |
| 48 : callback_(MakeRunnable(&CompilerUI::Output, this)) { | |
| 49 compiler_.Bind(mojo::InterfacePtrInfo<mojo::nacl::PexeCompiler>( | |
| 50 handle.Pass(), 0u)); | |
| 51 } | |
| 52 | |
| 53 // Synchronous method to compile pexe into object file. | |
| 54 mojo::String CompilePexe(mojo::String pexe_file_path) { | |
| 55 compiler_->PexeCompile(pexe_file_path, callback_); | |
|
Mark Seaborn
2015/10/27 17:30:20
Hmm, isn't invoking a method synchronously a commo
Sean Klein
2015/10/28 17:02:41
Done -- this also removed the need for base::Bind.
| |
| 56 compiler_.WaitForIncomingResponse(); | |
| 57 return output_; | |
| 58 } | |
| 59 | |
| 60 private: | |
| 61 mojo::nacl::PexeCompilerPtr compiler_; | |
| 62 mojo::Callback<void(mojo::String)> callback_; | |
| 63 mojo::String output_; | |
| 64 void Output(mojo::String output) { output_ = output; } | |
| 65 }; | |
| 66 | |
| 67 class LinkerUI { | |
| 68 public: | |
| 69 explicit LinkerUI(mojo::ScopedMessagePipeHandle handle) | |
| 70 : callback_(MakeRunnable(&LinkerUI::Output, this)) { | |
| 71 linker_.Bind(mojo::InterfacePtrInfo<mojo::nacl::PexeLinker>( | |
| 72 handle.Pass(), 0u)); | |
| 73 } | |
| 74 | |
| 75 // Synchronous method to link object file into nexe. | |
| 76 mojo::String LinkPexe(mojo::String object_file_path) { | |
| 77 linker_->PexeLink(object_file_path, callback_); | |
| 78 linker_.WaitForIncomingResponse(); | |
| 79 return output_; | |
| 80 } | |
| 81 | |
| 82 private: | |
| 83 mojo::nacl::PexeLinkerPtr linker_; | |
| 84 mojo::Callback<void(mojo::String)> callback_; | |
| 85 mojo::String output_; | |
| 86 void Output(mojo::String output) { output_ = output; } | |
| 87 }; | |
| 88 | |
| 89 } // namespace anonymous | |
| 90 | |
| 91 class PexeContentHandler : public mojo::ApplicationDelegate, | |
| 92 public mojo::ContentHandlerFactory::Delegate { | |
| 93 public: | |
| 94 PexeContentHandler() : content_handler_factory_(this) {} | |
| 95 | |
| 96 private: | |
| 97 // Overridden from ApplicationDelegate: | |
| 98 void Initialize(mojo::ApplicationImpl* app) override { | |
| 99 app->ConnectToService("mojo:pnacl_compile", &compiler_init_); | |
| 100 app->ConnectToService("mojo:pnacl_link", &linker_init_); | |
| 101 } | |
| 102 | |
| 103 // Overridden from ApplicationDelegate: | |
| 104 bool ConfigureIncomingConnection( | |
| 105 mojo::ApplicationConnection* connection) override { | |
| 106 connection->AddService(&content_handler_factory_); | |
| 107 return true; | |
| 108 } | |
| 109 | |
| 110 // Overridden from ContentHandlerFactory::ManagedDelegate: | |
| 111 void RunApplication( | |
| 112 mojo::InterfaceRequest<mojo::Application> application_request, | |
| 113 mojo::URLResponsePtr response) override { | |
| 114 // Needed to use Mojo interfaces on this thread. | |
| 115 base::MessageLoop loop(mojo::common::MessagePumpMojo::Create()); | |
| 116 // Create temporary file for pexe | |
| 117 base::FilePath pexe_file_path; | |
| 118 FILE* pexe_fp = CreateAndOpenTemporaryFile(&pexe_file_path); | |
| 119 if (!pexe_fp) | |
| 120 LOG(FATAL) << "Could not create temporary file for pexe"; | |
| 121 // Acquire the pexe. | |
| 122 if (!mojo::common::BlockingCopyToFile(response->body.Pass(), pexe_fp)) | |
| 123 LOG(FATAL) << "Could not copy pexe to file"; | |
| 124 if (fclose(pexe_fp)) | |
| 125 LOG(FATAL) << "Could not close pexe file"; | |
| 126 | |
| 127 // Compile the pexe into an object file | |
| 128 mojo::ScopedMessagePipeHandle parent_compile_pipe; | |
| 129 mojo::ScopedMessagePipeHandle child_compile_pipe; | |
| 130 if (CreateMessagePipe(nullptr, &parent_compile_pipe, &child_compile_pipe) != | |
| 131 MOJO_RESULT_OK) | |
| 132 LOG(FATAL) << "Could not create message pipe to compiler"; | |
| 133 compiler_init_->PexeCompilerStart(child_compile_pipe.Pass()); | |
| 134 | |
| 135 // Communicate with the compiler using a mojom interface. | |
| 136 CompilerUI compiler_ui(parent_compile_pipe.Pass()); | |
| 137 mojo::String object_file = compiler_ui.CompilePexe(pexe_file_path.value()); | |
| 138 | |
| 139 // Link the object file into a nexe | |
| 140 mojo::ScopedMessagePipeHandle parent_link_pipe; | |
| 141 mojo::ScopedMessagePipeHandle child_link_pipe; | |
| 142 if (CreateMessagePipe(nullptr, &parent_link_pipe, &child_link_pipe) != | |
| 143 MOJO_RESULT_OK) | |
| 144 LOG(FATAL) << "Could not create message pipe to linker"; | |
| 145 linker_init_->PexeLinkerStart(child_link_pipe.Pass()); | |
| 146 | |
| 147 // Communicate with the linker using a mojom interface. | |
| 148 LinkerUI linker_ui(parent_link_pipe.Pass()); | |
| 149 mojo::String nexe_file = linker_ui.LinkPexe(object_file); | |
| 150 | |
| 151 // Open the nexe file and launch it (with our mojo handle) | |
| 152 int nexe_fd = open(nexe_file.get().c_str(), O_RDONLY); | |
| 153 if (unlink(nexe_file.get().c_str())) | |
| 154 LOG(FATAL) << "Could not unlink temporary nexe file"; | |
| 155 if (nexe_fd < 0) | |
| 156 LOG(FATAL) << "Could not open nexe object file"; | |
| 157 | |
| 158 // Pass the handle connecting us with mojo_shell to the nexe. | |
| 159 MojoHandle handle = application_request.PassMessagePipe().release().value(); | |
| 160 ::nacl::MojoLaunchNexeNonsfi(nexe_fd, handle, | |
| 161 false /* enable_translation_irt */); | |
| 162 } | |
| 163 | |
| 164 private: | |
| 165 mojo::ContentHandlerFactory content_handler_factory_; | |
| 166 mojo::nacl::PexeCompilerInitPtr compiler_init_; | |
| 167 mojo::nacl::PexeLinkerInitPtr linker_init_; | |
| 168 | |
| 169 DISALLOW_COPY_AND_ASSIGN(PexeContentHandler); | |
| 170 }; | |
| 171 | |
| 172 } // namespace content_handler | |
| 173 } // namespace nacl | |
| 174 | |
| 175 MojoResult MojoMain(MojoHandle application_request) { | |
| 176 mojo::ApplicationRunnerChromium runner( | |
| 177 new nacl::content_handler::PexeContentHandler()); | |
| 178 return runner.Run(application_request); | |
| 179 } | |
| OLD | NEW |