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