| 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 #ifdef _MSC_VER | 5 #ifdef _MSC_VER |
| 6 // Do not warn about use of std::copy with raw pointers. | 6 // Do not warn about use of std::copy with raw pointers. |
| 7 #pragma warning(disable : 4996) | 7 #pragma warning(disable : 4996) |
| 8 #endif | 8 #endif |
| 9 | 9 |
| 10 #include "ppapi/native_client/src/trusted/plugin/plugin.h" | 10 #include "ppapi/native_client/src/trusted/plugin/plugin.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 | 46 |
| 47 // Up to 20 seconds | 47 // Up to 20 seconds |
| 48 const int64_t kTimeSmallMin = 1; // in ms | 48 const int64_t kTimeSmallMin = 1; // in ms |
| 49 const int64_t kTimeSmallMax = 20000; // in ms | 49 const int64_t kTimeSmallMax = 20000; // in ms |
| 50 const uint32_t kTimeSmallBuckets = 100; | 50 const uint32_t kTimeSmallBuckets = 100; |
| 51 | 51 |
| 52 const int64_t kSizeKBMin = 1; | 52 const int64_t kSizeKBMin = 1; |
| 53 const int64_t kSizeKBMax = 512*1024; // very large .nexe | 53 const int64_t kSizeKBMax = 512*1024; // very large .nexe |
| 54 const uint32_t kSizeKBBuckets = 100; | 54 const uint32_t kSizeKBBuckets = 100; |
| 55 | 55 |
| 56 // Converts a PP_FileHandle to a POSIX file descriptor. |
| 57 int32_t ConvertFileDescriptor(PP_FileHandle handle) { |
| 58 PLUGIN_PRINTF(("ConvertFileDescriptor, handle=%d\n", handle)); |
| 59 #if NACL_WINDOWS |
| 60 int32_t file_desc = NACL_NO_FILE_DESC; |
| 61 // On Windows, valid handles are 32 bit unsigned integers so this is safe. |
| 62 file_desc = reinterpret_cast<intptr_t>(handle); |
| 63 // Convert the Windows HANDLE from Pepper to a POSIX file descriptor. |
| 64 int32_t posix_desc = _open_osfhandle(file_desc, _O_RDWR | _O_BINARY); |
| 65 if (posix_desc == -1) { |
| 66 // Close the Windows HANDLE if it can't be converted. |
| 67 CloseHandle(reinterpret_cast<HANDLE>(file_desc)); |
| 68 return -1; |
| 69 } |
| 70 return posix_desc; |
| 71 #else |
| 72 return handle; |
| 73 #endif |
| 74 } |
| 75 |
| 76 |
| 56 } // namespace | 77 } // namespace |
| 57 | 78 |
| 58 void Plugin::ShutDownSubprocesses() { | 79 void Plugin::ShutDownSubprocesses() { |
| 59 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (this=%p)\n", | 80 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (this=%p)\n", |
| 60 static_cast<void*>(this))); | 81 static_cast<void*>(this))); |
| 61 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (%s)\n", | 82 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (%s)\n", |
| 62 main_subprocess_.detailed_description().c_str())); | 83 main_subprocess_.detailed_description().c_str())); |
| 63 | 84 |
| 64 // Shut down service runtime. This must be done before all other calls so | 85 // Shut down service runtime. This must be done before all other calls so |
| 65 // they don't block forever when waiting for the upcall thread to exit. | 86 // they don't block forever when waiting for the upcall thread to exit. |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 RequestNaClManifest(manifest_url.AsString()); | 352 RequestNaClManifest(manifest_url.AsString()); |
| 332 return true; | 353 return true; |
| 333 } | 354 } |
| 334 | 355 |
| 335 Plugin::Plugin(PP_Instance pp_instance) | 356 Plugin::Plugin(PP_Instance pp_instance) |
| 336 : pp::Instance(pp_instance), | 357 : pp::Instance(pp_instance), |
| 337 main_subprocess_("main subprocess", NULL, NULL), | 358 main_subprocess_("main subprocess", NULL, NULL), |
| 338 uses_nonsfi_mode_(false), | 359 uses_nonsfi_mode_(false), |
| 339 wrapper_factory_(NULL), | 360 wrapper_factory_(NULL), |
| 340 time_of_last_progress_event_(0), | 361 time_of_last_progress_event_(0), |
| 341 nexe_open_time_(-1), | |
| 342 manifest_id_(-1), | 362 manifest_id_(-1), |
| 363 nexe_handle_(PP_kInvalidFileHandle), |
| 343 nacl_interface_(NULL), | 364 nacl_interface_(NULL), |
| 344 uma_interface_(this) { | 365 uma_interface_(this) { |
| 345 PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%" | 366 PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%" |
| 346 NACL_PRId32 ")\n", static_cast<void*>(this), pp_instance)); | 367 NACL_PRId32 ")\n", static_cast<void*>(this), pp_instance)); |
| 347 callback_factory_.Initialize(this); | 368 callback_factory_.Initialize(this); |
| 348 nexe_downloader_.Initialize(this); | |
| 349 nacl_interface_ = GetNaClInterface(); | 369 nacl_interface_ = GetNaClInterface(); |
| 350 CHECK(nacl_interface_ != NULL); | 370 CHECK(nacl_interface_ != NULL); |
| 351 | 371 |
| 352 // Notify PPB_NaCl_Private that the instance is created before altering any | 372 // Notify PPB_NaCl_Private that the instance is created before altering any |
| 353 // state that it tracks. | 373 // state that it tracks. |
| 354 nacl_interface_->InstanceCreated(pp_instance); | 374 nacl_interface_->InstanceCreated(pp_instance); |
| 355 // We call set_exit_status() here to ensure that the 'exitStatus' property is | 375 // We call set_exit_status() here to ensure that the 'exitStatus' property is |
| 356 // set. This can only be called when nacl_interface_ is not NULL. | 376 // set. This can only be called when nacl_interface_ is not NULL. |
| 357 set_exit_status(-1); | 377 set_exit_status(-1); |
| 358 } | 378 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 | 436 |
| 417 bool Plugin::HandleDocumentLoad(const pp::URLLoader& url_loader) { | 437 bool Plugin::HandleDocumentLoad(const pp::URLLoader& url_loader) { |
| 418 PLUGIN_PRINTF(("Plugin::HandleDocumentLoad (this=%p)\n", | 438 PLUGIN_PRINTF(("Plugin::HandleDocumentLoad (this=%p)\n", |
| 419 static_cast<void*>(this))); | 439 static_cast<void*>(this))); |
| 420 // We don't know if the plugin will handle the document load, but return | 440 // We don't know if the plugin will handle the document load, but return |
| 421 // true in order to give it a chance to respond once the proxy is started. | 441 // true in order to give it a chance to respond once the proxy is started. |
| 422 return true; | 442 return true; |
| 423 } | 443 } |
| 424 | 444 |
| 425 void Plugin::NexeFileDidOpen(int32_t pp_error) { | 445 void Plugin::NexeFileDidOpen(int32_t pp_error) { |
| 426 NaClFileInfo tmp_info(nexe_downloader_.GetFileInfo()); | 446 if (pp_error != PP_OK) |
| 427 NaClFileInfoAutoCloser info(&tmp_info); | |
| 428 | |
| 429 int64_t nexe_bytes_read = -1; | |
| 430 if (pp_error == PP_OK && info.get_desc() != NACL_NO_FILE_DESC) { | |
| 431 struct stat stat_buf; | |
| 432 if (0 == fstat(info.get_desc(), &stat_buf)) | |
| 433 nexe_bytes_read = stat_buf.st_size; | |
| 434 } | |
| 435 | |
| 436 int64_t now = NaClGetTimeOfDayMicroseconds(); | |
| 437 int64_t download_time; | |
| 438 if (now < nexe_open_time_) | |
| 439 download_time = 0; | |
| 440 else | |
| 441 download_time = now - nexe_open_time_; | |
| 442 | |
| 443 nacl_interface_->NexeFileDidOpen( | |
| 444 pp_instance(), | |
| 445 pp_error, | |
| 446 info.get_desc(), | |
| 447 nexe_downloader_.status_code(), | |
| 448 nexe_bytes_read, | |
| 449 nexe_downloader_.url().c_str(), | |
| 450 download_time / 1000); | |
| 451 | |
| 452 if (nexe_bytes_read == -1) | |
| 453 return; | 447 return; |
| 454 | 448 |
| 449 int32_t desc = ConvertFileDescriptor(nexe_handle_); |
| 450 nexe_handle_ = PP_kInvalidFileHandle; // Clear out nexe handle. |
| 451 |
| 455 nacl::scoped_ptr<nacl::DescWrapper> | 452 nacl::scoped_ptr<nacl::DescWrapper> |
| 456 wrapper(wrapper_factory()->MakeFileDesc(info.Release().desc, O_RDONLY)); | 453 wrapper(wrapper_factory()->MakeFileDesc(desc, O_RDONLY)); |
| 457 NaClLog(4, "NexeFileDidOpen: invoking LoadNaClModule\n"); | 454 NaClLog(4, "NexeFileDidOpen: invoking LoadNaClModule\n"); |
| 458 LoadNaClModule( | 455 LoadNaClModule( |
| 459 wrapper.release(), | 456 wrapper.release(), |
| 460 uses_nonsfi_mode_, | 457 uses_nonsfi_mode_, |
| 461 true, /* enable_dyncode_syscalls */ | 458 true, /* enable_dyncode_syscalls */ |
| 462 true, /* enable_exception_handling */ | 459 true, /* enable_exception_handling */ |
| 463 false, /* enable_crash_throttling */ | 460 false, /* enable_crash_throttling */ |
| 464 callback_factory_.NewCallback(&Plugin::NexeFileDidOpenContinuation), | 461 callback_factory_.NewCallback(&Plugin::NexeFileDidOpenContinuation), |
| 465 callback_factory_.NewCallback(&Plugin::NexeDidCrash)); | 462 callback_factory_.NewCallback(&Plugin::NexeDidCrash)); |
| 466 } | 463 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 HistogramSizeKB("NaCl.Perf.Size.Manifest", | 546 HistogramSizeKB("NaCl.Perf.Size.Manifest", |
| 550 static_cast<int32_t>(manifest_json.length() / 1024)); | 547 static_cast<int32_t>(manifest_json.length() / 1024)); |
| 551 if (!SetManifestObject(manifest_json)) | 548 if (!SetManifestObject(manifest_json)) |
| 552 return; | 549 return; |
| 553 | 550 |
| 554 PP_Var pp_program_url; | 551 PP_Var pp_program_url; |
| 555 PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, 2}; | 552 PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, 2}; |
| 556 PP_Bool uses_nonsfi_mode; | 553 PP_Bool uses_nonsfi_mode; |
| 557 if (nacl_interface_->GetManifestProgramURL(pp_instance(), | 554 if (nacl_interface_->GetManifestProgramURL(pp_instance(), |
| 558 manifest_id_, &pp_program_url, &pnacl_options, &uses_nonsfi_mode)) { | 555 manifest_id_, &pp_program_url, &pnacl_options, &uses_nonsfi_mode)) { |
| 559 std::string program_url = pp::Var(pp::PASS_REF, pp_program_url).AsString(); | 556 program_url_ = pp::Var(pp::PASS_REF, pp_program_url).AsString(); |
| 560 // TODO(teravest): Make ProcessNaClManifest take responsibility for more of | 557 // TODO(teravest): Make ProcessNaClManifest take responsibility for more of |
| 561 // this function. | 558 // this function. |
| 562 nacl_interface_->ProcessNaClManifest(pp_instance(), program_url.c_str()); | 559 nacl_interface_->ProcessNaClManifest(pp_instance(), program_url_.c_str()); |
| 563 uses_nonsfi_mode_ = PP_ToBool(uses_nonsfi_mode); | 560 uses_nonsfi_mode_ = PP_ToBool(uses_nonsfi_mode); |
| 564 if (pnacl_options.translate) { | 561 if (pnacl_options.translate) { |
| 565 pp::CompletionCallback translate_callback = | 562 pp::CompletionCallback translate_callback = |
| 566 callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate); | 563 callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate); |
| 567 pnacl_coordinator_.reset( | 564 pnacl_coordinator_.reset( |
| 568 PnaclCoordinator::BitcodeToNative(this, | 565 PnaclCoordinator::BitcodeToNative(this, |
| 569 program_url, | 566 program_url_, |
| 570 pnacl_options, | 567 pnacl_options, |
| 571 translate_callback)); | 568 translate_callback)); |
| 572 return; | 569 return; |
| 573 } else { | 570 } else { |
| 574 nexe_open_time_ = NaClGetTimeOfDayMicroseconds(); | 571 pp::CompletionCallback open_callback = |
| 575 // Try the fast path first. This will only block if the file is installed. | 572 callback_factory_.NewCallback(&Plugin::NexeFileDidOpen); |
| 576 if (OpenURLFast(program_url, &nexe_downloader_)) { | 573 // Will always call the callback on success or failure. |
| 577 NexeFileDidOpen(PP_OK); | 574 nacl_interface_->DownloadNexe(pp_instance(), |
| 578 } else { | 575 program_url_.c_str(), |
| 579 pp::CompletionCallback open_callback = | 576 &nexe_handle_, |
| 580 callback_factory_.NewCallback(&Plugin::NexeFileDidOpen); | 577 open_callback.pp_completion_callback()); |
| 581 // Will always call the callback on success or failure. | |
| 582 CHECK( | |
| 583 nexe_downloader_.Open(program_url, | |
| 584 DOWNLOAD_TO_FILE, | |
| 585 open_callback, | |
| 586 true, | |
| 587 &UpdateDownloadProgress)); | |
| 588 } | |
| 589 return; | 578 return; |
| 590 } | 579 } |
| 591 } | 580 } |
| 592 } | 581 } |
| 593 | 582 |
| 594 void Plugin::RequestNaClManifest(const nacl::string& url) { | 583 void Plugin::RequestNaClManifest(const nacl::string& url) { |
| 595 PLUGIN_PRINTF(("Plugin::RequestNaClManifest (url='%s')\n", url.c_str())); | 584 PLUGIN_PRINTF(("Plugin::RequestNaClManifest (url='%s')\n", url.c_str())); |
| 596 pp::CompletionCallback open_callback = | 585 pp::CompletionCallback open_callback = |
| 597 callback_factory_.NewCallback(&Plugin::NaClManifestFileDidOpen); | 586 callback_factory_.NewCallback(&Plugin::NaClManifestFileDidOpen); |
| 598 nacl_interface_->RequestNaClManifest(pp_instance(), | 587 nacl_interface_->RequestNaClManifest(pp_instance(), |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 // If true, will always call the callback on success or failure. | 675 // If true, will always call the callback on success or failure. |
| 687 return downloader->Open(url, | 676 return downloader->Open(url, |
| 688 DOWNLOAD_TO_FILE, | 677 DOWNLOAD_TO_FILE, |
| 689 open_callback, | 678 open_callback, |
| 690 true, | 679 true, |
| 691 &UpdateDownloadProgress); | 680 &UpdateDownloadProgress); |
| 692 } | 681 } |
| 693 | 682 |
| 694 | 683 |
| 695 void Plugin::ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes) { | 684 void Plugin::ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes) { |
| 696 const nacl::string& url = nexe_downloader_.url(); | |
| 697 nacl_interface_->ReportLoadSuccess( | 685 nacl_interface_->ReportLoadSuccess( |
| 698 pp_instance(), url.c_str(), loaded_bytes, total_bytes); | 686 pp_instance(), program_url_.c_str(), loaded_bytes, total_bytes); |
| 699 } | 687 } |
| 700 | 688 |
| 701 | 689 |
| 702 void Plugin::ReportLoadError(const ErrorInfo& error_info) { | 690 void Plugin::ReportLoadError(const ErrorInfo& error_info) { |
| 703 nacl_interface_->ReportLoadError(pp_instance(), | 691 nacl_interface_->ReportLoadError(pp_instance(), |
| 704 error_info.error_code(), | 692 error_info.error_code(), |
| 705 error_info.message().c_str(), | 693 error_info.message().c_str(), |
| 706 error_info.console_message().c_str()); | 694 error_info.console_message().c_str()); |
| 707 } | 695 } |
| 708 | 696 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 724 // Rate limit progress events to a maximum of 100 per second. | 712 // Rate limit progress events to a maximum of 100 per second. |
| 725 int64_t time = NaClGetTimeOfDayMicroseconds(); | 713 int64_t time = NaClGetTimeOfDayMicroseconds(); |
| 726 int64_t elapsed = time - plugin->time_of_last_progress_event_; | 714 int64_t elapsed = time - plugin->time_of_last_progress_event_; |
| 727 const int64_t kTenMilliseconds = 10000; | 715 const int64_t kTenMilliseconds = 10000; |
| 728 if (elapsed > kTenMilliseconds) { | 716 if (elapsed > kTenMilliseconds) { |
| 729 plugin->time_of_last_progress_event_ = time; | 717 plugin->time_of_last_progress_event_ = time; |
| 730 | 718 |
| 731 // Find the URL loader that sent this notification. | 719 // Find the URL loader that sent this notification. |
| 732 const FileDownloader* file_downloader = | 720 const FileDownloader* file_downloader = |
| 733 plugin->FindFileDownloader(pp_resource); | 721 plugin->FindFileDownloader(pp_resource); |
| 734 // If not a streamed file, it must be the .nexe loader. | 722 nacl::string url; |
| 735 if (file_downloader == NULL) | 723 if (file_downloader) |
| 736 file_downloader = &plugin->nexe_downloader_; | 724 url = file_downloader->url(); |
| 737 nacl::string url = file_downloader->url(); | |
| 738 LengthComputable length_computable = (total_bytes_to_be_received >= 0) ? | 725 LengthComputable length_computable = (total_bytes_to_be_received >= 0) ? |
| 739 LENGTH_IS_COMPUTABLE : LENGTH_IS_NOT_COMPUTABLE; | 726 LENGTH_IS_COMPUTABLE : LENGTH_IS_NOT_COMPUTABLE; |
| 740 | 727 |
| 741 plugin->EnqueueProgressEvent(PP_NACL_EVENT_PROGRESS, | 728 plugin->EnqueueProgressEvent(PP_NACL_EVENT_PROGRESS, |
| 742 url, | 729 url, |
| 743 length_computable, | 730 length_computable, |
| 744 bytes_received, | 731 bytes_received, |
| 745 total_bytes_to_be_received); | 732 total_bytes_to_be_received); |
| 746 } | 733 } |
| 747 } | 734 } |
| 748 } | 735 } |
| 749 | 736 |
| 750 const FileDownloader* Plugin::FindFileDownloader( | 737 const FileDownloader* Plugin::FindFileDownloader( |
| 751 PP_Resource url_loader) const { | 738 PP_Resource url_loader) const { |
| 752 const FileDownloader* file_downloader = NULL; | 739 const FileDownloader* file_downloader = NULL; |
| 753 if (url_loader == nexe_downloader_.url_loader()) { | 740 std::set<FileDownloader*>::const_iterator it = url_downloaders_.begin(); |
| 754 file_downloader = &nexe_downloader_; | 741 while (it != url_downloaders_.end()) { |
| 755 } else { | 742 if (url_loader == (*it)->url_loader()) { |
| 756 std::set<FileDownloader*>::const_iterator it = url_downloaders_.begin(); | 743 file_downloader = (*it); |
| 757 while (it != url_downloaders_.end()) { | 744 break; |
| 758 if (url_loader == (*it)->url_loader()) { | |
| 759 file_downloader = (*it); | |
| 760 break; | |
| 761 } | |
| 762 ++it; | |
| 763 } | 745 } |
| 746 ++it; |
| 764 } | 747 } |
| 765 return file_downloader; | 748 return file_downloader; |
| 766 } | 749 } |
| 767 | 750 |
| 768 void Plugin::ReportSelLdrLoadStatus(int status) { | 751 void Plugin::ReportSelLdrLoadStatus(int status) { |
| 769 HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status)); | 752 HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status)); |
| 770 } | 753 } |
| 771 | 754 |
| 772 void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type, | 755 void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type, |
| 773 const nacl::string& url, | 756 const nacl::string& url, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 | 812 |
| 830 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, | 813 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, |
| 831 int exit_status) { | 814 int exit_status) { |
| 832 DCHECK(pp::Module::Get()->core()->IsMainThread()); | 815 DCHECK(pp::Module::Get()->core()->IsMainThread()); |
| 833 DCHECK(nacl_interface_); | 816 DCHECK(nacl_interface_); |
| 834 nacl_interface_->SetExitStatus(pp_instance(), exit_status); | 817 nacl_interface_->SetExitStatus(pp_instance(), exit_status); |
| 835 } | 818 } |
| 836 | 819 |
| 837 | 820 |
| 838 } // namespace plugin | 821 } // namespace plugin |
| OLD | NEW |