• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
SelLdrStartParamsSelLdrStartParams45   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:
OpenManifestEntryResourceOpenManifestEntryResource70   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);
plugin()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 
main_service_runtime()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