| 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/checked_cast.h" | 10 #include "native_client/src/include/checked_cast.h" |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 error_already_reported_(false), | 358 error_already_reported_(false), |
| 359 off_the_record_(false), | 359 off_the_record_(false), |
| 360 pnacl_init_time_(0), | 360 pnacl_init_time_(0), |
| 361 pexe_size_(0), | 361 pexe_size_(0), |
| 362 pexe_bytes_compiled_(0), | 362 pexe_bytes_compiled_(0), |
| 363 expected_pexe_size_(-1) { | 363 expected_pexe_size_(-1) { |
| 364 PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n", | 364 PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n", |
| 365 static_cast<void*>(this), static_cast<void*>(plugin))); | 365 static_cast<void*>(this), static_cast<void*>(plugin))); |
| 366 callback_factory_.Initialize(this); | 366 callback_factory_.Initialize(this); |
| 367 ld_manifest_.reset(new PnaclLDManifest(plugin_->manifest(), manifest_.get())); | 367 ld_manifest_.reset(new PnaclLDManifest(plugin_->manifest(), manifest_.get())); |
| 368 pp::Module *module = pp::Module::Get(); |
| 369 DCHECK(module); |
| 370 nacl_hash_private_interface_ = static_cast<const PPB_NaCl_Hash_Private*>( |
| 371 module->GetBrowserInterface(PPB_NACL_HASH_PRIVATE_INTERFACE)); |
| 372 bitcode_hash_verifier_ = nacl_hash_private_interface_->CreateSHA256Hasher(); |
| 368 } | 373 } |
| 369 | 374 |
| 370 PnaclCoordinator::~PnaclCoordinator() { | 375 PnaclCoordinator::~PnaclCoordinator() { |
| 371 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p, " | 376 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p, " |
| 372 "translate_thread=%p\n", | 377 "translate_thread=%p\n", |
| 373 static_cast<void*>(this), translate_thread_.get())); | 378 static_cast<void*>(this), translate_thread_.get())); |
| 374 // Stopping the translate thread will cause the translate thread to try to | 379 // Stopping the translate thread will cause the translate thread to try to |
| 375 // run translation_complete_callback_ on the main thread. This destructor is | 380 // run translation_complete_callback_ on the main thread. This destructor is |
| 376 // running from the main thread, and by the time it exits, callback_factory_ | 381 // running from the main thread, and by the time it exits, callback_factory_ |
| 377 // will have been destroyed. This will result in the cancellation of | 382 // will have been destroyed. This will result in the cancellation of |
| 378 // translation_complete_callback_, so no notification will be delivered. | 383 // translation_complete_callback_, so no notification will be delivered. |
| 379 if (translate_thread_.get() != NULL) { | 384 if (translate_thread_.get() != NULL) { |
| 380 translate_thread_->AbortSubprocesses(); | 385 translate_thread_->AbortSubprocesses(); |
| 381 } | 386 } |
| 387 nacl_hash_private_interface_->Delete(bitcode_hash_verifier_); |
| 382 } | 388 } |
| 383 | 389 |
| 384 void PnaclCoordinator::ReportNonPpapiError(enum PluginErrorCode err_code, | 390 void PnaclCoordinator::ReportNonPpapiError(enum PluginErrorCode err_code, |
| 385 const nacl::string& message) { | 391 const nacl::string& message) { |
| 386 error_info_.SetReport(err_code, | 392 error_info_.SetReport(err_code, |
| 387 nacl::string("PnaclCoordinator: ") + message); | 393 nacl::string("PnaclCoordinator: ") + message); |
| 388 ExitWithError(); | 394 ExitWithError(); |
| 389 } | 395 } |
| 390 | 396 |
| 391 void PnaclCoordinator::ReportPpapiError(enum PluginErrorCode err_code, | 397 void PnaclCoordinator::ReportPpapiError(enum PluginErrorCode err_code, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 static_cast<int64_t>(nexe_size / 1024)); | 469 static_cast<int64_t>(nexe_size / 1024)); |
| 464 HistogramRatio("NaCl.Perf.Size.PexeNexeSizePct", pexe_size_, nexe_size); | 470 HistogramRatio("NaCl.Perf.Size.PexeNexeSizePct", pexe_size_, nexe_size); |
| 465 } | 471 } |
| 466 | 472 |
| 467 // The nexe is written to the temp_nexe_file_. We must Reset() the file | 473 // The nexe is written to the temp_nexe_file_. We must Reset() the file |
| 468 // pointer to be able to read it again from the beginning. | 474 // pointer to be able to read it again from the beginning. |
| 469 temp_nexe_file_->Reset(); | 475 temp_nexe_file_->Reset(); |
| 470 | 476 |
| 471 if (pnacl_options_.HasCacheKey() && cached_nexe_file_ != NULL) { | 477 if (pnacl_options_.HasCacheKey() && cached_nexe_file_ != NULL) { |
| 472 // We are using a cache, but had a cache miss, which is why we did the | 478 // We are using a cache, but had a cache miss, which is why we did the |
| 473 // translation. Reset cached_nexe_file_ to have a random name, | 479 // translation. |
| 474 // for scratch purposes, before renaming to the final cache_identity. | 480 if (BitcodeHashMatchesContents()) { |
| 475 cached_nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), | 481 // Reset cached_nexe_file_ to have a random name, for scratch purposes, |
| 476 nacl::string(kPnaclTempDir))); | 482 // before renaming to the final cache_identity. |
| 477 pp::CompletionCallback cb = callback_factory_.NewCallback( | 483 cached_nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), |
| 478 &PnaclCoordinator::CachedNexeOpenedForWrite); | 484 nacl::string(kPnaclTempDir))); |
| 479 cached_nexe_file_->OpenWrite(cb); | 485 pp::CompletionCallback cb = callback_factory_.NewCallback( |
| 486 &PnaclCoordinator::CachedNexeOpenedForWrite); |
| 487 cached_nexe_file_->OpenWrite(cb); |
| 488 } else { |
| 489 ReportNonPpapiError( |
| 490 ERROR_PNACL_CACHE_HASH_MISMATCH, |
| 491 "Bitcode hash does not match bitcode contents."); |
| 492 } |
| 480 } else { | 493 } else { |
| 481 // For now, tolerate bitcode that is missing a cache identity, and | 494 // For now, tolerate bitcode that is missing a cache identity, and |
| 482 // tolerate the lack of caching in incognito mode. | 495 // tolerate the lack of caching in incognito mode. |
| 483 PLUGIN_PRINTF(("PnaclCoordinator -- not caching.\n")); | 496 PLUGIN_PRINTF(("PnaclCoordinator -- not caching.\n")); |
| 484 NexeReadDidOpen(PP_OK); | 497 NexeReadDidOpen(PP_OK); |
| 485 } | 498 } |
| 486 } | 499 } |
| 487 | 500 |
| 501 bool PnaclCoordinator::BitcodeHashMatchesContents() { |
| 502 const nacl::string& expected_hash = pnacl_options_.GetBitcodeHash(); |
| 503 nacl::string actual_hash; |
| 504 uint8_t hash_digest[32]; |
| 505 nacl_hash_private_interface_->Finish(bitcode_hash_verifier_, |
| 506 &hash_digest, |
| 507 sizeof hash_digest); |
| 508 // Convert 32-byte binary digest to 64-byte hex digest for comparison. |
| 509 for (size_t i = 0; i < sizeof hash_digest; i+=8) { |
| 510 char buf[17]; // do 16 chars + a null byte at a time. |
| 511 SNPRINTF(buf, sizeof buf, "%02x%02x%02x%02x%02x%02x%02x%02x", |
| 512 hash_digest[i ], hash_digest[i+1], |
| 513 hash_digest[i+2], hash_digest[i+3], |
| 514 hash_digest[i+4], hash_digest[i+5], |
| 515 hash_digest[i+6], hash_digest[i+7]); |
| 516 actual_hash.append(buf); |
| 517 } |
| 518 if (expected_hash.size() != actual_hash.size()) { |
| 519 return false; |
| 520 } |
| 521 return nacl_hash_private_interface_->SecureMemEqual(expected_hash.c_str(), |
| 522 actual_hash.c_str(), |
| 523 expected_hash.size()); |
| 524 } |
| 525 |
| 488 void PnaclCoordinator::CachedNexeOpenedForWrite(int32_t pp_error) { | 526 void PnaclCoordinator::CachedNexeOpenedForWrite(int32_t pp_error) { |
| 489 if (pp_error != PP_OK) { | 527 if (pp_error != PP_OK) { |
| 490 if (pp_error == PP_ERROR_NOACCESS) { | 528 if (pp_error == PP_ERROR_NOACCESS) { |
| 491 ReportPpapiError( | 529 ReportPpapiError( |
| 492 ERROR_PNACL_CACHE_FILEOPEN_NOACCESS, | 530 ERROR_PNACL_CACHE_FILEOPEN_NOACCESS, |
| 493 pp_error, | 531 pp_error, |
| 494 "PNaCl translation cache failed to open file for write " | 532 "PNaCl translation cache failed to open file for write " |
| 495 "(no access)."); | 533 "(no access)."); |
| 496 return; | 534 return; |
| 497 } | 535 } |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 HistogramRatio("NaCl.Perf.PNaClLoadTime.PctCompiledWhenFullyDownloaded", | 941 HistogramRatio("NaCl.Perf.PNaClLoadTime.PctCompiledWhenFullyDownloaded", |
| 904 pexe_bytes_compiled_, pexe_size_); | 942 pexe_bytes_compiled_, pexe_size_); |
| 905 } | 943 } |
| 906 } | 944 } |
| 907 | 945 |
| 908 void PnaclCoordinator::BitcodeStreamGotData(int32_t pp_error, | 946 void PnaclCoordinator::BitcodeStreamGotData(int32_t pp_error, |
| 909 FileStreamData data) { | 947 FileStreamData data) { |
| 910 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamGotData (pp_error=%" | 948 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamGotData (pp_error=%" |
| 911 NACL_PRId32", data=%p)\n", pp_error, data ? &(*data)[0] : 0)); | 949 NACL_PRId32", data=%p)\n", pp_error, data ? &(*data)[0] : 0)); |
| 912 DCHECK(translate_thread_.get()); | 950 DCHECK(translate_thread_.get()); |
| 951 // If pp_error > 0, then it represents the number of bytes received. |
| 952 if (pp_error > 0) { |
| 953 pexe_size_ += pp_error; |
| 954 // Update hash for verification before data is taken by PutBytes. |
| 955 if (pnacl_options_.HasCacheKey()) { |
| 956 nacl_hash_private_interface_->Update(bitcode_hash_verifier_, |
| 957 &(*data)[0], |
| 958 pp_error); |
| 959 } |
| 960 } |
| 913 translate_thread_->PutBytes(data, pp_error); | 961 translate_thread_->PutBytes(data, pp_error); |
| 914 // If pp_error > 0, then it represents the number of bytes received. | |
| 915 if (data && pp_error > 0) { | |
| 916 pexe_size_ += pp_error; | |
| 917 } | |
| 918 } | 962 } |
| 919 | 963 |
| 920 StreamCallback PnaclCoordinator::GetCallback() { | 964 StreamCallback PnaclCoordinator::GetCallback() { |
| 921 return callback_factory_.NewCallbackWithOutput( | 965 return callback_factory_.NewCallbackWithOutput( |
| 922 &PnaclCoordinator::BitcodeStreamGotData); | 966 &PnaclCoordinator::BitcodeStreamGotData); |
| 923 } | 967 } |
| 924 | 968 |
| 925 void PnaclCoordinator::BitcodeGotCompiled(int32_t pp_error, | 969 void PnaclCoordinator::BitcodeGotCompiled(int32_t pp_error, |
| 926 int64_t bytes_compiled) { | 970 int64_t bytes_compiled) { |
| 927 // If we don't know the expected total yet, ask. | 971 // If we don't know the expected total yet, ask. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 obj_file_.get(), | 1029 obj_file_.get(), |
| 986 temp_nexe_file_.get(), | 1030 temp_nexe_file_.get(), |
| 987 &error_info_, | 1031 &error_info_, |
| 988 resources_.get(), | 1032 resources_.get(), |
| 989 &pnacl_options_, | 1033 &pnacl_options_, |
| 990 this, | 1034 this, |
| 991 plugin_); | 1035 plugin_); |
| 992 } | 1036 } |
| 993 | 1037 |
| 994 } // namespace plugin | 1038 } // namespace plugin |
| OLD | NEW |