1 // -*- c++ -*- 2 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 6 // The portable representation of an instance and root scriptable object. 7 // The PPAPI version of the plugin instantiates a subclass of this class. 8 9 #ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PLUGIN_H_ 10 #define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PLUGIN_H_ 11 12 #include <stdio.h> 13 14 #include <map> 15 #include <queue> 16 #include <set> 17 #include <string> 18 19 #include "native_client/src/include/nacl_macros.h" 20 #include "native_client/src/include/nacl_scoped_ptr.h" 21 #include "native_client/src/include/nacl_string.h" 22 #include "native_client/src/public/nacl_file_info.h" 23 24 #include "ppapi/c/private/ppb_nacl_private.h" 25 #include "ppapi/cpp/instance.h" 26 #include "ppapi/cpp/private/uma_private.h" 27 #include "ppapi/cpp/url_loader.h" 28 #include "ppapi/cpp/var.h" 29 #include "ppapi/cpp/view.h" 30 31 #include "ppapi/native_client/src/trusted/plugin/file_downloader.h" 32 #include "ppapi/native_client/src/trusted/plugin/nacl_subprocess.h" 33 #include "ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h" 34 #include "ppapi/native_client/src/trusted/plugin/service_runtime.h" 35 #include "ppapi/native_client/src/trusted/plugin/utility.h" 36 37 namespace nacl { 38 class DescWrapper; 39 class DescWrapperFactory; 40 } // namespace nacl 41 42 namespace pp { 43 class CompletionCallback; 44 class URLLoader; 45 class URLUtil_Dev; 46 } 47 48 namespace plugin { 49 50 class ErrorInfo; 51 class Manifest; 52 53 int32_t ConvertFileDescriptor(PP_FileHandle handle); 54 55 class Plugin : public pp::Instance { 56 public: 57 explicit Plugin(PP_Instance instance); 58 59 // ----- Methods inherited from pp::Instance: 60 61 // Initializes this plugin with <embed/object ...> tag attribute count |argc|, 62 // names |argn| and values |argn|. Returns false on failure. 63 // Gets called by the browser right after New(). 64 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); 65 66 // Handles document load, when the plugin is a MIME type handler. 67 virtual bool HandleDocumentLoad(const pp::URLLoader& url_loader); 68 69 // Load support. 70 // 71 // Starts NaCl module but does not wait until low-level 72 // initialization (e.g. ld.so dynamic loading of manifest files) is 73 // done. The module will become ready later, asynchronously. Other 74 // event handlers should block until the module is ready before 75 // trying to communicate with it, i.e., until nacl_ready_state is 76 // DONE. 77 // 78 // NB: currently we do not time out, so if the untrusted code 79 // does not signal that it is ready, then we will deadlock the main 80 // thread of the renderer on this subsequent event delivery. We 81 // should include a time-out at which point we declare the 82 // nacl_ready_state to be done, and let the normal crash detection 83 // mechanism(s) take over. 84 void LoadNaClModule(PP_NaClFileInfo file_info, 85 bool uses_nonsfi_mode, 86 bool enable_dyncode_syscalls, 87 bool enable_exception_handling, 88 bool enable_crash_throttling, 89 const pp::CompletionCallback& init_done_cb, 90 const pp::CompletionCallback& crash_cb); 91 92 // Finish hooking interfaces up, after low-level initialization is 93 // complete. 94 bool LoadNaClModuleContinuationIntern(); 95 96 // Continuation for starting SRPC/JSProxy services as appropriate. 97 // This is invoked as a callback when the NaCl module makes the 98 // init_done reverse RPC to tell us that low-level initialization 99 // such as ld.so processing is done. That initialization requires 100 // that the main thread be free in order to do Pepper 101 // main-thread-only operations such as file processing. 102 bool LoadNaClModuleContinuation(int32_t pp_error); 103 104 // Load support. 105 // A helper SRPC NaCl module can be loaded given a PP_FileHandle. 106 // Blocks until the helper module signals initialization is done. 107 // Does not update nacl_module_origin(). 108 // Returns NULL or the NaClSubprocess of the new helper NaCl module. 109 NaClSubprocess* LoadHelperNaClModule(const nacl::string& helper_url, 110 PP_FileHandle file_handle, 111 ErrorInfo* error_info); 112 113 // Report an error that was encountered while loading a module. 114 void ReportLoadError(const ErrorInfo& error_info); 115 wrapper_factory()116 nacl::DescWrapperFactory* wrapper_factory() const { return wrapper_factory_; } 117 118 // A helper function that indicates if |url| can be requested by the document 119 // under the same-origin policy. Strictly speaking, it may be possible for the 120 // document to request the URL using CORS even if this function returns false. 121 bool DocumentCanRequest(const std::string& url); 122 123 // set_exit_status may be called off the main thread. 124 void set_exit_status(int exit_status); 125 nacl_interface()126 const PPB_NaCl_Private* nacl_interface() const { return nacl_interface_; } uma_interface()127 pp::UMAPrivate& uma_interface() { return uma_interface_; } 128 129 private: 130 NACL_DISALLOW_COPY_AND_ASSIGN(Plugin); 131 // The browser will invoke the destructor via the pp::Instance 132 // pointer to this object, not from base's Delete(). 133 ~Plugin(); 134 135 // Shuts down socket connection, service runtime, and receive thread, 136 // in this order, for the main nacl subprocess. 137 void ShutDownSubprocesses(); 138 139 // Histogram helper functions, internal to Plugin so they can use 140 // uma_interface_ normally. 141 void HistogramTimeSmall(const std::string& name, int64_t ms); 142 143 // Load a nacl module from the file specified in file_handle. 144 // Only to be used from a background (non-main) thread for the PNaCl 145 // translator. This will fully initialize the |subprocess| if the load was 146 // successful. 147 bool LoadHelperNaClModule(PP_FileHandle file_handle, 148 NaClSubprocess* subprocess, 149 const SelLdrStartParams& params); 150 151 // Start sel_ldr from the main thread, given the start params. 152 // |pp_error| is set by CallOnMainThread (should be PP_OK). 153 void StartSelLdrOnMainThread(int32_t pp_error, 154 ServiceRuntime* service_runtime, 155 const SelLdrStartParams& params, 156 pp::CompletionCallback callback); 157 158 // Signals that StartSelLdr has finished. 159 // This is invoked on the main thread. 160 void SignalStartSelLdrDone(int32_t pp_error, 161 bool* started, 162 ServiceRuntime* service_runtime); 163 164 // Signals that the nexe is started. 165 // This is invoked on the main thread. 166 void SignalNexeStarted(int32_t pp_error, 167 bool* started, 168 ServiceRuntime* service_runtime); 169 170 // This is invoked on the main thread. 171 void LoadNexeAndStart(int32_t pp_error, 172 ServiceRuntime* service_runtime, 173 PP_NaClFileInfo file_info, 174 const pp::CompletionCallback& callback); 175 176 // Callback used when getting the URL for the .nexe file. If the URL loading 177 // is successful, the file descriptor is opened and can be passed to sel_ldr 178 // with the sandbox on. 179 void NexeFileDidOpen(int32_t pp_error); 180 void NexeFileDidOpenContinuation(int32_t pp_error); 181 182 // Callback used when the reverse channel closes. This is an 183 // asynchronous event that might turn into a JavaScript error or 184 // crash event -- this is controlled by the two state variables 185 // nacl_ready_state_ and nexe_error_reported_: If an error or crash 186 // had already been reported, no additional crash event is 187 // generated. If no error has been reported but nacl_ready_state_ 188 // is not DONE, then the loadend event has not been reported, and we 189 // enqueue an error event followed by loadend. If nacl_ready_state_ 190 // is DONE, then we are in the post-loadend (we need temporal 191 // predicate symbols), and we enqueue a crash event. 192 void NexeDidCrash(int32_t pp_error); 193 194 // Callback used when a .nexe is translated from bitcode. If the translation 195 // is successful, the file descriptor is opened and can be passed to sel_ldr 196 // with the sandbox on. 197 void BitcodeDidTranslate(int32_t pp_error); 198 void BitcodeDidTranslateContinuation(int32_t pp_error); 199 200 // NaCl ISA selection manifest file support. The manifest file is specified 201 // using the "nacl" attribute in the <embed> tag. First, the manifest URL (or 202 // data: URI) is fetched, then the JSON is parsed. Once a valid .nexe is 203 // chosen for the sandbox ISA, any current service runtime is shut down, the 204 // .nexe is loaded and run. 205 206 // Callback used when getting the manifest file as a local file descriptor. 207 void NaClManifestFileDidOpen(int32_t pp_error); 208 209 // Processes the JSON manifest string and starts loading the nexe. 210 void ProcessNaClManifest(const nacl::string& manifest_json); 211 212 void SetExitStatusOnMainThread(int32_t pp_error, int exit_status); 213 214 // Keep track of the NaCl module subprocess that was spun up in the plugin. 215 NaClSubprocess main_subprocess_; 216 217 bool uses_nonsfi_mode_; 218 219 nacl::DescWrapperFactory* wrapper_factory_; 220 221 // Original, unresolved URL for the .nexe program to load. 222 std::string program_url_; 223 224 pp::CompletionCallbackFactory<Plugin> callback_factory_; 225 226 nacl::scoped_ptr<PnaclCoordinator> pnacl_coordinator_; 227 228 int exit_status_; 229 230 PP_NaClFileInfo nexe_file_info_; 231 232 const PPB_NaCl_Private* nacl_interface_; 233 pp::UMAPrivate uma_interface_; 234 }; 235 236 } // namespace plugin 237 238 #endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PLUGIN_H_ 239