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 |