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 #include "native_client/src/trusted/plugin/pnacl_coordinator.h" | 5 #include "native_client/src/trusted/plugin/pnacl_coordinator.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "native_client/src/include/checked_cast.h" | 10 #include "native_client/src/include/checked_cast.h" |
11 #include "native_client/src/include/portability_io.h" | 11 #include "native_client/src/include/portability_io.h" |
12 #include "native_client/src/shared/platform/nacl_check.h" | 12 #include "native_client/src/shared/platform/nacl_check.h" |
13 #include "native_client/src/trusted/plugin/local_temp_file.h" | 13 #include "native_client/src/trusted/plugin/local_temp_file.h" |
14 #include "native_client/src/trusted/plugin/manifest.h" | 14 #include "native_client/src/trusted/plugin/manifest.h" |
| 15 #include "native_client/src/trusted/plugin/nacl_http_response_headers.h" |
15 #include "native_client/src/trusted/plugin/plugin.h" | 16 #include "native_client/src/trusted/plugin/plugin.h" |
16 #include "native_client/src/trusted/plugin/plugin_error.h" | 17 #include "native_client/src/trusted/plugin/plugin_error.h" |
17 #include "native_client/src/trusted/plugin/pnacl_translate_thread.h" | 18 #include "native_client/src/trusted/plugin/pnacl_translate_thread.h" |
18 #include "native_client/src/trusted/plugin/service_runtime.h" | 19 #include "native_client/src/trusted/plugin/service_runtime.h" |
19 #include "native_client/src/trusted/plugin/temporary_file.h" | 20 #include "native_client/src/trusted/plugin/temporary_file.h" |
20 #include "native_client/src/trusted/service_runtime/include/sys/stat.h" | 21 #include "native_client/src/trusted/service_runtime/include/sys/stat.h" |
21 | 22 |
22 #include "ppapi/c/pp_bool.h" | 23 #include "ppapi/c/pp_bool.h" |
23 #include "ppapi/c/pp_errors.h" | 24 #include "ppapi/c/pp_errors.h" |
24 #include "ppapi/c/ppb_file_io.h" | 25 #include "ppapi/c/ppb_file_io.h" |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 "(in progress)."); | 685 "(in progress)."); |
685 return; | 686 return; |
686 } | 687 } |
687 ReportPpapiError( | 688 ReportPpapiError( |
688 ERROR_PNACL_CACHE_OPEN_OTHER, | 689 ERROR_PNACL_CACHE_OPEN_OTHER, |
689 pp_error, | 690 pp_error, |
690 "File system for PNaCl translation cache failed to open."); | 691 "File system for PNaCl translation cache failed to open."); |
691 } | 692 } |
692 } else { | 693 } else { |
693 // We don't have a cache, so do the non-cached codepath. | 694 // We don't have a cache, so do the non-cached codepath. |
694 CachedFileDidOpen(PP_ERROR_FAILED); | 695 OpenBitcodeStream(); |
695 } | 696 } |
696 } | 697 } |
697 | 698 |
698 void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) { | 699 void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) { |
699 PLUGIN_PRINTF(("PnaclCoordinator::FileSystemDidOpen (pp_error=%" | 700 PLUGIN_PRINTF(("PnaclCoordinator::FileSystemDidOpen (pp_error=%" |
700 NACL_PRId32")\n", pp_error)); | 701 NACL_PRId32")\n", pp_error)); |
701 if (pp_error != PP_OK) { | 702 if (pp_error != PP_OK) { |
702 if (pp_error == PP_ERROR_NOACCESS) { | 703 if (pp_error == PP_ERROR_NOACCESS) { |
703 ReportPpapiError( | 704 ReportPpapiError( |
704 ERROR_PNACL_CACHE_OPEN_NOACCESS, | 705 ERROR_PNACL_CACHE_OPEN_NOACCESS, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 "PNaCl translation cache directory creation/check failed " | 747 "PNaCl translation cache directory creation/check failed " |
747 "(no access)."); | 748 "(no access)."); |
748 return; | 749 return; |
749 } | 750 } |
750 ReportPpapiError( | 751 ReportPpapiError( |
751 ERROR_PNACL_CACHE_DIRECTORY_CREATE, | 752 ERROR_PNACL_CACHE_DIRECTORY_CREATE, |
752 pp_error, | 753 pp_error, |
753 "PNaCl translation cache directory creation/check failed."); | 754 "PNaCl translation cache directory creation/check failed."); |
754 return; | 755 return; |
755 } | 756 } |
756 if (pnacl_options_.HasCacheKey()) { | 757 OpenBitcodeStream(); |
| 758 } |
| 759 |
| 760 void PnaclCoordinator::OpenBitcodeStream() { |
| 761 // Now open the pexe stream. |
| 762 streaming_downloader_.reset(new FileDownloader()); |
| 763 streaming_downloader_->Initialize(plugin_); |
| 764 |
| 765 // Even though we haven't started downloading, create the translation |
| 766 // thread object immediately. This ensures that any pieces of the file |
| 767 // that get downloaded before the compilation thread is accepting |
| 768 // SRPCs won't get dropped. |
| 769 translate_thread_.reset(new PnaclTranslateThread()); |
| 770 if (translate_thread_ == NULL) { |
| 771 ReportNonPpapiError(ERROR_PNACL_THREAD_CREATE, |
| 772 "could not allocate translation thread."); |
| 773 return; |
| 774 } |
| 775 // We also want to open the object file now so the |
| 776 // translator can start writing to it during streaming translation. |
| 777 obj_file_.reset(new TempFile(plugin_)); |
| 778 pp::CompletionCallback obj_cb = |
| 779 callback_factory_.NewCallback(&PnaclCoordinator::ObjectFileDidOpen); |
| 780 obj_file_->Open(obj_cb); |
| 781 |
| 782 pp::CompletionCallback cb = |
| 783 callback_factory_.NewCallback(&PnaclCoordinator::BitcodeStreamDidOpen); |
| 784 if (!streaming_downloader_->OpenStream(pexe_url_, cb, this)) { |
| 785 ReportNonPpapiError(ERROR_PNACL_PEXE_FETCH_OTHER, |
| 786 nacl::string("failed to open stream ") + pexe_url_); |
| 787 } |
| 788 } |
| 789 |
| 790 void PnaclCoordinator::BitcodeStreamDidOpen(int32_t pp_error) { |
| 791 if (pp_error != PP_OK) { |
| 792 BitcodeStreamDidFinish(pp_error); |
| 793 return; |
| 794 } |
| 795 |
| 796 if (!off_the_record_) { |
| 797 // Get the cache key and try to open an existing entry. |
| 798 nacl::string headers = streaming_downloader_->GetResponseHeaders(); |
| 799 NaClHttpResponseHeaders parser; |
| 800 parser.Parse(headers); |
| 801 nacl::string cache_validators = parser.GetCacheValidators(); |
| 802 if (parser.CacheControlNoStore() || cache_validators.empty()) { |
| 803 // We can't cache in this case. |
| 804 pnacl_options_.set_cache_validators(""); |
| 805 CachedFileDidOpen(PP_ERROR_FAILED); |
| 806 return; |
| 807 } else { |
| 808 nacl::string url = streaming_downloader_->url(); |
| 809 // For now, combine the cache_validators + the URL as the key. |
| 810 // When we change the cache backend to be not-origin-specific |
| 811 // we should send the URL separately, and check in the browser's |
| 812 // RenderViewHost / SiteInstance's IsSameWebsite() to prevent |
| 813 // people from forging the URL for a different origin. |
| 814 pnacl_options_.set_cache_validators(cache_validators + url); |
| 815 } |
757 cached_nexe_file_.reset(new LocalTempFile( | 816 cached_nexe_file_.reset(new LocalTempFile( |
758 plugin_, file_system_.get(), | 817 plugin_, file_system_.get(), |
759 nacl::string(kPnaclTempDir), | 818 nacl::string(kPnaclTempDir), |
760 pnacl_options_.GetCacheKey())); | 819 pnacl_options_.GetCacheKey())); |
761 pp::CompletionCallback cb = | 820 pp::CompletionCallback cb = |
762 callback_factory_.NewCallback(&PnaclCoordinator::CachedFileDidOpen); | 821 callback_factory_.NewCallback(&PnaclCoordinator::CachedFileDidOpen); |
763 cached_nexe_file_->OpenRead(cb); | 822 cached_nexe_file_->OpenRead(cb); |
764 } else { | 823 } else { |
765 // For now, tolerate lack of cache identity... | 824 // No cache case. |
766 CachedFileDidOpen(PP_ERROR_FAILED); | 825 CachedFileDidOpen(PP_ERROR_FAILED); |
767 } | 826 } |
768 } | 827 } |
769 | 828 |
770 void PnaclCoordinator::CachedFileDidOpen(int32_t pp_error) { | 829 void PnaclCoordinator::CachedFileDidOpen(int32_t pp_error) { |
771 PLUGIN_PRINTF(("PnaclCoordinator::CachedFileDidOpen (pp_error=%" | 830 PLUGIN_PRINTF(("PnaclCoordinator::CachedFileDidOpen (pp_error=%" |
772 NACL_PRId32")\n", pp_error)); | 831 NACL_PRId32")\n", pp_error)); |
773 if (pp_error == PP_OK) { | 832 if (pp_error == PP_OK) { |
| 833 // Cache hit -- no need to stream the rest of the file. |
| 834 streaming_downloader_.reset(NULL); |
774 HistogramEnumerateTranslationCache(true); | 835 HistogramEnumerateTranslationCache(true); |
775 NexeReadDidOpen(PP_OK); | 836 NexeReadDidOpen(PP_OK); |
776 return; | 837 return; |
777 } | 838 } |
778 // Otherwise, the cache file is missing, or the cache simply | 839 // Otherwise, the cache file is missing so we must translate. |
779 // cannot be created (e.g., incognito mode), so we must translate. | |
780 HistogramEnumerateTranslationCache(false); | 840 HistogramEnumerateTranslationCache(false); |
781 | 841 |
782 // Create the translation thread object immediately. This ensures that any | 842 // Continue streaming. |
783 // pieces of the file that get downloaded before the compilation thread | |
784 // is accepting SRPCs won't get dropped. | |
785 translate_thread_.reset(new PnaclTranslateThread()); | |
786 if (translate_thread_ == NULL) { | |
787 ReportNonPpapiError(ERROR_PNACL_THREAD_CREATE, | |
788 "could not allocate translation thread."); | |
789 return; | |
790 } | |
791 // We also want to open the object file now so the | |
792 // translator can start writing to it during streaming translation. | |
793 obj_file_.reset(new TempFile(plugin_)); | |
794 pp::CompletionCallback obj_cb = | |
795 callback_factory_.NewCallback(&PnaclCoordinator::ObjectFileDidOpen); | |
796 obj_file_->Open(obj_cb); | |
797 | |
798 streaming_downloader_.reset(new FileDownloader()); | |
799 streaming_downloader_->Initialize(plugin_); | |
800 pp::CompletionCallback cb = | 843 pp::CompletionCallback cb = |
801 callback_factory_.NewCallback( | 844 callback_factory_.NewCallback(&PnaclCoordinator::BitcodeStreamDidFinish); |
802 &PnaclCoordinator::BitcodeStreamDidFinish); | 845 streaming_downloader_->FinishStreaming(cb); |
803 | |
804 if (!streaming_downloader_->OpenStream(pexe_url_, cb, this)) { | |
805 ReportNonPpapiError(ERROR_PNACL_PEXE_FETCH_OTHER, | |
806 nacl::string("failed to open stream ") + pexe_url_); | |
807 } | |
808 } | 846 } |
809 | 847 |
810 void PnaclCoordinator::BitcodeStreamDidFinish(int32_t pp_error) { | 848 void PnaclCoordinator::BitcodeStreamDidFinish(int32_t pp_error) { |
811 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamDidFinish (pp_error=%" | 849 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamDidFinish (pp_error=%" |
812 NACL_PRId32")\n", pp_error)); | 850 NACL_PRId32")\n", pp_error)); |
813 if (pp_error != PP_OK) { | 851 if (pp_error != PP_OK) { |
814 // Defer reporting the error and cleanup until after the translation | 852 // Defer reporting the error and cleanup until after the translation |
815 // thread returns, because it may be accessing the coordinator's | 853 // thread returns, because it may be accessing the coordinator's |
816 // objects or writing to the files. | 854 // objects or writing to the files. |
817 translate_finish_error_ = pp_error; | 855 translate_finish_error_ = pp_error; |
(...skipping 15 matching lines...) Expand all Loading... |
833 HistogramRatio("NaCl.Perf.PNaClLoadTime.PctCompiledWhenFullyDownloaded", | 871 HistogramRatio("NaCl.Perf.PNaClLoadTime.PctCompiledWhenFullyDownloaded", |
834 pexe_bytes_compiled_, pexe_size_); | 872 pexe_bytes_compiled_, pexe_size_); |
835 } | 873 } |
836 } | 874 } |
837 | 875 |
838 void PnaclCoordinator::BitcodeStreamGotData(int32_t pp_error, | 876 void PnaclCoordinator::BitcodeStreamGotData(int32_t pp_error, |
839 FileStreamData data) { | 877 FileStreamData data) { |
840 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamGotData (pp_error=%" | 878 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamGotData (pp_error=%" |
841 NACL_PRId32", data=%p)\n", pp_error, data ? &(*data)[0] : 0)); | 879 NACL_PRId32", data=%p)\n", pp_error, data ? &(*data)[0] : 0)); |
842 DCHECK(translate_thread_.get()); | 880 DCHECK(translate_thread_.get()); |
| 881 |
843 translate_thread_->PutBytes(data, pp_error); | 882 translate_thread_->PutBytes(data, pp_error); |
844 // If pp_error > 0, then it represents the number of bytes received. | 883 // If pp_error > 0, then it represents the number of bytes received. |
845 if (data && pp_error > 0) { | 884 if (data && pp_error > 0) { |
846 pexe_size_ += pp_error; | 885 pexe_size_ += pp_error; |
847 } | 886 } |
848 } | 887 } |
849 | 888 |
850 StreamCallback PnaclCoordinator::GetCallback() { | 889 StreamCallback PnaclCoordinator::GetCallback() { |
851 return callback_factory_.NewCallbackWithOutput( | 890 return callback_factory_.NewCallbackWithOutput( |
852 &PnaclCoordinator::BitcodeStreamGotData); | 891 &PnaclCoordinator::BitcodeStreamGotData); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
924 obj_file_.get(), | 963 obj_file_.get(), |
925 temp_nexe_file_.get(), | 964 temp_nexe_file_.get(), |
926 &error_info_, | 965 &error_info_, |
927 resources_.get(), | 966 resources_.get(), |
928 &pnacl_options_, | 967 &pnacl_options_, |
929 this, | 968 this, |
930 plugin_); | 969 plugin_); |
931 } | 970 } |
932 | 971 |
933 } // namespace plugin | 972 } // namespace plugin |
OLD | NEW |