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