OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "native_client/src/trusted/plugin/pnacl_coordinator.h" | 5 #include "native_client/src/trusted/plugin/pnacl_coordinator.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "native_client/src/include/portability_io.h" | 10 #include "native_client/src/include/portability_io.h" |
11 #include "native_client/src/shared/platform/nacl_check.h" | 11 #include "native_client/src/shared/platform/nacl_check.h" |
12 #include "native_client/src/shared/platform/nacl_sync_raii.h" | 12 #include "native_client/src/trusted/plugin/local_temp_file.h" |
13 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" | |
14 #include "native_client/src/trusted/plugin/manifest.h" | 13 #include "native_client/src/trusted/plugin/manifest.h" |
15 #include "native_client/src/trusted/plugin/nacl_subprocess.h" | |
16 #include "native_client/src/trusted/plugin/nexe_arch.h" | |
17 #include "native_client/src/trusted/plugin/plugin.h" | 14 #include "native_client/src/trusted/plugin/plugin.h" |
18 #include "native_client/src/trusted/plugin/plugin_error.h" | 15 #include "native_client/src/trusted/plugin/plugin_error.h" |
| 16 #include "native_client/src/trusted/plugin/pnacl_translate_thread.h" |
19 #include "native_client/src/trusted/plugin/service_runtime.h" | 17 #include "native_client/src/trusted/plugin/service_runtime.h" |
20 #include "native_client/src/trusted/plugin/srpc_params.h" | |
21 #include "native_client/src/trusted/plugin/utility.h" | |
22 #include "native_client/src/trusted/service_runtime/include/sys/stat.h" | 18 #include "native_client/src/trusted/service_runtime/include/sys/stat.h" |
23 | 19 |
24 #include "ppapi/c/pp_errors.h" | 20 #include "ppapi/c/pp_errors.h" |
25 #include "ppapi/c/ppb_file_io.h" | 21 #include "ppapi/c/ppb_file_io.h" |
26 #include "ppapi/cpp/file_io.h" | 22 #include "ppapi/cpp/file_io.h" |
27 | 23 |
28 namespace plugin { | |
29 | |
30 class Plugin; | |
31 | |
32 namespace { | 24 namespace { |
33 | |
34 const char kLlcUrl[] = "llc"; | |
35 const char kLdUrl[] = "ld"; | |
36 const char kPnaclTempDir[] = "/.pnacl"; | 25 const char kPnaclTempDir[] = "/.pnacl"; |
37 | |
38 nacl::string ExtensionUrl() { | |
39 // TODO(sehr,jvoung): Find a better way to express the URL for the pnacl | |
40 // extension than a constant string here. | |
41 const nacl::string kPnaclExtensionOrigin = | |
42 "chrome-extension://gcodniebolpnpaiggndmcmmfpldlknih/"; | |
43 return kPnaclExtensionOrigin + GetSandboxISA() + "/"; | |
44 } | 26 } |
45 | 27 |
46 nacl::string Random32CharHexString(struct NaClDescRng* rng) { | 28 namespace plugin { |
47 struct NaClDesc* desc = reinterpret_cast<struct NaClDesc*>(rng); | |
48 const struct NaClDescVtbl* vtbl = | |
49 reinterpret_cast<const struct NaClDescVtbl*>(desc->base.vtbl); | |
50 | |
51 nacl::string hex_string; | |
52 const int32_t kTempFileNameWords = 4; | |
53 for (int32_t i = 0; i < kTempFileNameWords; ++i) { | |
54 int32_t num; | |
55 CHECK(sizeof num == vtbl->Read(desc, | |
56 reinterpret_cast<char*>(&num), | |
57 sizeof num)); | |
58 char frag[16]; | |
59 SNPRINTF(frag, sizeof frag, "%08x", num); | |
60 hex_string += nacl::string(frag); | |
61 } | |
62 return hex_string; | |
63 } | |
64 | |
65 // Some constants for PnaclFileDescPair::GetFD readability. | |
66 const bool kReadOnly = false; | |
67 const bool kWriteable = true; | |
68 } // namespace | |
69 | |
70 ////////////////////////////////////////////////////////////////////// | |
71 // Local temporary file access. | |
72 ////////////////////////////////////////////////////////////////////// | |
73 | |
74 uint32_t LocalTempFile::next_identifier = 0; | |
75 | |
76 LocalTempFile::LocalTempFile(Plugin* plugin, | |
77 pp::FileSystem* file_system) | |
78 : plugin_(plugin), | |
79 file_system_(file_system) { | |
80 PLUGIN_PRINTF(("LocalTempFile::LocalTempFile (plugin=%p, " | |
81 "file_system=%p)\n", | |
82 static_cast<void*>(plugin), static_cast<void*>(file_system))); | |
83 Initialize(); | |
84 } | |
85 | |
86 LocalTempFile::LocalTempFile(Plugin* plugin, | |
87 pp::FileSystem* file_system, | |
88 const nacl::string &filename) | |
89 : plugin_(plugin), | |
90 file_system_(file_system), | |
91 filename_(nacl::string(kPnaclTempDir) + "/" + filename) { | |
92 PLUGIN_PRINTF(("LocalTempFile::LocalTempFile (plugin=%p, " | |
93 "file_system=%p, filename=%s)\n", | |
94 static_cast<void*>(plugin), static_cast<void*>(file_system), | |
95 filename.c_str())); | |
96 file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); | |
97 Initialize(); | |
98 } | |
99 | |
100 void LocalTempFile::Initialize() { | |
101 callback_factory_.Initialize(this); | |
102 rng_desc_ = (struct NaClDescRng *) malloc(sizeof *rng_desc_); | |
103 CHECK(rng_desc_ != NULL); | |
104 CHECK(NaClDescRngCtor(rng_desc_)); | |
105 file_io_trusted_ = static_cast<const PPB_FileIOTrusted*>( | |
106 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE)); | |
107 ++next_identifier; | |
108 SNPRINTF(reinterpret_cast<char *>(identifier_), sizeof identifier_, | |
109 "%"NACL_PRIu32, next_identifier); | |
110 } | |
111 | |
112 LocalTempFile::~LocalTempFile() { | |
113 PLUGIN_PRINTF(("LocalTempFile::~LocalTempFile\n")); | |
114 NaClDescUnref(reinterpret_cast<NaClDesc*>(rng_desc_)); | |
115 } | |
116 | |
117 void LocalTempFile::OpenWrite(const pp::CompletionCallback& cb) { | |
118 done_callback_ = cb; | |
119 // If we don't already have a filename, generate one. | |
120 if (filename_ == "") { | |
121 // Get a random temp file name. | |
122 filename_ = | |
123 nacl::string(kPnaclTempDir) + "/" + Random32CharHexString(rng_desc_); | |
124 // Remember the ref used to open for writing and reading. | |
125 file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); | |
126 } | |
127 PLUGIN_PRINTF(("LocalTempFile::OpenWrite: %s\n", filename_.c_str())); | |
128 // Open the writeable file. | |
129 write_io_.reset(new pp::FileIO(plugin_)); | |
130 pp::CompletionCallback open_write_cb = | |
131 callback_factory_.NewCallback(&LocalTempFile::WriteFileDidOpen); | |
132 write_io_->Open(*file_ref_, | |
133 PP_FILEOPENFLAG_WRITE | | |
134 PP_FILEOPENFLAG_CREATE | | |
135 PP_FILEOPENFLAG_EXCLUSIVE, | |
136 open_write_cb); | |
137 } | |
138 | |
139 int32_t LocalTempFile::GetFD(int32_t pp_error, | |
140 const pp::Resource& resource, | |
141 bool is_writable) { | |
142 PLUGIN_PRINTF(("LocalTempFile::GetFD (pp_error=%"NACL_PRId32 | |
143 ", is_writable=%d)\n", pp_error, is_writable)); | |
144 if (pp_error != PP_OK) { | |
145 PLUGIN_PRINTF(("LocalTempFile::GetFD pp_error != PP_OK\n")); | |
146 return -1; | |
147 } | |
148 int32_t file_desc = | |
149 file_io_trusted_->GetOSFileDescriptor(resource.pp_resource()); | |
150 #if NACL_WINDOWS | |
151 // Convert the Windows HANDLE from Pepper to a POSIX file descriptor. | |
152 int32_t open_flags = ((is_writable ? _O_RDWR : _O_RDONLY) | _O_BINARY); | |
153 int32_t posix_desc = _open_osfhandle(file_desc, open_flags); | |
154 if (posix_desc == -1) { | |
155 // Close the Windows HANDLE if it can't be converted. | |
156 CloseHandle(reinterpret_cast<HANDLE>(file_desc)); | |
157 PLUGIN_PRINTF(("LocalTempFile::GetFD _open_osfhandle failed.\n")); | |
158 return NACL_NO_FILE_DESC; | |
159 } | |
160 file_desc = posix_desc; | |
161 #endif | |
162 int32_t file_desc_ok_to_close = DUP(file_desc); | |
163 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) { | |
164 PLUGIN_PRINTF(("LocalTempFile::GetFD dup failed.\n")); | |
165 return -1; | |
166 } | |
167 return file_desc_ok_to_close; | |
168 } | |
169 | |
170 void LocalTempFile::WriteFileDidOpen(int32_t pp_error) { | |
171 PLUGIN_PRINTF(("LocalTempFile::WriteFileDidOpen (pp_error=%" | |
172 NACL_PRId32")\n", pp_error)); | |
173 if (pp_error == PP_ERROR_FILEEXISTS) { | |
174 // Filenames clashed, retry. | |
175 filename_ = ""; | |
176 OpenWrite(done_callback_); | |
177 } | |
178 // Run the client's completion callback. | |
179 pp::Core* core = pp::Module::Get()->core(); | |
180 if (pp_error != PP_OK) { | |
181 core->CallOnMainThread(0, done_callback_, pp_error); | |
182 return; | |
183 } | |
184 // Remember the object temporary file descriptor. | |
185 int32_t fd = GetFD(pp_error, *write_io_, kWriteable); | |
186 if (fd < 0) { | |
187 core->CallOnMainThread(0, done_callback_, pp_error); | |
188 return; | |
189 } | |
190 // The descriptor for a writeable file needs to have quota management. | |
191 write_wrapper_.reset( | |
192 plugin_->wrapper_factory()->MakeFileDescQuota(fd, O_RDWR, identifier_)); | |
193 core->CallOnMainThread(0, done_callback_, PP_OK); | |
194 } | |
195 | |
196 void LocalTempFile::OpenRead(const pp::CompletionCallback& cb) { | |
197 PLUGIN_PRINTF(("LocalTempFile::OpenRead: %s\n", filename_.c_str())); | |
198 done_callback_ = cb; | |
199 // Open the read only file. | |
200 read_io_.reset(new pp::FileIO(plugin_)); | |
201 pp::CompletionCallback open_read_cb = | |
202 callback_factory_.NewCallback(&LocalTempFile::ReadFileDidOpen); | |
203 read_io_->Open(*file_ref_, PP_FILEOPENFLAG_READ, open_read_cb); | |
204 } | |
205 | |
206 void LocalTempFile::ReadFileDidOpen(int32_t pp_error) { | |
207 PLUGIN_PRINTF(("LocalTempFile::ReadFileDidOpen (pp_error=%" | |
208 NACL_PRId32")\n", pp_error)); | |
209 // Run the client's completion callback. | |
210 pp::Core* core = pp::Module::Get()->core(); | |
211 if (pp_error != PP_OK) { | |
212 core->CallOnMainThread(0, done_callback_, pp_error); | |
213 return; | |
214 } | |
215 // Remember the object temporary file descriptor. | |
216 int32_t fd = GetFD(pp_error, *read_io_, kReadOnly); | |
217 if (fd < 0) { | |
218 core->CallOnMainThread(0, done_callback_, PP_ERROR_FAILED); | |
219 return; | |
220 } | |
221 read_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY)); | |
222 core->CallOnMainThread(0, done_callback_, PP_OK); | |
223 } | |
224 | |
225 void LocalTempFile::Close(const pp::CompletionCallback& cb) { | |
226 PLUGIN_PRINTF(("LocalTempFile::Close: %s\n", filename_.c_str())); | |
227 // Close the open DescWrappers and FileIOs. | |
228 if (write_io_.get() != NULL) { | |
229 write_io_->Close(); | |
230 } | |
231 write_wrapper_.reset(NULL); | |
232 write_io_.reset(NULL); | |
233 if (read_io_.get() != NULL) { | |
234 read_io_->Close(); | |
235 } | |
236 read_wrapper_.reset(NULL); | |
237 read_io_.reset(NULL); | |
238 // Run the client's completion callback. | |
239 pp::Core* core = pp::Module::Get()->core(); | |
240 core->CallOnMainThread(0, cb, PP_OK); | |
241 } | |
242 | |
243 void LocalTempFile::Delete(const pp::CompletionCallback& cb) { | |
244 PLUGIN_PRINTF(("LocalTempFile::Delete: %s\n", filename_.c_str())); | |
245 file_ref_->Delete(cb); | |
246 } | |
247 | |
248 void LocalTempFile::Rename(const nacl::string& new_name, | |
249 const pp::CompletionCallback& cb) { | |
250 // Rename the temporary file. | |
251 filename_ = nacl::string(kPnaclTempDir) + "/" + new_name; | |
252 PLUGIN_PRINTF(("LocalTempFile::Rename %s to %s\n", | |
253 file_ref_->GetName().AsString().c_str(), | |
254 filename_.c_str())); | |
255 // Remember the old ref until the rename is complete. | |
256 old_ref_.reset(file_ref_.release()); | |
257 file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); | |
258 old_ref_->Rename(*file_ref_, cb); | |
259 } | |
260 | |
261 void LocalTempFile::FinishRename() { | |
262 // Now we can release the old ref. | |
263 old_ref_.reset(NULL); | |
264 } | |
265 | |
266 | 29 |
267 ////////////////////////////////////////////////////////////////////// | 30 ////////////////////////////////////////////////////////////////////// |
268 // Pnacl-specific manifest support. | 31 // Pnacl-specific manifest support. |
269 ////////////////////////////////////////////////////////////////////// | 32 ////////////////////////////////////////////////////////////////////// |
270 class ExtensionManifest : public Manifest { | 33 class ExtensionManifest : public Manifest { |
271 public: | 34 public: |
272 explicit ExtensionManifest(const pp::URLUtil_Dev* url_util) | 35 explicit ExtensionManifest(const pp::URLUtil_Dev* url_util) |
273 : url_util_(url_util), | 36 : url_util_(url_util), |
274 manifest_base_url_(ExtensionUrl()) { } | 37 manifest_base_url_(PnaclUrls::GetExtensionUrl()) { } |
275 virtual ~ExtensionManifest() { } | 38 virtual ~ExtensionManifest() { } |
276 | 39 |
277 virtual bool GetProgramURL(nacl::string* full_url, | 40 virtual bool GetProgramURL(nacl::string* full_url, |
278 nacl::string* cache_identity, | 41 nacl::string* cache_identity, |
279 ErrorInfo* error_info, | 42 ErrorInfo* error_info, |
280 bool* pnacl_translate) const { | 43 bool* pnacl_translate) const { |
281 // Does not contain program urls. | 44 // Does not contain program urls. |
282 UNREFERENCED_PARAMETER(full_url); | 45 UNREFERENCED_PARAMETER(full_url); |
283 UNREFERENCED_PARAMETER(cache_identity); | 46 UNREFERENCED_PARAMETER(cache_identity); |
284 UNREFERENCED_PARAMETER(error_info); | 47 UNREFERENCED_PARAMETER(error_info); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 const pp::CompletionCallback& translate_notify_callback) { | 172 const pp::CompletionCallback& translate_notify_callback) { |
410 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (plugin=%p, pexe=%s)\n", | 173 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (plugin=%p, pexe=%s)\n", |
411 static_cast<void*>(plugin), pexe_url.c_str())); | 174 static_cast<void*>(plugin), pexe_url.c_str())); |
412 PnaclCoordinator* coordinator = | 175 PnaclCoordinator* coordinator = |
413 new PnaclCoordinator(plugin, pexe_url, | 176 new PnaclCoordinator(plugin, pexe_url, |
414 cache_identity, translate_notify_callback); | 177 cache_identity, translate_notify_callback); |
415 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (manifest=%p)\n", | 178 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (manifest=%p)\n", |
416 reinterpret_cast<const void*>(coordinator->manifest_.get()))); | 179 reinterpret_cast<const void*>(coordinator->manifest_.get()))); |
417 // Load llc and ld. | 180 // Load llc and ld. |
418 std::vector<nacl::string> resource_urls; | 181 std::vector<nacl::string> resource_urls; |
419 resource_urls.push_back(kLlcUrl); | 182 resource_urls.push_back(PnaclUrls::GetLlcUrl()); |
420 resource_urls.push_back(kLdUrl); | 183 resource_urls.push_back(PnaclUrls::GetLdUrl()); |
421 pp::CompletionCallback resources_cb = | 184 pp::CompletionCallback resources_cb = |
422 coordinator->callback_factory_.NewCallback( | 185 coordinator->callback_factory_.NewCallback( |
423 &PnaclCoordinator::ResourcesDidLoad); | 186 &PnaclCoordinator::ResourcesDidLoad); |
424 coordinator->resources_.reset( | 187 coordinator->resources_.reset( |
425 new PnaclResources(plugin, | 188 new PnaclResources(plugin, |
426 coordinator, | 189 coordinator, |
427 coordinator->manifest_.get(), | 190 coordinator->manifest_.get(), |
428 resource_urls, | 191 resource_urls, |
429 resources_cb)); | 192 resources_cb)); |
430 CHECK(coordinator->resources_ != NULL); | 193 CHECK(coordinator->resources_ != NULL); |
(...skipping 21 matching lines...) Expand all Loading... |
452 return file_desc_ok_to_close; | 215 return file_desc_ok_to_close; |
453 } | 216 } |
454 | 217 |
455 PnaclCoordinator::PnaclCoordinator( | 218 PnaclCoordinator::PnaclCoordinator( |
456 Plugin* plugin, | 219 Plugin* plugin, |
457 const nacl::string& pexe_url, | 220 const nacl::string& pexe_url, |
458 const nacl::string& cache_identity, | 221 const nacl::string& cache_identity, |
459 const pp::CompletionCallback& translate_notify_callback) | 222 const pp::CompletionCallback& translate_notify_callback) |
460 : plugin_(plugin), | 223 : plugin_(plugin), |
461 translate_notify_callback_(translate_notify_callback), | 224 translate_notify_callback_(translate_notify_callback), |
462 subprocesses_should_die_(false), | |
463 file_system_(new pp::FileSystem(plugin, PP_FILESYSTEMTYPE_LOCALTEMPORARY)), | 225 file_system_(new pp::FileSystem(plugin, PP_FILESYSTEMTYPE_LOCALTEMPORARY)), |
464 manifest_(new ExtensionManifest(plugin->url_util())), | 226 manifest_(new ExtensionManifest(plugin->url_util())), |
465 pexe_url_(pexe_url), | 227 pexe_url_(pexe_url), |
466 cache_identity_(cache_identity), | 228 cache_identity_(cache_identity), |
467 error_already_reported_(false) { | 229 error_already_reported_(false) { |
468 PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n", | 230 PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n", |
469 static_cast<void*>(this), static_cast<void*>(plugin))); | 231 static_cast<void*>(this), static_cast<void*>(plugin))); |
470 callback_factory_.Initialize(this); | 232 callback_factory_.Initialize(this); |
471 NaClXMutexCtor(&subprocess_mu_); | |
472 ld_manifest_.reset(new PnaclLDManifest(plugin_->manifest(), manifest_.get())); | 233 ld_manifest_.reset(new PnaclLDManifest(plugin_->manifest(), manifest_.get())); |
473 } | 234 } |
474 | 235 |
475 PnaclCoordinator::~PnaclCoordinator() { | 236 PnaclCoordinator::~PnaclCoordinator() { |
476 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n", | 237 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n", |
477 static_cast<void*>(this))); | 238 static_cast<void*>(this))); |
478 // Stopping the translate thread will cause the translate thread to try to | 239 // Stopping the translate thread will cause the translate thread to try to |
479 // run translation_complete_callback_ on the main thread. This destructor is | 240 // run translation_complete_callback_ on the main thread. This destructor is |
480 // running from the main thread, and by the time it exits, callback_factory_ | 241 // running from the main thread, and by the time it exits, callback_factory_ |
481 // will have been destroyed. This will result in the cancellation of | 242 // will have been destroyed. This will result in the cancellation of |
482 // translation_complete_callback_, so no notification will be delivered. | 243 // translation_complete_callback_, so no notification will be delivered. |
483 if (translate_thread_.get() != NULL) { | 244 if (translate_thread_.get() != NULL) { |
484 SetSubprocessesShouldDie(true); | 245 translate_thread_->SetSubprocessesShouldDie(true); |
485 } | 246 } |
486 NaClMutexDtor(&subprocess_mu_); | |
487 } | 247 } |
488 | 248 |
489 void PnaclCoordinator::ReportNonPpapiError(const nacl::string& message) { | 249 void PnaclCoordinator::ReportNonPpapiError(const nacl::string& message) { |
490 error_info_.SetReport(ERROR_UNKNOWN, | 250 error_info_.SetReport(ERROR_UNKNOWN, |
491 nacl::string("PnaclCoordinator: ") + message); | 251 nacl::string("PnaclCoordinator: ") + message); |
492 ReportPpapiError(PP_ERROR_FAILED); | 252 ReportPpapiError(PP_ERROR_FAILED); |
493 } | 253 } |
494 | 254 |
495 void PnaclCoordinator::ReportPpapiError(int32_t pp_error, | 255 void PnaclCoordinator::ReportPpapiError(int32_t pp_error, |
496 const nacl::string& message) { | 256 const nacl::string& message) { |
(...skipping 17 matching lines...) Expand all Loading... |
514 callback_factory_.CancelAll(); | 274 callback_factory_.CancelAll(); |
515 if (!error_already_reported_) { | 275 if (!error_already_reported_) { |
516 error_already_reported_ = true; | 276 error_already_reported_ = true; |
517 translate_notify_callback_.Run(pp_error); | 277 translate_notify_callback_.Run(pp_error); |
518 } else { | 278 } else { |
519 PLUGIN_PRINTF(("PnaclCoordinator::ReportPpapiError an earlier error was " | 279 PLUGIN_PRINTF(("PnaclCoordinator::ReportPpapiError an earlier error was " |
520 "already reported -- Skipping.\n")); | 280 "already reported -- Skipping.\n")); |
521 } | 281 } |
522 } | 282 } |
523 | 283 |
| 284 // Signal that Pnacl translation completed normally. |
524 void PnaclCoordinator::TranslateFinished(int32_t pp_error) { | 285 void PnaclCoordinator::TranslateFinished(int32_t pp_error) { |
525 PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished (pp_error=%" | 286 PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished (pp_error=%" |
526 NACL_PRId32")\n", pp_error)); | 287 NACL_PRId32")\n", pp_error)); |
527 // Save the translate error code, and inspect after cleaning up junk files. | 288 // Save the translate error code, and inspect after cleaning up junk files. |
528 // Note: If there was a surfaway and the file objects were actually | 289 // Note: If there was a surfaway and the file objects were actually |
529 // destroyed, then we are in trouble since the obj_file_, nexe_file_, | 290 // destroyed, then we are in trouble since the obj_file_, nexe_file_, |
530 // etc. may have been destroyed. | 291 // etc. may have been destroyed. |
531 // TODO(jvoung,sehr): Fix. | 292 // TODO(jvoung,sehr): Fix. |
532 translate_finish_error_ = pp_error; | 293 translate_finish_error_ = pp_error; |
533 | 294 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress); | 381 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress); |
621 translate_notify_callback_.Run(pp_error); | 382 translate_notify_callback_.Run(pp_error); |
622 } | 383 } |
623 | 384 |
624 void PnaclCoordinator::NexeFileWasDeleted(int32_t pp_error) { | 385 void PnaclCoordinator::NexeFileWasDeleted(int32_t pp_error) { |
625 PLUGIN_PRINTF(("PnaclCoordinator::NexeFileWasDeleted (pp_error=%" | 386 PLUGIN_PRINTF(("PnaclCoordinator::NexeFileWasDeleted (pp_error=%" |
626 NACL_PRId32")\n", pp_error)); | 387 NACL_PRId32")\n", pp_error)); |
627 ReportPpapiError(translate_finish_error_); | 388 ReportPpapiError(translate_finish_error_); |
628 } | 389 } |
629 | 390 |
630 void PnaclCoordinator::TranslateFailed(const nacl::string& error_string) { | |
631 PLUGIN_PRINTF(("PnaclCoordinator::TranslateFailed (error_string='%s')\n", | |
632 error_string.c_str())); | |
633 pp::Core* core = pp::Module::Get()->core(); | |
634 error_info_.SetReport(ERROR_UNKNOWN, | |
635 nacl::string("PnaclCoordinator: ") + error_string); | |
636 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); | |
637 } | |
638 | |
639 void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) { | 391 void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) { |
640 PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%" | 392 PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%" |
641 NACL_PRId32")\n", pp_error)); | 393 NACL_PRId32")\n", pp_error)); |
642 if (pp_error != PP_OK) { | 394 if (pp_error != PP_OK) { |
643 ReportPpapiError(pp_error, "resources failed to load."); | 395 ReportPpapiError(pp_error, "resources failed to load."); |
644 return; | 396 return; |
645 } | 397 } |
646 // Open the local temporary file system to create the temporary files | 398 // Open the local temporary file system to create the temporary files |
647 // for the object and nexe. | 399 // for the object and nexe. |
648 pp::CompletionCallback cb = | 400 pp::CompletionCallback cb = |
649 callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen); | 401 callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen); |
650 if (!file_system_->Open(0, cb)) { | 402 if (!file_system_->Open(0, cb)) { |
651 ReportNonPpapiError("failed to open file system."); | 403 ReportNonPpapiError("failed to open file system."); |
652 } | 404 } |
653 } | 405 } |
654 | 406 |
655 void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) { | 407 void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) { |
656 PLUGIN_PRINTF(("PnaclCoordinator::FileSystemDidOpen (pp_error=%" | 408 PLUGIN_PRINTF(("PnaclCoordinator::FileSystemDidOpen (pp_error=%" |
657 NACL_PRId32")\n", pp_error)); | 409 NACL_PRId32")\n", pp_error)); |
658 if (pp_error != PP_OK) { | 410 if (pp_error != PP_OK) { |
659 ReportPpapiError(pp_error, "file system didn't open."); | 411 ReportPpapiError(pp_error, "file system didn't open."); |
660 return; | 412 return; |
661 } | 413 } |
662 dir_ref_.reset(new pp::FileRef(*file_system_, kPnaclTempDir)); | 414 dir_ref_.reset(new pp::FileRef(*file_system_, |
| 415 kPnaclTempDir)); |
663 dir_io_.reset(new pp::FileIO(plugin_)); | 416 dir_io_.reset(new pp::FileIO(plugin_)); |
664 // Attempt to create the directory. | 417 // Attempt to create the directory. |
665 pp::CompletionCallback cb = | 418 pp::CompletionCallback cb = |
666 callback_factory_.NewCallback(&PnaclCoordinator::DirectoryWasCreated); | 419 callback_factory_.NewCallback(&PnaclCoordinator::DirectoryWasCreated); |
667 dir_ref_->MakeDirectory(cb); | 420 dir_ref_->MakeDirectory(cb); |
668 } | 421 } |
669 | 422 |
670 void PnaclCoordinator::DirectoryWasCreated(int32_t pp_error) { | 423 void PnaclCoordinator::DirectoryWasCreated(int32_t pp_error) { |
671 PLUGIN_PRINTF(("PnaclCoordinator::DirectoryWasCreated (pp_error=%" | 424 PLUGIN_PRINTF(("PnaclCoordinator::DirectoryWasCreated (pp_error=%" |
672 NACL_PRId32")\n", pp_error)); | 425 NACL_PRId32")\n", pp_error)); |
673 if (pp_error != PP_ERROR_FILEEXISTS && pp_error != PP_OK) { | 426 if (pp_error != PP_ERROR_FILEEXISTS && pp_error != PP_OK) { |
674 // Directory did not exist and could not be created. | 427 // Directory did not exist and could not be created. |
675 ReportPpapiError(pp_error, "directory creation/check failed."); | 428 ReportPpapiError(pp_error, "directory creation/check failed."); |
676 return; | 429 return; |
677 } | 430 } |
678 if (cache_identity_ != "") { | 431 if (cache_identity_ != "") { |
679 nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), | 432 nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), |
| 433 nacl::string(kPnaclTempDir), |
680 cache_identity_)); | 434 cache_identity_)); |
681 pp::CompletionCallback cb = | 435 pp::CompletionCallback cb = |
682 callback_factory_.NewCallback(&PnaclCoordinator::CachedFileDidOpen); | 436 callback_factory_.NewCallback(&PnaclCoordinator::CachedFileDidOpen); |
683 nexe_file_->OpenRead(cb); | 437 nexe_file_->OpenRead(cb); |
684 } else { | 438 } else { |
685 // For now, tolerate lack of cache identity... | 439 // For now, tolerate lack of cache identity... |
686 CachedFileDidOpen(PP_ERROR_FAILED); | 440 CachedFileDidOpen(PP_ERROR_FAILED); |
687 } | 441 } |
688 } | 442 } |
689 | 443 |
(...skipping 17 matching lines...) Expand all Loading... |
707 NACL_PRId32")\n", pp_error)); | 461 NACL_PRId32")\n", pp_error)); |
708 // We have to get the fd immediately after streaming, otherwise it | 462 // We have to get the fd immediately after streaming, otherwise it |
709 // seems like the temp file will get GC'ed. | 463 // seems like the temp file will get GC'ed. |
710 int32_t fd = GetLoadedFileDesc(pp_error, pexe_url_, "pexe"); | 464 int32_t fd = GetLoadedFileDesc(pp_error, pexe_url_, "pexe"); |
711 if (fd < 0) { | 465 if (fd < 0) { |
712 // Error already reported by GetLoadedFileDesc(). | 466 // Error already reported by GetLoadedFileDesc(). |
713 return; | 467 return; |
714 } | 468 } |
715 pexe_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY)); | 469 pexe_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY)); |
716 | 470 |
717 obj_file_.reset(new LocalTempFile(plugin_, file_system_.get())); | 471 obj_file_.reset(new LocalTempFile(plugin_, file_system_.get(), |
| 472 nacl::string(kPnaclTempDir))); |
718 pp::CompletionCallback cb = | 473 pp::CompletionCallback cb = |
719 callback_factory_.NewCallback(&PnaclCoordinator::ObjectWriteDidOpen); | 474 callback_factory_.NewCallback(&PnaclCoordinator::ObjectWriteDidOpen); |
720 obj_file_->OpenWrite(cb); | 475 obj_file_->OpenWrite(cb); |
721 } | 476 } |
722 | 477 |
723 void PnaclCoordinator::ObjectWriteDidOpen(int32_t pp_error) { | 478 void PnaclCoordinator::ObjectWriteDidOpen(int32_t pp_error) { |
724 PLUGIN_PRINTF(("PnaclCoordinator::ObjectWriteDidOpen (pp_error=%" | 479 PLUGIN_PRINTF(("PnaclCoordinator::ObjectWriteDidOpen (pp_error=%" |
725 NACL_PRId32")\n", pp_error)); | 480 NACL_PRId32")\n", pp_error)); |
726 if (pp_error != PP_OK) { | 481 if (pp_error != PP_OK) { |
727 ReportPpapiError(pp_error); | 482 ReportPpapiError(pp_error); |
728 return; | 483 return; |
729 } | 484 } |
730 pp::CompletionCallback cb = | 485 pp::CompletionCallback cb = |
731 callback_factory_.NewCallback(&PnaclCoordinator::ObjectReadDidOpen); | 486 callback_factory_.NewCallback(&PnaclCoordinator::ObjectReadDidOpen); |
732 obj_file_->OpenRead(cb); | 487 obj_file_->OpenRead(cb); |
733 } | 488 } |
734 | 489 |
735 void PnaclCoordinator::ObjectReadDidOpen(int32_t pp_error) { | 490 void PnaclCoordinator::ObjectReadDidOpen(int32_t pp_error) { |
736 PLUGIN_PRINTF(("PnaclCoordinator::ObjectReadDidOpen (pp_error=%" | 491 PLUGIN_PRINTF(("PnaclCoordinator::ObjectReadDidOpen (pp_error=%" |
737 NACL_PRId32")\n", pp_error)); | 492 NACL_PRId32")\n", pp_error)); |
738 if (pp_error != PP_OK) { | 493 if (pp_error != PP_OK) { |
739 ReportPpapiError(pp_error); | 494 ReportPpapiError(pp_error); |
740 return; | 495 return; |
741 } | 496 } |
742 // Create the nexe file for connecting ld and sel_ldr. | 497 // Create the nexe file for connecting ld and sel_ldr. |
743 // Start translation when done with this last step of setup! | 498 // Start translation when done with this last step of setup! |
744 nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get())); | 499 nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), |
| 500 nacl::string(kPnaclTempDir))); |
745 pp::CompletionCallback cb = | 501 pp::CompletionCallback cb = |
746 callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate); | 502 callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate); |
747 nexe_file_->OpenWrite(cb); | 503 nexe_file_->OpenWrite(cb); |
748 } | 504 } |
749 | 505 |
750 void PnaclCoordinator::RunTranslate(int32_t pp_error) { | 506 void PnaclCoordinator::RunTranslate(int32_t pp_error) { |
751 PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%" | 507 PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%" |
752 NACL_PRId32")\n", pp_error)); | 508 NACL_PRId32")\n", pp_error)); |
753 // Invoke llc followed by ld off the main thread. This allows use of | 509 // Invoke llc followed by ld off the main thread. This allows use of |
754 // blocking RPCs that would otherwise block the JavaScript main thread. | 510 // blocking RPCs that would otherwise block the JavaScript main thread. |
755 report_translate_finished_ = | 511 pp::CompletionCallback report_translate_finished = |
756 callback_factory_.NewCallback(&PnaclCoordinator::TranslateFinished); | 512 callback_factory_.NewCallback(&PnaclCoordinator::TranslateFinished); |
757 translate_thread_.reset(new NaClThread); | 513 translate_thread_.reset(new PnaclTranslateThread()); |
758 if (translate_thread_ == NULL) { | 514 if (translate_thread_ == NULL) { |
759 ReportNonPpapiError("could not allocate thread struct."); | 515 ReportNonPpapiError("could not allocate translation thread."); |
760 return; | 516 return; |
761 } | 517 } |
762 const int32_t kArbitraryStackSize = 128 * 1024; | 518 translate_thread_->RunTranslate(report_translate_finished, |
763 if (!NaClThreadCreateJoinable(translate_thread_.get(), | 519 manifest_.get(), |
764 DoTranslateThread, | 520 ld_manifest_.get(), |
765 this, | 521 obj_file_.get(), |
766 kArbitraryStackSize)) { | 522 nexe_file_.get(), |
767 ReportNonPpapiError("could not create thread."); | 523 pexe_wrapper_.get(), |
768 } | 524 &error_info_, |
769 } | 525 resources_.get(), |
770 | 526 plugin_); |
771 NaClSubprocess* PnaclCoordinator::StartSubprocess( | |
772 const nacl::string& url_for_nexe, | |
773 const Manifest* manifest) { | |
774 PLUGIN_PRINTF(("PnaclCoordinator::StartSubprocess (url_for_nexe=%s)\n", | |
775 url_for_nexe.c_str())); | |
776 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(url_for_nexe); | |
777 nacl::scoped_ptr<NaClSubprocess> subprocess( | |
778 plugin_->LoadHelperNaClModule(wrapper, manifest, &error_info_)); | |
779 if (subprocess.get() == NULL) { | |
780 PLUGIN_PRINTF(( | |
781 "PnaclCoordinator::StartSubprocess: subprocess creation failed\n")); | |
782 return NULL; | |
783 } | |
784 return subprocess.release(); | |
785 } | |
786 | |
787 // TODO(sehr): the thread body should be in a class by itself with a delegate | |
788 // class for interfacing with the rest of the coordinator. | |
789 void WINAPI PnaclCoordinator::DoTranslateThread(void* arg) { | |
790 PnaclCoordinator* coordinator = reinterpret_cast<PnaclCoordinator*>(arg); | |
791 | |
792 nacl::scoped_ptr<NaClSubprocess> llc_subprocess( | |
793 coordinator->StartSubprocess(kLlcUrl, coordinator->manifest_.get())); | |
794 if (llc_subprocess == NULL) { | |
795 coordinator->TranslateFailed("Compile process could not be created."); | |
796 return; | |
797 } | |
798 // Run LLC. | |
799 SrpcParams params; | |
800 nacl::DescWrapper* llc_out_file = coordinator->obj_file_->write_wrapper(); | |
801 PluginReverseInterface* llc_reverse = | |
802 llc_subprocess->service_runtime()->rev_interface(); | |
803 llc_reverse->AddQuotaManagedFile(coordinator->obj_file_->identifier(), | |
804 coordinator->obj_file_->write_file_io()); | |
805 if (!llc_subprocess->InvokeSrpcMethod("RunWithDefaultCommandLine", | |
806 "hh", | |
807 ¶ms, | |
808 coordinator->pexe_wrapper_->desc(), | |
809 llc_out_file->desc())) { | |
810 coordinator->TranslateFailed("compile failed."); | |
811 return; | |
812 } | |
813 // LLC returns values that are used to determine how linking is done. | |
814 int is_shared_library = (params.outs()[0]->u.ival != 0); | |
815 nacl::string soname = params.outs()[1]->arrays.str; | |
816 nacl::string lib_dependencies = params.outs()[2]->arrays.str; | |
817 PLUGIN_PRINTF(("PnaclCoordinator: compile (coordinator=%p) succeeded" | |
818 " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n", | |
819 arg, is_shared_library, soname.c_str(), | |
820 lib_dependencies.c_str())); | |
821 // Shut down the llc subprocess. | |
822 llc_subprocess.reset(NULL); | |
823 if (coordinator->SubprocessesShouldDie()) { | |
824 coordinator->TranslateFailed("stopped by coordinator."); | |
825 return; | |
826 } | |
827 nacl::scoped_ptr<NaClSubprocess> ld_subprocess( | |
828 coordinator->StartSubprocess(kLdUrl, coordinator->ld_manifest_.get())); | |
829 if (ld_subprocess == NULL) { | |
830 coordinator->TranslateFailed("Link process could not be created."); | |
831 return; | |
832 } | |
833 // Run LD. | |
834 nacl::DescWrapper* ld_in_file = coordinator->obj_file_->read_wrapper(); | |
835 nacl::DescWrapper* ld_out_file = coordinator->nexe_file_->write_wrapper(); | |
836 PluginReverseInterface* ld_reverse = | |
837 ld_subprocess->service_runtime()->rev_interface(); | |
838 ld_reverse->AddQuotaManagedFile(coordinator->nexe_file_->identifier(), | |
839 coordinator->nexe_file_->write_file_io()); | |
840 if (!ld_subprocess->InvokeSrpcMethod("RunWithDefaultCommandLine", | |
841 "hhiCC", | |
842 ¶ms, | |
843 ld_in_file->desc(), | |
844 ld_out_file->desc(), | |
845 is_shared_library, | |
846 soname.c_str(), | |
847 lib_dependencies.c_str())) { | |
848 coordinator->TranslateFailed("link failed."); | |
849 return; | |
850 } | |
851 PLUGIN_PRINTF(("PnaclCoordinator: link (coordinator=%p) succeeded\n", arg)); | |
852 // Shut down the ld subprocess. | |
853 ld_subprocess.reset(NULL); | |
854 if (coordinator->SubprocessesShouldDie()) { | |
855 coordinator->TranslateFailed("stopped by coordinator."); | |
856 return; | |
857 } | |
858 pp::Core* core = pp::Module::Get()->core(); | |
859 core->CallOnMainThread(0, coordinator->report_translate_finished_, PP_OK); | |
860 } | |
861 | |
862 bool PnaclCoordinator::SubprocessesShouldDie() { | |
863 nacl::MutexLocker ml(&subprocess_mu_); | |
864 return subprocesses_should_die_; | |
865 } | |
866 | |
867 void PnaclCoordinator::SetSubprocessesShouldDie(bool subprocesses_should_die) { | |
868 nacl::MutexLocker ml(&subprocess_mu_); | |
869 subprocesses_should_die_ = subprocesses_should_die; | |
870 } | 527 } |
871 | 528 |
872 } // namespace plugin | 529 } // namespace plugin |
OLD | NEW |