1 // Copyright 2012 The Chromium Authors 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 COMPONENTS_NACL_RENDERER_PLUGIN_PNACL_COORDINATOR_H_ 6 #define COMPONENTS_NACL_RENDERER_PLUGIN_PNACL_COORDINATOR_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <memory> 12 #include <vector> 13 14 #include "base/files/file.h" 15 #include "base/time/time.h" 16 #include "components/nacl/renderer/plugin/nacl_subprocess.h" 17 #include "components/nacl/renderer/plugin/plugin_error.h" 18 #include "components/nacl/renderer/plugin/pnacl_resources.h" 19 #include "ppapi/cpp/completion_callback.h" 20 #include "ppapi/utility/completion_callback_factory.h" 21 22 struct PP_PNaClOptions; 23 24 namespace plugin { 25 26 class Plugin; 27 class PnaclCoordinator; 28 class PnaclTranslateThread; 29 30 // A class invoked by Plugin to handle PNaCl client-side translation. 31 // Usage: 32 // (1) Invoke the factory method, e.g., 33 // PnaclCoordinator* coord = BitcodeToNative(plugin, 34 // "http://foo.com/my.pexe", 35 // pnacl_options, 36 // translate_notify_callback); 37 // (2) translate_notify_callback gets invoked when translation is complete. 38 // If the translation was successful, the pp_error argument is PP_OK. 39 // Other values indicate errors. 40 // (3) After finish_callback runs, get the file descriptor of the translated 41 // nexe, e.g., 42 // fd = coord->TakeTranslatedFileHandle(); 43 // (4) Load the nexe from "fd". 44 // (5) delete coord. 45 // 46 // Translation proceeds in two steps: 47 // (1) llc translates the bitcode in pexe_url_ to an object in obj_file_. 48 // (2) ld links the object code in obj_file_ and produces a nexe in nexe_file_. 49 class PnaclCoordinator { 50 public: 51 PnaclCoordinator(const PnaclCoordinator&) = delete; 52 PnaclCoordinator& operator=(const PnaclCoordinator&) = delete; 53 54 virtual ~PnaclCoordinator(); 55 56 // The factory method for translations. 57 static PnaclCoordinator* BitcodeToNative( 58 Plugin* plugin, 59 const std::string& pexe_url, 60 const PP_PNaClOptions& pnacl_options, 61 const pp::CompletionCallback& translate_notify_callback); 62 63 // Call this to take ownership of the FD of the translated nexe after 64 // BitcodeToNative has completed (and the finish_callback called). 65 PP_FileHandle TakeTranslatedFileHandle(); 66 67 // Return a callback that should be notified when |bytes_compiled| bytes 68 // have been compiled. 69 pp::CompletionCallback GetCompileProgressCallback(int64_t bytes_compiled); 70 71 // Return true if we should delay the progress event reporting. 72 // This delay approximates: 73 // - the size of the buffer of bytes sent but not-yet-compiled by LLC. 74 // - the linking time. ShouldDelayProgressEvent()75 bool ShouldDelayProgressEvent() { 76 const uint32_t kProgressEventSlopPct = 5; 77 return ((expected_pexe_size_ - pexe_bytes_compiled_) * 100 / 78 expected_pexe_size_) < kProgressEventSlopPct; 79 } 80 81 82 void BitcodeStreamCacheHit(PP_FileHandle handle); 83 void BitcodeStreamCacheMiss(int64_t expected_pexe_size, 84 PP_FileHandle handle); 85 86 // Invoked when a pexe data chunk arrives (when using streaming translation) 87 void BitcodeStreamGotData(const void* data, int32_t length); 88 89 // Invoked when the pexe download finishes (using streaming translation) 90 void BitcodeStreamDidFinish(int32_t pp_error); 91 92 private: 93 // BitcodeToNative is the factory method for PnaclCoordinators. 94 // Therefore the constructor is private. 95 PnaclCoordinator(Plugin* plugin, 96 const std::string& pexe_url, 97 const PP_PNaClOptions& pnacl_options, 98 const pp::CompletionCallback& translate_notify_callback); 99 100 // Invoke to issue a GET request for bitcode. 101 void OpenBitcodeStream(); 102 103 // Invoked when a pexe data chunk is compiled. 104 void BitcodeGotCompiled(int32_t pp_error, int64_t bytes_compiled); 105 // Once llc and ld nexes have been loaded and the two temporary files have 106 // been created, this starts the translation. Translation starts two 107 // subprocesses, one for llc and one for ld. 108 void LoadCompiler(); 109 void RunCompile(int32_t pp_error, base::TimeTicks compile_load_start_time); 110 void LoadLinker(int32_t pp_error); 111 void RunLink(int32_t pp_error, base::TimeTicks ld_load_start_time); 112 113 // Invoked when translation is finished. 114 void TranslateFinished(int32_t pp_error); 115 116 // Invoked when the read descriptor for nexe_file_ is created. 117 void NexeReadDidOpen(); 118 119 // Bring control back to the plugin by invoking the 120 // |translate_notify_callback_|. This does not set the ErrorInfo report, 121 // it is assumed that it was already set. 122 void ExitWithError(); 123 // Run |translate_notify_callback_| with an error condition that is not 124 // PPAPI specific. Also set ErrorInfo report. 125 void ReportNonPpapiError(PP_NaClError err, const std::string& message); 126 127 // Keeps track of the pp_error upon entry to TranslateFinished, 128 // for inspection after cleanup. 129 int32_t translate_finish_error_; 130 131 // The plugin owning the nexe for which we are doing translation. 132 Plugin* plugin_; 133 134 pp::CompletionCallback translate_notify_callback_; 135 // Set to true when the translation (if applicable) is finished and the nexe 136 // file is loaded, (or when there was an error), and the browser has been 137 // notified via ReportTranslationFinished. If it is not set before 138 // plugin/coordinator destruction, the destructor will call 139 // ReportTranslationFinished. 140 bool translation_finished_reported_; 141 // Threadsafety is required to support file lookups. 142 pp::CompletionCallbackFactory<PnaclCoordinator, 143 pp::ThreadSafeThreadTraits> callback_factory_; 144 145 // An auxiliary class that manages downloaded resources (llc and ld nexes). 146 std::unique_ptr<PnaclResources> resources_; 147 NaClSubprocess compiler_subprocess_; 148 NaClSubprocess ld_subprocess_; 149 150 // The URL for the pexe file. 151 std::string pexe_url_; 152 // Options for translation. 153 PP_PNaClOptions pnacl_options_; 154 // Architecture-specific attributes used for translation. These are 155 // supplied by Chrome, not the developer, and are therefore different 156 // from PNaCl options. 157 std::string architecture_attributes_; 158 159 // Object file, produced by the translator and consumed by the linker. 160 std::vector<base::File> obj_files_; 161 // Number of split modules for llc. 162 int split_module_count_; 163 // Number of threads for llc / subzero. 164 int num_threads_; 165 166 // Translated nexe file, produced by the linker. 167 base::File temp_nexe_file_; 168 169 // Used to report information when errors (PPAPI or otherwise) are reported. 170 ErrorInfo error_info_; 171 172 // True if an error was already reported, and translate_notify_callback_ 173 // was already run/consumed. 174 bool error_already_reported_; 175 176 // State for timing and size information for UMA stats. 177 int64_t pexe_size_; // Count as we stream -- will converge to pexe size. 178 int64_t pexe_bytes_compiled_; // Count as we compile. 179 int64_t expected_pexe_size_; // Expected download total (-1 if unknown). 180 181 // The helper thread used to do translations via SRPC. 182 // It accesses fields of PnaclCoordinator so it must have a 183 // shorter lifetime. 184 std::unique_ptr<PnaclTranslateThread> translate_thread_; 185 }; 186 187 //---------------------------------------------------------------------- 188 189 } // namespace plugin; 190 #endif // COMPONENTS_NACL_RENDERER_PLUGIN_PNACL_COORDINATOR_H_ 191