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/pexe_linker.mojom.h" | |
16 #include "services/nacl/pexe_translator.mojom.h" | |
17 | |
18 namespace nacl { | |
19 namespace content_handler { | |
20 namespace { | |
21 | |
22 void WriteStringToHandle(MojoHandle handle, const char* str, uint32_t size) { | |
23 MojoResult result; | |
24 result = MojoWriteMessage(handle, str, size, nullptr, 0, | |
25 MOJO_WRITE_MESSAGE_FLAG_NONE); | |
26 if (result != MOJO_RESULT_OK) | |
27 LOG(FATAL) << "Could not write message to handle"; | |
28 } | |
29 | |
30 void ReadStringFromHandle(MojoHandle handle, char* str, uint32_t* size) { | |
31 MojoResult result; | |
32 do { | |
33 result = MojoReadMessage(handle, str, size, nullptr, 0, | |
34 MOJO_READ_MESSAGE_FLAG_NONE); | |
35 if (result == MOJO_RESULT_SHOULD_WAIT) { | |
36 result = MojoWait(handle, | |
37 MOJO_HANDLE_SIGNAL_READABLE, | |
38 MOJO_DEADLINE_INDEFINITE, | |
39 nullptr); | |
40 if (result != MOJO_RESULT_OK) | |
41 LOG(FATAL) << "Error waiting for string"; | |
42 } else { | |
43 break; | |
44 } | |
45 } while (true); | |
46 if (result != MOJO_RESULT_OK) | |
47 LOG(FATAL) << "Could not read message from handle"; | |
48 str[*size] = '\0'; | |
49 } | |
50 | |
51 } // namespace anonymous | |
52 | |
53 class PexeContentHandler : public mojo::ApplicationDelegate, | |
54 public mojo::ContentHandlerFactory::Delegate { | |
55 public: | |
56 PexeContentHandler() : content_handler_factory_(this) {} | |
57 | |
58 private: | |
59 // Overridden from ApplicationDelegate: | |
60 void Initialize(mojo::ApplicationImpl* app) override { | |
61 app->ConnectToService("mojo:pexe_translator_app", &translator_); | |
Mark Seaborn
2015/10/20 22:28:58
I'm curious whether this could just be done in Run
Sean Klein
2015/10/22 21:50:00
I'm not entirely sure -- the ApplicationImpl point
| |
62 app->ConnectToService("mojo:pexe_linker_app", &linker_); | |
63 } | |
64 | |
65 // Overridden from ApplicationDelegate: | |
66 bool ConfigureIncomingConnection( | |
67 mojo::ApplicationConnection* connection) override { | |
68 connection->AddService(&content_handler_factory_); | |
69 return true; | |
70 } | |
71 | |
72 // Overridden from ContentHandlerFactory::ManagedDelegate: | |
73 void RunApplication( | |
74 mojo::InterfaceRequest<mojo::Application> application_request, | |
75 mojo::URLResponsePtr response) override { | |
76 // Needed to use Mojo interfaces on this thread. | |
77 base::MessageLoop loop(mojo::common::MessagePumpMojo::Create()); | |
78 // Acquire the pexe. | |
79 base::FilePath pexe_file_path = | |
80 mojo::common::BlockingCopyToNewTempFile(response->body.Pass()); | |
81 if (pexe_file_path.empty()) { | |
82 LOG(FATAL) << "Could not redirect pexe to temp file"; | |
83 } | |
84 | |
85 // Translate the pexe into an object file | |
86 mojo::ScopedMessagePipeHandle parent_compile_pipe; | |
87 mojo::ScopedMessagePipeHandle child_compile_pipe; | |
88 if (CreateMessagePipe(nullptr, &parent_compile_pipe, &child_compile_pipe) != | |
89 MOJO_RESULT_OK) | |
90 LOG(FATAL) << "Could not create message pipe to translator"; | |
91 translator_->PexeTranslate(child_compile_pipe.Pass()); | |
92 | |
93 // Write the name of the pexe to the translating service. | |
94 WriteStringToHandle(parent_compile_pipe.get().value(), | |
95 pexe_file_path.value().c_str(), | |
96 pexe_file_path.value().size()); | |
97 // Read the name of the output object from the translating service. | |
98 char obj_file_name[PATH_MAX + 1]; | |
99 uint32_t path_size = sizeof(obj_file_name); | |
100 ReadStringFromHandle(parent_compile_pipe.get().value(), | |
101 obj_file_name, &path_size); | |
102 | |
103 // Link the object file into a nexe | |
104 mojo::ScopedMessagePipeHandle parent_link_pipe; | |
105 mojo::ScopedMessagePipeHandle child_link_pipe; | |
106 if (CreateMessagePipe(nullptr, &parent_link_pipe, &child_link_pipe) != | |
107 MOJO_RESULT_OK) | |
108 LOG(FATAL) << "Could not create message pipe to linker"; | |
109 | |
110 linker_->PexeLink(child_link_pipe.Pass()); | |
111 | |
112 // Write the name of the object file to the linking service. | |
113 WriteStringToHandle(parent_link_pipe.get().value(), | |
114 obj_file_name, | |
115 path_size); | |
116 // Read the name of the output nexe from the linking service. | |
117 char nexe_file_name[PATH_MAX + 1]; | |
118 path_size = sizeof(nexe_file_name); | |
119 ReadStringFromHandle(parent_link_pipe.get().value(), | |
120 nexe_file_name, &path_size); | |
121 | |
122 // Open the nexe file and launch it (with our mojo handle) | |
123 int nexe_fd = open(nexe_file_name, O_RDONLY); | |
124 if (unlink(nexe_file_name)) | |
125 LOG(FATAL) << "Could not unlink temporary nexe file"; | |
126 if (nexe_fd < 0) | |
127 LOG(FATAL) << "Could not open nexe object file"; | |
128 | |
129 // Pass the handle connecting us with mojo_shell to the nexe. | |
130 MojoHandle handle = application_request.PassMessagePipe().release().value(); | |
131 ::nacl::MojoLaunchNexeNonsfi(nexe_fd, handle); | |
132 } | |
133 | |
134 private: | |
135 mojo::ContentHandlerFactory content_handler_factory_; | |
136 mojo::nacl::PexeTranslatorPtr translator_; | |
137 mojo::nacl::PexeLinkerPtr linker_; | |
138 | |
139 DISALLOW_COPY_AND_ASSIGN(PexeContentHandler); | |
140 }; | |
141 | |
142 } // namespace content_handler | |
143 } // namespace nacl | |
144 | |
145 MojoResult MojoMain(MojoHandle application_request) { | |
146 mojo::ApplicationRunnerChromium runner( | |
147 new nacl::content_handler::PexeContentHandler()); | |
148 return runner.Run(application_request); | |
149 } | |
OLD | NEW |