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