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