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