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_->CreateSHA256Hash(); | |
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_, | |
Derek Schuff
2013/04/30 23:52:38
The hash we put in the bitcode header is not the h
jvoung (off chromium)
2013/05/01 00:01:30
The current hash generator is a function in the SD
| |
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 |