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