| 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 | 53 |
| 54 // Up to 20 seconds | 54 // Up to 20 seconds |
| 55 const int64_t kTimeSmallMin = 1; // in ms | 55 const int64_t kTimeSmallMin = 1; // in ms |
| 56 const int64_t kTimeSmallMax = 20000; // in ms | 56 const int64_t kTimeSmallMax = 20000; // in ms |
| 57 const uint32_t kTimeSmallBuckets = 100; | 57 const uint32_t kTimeSmallBuckets = 100; |
| 58 | 58 |
| 59 const int64_t kSizeKBMin = 1; | 59 const int64_t kSizeKBMin = 1; |
| 60 const int64_t kSizeKBMax = 512*1024; // very large .nexe | 60 const int64_t kSizeKBMax = 512*1024; // very large .nexe |
| 61 const uint32_t kSizeKBBuckets = 100; | 61 const uint32_t kSizeKBBuckets = 100; |
| 62 | 62 |
| 63 // Converts a PP_FileHandle to a POSIX file descriptor. |
| 64 int32_t ConvertFileDescriptor(PP_FileHandle handle) { |
| 65 PLUGIN_PRINTF(("ConvertFileDescriptor, handle=%d\n", handle)); |
| 66 #if NACL_WINDOWS |
| 67 int32_t file_desc = NACL_NO_FILE_DESC; |
| 68 // On Windows, valid handles are 32 bit unsigned integers so this is safe. |
| 69 file_desc = reinterpret_cast<uintptr_t>(handle); |
| 70 // Convert the Windows HANDLE from Pepper to a POSIX file descriptor. |
| 71 int32_t posix_desc = _open_osfhandle(file_desc, _O_RDWR | _O_BINARY); |
| 72 if (posix_desc == -1) { |
| 73 // Close the Windows HANDLE if it can't be converted. |
| 74 CloseHandle(reinterpret_cast<HANDLE>(file_desc)); |
| 75 return -1; |
| 76 } |
| 77 return posix_desc; |
| 78 #else |
| 79 return handle; |
| 80 #endif |
| 81 } |
| 82 |
| 83 |
| 63 } // namespace | 84 } // namespace |
| 64 | 85 |
| 65 void Plugin::ShutDownSubprocesses() { | 86 void Plugin::ShutDownSubprocesses() { |
| 66 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (this=%p)\n", | 87 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (this=%p)\n", |
| 67 static_cast<void*>(this))); | 88 static_cast<void*>(this))); |
| 68 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (%s)\n", | 89 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (%s)\n", |
| 69 main_subprocess_.detailed_description().c_str())); | 90 main_subprocess_.detailed_description().c_str())); |
| 70 | 91 |
| 71 // Shut down service runtime. This must be done before all other calls so | 92 // Shut down service runtime. This must be done before all other calls so |
| 72 // they don't block forever when waiting for the upcall thread to exit. | 93 // they don't block forever when waiting for the upcall thread to exit. |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 RequestNaClManifest(manifest_url.AsString()); | 382 RequestNaClManifest(manifest_url.AsString()); |
| 362 return true; | 383 return true; |
| 363 } | 384 } |
| 364 | 385 |
| 365 Plugin::Plugin(PP_Instance pp_instance) | 386 Plugin::Plugin(PP_Instance pp_instance) |
| 366 : pp::Instance(pp_instance), | 387 : pp::Instance(pp_instance), |
| 367 main_subprocess_("main subprocess", NULL, NULL), | 388 main_subprocess_("main subprocess", NULL, NULL), |
| 368 uses_nonsfi_mode_(false), | 389 uses_nonsfi_mode_(false), |
| 369 wrapper_factory_(NULL), | 390 wrapper_factory_(NULL), |
| 370 time_of_last_progress_event_(0), | 391 time_of_last_progress_event_(0), |
| 371 nexe_open_time_(-1), | |
| 372 manifest_id_(-1), | 392 manifest_id_(-1), |
| 393 nexe_handle_(PP_kInvalidFileHandle), |
| 373 nacl_interface_(NULL), | 394 nacl_interface_(NULL), |
| 374 uma_interface_(this) { | 395 uma_interface_(this) { |
| 375 PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%" | 396 PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%" |
| 376 NACL_PRId32 ")\n", static_cast<void*>(this), pp_instance)); | 397 NACL_PRId32 ")\n", static_cast<void*>(this), pp_instance)); |
| 377 callback_factory_.Initialize(this); | 398 callback_factory_.Initialize(this); |
| 378 nexe_downloader_.Initialize(this); | |
| 379 nacl_interface_ = GetNaClInterface(); | 399 nacl_interface_ = GetNaClInterface(); |
| 380 CHECK(nacl_interface_ != NULL); | 400 CHECK(nacl_interface_ != NULL); |
| 381 | 401 |
| 382 // Notify PPB_NaCl_Private that the instance is created before altering any | 402 // Notify PPB_NaCl_Private that the instance is created before altering any |
| 383 // state that it tracks. | 403 // state that it tracks. |
| 384 nacl_interface_->InstanceCreated(pp_instance); | 404 nacl_interface_->InstanceCreated(pp_instance); |
| 385 // We call set_exit_status() here to ensure that the 'exitStatus' property is | 405 // We call set_exit_status() here to ensure that the 'exitStatus' property is |
| 386 // set. This can only be called when nacl_interface_ is not NULL. | 406 // set. This can only be called when nacl_interface_ is not NULL. |
| 387 set_exit_status(-1); | 407 set_exit_status(-1); |
| 388 } | 408 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 | 466 |
| 447 bool Plugin::HandleDocumentLoad(const pp::URLLoader& url_loader) { | 467 bool Plugin::HandleDocumentLoad(const pp::URLLoader& url_loader) { |
| 448 PLUGIN_PRINTF(("Plugin::HandleDocumentLoad (this=%p)\n", | 468 PLUGIN_PRINTF(("Plugin::HandleDocumentLoad (this=%p)\n", |
| 449 static_cast<void*>(this))); | 469 static_cast<void*>(this))); |
| 450 // We don't know if the plugin will handle the document load, but return | 470 // We don't know if the plugin will handle the document load, but return |
| 451 // true in order to give it a chance to respond once the proxy is started. | 471 // true in order to give it a chance to respond once the proxy is started. |
| 452 return true; | 472 return true; |
| 453 } | 473 } |
| 454 | 474 |
| 455 void Plugin::NexeFileDidOpen(int32_t pp_error) { | 475 void Plugin::NexeFileDidOpen(int32_t pp_error) { |
| 456 NaClFileInfo tmp_info(nexe_downloader_.GetFileInfo()); | 476 if (pp_error != PP_OK) |
| 457 NaClFileInfoAutoCloser info(&tmp_info); | |
| 458 | |
| 459 int64_t nexe_bytes_read = -1; | |
| 460 if (pp_error == PP_OK && info.get_desc() != NACL_NO_FILE_DESC) { | |
| 461 struct stat stat_buf; | |
| 462 if (0 == fstat(info.get_desc(), &stat_buf)) | |
| 463 nexe_bytes_read = stat_buf.st_size; | |
| 464 } | |
| 465 | |
| 466 int64_t now = NaClGetTimeOfDayMicroseconds(); | |
| 467 int64_t download_time; | |
| 468 if (now < nexe_open_time_) | |
| 469 download_time = 0; | |
| 470 else | |
| 471 download_time = now - nexe_open_time_; | |
| 472 | |
| 473 nacl_interface_->NexeFileDidOpen( | |
| 474 pp_instance(), | |
| 475 pp_error, | |
| 476 info.get_desc(), | |
| 477 nexe_downloader_.status_code(), | |
| 478 nexe_bytes_read, | |
| 479 nexe_downloader_.url().c_str(), | |
| 480 download_time / 1000); | |
| 481 | |
| 482 if (nexe_bytes_read == -1) | |
| 483 return; | 477 return; |
| 484 | 478 |
| 479 int32_t desc = ConvertFileDescriptor(nexe_handle_); |
| 480 nexe_handle_ = PP_kInvalidFileHandle; // Clear out nexe handle. |
| 481 |
| 485 nacl::scoped_ptr<nacl::DescWrapper> | 482 nacl::scoped_ptr<nacl::DescWrapper> |
| 486 wrapper(wrapper_factory()->MakeFileDesc(info.Release().desc, O_RDONLY)); | 483 wrapper(wrapper_factory()->MakeFileDesc(desc, O_RDONLY)); |
| 487 NaClLog(4, "NexeFileDidOpen: invoking LoadNaClModule\n"); | 484 NaClLog(4, "NexeFileDidOpen: invoking LoadNaClModule\n"); |
| 488 LoadNaClModule( | 485 LoadNaClModule( |
| 489 wrapper.release(), | 486 wrapper.release(), |
| 490 uses_nonsfi_mode_, | 487 uses_nonsfi_mode_, |
| 491 true, /* enable_dyncode_syscalls */ | 488 true, /* enable_dyncode_syscalls */ |
| 492 true, /* enable_exception_handling */ | 489 true, /* enable_exception_handling */ |
| 493 false, /* enable_crash_throttling */ | 490 false, /* enable_crash_throttling */ |
| 494 callback_factory_.NewCallback(&Plugin::NexeFileDidOpenContinuation), | 491 callback_factory_.NewCallback(&Plugin::NexeFileDidOpenContinuation), |
| 495 callback_factory_.NewCallback(&Plugin::NexeDidCrash)); | 492 callback_factory_.NewCallback(&Plugin::NexeDidCrash)); |
| 496 } | 493 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 HistogramSizeKB("NaCl.Perf.Size.Manifest", | 575 HistogramSizeKB("NaCl.Perf.Size.Manifest", |
| 579 static_cast<int32_t>(manifest_json.length() / 1024)); | 576 static_cast<int32_t>(manifest_json.length() / 1024)); |
| 580 if (!SetManifestObject(manifest_json)) | 577 if (!SetManifestObject(manifest_json)) |
| 581 return; | 578 return; |
| 582 | 579 |
| 583 PP_Var pp_program_url; | 580 PP_Var pp_program_url; |
| 584 PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, 2}; | 581 PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, 2}; |
| 585 PP_Bool uses_nonsfi_mode; | 582 PP_Bool uses_nonsfi_mode; |
| 586 if (nacl_interface_->GetManifestProgramURL(pp_instance(), | 583 if (nacl_interface_->GetManifestProgramURL(pp_instance(), |
| 587 manifest_id_, &pp_program_url, &pnacl_options, &uses_nonsfi_mode)) { | 584 manifest_id_, &pp_program_url, &pnacl_options, &uses_nonsfi_mode)) { |
| 588 std::string program_url = pp::Var(pp::PASS_REF, pp_program_url).AsString(); | 585 program_url_ = pp::Var(pp::PASS_REF, pp_program_url).AsString(); |
| 589 // TODO(teravest): Make ProcessNaClManifest take responsibility for more of | 586 // TODO(teravest): Make ProcessNaClManifest take responsibility for more of |
| 590 // this function. | 587 // this function. |
| 591 nacl_interface_->ProcessNaClManifest(pp_instance(), program_url.c_str()); | 588 nacl_interface_->ProcessNaClManifest(pp_instance(), program_url_.c_str()); |
| 592 uses_nonsfi_mode_ = PP_ToBool(uses_nonsfi_mode); | 589 uses_nonsfi_mode_ = PP_ToBool(uses_nonsfi_mode); |
| 593 if (pnacl_options.translate) { | 590 if (pnacl_options.translate) { |
| 594 pp::CompletionCallback translate_callback = | 591 pp::CompletionCallback translate_callback = |
| 595 callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate); | 592 callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate); |
| 596 pnacl_coordinator_.reset( | 593 pnacl_coordinator_.reset( |
| 597 PnaclCoordinator::BitcodeToNative(this, | 594 PnaclCoordinator::BitcodeToNative(this, |
| 598 program_url, | 595 program_url_, |
| 599 pnacl_options, | 596 pnacl_options, |
| 600 translate_callback)); | 597 translate_callback)); |
| 601 return; | 598 return; |
| 602 } else { | 599 } else { |
| 603 nexe_open_time_ = NaClGetTimeOfDayMicroseconds(); | 600 pp::CompletionCallback open_callback = |
| 604 // Try the fast path first. This will only block if the file is installed. | 601 callback_factory_.NewCallback(&Plugin::NexeFileDidOpen); |
| 605 if (OpenURLFast(program_url, &nexe_downloader_)) { | 602 // Will always call the callback on success or failure. |
| 606 NexeFileDidOpen(PP_OK); | 603 nacl_interface_->DownloadNexe(pp_instance(), |
| 607 } else { | 604 program_url_.c_str(), |
| 608 pp::CompletionCallback open_callback = | 605 &nexe_handle_, |
| 609 callback_factory_.NewCallback(&Plugin::NexeFileDidOpen); | 606 open_callback.pp_completion_callback()); |
| 610 // Will always call the callback on success or failure. | |
| 611 CHECK( | |
| 612 nexe_downloader_.Open(program_url, | |
| 613 DOWNLOAD_TO_FILE, | |
| 614 open_callback, | |
| 615 true, | |
| 616 &UpdateDownloadProgress)); | |
| 617 } | |
| 618 return; | 607 return; |
| 619 } | 608 } |
| 620 } | 609 } |
| 621 } | 610 } |
| 622 | 611 |
| 623 void Plugin::RequestNaClManifest(const nacl::string& url) { | 612 void Plugin::RequestNaClManifest(const nacl::string& url) { |
| 624 PLUGIN_PRINTF(("Plugin::RequestNaClManifest (url='%s')\n", url.c_str())); | 613 PLUGIN_PRINTF(("Plugin::RequestNaClManifest (url='%s')\n", url.c_str())); |
| 625 PP_Bool is_data_uri; | 614 PP_Bool is_data_uri; |
| 626 ErrorInfo error_info; | 615 ErrorInfo error_info; |
| 627 if (!nacl_interface_->RequestNaClManifest(pp_instance(), url.c_str(), | 616 if (!nacl_interface_->RequestNaClManifest(pp_instance(), url.c_str(), |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 // If true, will always call the callback on success or failure. | 733 // If true, will always call the callback on success or failure. |
| 745 return downloader->Open(url, | 734 return downloader->Open(url, |
| 746 DOWNLOAD_TO_FILE, | 735 DOWNLOAD_TO_FILE, |
| 747 open_callback, | 736 open_callback, |
| 748 true, | 737 true, |
| 749 &UpdateDownloadProgress); | 738 &UpdateDownloadProgress); |
| 750 } | 739 } |
| 751 | 740 |
| 752 | 741 |
| 753 void Plugin::ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes) { | 742 void Plugin::ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes) { |
| 754 const nacl::string& url = nexe_downloader_.url(); | |
| 755 nacl_interface_->ReportLoadSuccess( | 743 nacl_interface_->ReportLoadSuccess( |
| 756 pp_instance(), url.c_str(), loaded_bytes, total_bytes); | 744 pp_instance(), program_url_.c_str(), loaded_bytes, total_bytes); |
| 757 } | 745 } |
| 758 | 746 |
| 759 | 747 |
| 760 void Plugin::ReportLoadError(const ErrorInfo& error_info) { | 748 void Plugin::ReportLoadError(const ErrorInfo& error_info) { |
| 761 nacl_interface_->ReportLoadError(pp_instance(), | 749 nacl_interface_->ReportLoadError(pp_instance(), |
| 762 error_info.error_code(), | 750 error_info.error_code(), |
| 763 error_info.message().c_str(), | 751 error_info.message().c_str(), |
| 764 error_info.console_message().c_str()); | 752 error_info.console_message().c_str()); |
| 765 } | 753 } |
| 766 | 754 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 782 // Rate limit progress events to a maximum of 100 per second. | 770 // Rate limit progress events to a maximum of 100 per second. |
| 783 int64_t time = NaClGetTimeOfDayMicroseconds(); | 771 int64_t time = NaClGetTimeOfDayMicroseconds(); |
| 784 int64_t elapsed = time - plugin->time_of_last_progress_event_; | 772 int64_t elapsed = time - plugin->time_of_last_progress_event_; |
| 785 const int64_t kTenMilliseconds = 10000; | 773 const int64_t kTenMilliseconds = 10000; |
| 786 if (elapsed > kTenMilliseconds) { | 774 if (elapsed > kTenMilliseconds) { |
| 787 plugin->time_of_last_progress_event_ = time; | 775 plugin->time_of_last_progress_event_ = time; |
| 788 | 776 |
| 789 // Find the URL loader that sent this notification. | 777 // Find the URL loader that sent this notification. |
| 790 const FileDownloader* file_downloader = | 778 const FileDownloader* file_downloader = |
| 791 plugin->FindFileDownloader(pp_resource); | 779 plugin->FindFileDownloader(pp_resource); |
| 792 // If not a streamed file, it must be the .nexe loader. | 780 nacl::string url; |
| 793 if (file_downloader == NULL) | 781 if (file_downloader) |
| 794 file_downloader = &plugin->nexe_downloader_; | 782 url = file_downloader->url(); |
| 795 nacl::string url = file_downloader->url(); | |
| 796 LengthComputable length_computable = (total_bytes_to_be_received >= 0) ? | 783 LengthComputable length_computable = (total_bytes_to_be_received >= 0) ? |
| 797 LENGTH_IS_COMPUTABLE : LENGTH_IS_NOT_COMPUTABLE; | 784 LENGTH_IS_COMPUTABLE : LENGTH_IS_NOT_COMPUTABLE; |
| 798 | 785 |
| 799 plugin->EnqueueProgressEvent(PP_NACL_EVENT_PROGRESS, | 786 plugin->EnqueueProgressEvent(PP_NACL_EVENT_PROGRESS, |
| 800 url, | 787 url, |
| 801 length_computable, | 788 length_computable, |
| 802 bytes_received, | 789 bytes_received, |
| 803 total_bytes_to_be_received); | 790 total_bytes_to_be_received); |
| 804 } | 791 } |
| 805 } | 792 } |
| 806 } | 793 } |
| 807 | 794 |
| 808 const FileDownloader* Plugin::FindFileDownloader( | 795 const FileDownloader* Plugin::FindFileDownloader( |
| 809 PP_Resource url_loader) const { | 796 PP_Resource url_loader) const { |
| 810 const FileDownloader* file_downloader = NULL; | 797 const FileDownloader* file_downloader = NULL; |
| 811 if (url_loader == nexe_downloader_.url_loader()) { | 798 std::set<FileDownloader*>::const_iterator it = url_downloaders_.begin(); |
| 812 file_downloader = &nexe_downloader_; | 799 while (it != url_downloaders_.end()) { |
| 813 } else { | 800 if (url_loader == (*it)->url_loader()) { |
| 814 std::set<FileDownloader*>::const_iterator it = url_downloaders_.begin(); | 801 file_downloader = (*it); |
| 815 while (it != url_downloaders_.end()) { | 802 break; |
| 816 if (url_loader == (*it)->url_loader()) { | |
| 817 file_downloader = (*it); | |
| 818 break; | |
| 819 } | |
| 820 ++it; | |
| 821 } | 803 } |
| 804 ++it; |
| 822 } | 805 } |
| 823 return file_downloader; | 806 return file_downloader; |
| 824 } | 807 } |
| 825 | 808 |
| 826 void Plugin::ReportSelLdrLoadStatus(int status) { | 809 void Plugin::ReportSelLdrLoadStatus(int status) { |
| 827 HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status)); | 810 HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status)); |
| 828 } | 811 } |
| 829 | 812 |
| 830 void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type, | 813 void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type, |
| 831 const nacl::string& url, | 814 const nacl::string& url, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 | 870 |
| 888 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, | 871 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, |
| 889 int exit_status) { | 872 int exit_status) { |
| 890 DCHECK(pp::Module::Get()->core()->IsMainThread()); | 873 DCHECK(pp::Module::Get()->core()->IsMainThread()); |
| 891 DCHECK(nacl_interface_); | 874 DCHECK(nacl_interface_); |
| 892 nacl_interface_->SetExitStatus(pp_instance(), exit_status); | 875 nacl_interface_->SetExitStatus(pp_instance(), exit_status); |
| 893 } | 876 } |
| 894 | 877 |
| 895 | 878 |
| 896 } // namespace plugin | 879 } // namespace plugin |
| OLD | NEW |