| 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 | 51 |
| 52 // Up to 20 seconds | 52 // Up to 20 seconds |
| 53 const int64_t kTimeSmallMin = 1; // in ms | 53 const int64_t kTimeSmallMin = 1; // in ms |
| 54 const int64_t kTimeSmallMax = 20000; // in ms | 54 const int64_t kTimeSmallMax = 20000; // in ms |
| 55 const uint32_t kTimeSmallBuckets = 100; | 55 const uint32_t kTimeSmallBuckets = 100; |
| 56 | 56 |
| 57 const int64_t kSizeKBMin = 1; | 57 const int64_t kSizeKBMin = 1; |
| 58 const int64_t kSizeKBMax = 512*1024; // very large .nexe | 58 const int64_t kSizeKBMax = 512*1024; // very large .nexe |
| 59 const uint32_t kSizeKBBuckets = 100; | 59 const uint32_t kSizeKBBuckets = 100; |
| 60 | 60 |
| 61 // Converts a PP_FileHandle to a POSIX file descriptor. |
| 62 int32_t ConvertFileDescriptor(PP_FileHandle handle) { |
| 63 PLUGIN_PRINTF(("ConvertFileDescriptor, handle=%d\n", handle)); |
| 64 #if NACL_WINDOWS |
| 65 int32_t file_desc = NACL_NO_FILE_DESC; |
| 66 // On Windows, valid handles are 32 bit unsigned integers so this is safe. |
| 67 file_desc = reinterpret_cast<intptr_t>(handle); |
| 68 // Convert the Windows HANDLE from Pepper to a POSIX file descriptor. |
| 69 int32_t posix_desc = _open_osfhandle(file_desc, _O_RDWR | _O_BINARY); |
| 70 if (posix_desc == -1) { |
| 71 // Close the Windows HANDLE if it can't be converted. |
| 72 CloseHandle(reinterpret_cast<HANDLE>(file_desc)); |
| 73 return -1; |
| 74 } |
| 75 return posix_desc; |
| 76 #else |
| 77 return handle; |
| 78 #endif |
| 79 } |
| 80 |
| 81 |
| 61 } // namespace | 82 } // namespace |
| 62 | 83 |
| 63 void Plugin::ShutDownSubprocesses() { | 84 void Plugin::ShutDownSubprocesses() { |
| 64 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (this=%p)\n", | 85 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (this=%p)\n", |
| 65 static_cast<void*>(this))); | 86 static_cast<void*>(this))); |
| 66 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (%s)\n", | 87 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (%s)\n", |
| 67 main_subprocess_.detailed_description().c_str())); | 88 main_subprocess_.detailed_description().c_str())); |
| 68 | 89 |
| 69 // Shut down service runtime. This must be done before all other calls so | 90 // Shut down service runtime. This must be done before all other calls so |
| 70 // they don't block forever when waiting for the upcall thread to exit. | 91 // 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... |
| 336 RequestNaClManifest(manifest_url.AsString()); | 357 RequestNaClManifest(manifest_url.AsString()); |
| 337 return true; | 358 return true; |
| 338 } | 359 } |
| 339 | 360 |
| 340 Plugin::Plugin(PP_Instance pp_instance) | 361 Plugin::Plugin(PP_Instance pp_instance) |
| 341 : pp::Instance(pp_instance), | 362 : pp::Instance(pp_instance), |
| 342 main_subprocess_("main subprocess", NULL, NULL), | 363 main_subprocess_("main subprocess", NULL, NULL), |
| 343 uses_nonsfi_mode_(false), | 364 uses_nonsfi_mode_(false), |
| 344 wrapper_factory_(NULL), | 365 wrapper_factory_(NULL), |
| 345 time_of_last_progress_event_(0), | 366 time_of_last_progress_event_(0), |
| 346 nexe_open_time_(-1), | |
| 347 manifest_id_(-1), | 367 manifest_id_(-1), |
| 368 nexe_handle_(PP_kInvalidFileHandle), |
| 348 nacl_interface_(NULL), | 369 nacl_interface_(NULL), |
| 349 uma_interface_(this) { | 370 uma_interface_(this) { |
| 350 PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%" | 371 PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%" |
| 351 NACL_PRId32 ")\n", static_cast<void*>(this), pp_instance)); | 372 NACL_PRId32 ")\n", static_cast<void*>(this), pp_instance)); |
| 352 callback_factory_.Initialize(this); | 373 callback_factory_.Initialize(this); |
| 353 nexe_downloader_.Initialize(this); | |
| 354 nacl_interface_ = GetNaClInterface(); | 374 nacl_interface_ = GetNaClInterface(); |
| 355 CHECK(nacl_interface_ != NULL); | 375 CHECK(nacl_interface_ != NULL); |
| 356 | 376 |
| 357 // Notify PPB_NaCl_Private that the instance is created before altering any | 377 // Notify PPB_NaCl_Private that the instance is created before altering any |
| 358 // state that it tracks. | 378 // state that it tracks. |
| 359 nacl_interface_->InstanceCreated(pp_instance); | 379 nacl_interface_->InstanceCreated(pp_instance); |
| 360 // We call set_exit_status() here to ensure that the 'exitStatus' property is | 380 // We call set_exit_status() here to ensure that the 'exitStatus' property is |
| 361 // set. This can only be called when nacl_interface_ is not NULL. | 381 // set. This can only be called when nacl_interface_ is not NULL. |
| 362 set_exit_status(-1); | 382 set_exit_status(-1); |
| 363 } | 383 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 | 441 |
| 422 bool Plugin::HandleDocumentLoad(const pp::URLLoader& url_loader) { | 442 bool Plugin::HandleDocumentLoad(const pp::URLLoader& url_loader) { |
| 423 PLUGIN_PRINTF(("Plugin::HandleDocumentLoad (this=%p)\n", | 443 PLUGIN_PRINTF(("Plugin::HandleDocumentLoad (this=%p)\n", |
| 424 static_cast<void*>(this))); | 444 static_cast<void*>(this))); |
| 425 // We don't know if the plugin will handle the document load, but return | 445 // We don't know if the plugin will handle the document load, but return |
| 426 // true in order to give it a chance to respond once the proxy is started. | 446 // true in order to give it a chance to respond once the proxy is started. |
| 427 return true; | 447 return true; |
| 428 } | 448 } |
| 429 | 449 |
| 430 void Plugin::NexeFileDidOpen(int32_t pp_error) { | 450 void Plugin::NexeFileDidOpen(int32_t pp_error) { |
| 431 NaClFileInfo tmp_info(nexe_downloader_.GetFileInfo()); | 451 if (pp_error != PP_OK) |
| 432 NaClFileInfoAutoCloser info(&tmp_info); | |
| 433 | |
| 434 int64_t nexe_bytes_read = -1; | |
| 435 if (pp_error == PP_OK && info.get_desc() != NACL_NO_FILE_DESC) { | |
| 436 struct stat stat_buf; | |
| 437 if (0 == fstat(info.get_desc(), &stat_buf)) | |
| 438 nexe_bytes_read = stat_buf.st_size; | |
| 439 } | |
| 440 | |
| 441 int64_t now = NaClGetTimeOfDayMicroseconds(); | |
| 442 int64_t download_time; | |
| 443 if (now < nexe_open_time_) | |
| 444 download_time = 0; | |
| 445 else | |
| 446 download_time = now - nexe_open_time_; | |
| 447 | |
| 448 nacl_interface_->NexeFileDidOpen( | |
| 449 pp_instance(), | |
| 450 pp_error, | |
| 451 info.get_desc(), | |
| 452 nexe_downloader_.status_code(), | |
| 453 nexe_bytes_read, | |
| 454 nexe_downloader_.url().c_str(), | |
| 455 download_time / 1000); | |
| 456 | |
| 457 if (nexe_bytes_read == -1) | |
| 458 return; | 452 return; |
| 459 | 453 |
| 454 int32_t desc = ConvertFileDescriptor(nexe_handle_); |
| 455 nexe_handle_ = PP_kInvalidFileHandle; // Clear out nexe handle. |
| 456 |
| 460 nacl::scoped_ptr<nacl::DescWrapper> | 457 nacl::scoped_ptr<nacl::DescWrapper> |
| 461 wrapper(wrapper_factory()->MakeFileDesc(info.Release().desc, O_RDONLY)); | 458 wrapper(wrapper_factory()->MakeFileDesc(desc, O_RDONLY)); |
| 462 NaClLog(4, "NexeFileDidOpen: invoking LoadNaClModule\n"); | 459 NaClLog(4, "NexeFileDidOpen: invoking LoadNaClModule\n"); |
| 463 LoadNaClModule( | 460 LoadNaClModule( |
| 464 wrapper.release(), | 461 wrapper.release(), |
| 465 uses_nonsfi_mode_, | 462 uses_nonsfi_mode_, |
| 466 true, /* enable_dyncode_syscalls */ | 463 true, /* enable_dyncode_syscalls */ |
| 467 true, /* enable_exception_handling */ | 464 true, /* enable_exception_handling */ |
| 468 false, /* enable_crash_throttling */ | 465 false, /* enable_crash_throttling */ |
| 469 callback_factory_.NewCallback(&Plugin::NexeFileDidOpenContinuation), | 466 callback_factory_.NewCallback(&Plugin::NexeFileDidOpenContinuation), |
| 470 callback_factory_.NewCallback(&Plugin::NexeDidCrash)); | 467 callback_factory_.NewCallback(&Plugin::NexeDidCrash)); |
| 471 } | 468 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 HistogramSizeKB("NaCl.Perf.Size.Manifest", | 551 HistogramSizeKB("NaCl.Perf.Size.Manifest", |
| 555 static_cast<int32_t>(manifest_json.length() / 1024)); | 552 static_cast<int32_t>(manifest_json.length() / 1024)); |
| 556 if (!SetManifestObject(manifest_json)) | 553 if (!SetManifestObject(manifest_json)) |
| 557 return; | 554 return; |
| 558 | 555 |
| 559 PP_Var pp_program_url; | 556 PP_Var pp_program_url; |
| 560 PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, 2}; | 557 PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, 2}; |
| 561 PP_Bool uses_nonsfi_mode; | 558 PP_Bool uses_nonsfi_mode; |
| 562 if (nacl_interface_->GetManifestProgramURL(pp_instance(), | 559 if (nacl_interface_->GetManifestProgramURL(pp_instance(), |
| 563 manifest_id_, &pp_program_url, &pnacl_options, &uses_nonsfi_mode)) { | 560 manifest_id_, &pp_program_url, &pnacl_options, &uses_nonsfi_mode)) { |
| 564 std::string program_url = pp::Var(pp::PASS_REF, pp_program_url).AsString(); | 561 program_url_ = pp::Var(pp::PASS_REF, pp_program_url).AsString(); |
| 565 // TODO(teravest): Make ProcessNaClManifest take responsibility for more of | 562 // TODO(teravest): Make ProcessNaClManifest take responsibility for more of |
| 566 // this function. | 563 // this function. |
| 567 nacl_interface_->ProcessNaClManifest(pp_instance(), program_url.c_str()); | 564 nacl_interface_->ProcessNaClManifest(pp_instance(), program_url_.c_str()); |
| 568 uses_nonsfi_mode_ = PP_ToBool(uses_nonsfi_mode); | 565 uses_nonsfi_mode_ = PP_ToBool(uses_nonsfi_mode); |
| 569 if (pnacl_options.translate) { | 566 if (pnacl_options.translate) { |
| 570 pp::CompletionCallback translate_callback = | 567 pp::CompletionCallback translate_callback = |
| 571 callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate); | 568 callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate); |
| 572 pnacl_coordinator_.reset( | 569 pnacl_coordinator_.reset( |
| 573 PnaclCoordinator::BitcodeToNative(this, | 570 PnaclCoordinator::BitcodeToNative(this, |
| 574 program_url, | 571 program_url_, |
| 575 pnacl_options, | 572 pnacl_options, |
| 576 translate_callback)); | 573 translate_callback)); |
| 577 return; | 574 return; |
| 578 } else { | 575 } else { |
| 579 nexe_open_time_ = NaClGetTimeOfDayMicroseconds(); | 576 pp::CompletionCallback open_callback = |
| 580 // Try the fast path first. This will only block if the file is installed. | 577 callback_factory_.NewCallback(&Plugin::NexeFileDidOpen); |
| 581 if (OpenURLFast(program_url, &nexe_downloader_)) { | 578 // Will always call the callback on success or failure. |
| 582 NexeFileDidOpen(PP_OK); | 579 nacl_interface_->DownloadNexe(pp_instance(), |
| 583 } else { | 580 program_url_.c_str(), |
| 584 pp::CompletionCallback open_callback = | 581 &nexe_handle_, |
| 585 callback_factory_.NewCallback(&Plugin::NexeFileDidOpen); | 582 open_callback.pp_completion_callback()); |
| 586 // Will always call the callback on success or failure. | |
| 587 CHECK( | |
| 588 nexe_downloader_.Open(program_url, | |
| 589 DOWNLOAD_TO_FILE, | |
| 590 open_callback, | |
| 591 true, | |
| 592 &UpdateDownloadProgress)); | |
| 593 } | |
| 594 return; | 583 return; |
| 595 } | 584 } |
| 596 } | 585 } |
| 597 } | 586 } |
| 598 | 587 |
| 599 void Plugin::RequestNaClManifest(const nacl::string& url) { | 588 void Plugin::RequestNaClManifest(const nacl::string& url) { |
| 600 PLUGIN_PRINTF(("Plugin::RequestNaClManifest (url='%s')\n", url.c_str())); | 589 PLUGIN_PRINTF(("Plugin::RequestNaClManifest (url='%s')\n", url.c_str())); |
| 601 PP_Bool is_data_uri; | 590 PP_Bool is_data_uri; |
| 602 ErrorInfo error_info; | 591 ErrorInfo error_info; |
| 603 if (!nacl_interface_->RequestNaClManifest(pp_instance(), url.c_str(), | 592 if (!nacl_interface_->RequestNaClManifest(pp_instance(), url.c_str(), |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 // If true, will always call the callback on success or failure. | 706 // If true, will always call the callback on success or failure. |
| 718 return downloader->Open(url, | 707 return downloader->Open(url, |
| 719 DOWNLOAD_TO_FILE, | 708 DOWNLOAD_TO_FILE, |
| 720 open_callback, | 709 open_callback, |
| 721 true, | 710 true, |
| 722 &UpdateDownloadProgress); | 711 &UpdateDownloadProgress); |
| 723 } | 712 } |
| 724 | 713 |
| 725 | 714 |
| 726 void Plugin::ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes) { | 715 void Plugin::ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes) { |
| 727 const nacl::string& url = nexe_downloader_.url(); | |
| 728 nacl_interface_->ReportLoadSuccess( | 716 nacl_interface_->ReportLoadSuccess( |
| 729 pp_instance(), url.c_str(), loaded_bytes, total_bytes); | 717 pp_instance(), program_url_.c_str(), loaded_bytes, total_bytes); |
| 730 } | 718 } |
| 731 | 719 |
| 732 | 720 |
| 733 void Plugin::ReportLoadError(const ErrorInfo& error_info) { | 721 void Plugin::ReportLoadError(const ErrorInfo& error_info) { |
| 734 nacl_interface_->ReportLoadError(pp_instance(), | 722 nacl_interface_->ReportLoadError(pp_instance(), |
| 735 error_info.error_code(), | 723 error_info.error_code(), |
| 736 error_info.message().c_str(), | 724 error_info.message().c_str(), |
| 737 error_info.console_message().c_str()); | 725 error_info.console_message().c_str()); |
| 738 } | 726 } |
| 739 | 727 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 755 // Rate limit progress events to a maximum of 100 per second. | 743 // Rate limit progress events to a maximum of 100 per second. |
| 756 int64_t time = NaClGetTimeOfDayMicroseconds(); | 744 int64_t time = NaClGetTimeOfDayMicroseconds(); |
| 757 int64_t elapsed = time - plugin->time_of_last_progress_event_; | 745 int64_t elapsed = time - plugin->time_of_last_progress_event_; |
| 758 const int64_t kTenMilliseconds = 10000; | 746 const int64_t kTenMilliseconds = 10000; |
| 759 if (elapsed > kTenMilliseconds) { | 747 if (elapsed > kTenMilliseconds) { |
| 760 plugin->time_of_last_progress_event_ = time; | 748 plugin->time_of_last_progress_event_ = time; |
| 761 | 749 |
| 762 // Find the URL loader that sent this notification. | 750 // Find the URL loader that sent this notification. |
| 763 const FileDownloader* file_downloader = | 751 const FileDownloader* file_downloader = |
| 764 plugin->FindFileDownloader(pp_resource); | 752 plugin->FindFileDownloader(pp_resource); |
| 765 // If not a streamed file, it must be the .nexe loader. | 753 nacl::string url; |
| 766 if (file_downloader == NULL) | 754 if (file_downloader) |
| 767 file_downloader = &plugin->nexe_downloader_; | 755 url = file_downloader->url(); |
| 768 nacl::string url = file_downloader->url(); | |
| 769 LengthComputable length_computable = (total_bytes_to_be_received >= 0) ? | 756 LengthComputable length_computable = (total_bytes_to_be_received >= 0) ? |
| 770 LENGTH_IS_COMPUTABLE : LENGTH_IS_NOT_COMPUTABLE; | 757 LENGTH_IS_COMPUTABLE : LENGTH_IS_NOT_COMPUTABLE; |
| 771 | 758 |
| 772 plugin->EnqueueProgressEvent(PP_NACL_EVENT_PROGRESS, | 759 plugin->EnqueueProgressEvent(PP_NACL_EVENT_PROGRESS, |
| 773 url, | 760 url, |
| 774 length_computable, | 761 length_computable, |
| 775 bytes_received, | 762 bytes_received, |
| 776 total_bytes_to_be_received); | 763 total_bytes_to_be_received); |
| 777 } | 764 } |
| 778 } | 765 } |
| 779 } | 766 } |
| 780 | 767 |
| 781 const FileDownloader* Plugin::FindFileDownloader( | 768 const FileDownloader* Plugin::FindFileDownloader( |
| 782 PP_Resource url_loader) const { | 769 PP_Resource url_loader) const { |
| 783 const FileDownloader* file_downloader = NULL; | 770 const FileDownloader* file_downloader = NULL; |
| 784 if (url_loader == nexe_downloader_.url_loader()) { | 771 std::set<FileDownloader*>::const_iterator it = url_downloaders_.begin(); |
| 785 file_downloader = &nexe_downloader_; | 772 while (it != url_downloaders_.end()) { |
| 786 } else { | 773 if (url_loader == (*it)->url_loader()) { |
| 787 std::set<FileDownloader*>::const_iterator it = url_downloaders_.begin(); | 774 file_downloader = (*it); |
| 788 while (it != url_downloaders_.end()) { | 775 break; |
| 789 if (url_loader == (*it)->url_loader()) { | |
| 790 file_downloader = (*it); | |
| 791 break; | |
| 792 } | |
| 793 ++it; | |
| 794 } | 776 } |
| 777 ++it; |
| 795 } | 778 } |
| 796 return file_downloader; | 779 return file_downloader; |
| 797 } | 780 } |
| 798 | 781 |
| 799 void Plugin::ReportSelLdrLoadStatus(int status) { | 782 void Plugin::ReportSelLdrLoadStatus(int status) { |
| 800 HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status)); | 783 HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status)); |
| 801 } | 784 } |
| 802 | 785 |
| 803 void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type, | 786 void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type, |
| 804 const nacl::string& url, | 787 const nacl::string& url, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 860 | 843 |
| 861 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, | 844 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, |
| 862 int exit_status) { | 845 int exit_status) { |
| 863 DCHECK(pp::Module::Get()->core()->IsMainThread()); | 846 DCHECK(pp::Module::Get()->core()->IsMainThread()); |
| 864 DCHECK(nacl_interface_); | 847 DCHECK(nacl_interface_); |
| 865 nacl_interface_->SetExitStatus(pp_instance(), exit_status); | 848 nacl_interface_->SetExitStatus(pp_instance(), exit_status); |
| 866 } | 849 } |
| 867 | 850 |
| 868 | 851 |
| 869 } // namespace plugin | 852 } // namespace plugin |
| OLD | NEW |