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: | |
Sean Klein
2015/11/03 14:31:01
Fixed this incorrect comment regarding ManagedDele
| |
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()); | |
jamesr
2015/11/02 23:00:02
why do you need to create another message loop? m
Sean Klein
2015/11/03 14:31:01
As discussed offline, the ContentHandlerFactory is
| |
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 |