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 "base/files/file_util.h" | |
6 #include "base/files/scoped_file.h" | |
7 #include "base/message_loop/message_loop.h" | |
8 #include "build/build_config.h" | |
9 #include "mojo/application/content_handler_factory.h" | |
10 #include "mojo/data_pipe_utils/data_pipe_utils.h" | |
11 #include "mojo/environment/scoped_chromium_init.h" | |
12 #include "mojo/message_pump/message_pump_mojo.h" | |
13 #include "mojo/nacl/sfi/nacl_bindings/monacl_sel_main.h" | |
14 #include "mojo/public/c/system/main.h" | |
15 #include "mojo/public/cpp/application/application_impl_base.h" | |
16 #include "mojo/public/cpp/application/connect.h" | |
17 #include "mojo/public/cpp/application/run_application.h" | |
18 #include "mojo/public/cpp/application/service_provider_impl.h" | |
19 #include "mojo/services/network/interfaces/network_service.mojom.h" | |
20 #include "mojo/services/network/interfaces/url_loader.mojom.h" | |
21 #include "native_client/src/public/nacl_desc.h" | |
22 #include "url/gurl.h" | |
23 | |
24 namespace nacl { | |
25 namespace content_handler { | |
26 | |
27 namespace { | |
28 base::ScopedFILE TempFileForURL(mojo::URLLoaderPtr& url_loader, | |
29 const GURL& url) { | |
30 mojo::URLRequestPtr request(mojo::URLRequest::New()); | |
31 request->url = url.spec(); | |
32 request->method = "GET"; | |
33 request->auto_follow_redirects = true; | |
34 | |
35 // Handle the callback synchonously. | |
36 mojo::URLResponsePtr response; | |
37 url_loader->Start(request.Pass(), [&response](mojo::URLResponsePtr r) { | |
38 response = r.Pass(); | |
39 }); | |
40 url_loader.WaitForIncomingResponse(); | |
41 CHECK(!response.is_null()) << "Empty response (missed a callback?)"; | |
42 | |
43 if (response->error) { | |
44 LOG(ERROR) << "could not load " << url.spec() << " (" | |
45 << response->error->code << ") " | |
46 << response->error->description.get().c_str(); | |
47 return nullptr; | |
48 } | |
49 | |
50 return mojo::common::BlockingCopyToTempFile(response->body.Pass()); | |
51 } | |
52 | |
53 NaClDesc* FileStreamToNaClDesc(FILE* file_stream) { | |
54 // Get file handle | |
55 int fd = fileno(file_stream); | |
56 CHECK_NE(fd, -1) << "Could not open the stream pointer's file descriptor"; | |
57 | |
58 // These file descriptors must be dup'd, since NaClDesc takes ownership | |
59 // of the file descriptor. The descriptor is still needed to close | |
60 // the file stream. | |
61 fd = dup(fd); | |
62 CHECK_NE(fd, -1) << "Could not dup the file descriptor"; | |
63 | |
64 NaClDesc* desc = NaClDescCreateWithFilePathMetadata(fd, ""); | |
65 | |
66 // Clean up. | |
67 CHECK_EQ(fclose(file_stream), 0) << "Failed to close temp file"; | |
68 | |
69 return desc; | |
70 } | |
71 | |
72 } // namespace | |
73 | |
74 class NaClContentHandler : public mojo::ApplicationImplBase, | |
75 public mojo::ContentHandlerFactory::Delegate { | |
76 public: | |
77 NaClContentHandler() {} | |
78 | |
79 private: | |
80 // Overridden from ApplicationImplBase: | |
81 void OnInitialize() override { | |
82 url_ = GURL(url()); | |
83 | |
84 mojo::NetworkServicePtr network_service; | |
85 mojo::ConnectToService(shell(), "mojo:network_service", | |
86 GetProxy(&network_service)); | |
87 | |
88 network_service->CreateURLLoader(GetProxy(&url_loader_)); | |
89 } | |
90 | |
91 // Overridden from ApplicationImplBase: | |
92 bool OnAcceptConnection( | |
93 mojo::ServiceProviderImpl* service_provider_impl) override { | |
94 service_provider_impl->AddService<mojo::ContentHandler>( | |
95 mojo::ContentHandlerFactory::GetInterfaceRequestHandler(this)); | |
96 return true; | |
97 } | |
98 | |
99 void LoadIRT(mojo::URLLoaderPtr& url_loader) { | |
100 // TODO(ncbray): support other architectures. | |
101 GURL irt_url; | |
102 #if defined(ARCH_CPU_X86_64) | |
103 irt_url = url_.Resolve("irt_x64/irt_mojo.nexe"); | |
104 #else | |
105 #error "Unknown / unsupported CPU architecture." | |
106 #endif | |
107 CHECK(irt_url.is_valid()) << "Cannot resolve IRT URL"; | |
108 | |
109 irt_fp_ = TempFileForURL(url_loader, irt_url); | |
110 CHECK(irt_fp_) << "Could not acquire the IRT"; | |
111 } | |
112 | |
113 // Overridden from ContentHandlerFactory::Delegate: | |
114 void RunApplication( | |
115 mojo::InterfaceRequest<mojo::Application> application_request, | |
116 mojo::URLResponsePtr response) override { | |
117 // Needed to use Mojo interfaces on this thread. | |
118 base::MessageLoop loop(mojo::common::MessagePumpMojo::Create()); | |
119 | |
120 // Acquire the nexe. | |
121 base::ScopedFILE nexe_fp = | |
122 mojo::common::BlockingCopyToTempFile(response->body.Pass()); | |
123 CHECK(nexe_fp) << "could not redirect nexe to temp file"; | |
124 | |
125 // Acquire the IRT. | |
126 mojo::URLLoaderPtr url_loader = url_loader_.Pass(); | |
127 LoadIRT(url_loader); | |
128 | |
129 NaClDesc* irt_desc = FileStreamToNaClDesc(irt_fp_.release()); | |
130 NaClDesc* nexe_desc = FileStreamToNaClDesc(nexe_fp.release()); | |
131 | |
132 // Run. | |
133 int exit_code = mojo::LaunchNaCl( | |
134 nexe_desc, irt_desc, 0, nullptr, | |
135 application_request.PassMessagePipe().release().value()); | |
136 | |
137 // Exits the process cleanly, does not return. | |
138 mojo::NaClExit(exit_code); | |
139 NOTREACHED(); | |
140 } | |
141 | |
142 GURL url_; | |
143 base::ScopedFILE irt_fp_; | |
144 | |
145 mojo::URLLoaderPtr url_loader_; | |
146 | |
147 DISALLOW_COPY_AND_ASSIGN(NaClContentHandler); | |
148 }; | |
149 | |
150 } // namespace content_handler | |
151 } // namespace nacl | |
152 | |
153 MojoResult MojoMain(MojoHandle application_request) { | |
154 mojo::ScopedChromiumInit init; | |
155 nacl::content_handler::NaClContentHandler nacl_content_handler; | |
156 return mojo::RunApplication(application_request, &nacl_content_handler); | |
157 } | |
OLD | NEW |