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 3 // found in the LICENSE file. 4 5 #ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_COORDINATOR_H_ 6 #define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_COORDINATOR_H_ 7 8 #include <set> 9 #include <map> 10 #include <vector> 11 12 #include "native_client/src/include/nacl_macros.h" 13 #include "native_client/src/include/nacl_string.h" 14 #include "native_client/src/shared/platform/nacl_sync_raii.h" 15 #include "native_client/src/shared/srpc/nacl_srpc.h" 16 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" 17 18 #include "ppapi/cpp/completion_callback.h" 19 20 #include "ppapi/native_client/src/trusted/plugin/callback_source.h" 21 #include "ppapi/native_client/src/trusted/plugin/file_downloader.h" 22 #include "ppapi/native_client/src/trusted/plugin/nacl_subprocess.h" 23 #include "ppapi/native_client/src/trusted/plugin/plugin_error.h" 24 #include "ppapi/native_client/src/trusted/plugin/pnacl_resources.h" 25 26 struct PP_PNaClOptions; 27 28 namespace plugin { 29 30 class Plugin; 31 class PnaclCoordinator; 32 class PnaclTranslateThread; 33 class TempFile; 34 35 // A class invoked by Plugin to handle PNaCl client-side translation. 36 // Usage: 37 // (1) Invoke the factory method, e.g., 38 // PnaclCoordinator* coord = BitcodeToNative(plugin, 39 // "http://foo.com/my.pexe", 40 // pnacl_options, 41 // TranslateNotifyCallback); 42 // (2) TranslateNotifyCallback gets invoked when translation is complete. 43 // If the translation was successful, the pp_error argument is PP_OK. 44 // Other values indicate errors. 45 // (3) After finish_callback runs, get the file descriptor of the translated 46 // nexe, e.g., 47 // fd = coord->ReleaseTranslatedFD(); 48 // (4) Load the nexe from "fd". 49 // (5) delete coord. 50 // 51 // Translation proceeds in two steps: 52 // (1) llc translates the bitcode in pexe_url_ to an object in obj_file_. 53 // (2) ld links the object code in obj_file_ and produces a nexe in nexe_file_. 54 class PnaclCoordinator: public CallbackSource<FileStreamData> { 55 public: 56 // Maximum number of object files passable to the translator. Cannot be 57 // changed without changing the RPC signatures. 58 const static size_t kMaxTranslatorObjectFiles = 16; 59 virtual ~PnaclCoordinator(); 60 61 // The factory method for translations. 62 static PnaclCoordinator* BitcodeToNative( 63 Plugin* plugin, 64 const nacl::string& pexe_url, 65 const PP_PNaClOptions& pnacl_options, 66 const pp::CompletionCallback& translate_notify_callback); 67 68 // Call this to take ownership of the FD of the translated nexe after 69 // BitcodeToNative has completed (and the finish_callback called). 70 PP_FileHandle TakeTranslatedFileHandle(); 71 72 // Implement FileDownloader's template of the CallbackSource interface. 73 // This method returns a callback which will be called by the FileDownloader 74 // to stream the bitcode data as it arrives. The callback 75 // (BitcodeStreamGotData) passes it to llc over SRPC. 76 StreamCallback GetCallback(); 77 78 // Return a callback that should be notified when |bytes_compiled| bytes 79 // have been compiled. 80 pp::CompletionCallback GetCompileProgressCallback(int64_t bytes_compiled); 81 82 // Get the last known load progress. 83 void GetCurrentProgress(int64_t* bytes_loaded, int64_t* bytes_total); 84 85 // Return true if we should delay the progress event reporting. 86 // This delay approximates: 87 // - the size of the buffer of bytes sent but not-yet-compiled by LLC. 88 // - the linking time. 89 bool ShouldDelayProgressEvent() { 90 const uint32_t kProgressEventSlopPct = 5; 91 return ((expected_pexe_size_ - pexe_bytes_compiled_) * 100 / 92 expected_pexe_size_) < kProgressEventSlopPct; 93 } 94 95 private: 96 NACL_DISALLOW_COPY_AND_ASSIGN(PnaclCoordinator); 97 98 // BitcodeToNative is the factory method for PnaclCoordinators. 99 // Therefore the constructor is private. 100 PnaclCoordinator(Plugin* plugin, 101 const nacl::string& pexe_url, 102 const PP_PNaClOptions& pnacl_options, 103 const pp::CompletionCallback& translate_notify_callback); 104 105 // Invoke to issue a GET request for bitcode. 106 void OpenBitcodeStream(); 107 // Invoked when we've started an URL fetch for the pexe to check for 108 // caching metadata. 109 void BitcodeStreamDidOpen(int32_t pp_error); 110 111 // Callback for when the resource info JSON file has been read. 112 void ResourceInfoWasRead(int32_t pp_error); 113 114 // Callback for when llc and ld have been downloaded. 115 void ResourcesDidLoad(int32_t pp_error); 116 // Invoked when we've gotten a temp FD for the nexe, either with the nexe 117 // data, or a writeable fd to save to. 118 void NexeFdDidOpen(int32_t pp_error); 119 // Invoked when a pexe data chunk arrives (when using streaming translation) 120 void BitcodeStreamGotData(int32_t pp_error, FileStreamData data); 121 // Invoked when a pexe data chunk is compiled. 122 void BitcodeGotCompiled(int32_t pp_error, int64_t bytes_compiled); 123 // Invoked when the pexe download finishes (using streaming translation) 124 void BitcodeStreamDidFinish(int32_t pp_error); 125 // Once llc and ld nexes have been loaded and the two temporary files have 126 // been created, this starts the translation. Translation starts two 127 // subprocesses, one for llc and one for ld. 128 void RunTranslate(int32_t pp_error); 129 130 // Invoked when translation is finished. 131 void TranslateFinished(int32_t pp_error); 132 133 // Invoked when the read descriptor for nexe_file_ is created. 134 void NexeReadDidOpen(int32_t pp_error); 135 136 // Bring control back to the plugin by invoking the 137 // |translate_notify_callback_|. This does not set the ErrorInfo report, 138 // it is assumed that it was already set. 139 void ExitWithError(); 140 // Run |translate_notify_callback_| with an error condition that is not 141 // PPAPI specific. Also set ErrorInfo report. 142 void ReportNonPpapiError(PP_NaClError err, const nacl::string& message); 143 // Run when faced with a PPAPI error condition. Bring control back to the 144 // plugin by invoking the |translate_notify_callback_|. 145 // Also set ErrorInfo report. 146 void ReportPpapiError(PP_NaClError err, 147 int32_t pp_error, const nacl::string& message); 148 149 150 // Keeps track of the pp_error upon entry to TranslateFinished, 151 // for inspection after cleanup. 152 int32_t translate_finish_error_; 153 154 // The plugin owning the nexe for which we are doing translation. 155 Plugin* plugin_; 156 157 pp::CompletionCallback translate_notify_callback_; 158 // Set to true when the translation (if applicable) is finished and the nexe 159 // file is loaded, (or when there was an error), and the browser has been 160 // notified via ReportTranslationFinished. If it is not set before 161 // plugin/coordinator destruction, the destructor will call 162 // ReportTranslationFinished. 163 bool translation_finished_reported_; 164 // Threadsafety is required to support file lookups. 165 pp::CompletionCallbackFactory<PnaclCoordinator, 166 pp::ThreadSafeThreadTraits> callback_factory_; 167 168 // An auxiliary class that manages downloaded resources (llc and ld nexes). 169 nacl::scoped_ptr<PnaclResources> resources_; 170 171 // The URL for the pexe file. 172 nacl::string pexe_url_; 173 // Options for translation. 174 PP_PNaClOptions pnacl_options_; 175 // Architecture-specific attributes used for translation. These are 176 // supplied by Chrome, not the developer, and are therefore different 177 // from PNaCl options. 178 nacl::string architecture_attributes_; 179 180 // Object file, produced by the translator and consumed by the linker. 181 std::vector<TempFile*> obj_files_; 182 nacl::scoped_ptr<nacl::DescWrapper> invalid_desc_wrapper_; 183 // Number of split modules (threads) for llc 184 int split_module_count_; 185 186 // Translated nexe file, produced by the linker. 187 nacl::scoped_ptr<TempFile> temp_nexe_file_; 188 // Passed to the browser, which sets it to true if there is a translation 189 // cache hit. 190 PP_Bool is_cache_hit_; 191 192 // Downloader for streaming translation 193 nacl::scoped_ptr<FileDownloader> streaming_downloader_; 194 195 // Used to report information when errors (PPAPI or otherwise) are reported. 196 ErrorInfo error_info_; 197 198 // True if an error was already reported, and translate_notify_callback_ 199 // was already run/consumed. 200 bool error_already_reported_; 201 202 // State for timing and size information for UMA stats. 203 int64_t pnacl_init_time_; 204 int64_t pexe_size_; // Count as we stream -- will converge to pexe size. 205 int64_t pexe_bytes_compiled_; // Count as we compile. 206 int64_t expected_pexe_size_; // Expected download total (-1 if unknown). 207 208 // The helper thread used to do translations via SRPC. 209 // It accesses fields of PnaclCoordinator so it must have a 210 // shorter lifetime. 211 nacl::scoped_ptr<PnaclTranslateThread> translate_thread_; 212 }; 213 214 //---------------------------------------------------------------------- 215 216 } // namespace plugin; 217 #endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_COORDINATOR_H_ 218