Home | History | Annotate | Download | only in plugin
      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