| 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 |