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 |