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