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 #include "ppapi/native_client/src/trusted/plugin/utility.h"
     28 
     29 struct NaClFileInfo;
     30 
     31 namespace nacl {
     32 class DescWrapper;
     33 }  // namespace
     34 
     35 namespace plugin {
     36 
     37 class OpenManifestEntryAsyncCallback;
     38 class Plugin;
     39 class SrpcClient;
     40 class ServiceRuntime;
     41 
     42 // Struct of params used by StartSelLdr.  Use a struct so that callback
     43 // creation templates aren't overwhelmed with too many parameters.
     44 struct SelLdrStartParams {
     45   SelLdrStartParams(const nacl::string& url,
     46                     bool uses_irt,
     47                     bool uses_ppapi,
     48                     bool enable_dyncode_syscalls,
     49                     bool enable_exception_handling,
     50                     bool enable_crash_throttling)
     51       : url(url),
     52         uses_irt(uses_irt),
     53         uses_ppapi(uses_ppapi),
     54         enable_dyncode_syscalls(enable_dyncode_syscalls),
     55         enable_exception_handling(enable_exception_handling),
     56         enable_crash_throttling(enable_crash_throttling) {
     57   }
     58   nacl::string url;
     59   bool uses_irt;
     60   bool uses_ppapi;
     61   bool enable_dev_interfaces;
     62   bool enable_dyncode_syscalls;
     63   bool enable_exception_handling;
     64   bool enable_crash_throttling;
     65 };
     66 
     67 // Callback resources are essentially our continuation state.
     68 struct OpenManifestEntryResource {
     69  public:
     70   OpenManifestEntryResource(const std::string& target_url,
     71                             struct NaClFileInfo* finfo,
     72                             bool* op_complete,
     73                             OpenManifestEntryAsyncCallback* callback)
     74       : url(target_url),
     75         file_info(finfo),
     76         op_complete_ptr(op_complete),
     77         callback(callback) {}
     78   ~OpenManifestEntryResource();
     79   void MaybeRunCallback(int32_t pp_error);
     80 
     81   std::string url;
     82   struct NaClFileInfo* file_info;
     83   PP_NaClFileInfo pp_file_info;
     84   bool* op_complete_ptr;
     85   OpenManifestEntryAsyncCallback* callback;
     86 };
     87 
     88 // Do not invoke from the main thread, since the main methods will
     89 // invoke CallOnMainThread and then wait on a condvar for the task to
     90 // complete: if invoked from the main thread, the main method not
     91 // returning (and thus unblocking the main thread) means that the
     92 // main-thread continuation methods will never get called, and thus
     93 // we'd get a deadlock.
     94 class PluginReverseInterface: public nacl::ReverseInterface {
     95  public:
     96   PluginReverseInterface(nacl::WeakRefAnchor* anchor,
     97                          Plugin* plugin,
     98                          ServiceRuntime* service_runtime,
     99                          pp::CompletionCallback init_done_cb,
    100                          pp::CompletionCallback crash_cb);
    101 
    102   virtual ~PluginReverseInterface();
    103 
    104   void ShutDown();
    105 
    106   virtual void DoPostMessage(nacl::string message);
    107 
    108   virtual void StartupInitializationComplete();
    109 
    110   virtual bool OpenManifestEntry(nacl::string url_key,
    111                                  struct NaClFileInfo *info);
    112 
    113   virtual bool CloseManifestEntry(int32_t desc);
    114 
    115   virtual void ReportCrash();
    116 
    117   virtual void ReportExitStatus(int exit_status);
    118 
    119   // TODO(teravest): Remove this method once it's gone from
    120   // nacl::ReverseInterface.
    121   virtual int64_t RequestQuotaForWrite(nacl::string file_id,
    122                                        int64_t offset,
    123                                        int64_t bytes_to_write);
    124 
    125   // This is a sibling of OpenManifestEntry. While OpenManifestEntry is
    126   // a sync function and must be called on a non-main thread,
    127   // OpenManifestEntryAsync must be called on the main thread. Upon completion
    128   // (even on error), callback will be invoked. The caller has responsibility
    129   // to keep the memory passed to info until callback is invoked.
    130   void OpenManifestEntryAsync(const nacl::string& key,
    131                               struct NaClFileInfo* info,
    132                               OpenManifestEntryAsyncCallback* callback);
    133 
    134  protected:
    135   virtual void OpenManifestEntry_MainThreadContinuation(
    136       OpenManifestEntryResource* p,
    137       int32_t err);
    138 
    139   virtual void StreamAsFile_MainThreadContinuation(
    140       OpenManifestEntryResource* p,
    141       int32_t result);
    142 
    143  private:
    144   nacl::WeakRefAnchor* anchor_;  // holds a ref
    145   Plugin* plugin_;  // value may be copied, but should be used only in
    146                     // main thread in WeakRef-protected callbacks.
    147   ServiceRuntime* service_runtime_;
    148   NaClMutex mu_;
    149   NaClCondVar cv_;
    150   bool shutting_down_;
    151 
    152   pp::CompletionCallback init_done_cb_;
    153   pp::CompletionCallback crash_cb_;
    154 };
    155 
    156 //  ServiceRuntime abstracts a NativeClient sel_ldr instance.
    157 class ServiceRuntime {
    158  public:
    159   // TODO(sehr): This class should also implement factory methods, using the
    160   // Start method below.
    161   ServiceRuntime(Plugin* plugin,
    162                  bool main_service_runtime,
    163                  bool uses_nonsfi_mode,
    164                  pp::CompletionCallback init_done_cb,
    165                  pp::CompletionCallback crash_cb);
    166   // The destructor terminates the sel_ldr process.
    167   ~ServiceRuntime();
    168 
    169   // Spawn the sel_ldr instance.
    170   void StartSelLdr(const SelLdrStartParams& params,
    171                    pp::CompletionCallback callback);
    172 
    173   // If starting sel_ldr from a background thread, wait for sel_ldr to
    174   // actually start. Returns |false| if timed out waiting for the process
    175   // to start. Otherwise, returns |true| if StartSelLdr is complete
    176   // (either successfully or unsuccessfully).
    177   bool WaitForSelLdrStart();
    178 
    179   // Signal to waiting threads that StartSelLdr is complete (either
    180   // successfully or unsuccessfully).
    181   void SignalStartSelLdrDone();
    182 
    183   // If starting the nexe from a background thread, wait for the nexe to
    184   // actually start.
    185   void WaitForNexeStart();
    186 
    187   // Signal to waiting threads that LoadNexeAndStart is complete (either
    188   // successfully or unsuccessfully).
    189   void SignalNexeStarted();
    190 
    191   // Establish an SrpcClient to the sel_ldr instance and load the nexe.
    192   // The nexe to be started is passed through |file_info|.
    193   // Upon completion |callback| is invoked with status code.
    194   // This function must be called on the main thread.
    195   void LoadNexeAndStart(PP_NaClFileInfo file_info,
    196                         const pp::CompletionCallback& callback);
    197 
    198   // Starts the application channel to the nexe.
    199   SrpcClient* SetupAppChannel();
    200 
    201   bool Log(int severity, const nacl::string& msg);
    202   Plugin* plugin() const { return plugin_; }
    203   void Shutdown();
    204 
    205   // exit_status is -1 when invalid; when we set it, we will ensure
    206   // that it is non-negative (the portion of the exit status from the
    207   // nexe that is transferred is the low 8 bits of the argument to the
    208   // exit syscall).
    209   int exit_status();  // const, but grabs mutex etc.
    210   void set_exit_status(int exit_status);
    211 
    212   nacl::string GetCrashLogOutput();
    213 
    214   bool main_service_runtime() const { return main_service_runtime_; }
    215 
    216  private:
    217   NACL_DISALLOW_COPY_AND_ASSIGN(ServiceRuntime);
    218   struct LoadNexeAndStartData;
    219   void LoadNexeAndStartAfterLoadModule(
    220       LoadNexeAndStartData* data, int32_t pp_error);
    221   void DidLoadNexeAndStart(LoadNexeAndStartData* data, int32_t pp_error);
    222 
    223   bool SetupCommandChannel();
    224   bool InitReverseService();
    225   void LoadModule(PP_NaClFileInfo file_info,
    226                   pp::CompletionCallback callback);
    227   void DidLoadModule(pp::CompletionCallback callback, int32_t pp_error);
    228   bool StartModule();
    229 
    230   NaClSrpcChannel command_channel_;
    231   Plugin* plugin_;
    232   bool main_service_runtime_;
    233   bool uses_nonsfi_mode_;
    234   nacl::ReverseService* reverse_service_;
    235   nacl::scoped_ptr<nacl::SelLdrLauncherBase> subprocess_;
    236 
    237   nacl::WeakRefAnchor* anchor_;
    238 
    239   PluginReverseInterface* rev_interface_;
    240 
    241   // Mutex and CondVar to protect start_sel_ldr_done_ and nexe_started_.
    242   NaClMutex mu_;
    243   NaClCondVar cond_;
    244   bool start_sel_ldr_done_;
    245   bool nexe_started_;
    246 };
    247 
    248 }  // namespace plugin
    249 
    250 #endif  // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
    251