OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/files/file_path.h" | |
6 #include "base/files/file_util.h" | 5 #include "base/files/file_util.h" |
7 #include "base/message_loop/message_loop.h" | 6 #include "base/message_loop/message_loop.h" |
8 #include "build/build_config.h" | 7 #include "build/build_config.h" |
9 #include "mojo/application/application_runner_chromium.h" | 8 #include "mojo/application/application_runner_chromium.h" |
10 #include "mojo/application/content_handler_factory.h" | 9 #include "mojo/application/content_handler_factory.h" |
11 #include "mojo/data_pipe_utils/data_pipe_utils.h" | 10 #include "mojo/data_pipe_utils/data_pipe_utils.h" |
12 #include "mojo/message_pump/message_pump_mojo.h" | 11 #include "mojo/message_pump/message_pump_mojo.h" |
13 #include "mojo/public/c/system/main.h" | 12 #include "mojo/public/c/system/main.h" |
14 #include "mojo/public/cpp/application/application_connection.h" | 13 #include "mojo/public/cpp/application/application_connection.h" |
15 #include "mojo/public/cpp/application/application_delegate.h" | 14 #include "mojo/public/cpp/application/application_delegate.h" |
16 #include "mojo/public/cpp/application/application_impl.h" | 15 #include "mojo/public/cpp/application/application_impl.h" |
17 #include "mojo/services/network/public/interfaces/network_service.mojom.h" | 16 #include "mojo/services/network/public/interfaces/network_service.mojom.h" |
18 #include "mojo/services/network/public/interfaces/url_loader.mojom.h" | 17 #include "mojo/services/network/public/interfaces/url_loader.mojom.h" |
19 #include "nacl_bindings/monacl_sel_main.h" | 18 #include "nacl_bindings/monacl_sel_main.h" |
20 #include "native_client/src/public/nacl_desc.h" | 19 #include "native_client/src/public/nacl_desc.h" |
21 #include "url/gurl.h" | 20 #include "url/gurl.h" |
22 | 21 |
23 namespace nacl { | 22 namespace nacl { |
24 namespace content_handler { | 23 namespace content_handler { |
25 | 24 |
26 namespace { | 25 namespace { |
27 bool URLResponseToTempFile(mojo::URLResponsePtr& response, | 26 FILE* TempFileForURL(mojo::URLLoaderPtr& url_loader, |
28 base::FilePath* file_path) { | 27 const GURL& url) { |
Mark Seaborn
2015/09/02 18:46:45
Nit: Fix indentation. Fits on previous line?
You
Sean Klein
2015/09/02 21:49:11
Done.
| |
29 if (!base::CreateTemporaryFile(file_path)) { | |
30 return false; | |
31 } | |
32 | |
33 if (!mojo::common::BlockingCopyToFile(response->body.Pass(), *file_path)) { | |
34 base::DeleteFile(*file_path, false); | |
35 return false; | |
36 } | |
37 | |
38 // TODO(ncbray): can we ensure temp file deletion even if we crash? | |
39 return true; | |
40 } | |
41 | |
42 bool TempFileForURL(mojo::URLLoaderPtr& url_loader, | |
43 const GURL& url, | |
44 base::FilePath* path) { | |
45 mojo::URLRequestPtr request(mojo::URLRequest::New()); | 28 mojo::URLRequestPtr request(mojo::URLRequest::New()); |
46 request->url = url.spec(); | 29 request->url = url.spec(); |
47 request->method = "GET"; | 30 request->method = "GET"; |
48 request->auto_follow_redirects = true; | 31 request->auto_follow_redirects = true; |
49 | 32 |
50 // Handle the callback synchonously. | 33 // Handle the callback synchonously. |
51 mojo::URLResponsePtr response; | 34 mojo::URLResponsePtr response; |
52 url_loader->Start(request.Pass(), [&response](mojo::URLResponsePtr r) { | 35 url_loader->Start(request.Pass(), [&response](mojo::URLResponsePtr r) { |
53 response = r.Pass(); | 36 response = r.Pass(); |
54 }); | 37 }); |
55 url_loader.WaitForIncomingResponse(); | 38 url_loader.WaitForIncomingResponse(); |
56 if (response.is_null()) { | 39 if (response.is_null()) { |
57 LOG(FATAL) << "something went horribly wrong (missed a callback?)"; | 40 LOG(FATAL) << "something went horribly wrong (missed a callback?)"; |
58 } | 41 } |
59 | 42 |
60 if (response->error) { | 43 if (response->error) { |
61 LOG(ERROR) << "could not load " << url.spec() << " (" | 44 LOG(ERROR) << "could not load " << url.spec() << " (" |
62 << response->error->code << ") " | 45 << response->error->code << ") " |
63 << response->error->description.get().c_str(); | 46 << response->error->description.get().c_str(); |
64 return false; | 47 return NULL; |
65 } | 48 } |
66 | 49 |
67 return URLResponseToTempFile(response, path); | 50 return mojo::common::BlockingCopyToTempFile(response->body.Pass()); |
68 } | |
69 | |
70 NaClDesc* NaClDescFromNexePath(base::FilePath& path) { | |
71 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ | | |
72 base::File::FLAG_EXECUTE); | |
73 if (!file.IsValid()) { | |
74 LOG(FATAL) << "failed to open " << path.value(); | |
75 } | |
76 // Note: potentially unsafe, assumes the file is immutable. This should be | |
77 // OK because we're currently only using temp files. | |
78 return NaClDescCreateWithFilePathMetadata(file.TakePlatformFile(), | |
79 path.AsUTF8Unsafe().c_str()); | |
80 } | 51 } |
81 | 52 |
82 } // namespace | 53 } // namespace |
83 | 54 |
84 class NaClContentHandler : public mojo::ApplicationDelegate, | 55 class NaClContentHandler : public mojo::ApplicationDelegate, |
85 public mojo::ContentHandlerFactory::Delegate { | 56 public mojo::ContentHandlerFactory::Delegate { |
86 public: | 57 public: |
87 NaClContentHandler() : content_handler_factory_(this) {} | 58 NaClContentHandler() : content_handler_factory_(this) {} |
88 | 59 |
89 private: | 60 private: |
(...skipping 12 matching lines...) Expand all Loading... | |
102 GURL irt_url; | 73 GURL irt_url; |
103 #if defined(ARCH_CPU_X86_64) | 74 #if defined(ARCH_CPU_X86_64) |
104 irt_url = url_.Resolve("irt_x64/irt_mojo.nexe"); | 75 irt_url = url_.Resolve("irt_x64/irt_mojo.nexe"); |
105 #else | 76 #else |
106 #error "Unknown / unsupported CPU architecture." | 77 #error "Unknown / unsupported CPU architecture." |
107 #endif | 78 #endif |
108 if (!irt_url.is_valid()) { | 79 if (!irt_url.is_valid()) { |
109 LOG(FATAL) << "Cannot resolve IRT URL"; | 80 LOG(FATAL) << "Cannot resolve IRT URL"; |
110 } | 81 } |
111 | 82 |
112 if (!TempFileForURL(url_loader, irt_url, &irt_path_)) { | 83 if ((irt_fp_ = TempFileForURL(url_loader, irt_url)) == NULL) { |
Mark Seaborn
2015/09/02 18:46:45
I'd prefer using two lines for this, to avoid doin
Sean Klein
2015/09/02 21:49:11
Done.
| |
113 LOG(FATAL) << "Could not aquire the IRT"; | 84 LOG(FATAL) << "Could not acquire the IRT"; |
114 } | 85 } |
115 } | 86 } |
116 | 87 |
117 // Overridden from ApplicationDelegate: | 88 // Overridden from ApplicationDelegate: |
118 bool ConfigureIncomingConnection( | 89 bool ConfigureIncomingConnection( |
119 mojo::ApplicationConnection* connection) override { | 90 mojo::ApplicationConnection* connection) override { |
120 connection->AddService(&content_handler_factory_); | 91 connection->AddService(&content_handler_factory_); |
121 return true; | 92 return true; |
122 } | 93 } |
123 | 94 |
124 // Overridden from ContentHandlerFactory::ManagedDelegate: | 95 // Overridden from ContentHandlerFactory::ManagedDelegate: |
125 void RunApplication( | 96 void RunApplication( |
126 mojo::InterfaceRequest<mojo::Application> application_request, | 97 mojo::InterfaceRequest<mojo::Application> application_request, |
127 mojo::URLResponsePtr response) override { | 98 mojo::URLResponsePtr response) override { |
128 // Needed to use Mojo interfaces on this thread. | 99 // Needed to use Mojo interfaces on this thread. |
129 base::MessageLoop loop(mojo::common::MessagePumpMojo::Create()); | 100 base::MessageLoop loop(mojo::common::MessagePumpMojo::Create()); |
130 | 101 |
131 // Aquire the nexe. | 102 // Acquire the nexe. |
132 base::FilePath nexe_path; | 103 FILE* nexe_fp = mojo::common::BlockingCopyToTempFile( |
133 if (!URLResponseToTempFile(response, &nexe_path)) { | 104 response->body.Pass()); |
105 if (nexe_fp == NULL) { | |
134 LOG(FATAL) << "could not redirect nexe to temp file"; | 106 LOG(FATAL) << "could not redirect nexe to temp file"; |
135 } | 107 } |
136 | 108 |
137 // Aquire the IRT. | 109 // Acquire the IRT. |
138 mojo::URLLoaderPtr url_loader = url_loader_.Pass(); | 110 mojo::URLLoaderPtr url_loader = url_loader_.Pass(); |
139 LoadIRT(url_loader); | 111 LoadIRT(url_loader); |
140 | 112 |
141 // Get file handles to the IRT and nexe. | 113 // Get file handles to the IRT and nexe. |
142 NaClDesc* irt_desc = NaClDescFromNexePath(irt_path_); | 114 int irt_fd = fileno(irt_fp_); |
Mark Seaborn
2015/09/02 18:46:45
It looks like you could combine:
fileno() + dup()
Sean Klein
2015/09/02 21:49:11
Done.
| |
143 NaClDesc* nexe_desc = NaClDescFromNexePath(nexe_path); | 115 if (irt_fd == -1) { |
116 LOG(FATAL) << "Could not open the irt stream pointer's file descriptor"; | |
117 } | |
118 int nexe_fd = fileno(nexe_fp); | |
119 if (nexe_fd == -1) { | |
120 LOG(FATAL) << "Could not open the nexe stream pointer's file descriptor"; | |
121 } | |
122 | |
123 // These file descriptors must be dup'd, since NaClDesc takes ownership | |
124 // of the file descriptor. The descriptor is still needed to close | |
125 // the file stream. | |
126 if ((irt_fd = dup(irt_fd)) == -1) { | |
127 LOG(FATAL) << "Could not dup the irt file descriptor"; | |
128 } | |
129 if ((nexe_fd = dup(nexe_fd)) == -1) { | |
130 LOG(FATAL) << "Could not dup the nexe file descriptor"; | |
131 } | |
132 | |
133 NaClDesc* irt_desc = NaClDescCreateWithFilePathMetadata( | |
134 irt_fd, ""); | |
135 NaClDesc* nexe_desc = NaClDescCreateWithFilePathMetadata( | |
136 nexe_fd, ""); | |
144 | 137 |
145 // Run. | 138 // Run. |
146 int exit_code = mojo::LaunchNaCl( | 139 int exit_code = mojo::LaunchNaCl( |
147 nexe_desc, irt_desc, 0, NULL, | 140 nexe_desc, irt_desc, 0, NULL, |
148 application_request.PassMessagePipe().release().value()); | 141 application_request.PassMessagePipe().release().value()); |
149 | 142 |
150 // TODO(ncbray): are the file handles actually closed at this point? | |
151 | |
152 // Clean up. | 143 // Clean up. |
153 if (!base::DeleteFile(irt_path_, false)) { | 144 if (fclose(irt_fp_)) { |
Mark Seaborn
2015/09/02 18:46:45
Nit: you could do this before LaunchNaCl()
Sean Klein
2015/09/02 21:49:11
Done.
| |
154 LOG(FATAL) << "Failed to remove irt temp file " << irt_path_.value(); | 145 LOG(FATAL) << "Failed to close irt temp file"; |
155 } | 146 } |
156 if (!base::DeleteFile(nexe_path, false)) { | 147 if (fclose(nexe_fp)) { |
157 LOG(FATAL) << "Failed to remove nexe temp file " << nexe_path.value(); | 148 LOG(FATAL) << "Failed to close nexe temp file"; |
158 } | 149 } |
159 | 150 |
160 // Exits the process cleanly, does not return. | 151 // Exits the process cleanly, does not return. |
161 mojo::NaClExit(exit_code); | 152 mojo::NaClExit(exit_code); |
162 NOTREACHED(); | 153 NOTREACHED(); |
163 } | 154 } |
164 | 155 |
165 mojo::ContentHandlerFactory content_handler_factory_; | 156 mojo::ContentHandlerFactory content_handler_factory_; |
166 GURL url_; | 157 GURL url_; |
167 base::FilePath irt_path_; | 158 FILE* irt_fp_; |
168 | 159 |
169 mojo::URLLoaderPtr url_loader_; | 160 mojo::URLLoaderPtr url_loader_; |
170 | 161 |
171 DISALLOW_COPY_AND_ASSIGN(NaClContentHandler); | 162 DISALLOW_COPY_AND_ASSIGN(NaClContentHandler); |
172 }; | 163 }; |
173 | 164 |
174 } // namespace content_handler | 165 } // namespace content_handler |
175 } // namespace nacl | 166 } // namespace nacl |
176 | 167 |
177 MojoResult MojoMain(MojoHandle application_request) { | 168 MojoResult MojoMain(MojoHandle application_request) { |
178 mojo::ApplicationRunnerChromium runner( | 169 mojo::ApplicationRunnerChromium runner( |
179 new nacl::content_handler::NaClContentHandler()); | 170 new nacl::content_handler::NaClContentHandler()); |
180 return runner.Run(application_request); | 171 return runner.Run(application_request); |
181 } | 172 } |
OLD | NEW |