| 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 |