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 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 | 351 |
352 | 352 |
353 Plugin::~Plugin() { | 353 Plugin::~Plugin() { |
354 int64_t shutdown_start = NaClGetTimeOfDayMicroseconds(); | 354 int64_t shutdown_start = NaClGetTimeOfDayMicroseconds(); |
355 | 355 |
356 PLUGIN_PRINTF(("Plugin::~Plugin (this=%p)\n", | 356 PLUGIN_PRINTF(("Plugin::~Plugin (this=%p)\n", |
357 static_cast<void*>(this))); | 357 static_cast<void*>(this))); |
358 // Destroy the coordinator while the rest of the data is still there | 358 // Destroy the coordinator while the rest of the data is still there |
359 pnacl_coordinator_.reset(NULL); | 359 pnacl_coordinator_.reset(NULL); |
360 | 360 |
361 url_downloaders_.erase(url_downloaders_.begin(), url_downloaders_.end()); | |
362 | |
363 // Clean up accounting for our instance inside the NaCl interface. | 361 // Clean up accounting for our instance inside the NaCl interface. |
364 if (manifest_id_ != -1) | 362 if (manifest_id_ != -1) |
365 nacl_interface_->DestroyManifest(pp_instance(), manifest_id_); | 363 nacl_interface_->DestroyManifest(pp_instance(), manifest_id_); |
366 nacl_interface_->InstanceDestroyed(pp_instance()); | 364 nacl_interface_->InstanceDestroyed(pp_instance()); |
367 | 365 |
368 // ShutDownSubprocesses shuts down the main subprocess, which shuts | 366 // ShutDownSubprocesses shuts down the main subprocess, which shuts |
369 // down the main ServiceRuntime object, which kills the subprocess. | 367 // down the main ServiceRuntime object, which kills the subprocess. |
370 // As a side effect of the subprocess being killed, the reverse | 368 // As a side effect of the subprocess being killed, the reverse |
371 // services thread(s) will get EOF on the reverse channel(s), and | 369 // services thread(s) will get EOF on the reverse channel(s), and |
372 // the thread(s) will exit. In ServiceRuntime::Shutdown, we invoke | 370 // the thread(s) will exit. In ServiceRuntime::Shutdown, we invoke |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 void Plugin::RequestNaClManifest(const nacl::string& url) { | 550 void Plugin::RequestNaClManifest(const nacl::string& url) { |
553 PLUGIN_PRINTF(("Plugin::RequestNaClManifest (url='%s')\n", url.c_str())); | 551 PLUGIN_PRINTF(("Plugin::RequestNaClManifest (url='%s')\n", url.c_str())); |
554 pp::CompletionCallback open_callback = | 552 pp::CompletionCallback open_callback = |
555 callback_factory_.NewCallback(&Plugin::NaClManifestFileDidOpen); | 553 callback_factory_.NewCallback(&Plugin::NaClManifestFileDidOpen); |
556 nacl_interface_->RequestNaClManifest(pp_instance(), | 554 nacl_interface_->RequestNaClManifest(pp_instance(), |
557 url.c_str(), | 555 url.c_str(), |
558 &manifest_id_, | 556 &manifest_id_, |
559 open_callback.pp_completion_callback()); | 557 open_callback.pp_completion_callback()); |
560 } | 558 } |
561 | 559 |
562 void Plugin::UrlDidOpenForStreamAsFile( | 560 void Plugin::StreamAsFile(const nacl::string& url, |
563 int32_t pp_error, | 561 PP_NaClFileInfo* file_info, |
564 FileDownloader* url_downloader, | |
565 NaClFileInfo* out_file_info, | |
566 pp::CompletionCallback callback) { | |
567 PLUGIN_PRINTF(("Plugin::UrlDidOpen (pp_error=%" NACL_PRId32 | |
568 ", url_downloader=%p)\n", pp_error, | |
569 static_cast<void*>(url_downloader))); | |
570 url_downloaders_.erase(url_downloader); | |
571 nacl::scoped_ptr<FileDownloader> scoped_url_downloader(url_downloader); | |
572 NaClFileInfo tmp_info(scoped_url_downloader->GetFileInfo()); | |
573 NaClFileInfoAutoCloser *info = new NaClFileInfoAutoCloser(&tmp_info); | |
574 | |
575 if (pp_error != PP_OK) { | |
576 callback.Run(pp_error); | |
577 delete info; | |
578 } else if (info->get_desc() > NACL_NO_FILE_DESC) { | |
579 *out_file_info = info->Release(); | |
580 callback.Run(PP_OK); | |
581 } else { | |
582 callback.Run(PP_ERROR_FAILED); | |
583 delete info; | |
584 } | |
585 } | |
586 | |
587 bool Plugin::StreamAsFile(const nacl::string& url, | |
588 NaClFileInfo* out_file_info, | |
589 const pp::CompletionCallback& callback) { | 562 const pp::CompletionCallback& callback) { |
590 PLUGIN_PRINTF(("Plugin::StreamAsFile (url='%s')\n", url.c_str())); | 563 PLUGIN_PRINTF(("Plugin::StreamAsFile (url='%s')\n", url.c_str())); |
591 FileDownloader* downloader = new FileDownloader(); | 564 nacl_interface_->DownloadFile(pp_instance(), |
592 downloader->Initialize(this); | 565 url.c_str(), |
593 url_downloaders_.insert(downloader); | 566 file_info, |
594 | 567 callback.pp_completion_callback()); |
595 // Untrusted loads are always relative to the page's origin. | |
596 if (!GetNaClInterface()->ResolvesRelativeToPluginBaseUrl(pp_instance(), | |
597 url.c_str())) | |
598 return false; | |
599 | |
600 // Try the fast path first. This will only block if the file is installed. | |
601 if (OpenURLFast(url, downloader)) { | |
602 UrlDidOpenForStreamAsFile(PP_OK, downloader, out_file_info, callback); | |
603 return true; | |
604 } | |
605 | |
606 pp::CompletionCallback open_callback = callback_factory_.NewCallback( | |
607 &Plugin::UrlDidOpenForStreamAsFile, downloader, out_file_info, callback); | |
608 // If true, will always call the callback on success or failure. | |
609 return downloader->Open(url, | |
610 DOWNLOAD_TO_FILE, | |
611 open_callback, | |
612 true, | |
613 &UpdateDownloadProgress); | |
614 } | 568 } |
615 | 569 |
616 | |
617 void Plugin::ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes) { | 570 void Plugin::ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes) { |
618 nacl_interface_->ReportLoadSuccess( | 571 nacl_interface_->ReportLoadSuccess( |
619 pp_instance(), program_url_.c_str(), loaded_bytes, total_bytes); | 572 pp_instance(), program_url_.c_str(), loaded_bytes, total_bytes); |
620 } | 573 } |
621 | 574 |
622 | 575 |
623 void Plugin::ReportLoadError(const ErrorInfo& error_info) { | 576 void Plugin::ReportLoadError(const ErrorInfo& error_info) { |
624 nacl_interface_->ReportLoadError(pp_instance(), | 577 nacl_interface_->ReportLoadError(pp_instance(), |
625 error_info.error_code(), | 578 error_info.error_code(), |
626 error_info.message().c_str(), | 579 error_info.message().c_str(), |
627 error_info.console_message().c_str()); | 580 error_info.console_message().c_str()); |
628 } | 581 } |
629 | 582 |
630 | 583 |
631 void Plugin::ReportLoadAbort() { | 584 void Plugin::ReportLoadAbort() { |
632 nacl_interface_->ReportLoadAbort(pp_instance()); | 585 nacl_interface_->ReportLoadAbort(pp_instance()); |
633 } | 586 } |
634 | 587 |
635 void Plugin::UpdateDownloadProgress( | |
636 PP_Instance pp_instance, | |
637 PP_Resource pp_resource, | |
638 int64_t /*bytes_sent*/, | |
639 int64_t /*total_bytes_to_be_sent*/, | |
640 int64_t bytes_received, | |
641 int64_t total_bytes_to_be_received) { | |
642 Instance* instance = pp::Module::Get()->InstanceForPPInstance(pp_instance); | |
643 if (instance != NULL) { | |
644 Plugin* plugin = static_cast<Plugin*>(instance); | |
645 // Rate limit progress events to a maximum of 100 per second. | |
646 int64_t time = NaClGetTimeOfDayMicroseconds(); | |
647 int64_t elapsed = time - plugin->time_of_last_progress_event_; | |
648 const int64_t kTenMilliseconds = 10000; | |
649 if (elapsed > kTenMilliseconds) { | |
650 plugin->time_of_last_progress_event_ = time; | |
651 | |
652 // Find the URL loader that sent this notification. | |
653 const FileDownloader* file_downloader = | |
654 plugin->FindFileDownloader(pp_resource); | |
655 nacl::string url; | |
656 if (file_downloader) | |
657 url = file_downloader->url(); | |
658 LengthComputable length_computable = (total_bytes_to_be_received >= 0) ? | |
659 LENGTH_IS_COMPUTABLE : LENGTH_IS_NOT_COMPUTABLE; | |
660 | |
661 plugin->EnqueueProgressEvent(PP_NACL_EVENT_PROGRESS, | |
662 url, | |
663 length_computable, | |
664 bytes_received, | |
665 total_bytes_to_be_received); | |
666 } | |
667 } | |
668 } | |
669 | |
670 const FileDownloader* Plugin::FindFileDownloader( | |
671 PP_Resource url_loader) const { | |
672 const FileDownloader* file_downloader = NULL; | |
673 std::set<FileDownloader*>::const_iterator it = url_downloaders_.begin(); | |
674 while (it != url_downloaders_.end()) { | |
675 if (url_loader == (*it)->url_loader()) { | |
676 file_downloader = (*it); | |
677 break; | |
678 } | |
679 ++it; | |
680 } | |
681 return file_downloader; | |
682 } | |
683 | |
684 void Plugin::ReportSelLdrLoadStatus(int status) { | 588 void Plugin::ReportSelLdrLoadStatus(int status) { |
685 HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status)); | 589 HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status)); |
686 } | 590 } |
687 | 591 |
688 void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type, | 592 void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type, |
689 const nacl::string& url, | 593 const nacl::string& url, |
690 LengthComputable length_computable, | 594 LengthComputable length_computable, |
691 uint64_t loaded_bytes, | 595 uint64_t loaded_bytes, |
692 uint64_t total_bytes) { | 596 uint64_t total_bytes) { |
693 PLUGIN_PRINTF(("Plugin::EnqueueProgressEvent (" | 597 PLUGIN_PRINTF(("Plugin::EnqueueProgressEvent (" |
694 "event_type='%d', url='%s', length_computable=%d, " | 598 "event_type='%d', url='%s', length_computable=%d, " |
695 "loaded=%" NACL_PRIu64 ", total=%" NACL_PRIu64 ")\n", | 599 "loaded=%" NACL_PRIu64 ", total=%" NACL_PRIu64 ")\n", |
696 static_cast<int>(event_type), | 600 static_cast<int>(event_type), |
697 url.c_str(), | 601 url.c_str(), |
698 static_cast<int>(length_computable), | 602 static_cast<int>(length_computable), |
699 loaded_bytes, | 603 loaded_bytes, |
700 total_bytes)); | 604 total_bytes)); |
701 | 605 |
702 nacl_interface_->DispatchEvent( | 606 nacl_interface_->DispatchEvent( |
703 pp_instance(), | 607 pp_instance(), |
704 event_type, | 608 event_type, |
705 url.c_str(), | 609 url.c_str(), |
706 length_computable == LENGTH_IS_COMPUTABLE ? PP_TRUE : PP_FALSE, | 610 length_computable == LENGTH_IS_COMPUTABLE ? PP_TRUE : PP_FALSE, |
707 loaded_bytes, | 611 loaded_bytes, |
708 total_bytes); | 612 total_bytes); |
709 } | 613 } |
710 | 614 |
711 bool Plugin::OpenURLFast(const nacl::string& url, | |
712 FileDownloader* downloader) { | |
713 uint64_t file_token_lo = 0; | |
714 uint64_t file_token_hi = 0; | |
715 PP_FileHandle file_handle = | |
716 nacl_interface()->OpenNaClExecutable(pp_instance(), | |
717 url.c_str(), | |
718 &file_token_lo, &file_token_hi); | |
719 // We shouldn't hit this if the file URL is in an installed app. | |
720 if (file_handle == PP_kInvalidFileHandle) | |
721 return false; | |
722 | |
723 // FileDownloader takes ownership of the file handle. | |
724 downloader->OpenFast(url, file_handle, file_token_lo, file_token_hi); | |
725 return true; | |
726 } | |
727 | |
728 bool Plugin::DocumentCanRequest(const std::string& url) { | 615 bool Plugin::DocumentCanRequest(const std::string& url) { |
729 CHECK(pp::Module::Get()->core()->IsMainThread()); | 616 CHECK(pp::Module::Get()->core()->IsMainThread()); |
730 CHECK(pp::URLUtil_Dev::Get() != NULL); | 617 CHECK(pp::URLUtil_Dev::Get() != NULL); |
731 return pp::URLUtil_Dev::Get()->DocumentCanRequest(this, pp::Var(url)); | 618 return pp::URLUtil_Dev::Get()->DocumentCanRequest(this, pp::Var(url)); |
732 } | 619 } |
733 | 620 |
734 void Plugin::set_exit_status(int exit_status) { | 621 void Plugin::set_exit_status(int exit_status) { |
735 pp::Core* core = pp::Module::Get()->core(); | 622 pp::Core* core = pp::Module::Get()->core(); |
736 if (core->IsMainThread()) { | 623 if (core->IsMainThread()) { |
737 SetExitStatusOnMainThread(PP_OK, exit_status); | 624 SetExitStatusOnMainThread(PP_OK, exit_status); |
738 } else { | 625 } else { |
739 pp::CompletionCallback callback = | 626 pp::CompletionCallback callback = |
740 callback_factory_.NewCallback(&Plugin::SetExitStatusOnMainThread, | 627 callback_factory_.NewCallback(&Plugin::SetExitStatusOnMainThread, |
741 exit_status); | 628 exit_status); |
742 core->CallOnMainThread(0, callback, 0); | 629 core->CallOnMainThread(0, callback, 0); |
743 } | 630 } |
744 } | 631 } |
745 | 632 |
746 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, | 633 void Plugin::SetExitStatusOnMainThread(int32_t pp_error, |
747 int exit_status) { | 634 int exit_status) { |
748 DCHECK(pp::Module::Get()->core()->IsMainThread()); | 635 DCHECK(pp::Module::Get()->core()->IsMainThread()); |
749 DCHECK(nacl_interface_); | 636 DCHECK(nacl_interface_); |
750 nacl_interface_->SetExitStatus(pp_instance(), exit_status); | 637 nacl_interface_->SetExitStatus(pp_instance(), exit_status); |
751 } | 638 } |
752 | 639 |
753 | 640 |
754 } // namespace plugin | 641 } // namespace plugin |
OLD | NEW |