Home | History | Annotate | Download | only in plugin
      1 /* -*- c++ -*- */
      2 /*
      3  * Copyright (c) 2012 The Chromium Authors. All rights reserved.
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 // A class containing information regarding a socket connection to a
      9 // service runtime instance.
     10 
     11 #ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
     12 #define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
     13 
     14 #include <map>
     15 
     16 #include "native_client/src/include/nacl_macros.h"
     17 #include "native_client/src/include/nacl_scoped_ptr.h"
     18 #include "native_client/src/include/nacl_string.h"
     19 #include "native_client/src/shared/platform/nacl_sync.h"
     20 #include "native_client/src/shared/srpc/nacl_srpc.h"
     21 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
     22 #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
     23 #include "native_client/src/trusted/reverse_service/reverse_service.h"
     24 #include "native_client/src/trusted/weak_ref/weak_ref.h"
     25 
     26 #include "ppapi/c/trusted/ppb_file_io_trusted.h"
     27 #include "ppapi/cpp/completion_callback.h"
     28 
     29 #include "ppapi/native_client/src/trusted/plugin/utility.h"
     30 
     31 struct NaClFileInfo;
     32 
     33 namespace nacl {
     34 class DescWrapper;
     35 }  // namespace
     36 
     37 namespace pp {
     38 class FileIO;
     39 }  // namespace
     40 
     41 namespace plugin {
     42 
     43 class ErrorInfo;
     44 class Manifest;
     45 class Plugin;
     46 class PnaclCoordinator;
     47 class SrpcClient;
     48 class ServiceRuntime;
     49 
     50 // Struct of params used by StartSelLdr.  Use a struct so that callback
     51 // creation templates aren't overwhelmed with too many parameters.
     52 struct SelLdrStartParams {
     53   SelLdrStartParams(const nacl::string& url,
     54                     ErrorInfo* error_info,
     55                     bool uses_irt,
     56                     bool uses_ppapi,
     57                     bool enable_dev_interfaces,
     58                     bool enable_dyncode_syscalls,
     59                     bool enable_exception_handling)
     60       : url(url),
     61         error_info(error_info),
     62         uses_irt(uses_irt),
     63         uses_ppapi(uses_ppapi),
     64         enable_dev_interfaces(enable_dev_interfaces),
     65         enable_dyncode_syscalls(enable_dyncode_syscalls),
     66         enable_exception_handling(enable_exception_handling) {
     67   }
     68   nacl::string url;
     69   ErrorInfo* error_info;
     70   bool uses_irt;
     71   bool uses_ppapi;
     72   bool enable_dev_interfaces;
     73   bool enable_dyncode_syscalls;
     74   bool enable_exception_handling;
     75 };
     76 
     77 // Callback resources are essentially our continuation state.
     78 
     79 struct LogToJavaScriptConsoleResource {
     80  public:
     81   explicit LogToJavaScriptConsoleResource(std::string msg)
     82       : message(msg) {}
     83   std::string message;
     84 };
     85 
     86 struct PostMessageResource {
     87  public:
     88   explicit PostMessageResource(std::string msg)
     89       : message(msg) {}
     90   std::string message;
     91 };
     92 
     93 struct OpenManifestEntryResource {
     94  public:
     95   OpenManifestEntryResource(const std::string& target_url,
     96                             struct NaClFileInfo* finfo,
     97                             ErrorInfo* infop,
     98                             bool* op_complete)
     99       : url(target_url),
    100         file_info(finfo),
    101         error_info(infop),
    102         op_complete_ptr(op_complete) {}
    103   std::string url;
    104   struct NaClFileInfo* file_info;
    105   ErrorInfo* error_info;
    106   bool* op_complete_ptr;
    107 };
    108 
    109 struct CloseManifestEntryResource {
    110  public:
    111   CloseManifestEntryResource(int32_t desc_to_close,
    112                              bool* op_complete,
    113                              bool* op_result)
    114       : desc(desc_to_close),
    115         op_complete_ptr(op_complete),
    116         op_result_ptr(op_result) {}
    117 
    118   int32_t desc;
    119   bool* op_complete_ptr;
    120   bool* op_result_ptr;
    121 };
    122 
    123 enum QuotaDataType {
    124   PepperQuotaType,
    125   TempQuotaType
    126 };
    127 
    128 struct QuotaData {
    129   QuotaData(QuotaDataType type_, PP_Resource resource_)
    130       : type(type_), resource(resource_) {}
    131   QuotaData()
    132       : type(PepperQuotaType), resource(0) {}
    133 
    134   QuotaDataType type;
    135   PP_Resource resource;
    136 };
    137 
    138 struct QuotaRequest {
    139  public:
    140   QuotaRequest(QuotaData quota_data,
    141                int64_t start_offset,
    142                int64_t quota_bytes_requested,
    143                int64_t* quota_bytes_granted,
    144                bool* op_complete)
    145       : data(quota_data),
    146         offset(start_offset),
    147         bytes_requested(quota_bytes_requested),
    148         bytes_granted(quota_bytes_granted),
    149         op_complete_ptr(op_complete) { }
    150 
    151   QuotaData data;
    152   int64_t offset;
    153   int64_t bytes_requested;
    154   int64_t* bytes_granted;
    155   bool* op_complete_ptr;
    156 };
    157 
    158 // Do not invoke from the main thread, since the main methods will
    159 // invoke CallOnMainThread and then wait on a condvar for the task to
    160 // complete: if invoked from the main thread, the main method not
    161 // returning (and thus unblocking the main thread) means that the
    162 // main-thread continuation methods will never get called, and thus
    163 // we'd get a deadlock.
    164 class PluginReverseInterface: public nacl::ReverseInterface {
    165  public:
    166   PluginReverseInterface(nacl::WeakRefAnchor* anchor,
    167                          Plugin* plugin,
    168                          const Manifest* manifest,
    169                          ServiceRuntime* service_runtime,
    170                          pp::CompletionCallback init_done_cb,
    171                          pp::CompletionCallback crash_cb);
    172 
    173   virtual ~PluginReverseInterface();
    174 
    175   void ShutDown();
    176 
    177   virtual void Log(nacl::string message);
    178 
    179   virtual void DoPostMessage(nacl::string message);
    180 
    181   virtual void StartupInitializationComplete();
    182 
    183   virtual bool EnumerateManifestKeys(std::set<nacl::string>* out_keys);
    184 
    185   virtual bool OpenManifestEntry(nacl::string url_key,
    186                                  struct NaClFileInfo *info);
    187 
    188   virtual bool CloseManifestEntry(int32_t desc);
    189 
    190   virtual void ReportCrash();
    191 
    192   virtual void ReportExitStatus(int exit_status);
    193 
    194   virtual int64_t RequestQuotaForWrite(nacl::string file_id,
    195                                        int64_t offset,
    196                                        int64_t bytes_to_write);
    197 
    198   void AddQuotaManagedFile(const nacl::string& file_id,
    199                            const pp::FileIO& file_io);
    200   void AddTempQuotaManagedFile(const nacl::string& file_id);
    201 
    202  protected:
    203   virtual void Log_MainThreadContinuation(LogToJavaScriptConsoleResource* p,
    204                                           int32_t err);
    205 
    206   virtual void PostMessage_MainThreadContinuation(PostMessageResource* p,
    207                                                   int32_t err);
    208 
    209   virtual void OpenManifestEntry_MainThreadContinuation(
    210       OpenManifestEntryResource* p,
    211       int32_t err);
    212 
    213   virtual void StreamAsFile_MainThreadContinuation(
    214       OpenManifestEntryResource* p,
    215       int32_t result);
    216 
    217   virtual void BitcodeTranslate_MainThreadContinuation(
    218       OpenManifestEntryResource* p,
    219       int32_t result);
    220 
    221   virtual void CloseManifestEntry_MainThreadContinuation(
    222       CloseManifestEntryResource* cls,
    223       int32_t err);
    224 
    225   virtual void QuotaRequest_MainThreadContinuation(
    226       QuotaRequest* request,
    227       int32_t err);
    228 
    229   virtual void QuotaRequest_MainThreadResponse(
    230       QuotaRequest* request,
    231       int32_t err);
    232 
    233  private:
    234   nacl::WeakRefAnchor* anchor_;  // holds a ref
    235   Plugin* plugin_;  // value may be copied, but should be used only in
    236                     // main thread in WeakRef-protected callbacks.
    237   const Manifest* manifest_;
    238   ServiceRuntime* service_runtime_;
    239   NaClMutex mu_;
    240   NaClCondVar cv_;
    241   std::map<int64_t, QuotaData> quota_map_;
    242   bool shutting_down_;
    243 
    244   nacl::scoped_ptr<PnaclCoordinator> pnacl_coordinator_;
    245 
    246   pp::CompletionCallback init_done_cb_;
    247   pp::CompletionCallback crash_cb_;
    248 };
    249 
    250 //  ServiceRuntime abstracts a NativeClient sel_ldr instance.
    251 class ServiceRuntime {
    252  public:
    253   // TODO(sehr): This class should also implement factory methods, using the
    254   // Start method below.
    255   ServiceRuntime(Plugin* plugin,
    256                  const Manifest* manifest,
    257                  bool should_report_uma,
    258                  pp::CompletionCallback init_done_cb,
    259                  pp::CompletionCallback crash_cb);
    260   // The destructor terminates the sel_ldr process.
    261   ~ServiceRuntime();
    262 
    263   // Spawn the sel_ldr instance. On success, returns true.
    264   // On failure, returns false and |error_string| is set to something
    265   // describing the error.
    266   bool StartSelLdr(const SelLdrStartParams& params);
    267 
    268   // If starting sel_ldr from a background thread, wait for sel_ldr to
    269   // actually start.
    270   void WaitForSelLdrStart();
    271 
    272   // Signal to waiting threads that StartSelLdr is complete.
    273   // Done externally, in case external users want to write to shared
    274   // memory that is yet to be fenced.
    275   void SignalStartSelLdrDone();
    276 
    277   // Establish an SrpcClient to the sel_ldr instance and load the nexe.
    278   // The nexe to be started is passed through |nacl_file_desc|.
    279   // On success, returns true. On failure, returns false and |error_string|
    280   // is set to something describing the error.
    281   bool LoadNexeAndStart(nacl::DescWrapper* nacl_file_desc,
    282                         ErrorInfo* error_info,
    283                         const pp::CompletionCallback& crash_cb);
    284 
    285   // Starts the application channel to the nexe.
    286   SrpcClient* SetupAppChannel();
    287 
    288   bool Log(int severity, const nacl::string& msg);
    289   Plugin* plugin() const { return plugin_; }
    290   void Shutdown();
    291 
    292   // exit_status is -1 when invalid; when we set it, we will ensure
    293   // that it is non-negative (the portion of the exit status from the
    294   // nexe that is transferred is the low 8 bits of the argument to the
    295   // exit syscall).
    296   int exit_status();  // const, but grabs mutex etc.
    297   void set_exit_status(int exit_status);
    298 
    299   nacl::string GetCrashLogOutput();
    300 
    301   // To establish quota callbacks the pnacl coordinator needs to communicate
    302   // with the reverse interface.
    303   PluginReverseInterface* rev_interface() const { return rev_interface_; }
    304 
    305  private:
    306   NACL_DISALLOW_COPY_AND_ASSIGN(ServiceRuntime);
    307   bool InitCommunication(nacl::DescWrapper* shm, ErrorInfo* error_info);
    308 
    309   NaClSrpcChannel command_channel_;
    310   Plugin* plugin_;
    311   bool should_report_uma_;
    312   nacl::ReverseService* reverse_service_;
    313   nacl::scoped_ptr<nacl::SelLdrLauncherBase> subprocess_;
    314 
    315   nacl::WeakRefAnchor* anchor_;
    316 
    317   PluginReverseInterface* rev_interface_;
    318 
    319   // Mutex to protect exit_status_.
    320   // Also, in conjunction with cond_ it is used to signal when
    321   // StartSelLdr is complete with either success or error.
    322   NaClMutex mu_;
    323   NaClCondVar cond_;
    324   int exit_status_;
    325   bool start_sel_ldr_done_;
    326 };
    327 
    328 }  // namespace plugin
    329 
    330 #endif  // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
    331