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 |