Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ppapi / native_client / src / trusted / plugin / plugin.h
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/trusted/validator/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 class Plugin : public pp::Instance {
54  public:
55   explicit Plugin(PP_Instance instance);
56
57   // ----- Methods inherited from pp::Instance:
58
59   // Initializes this plugin with <embed/object ...> tag attribute count |argc|,
60   // names |argn| and values |argn|. Returns false on failure.
61   // Gets called by the browser right after New().
62   virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
63
64   // Handles document load, when the plugin is a MIME type handler.
65   virtual bool HandleDocumentLoad(const pp::URLLoader& url_loader);
66
67   // ----- Plugin interface support.
68
69   // Load support.
70   // NaCl module can be loaded given a DescWrapper.
71   //
72   // Starts NaCl module but does not wait until low-level
73   // initialization (e.g., ld.so dynamic loading of manifest files) is
74   // done.  The module will become ready later, asynchronously.  Other
75   // event handlers should block until the module is ready before
76   // trying to communicate with it, i.e., until nacl_ready_state is
77   // DONE.
78   //
79   // NB: currently we do not time out, so if the untrusted code
80   // does not signal that it is ready, then we will deadlock the main
81   // thread of the renderer on this subsequent event delivery.  We
82   // should include a time-out at which point we declare the
83   // nacl_ready_state to be done, and let the normal crash detection
84   // mechanism(s) take over.
85   //
86   // Updates nacl_module_origin() and nacl_module_url().
87   void LoadNaClModule(nacl::DescWrapper* wrapper,
88                       bool uses_nonsfi_mode,
89                       bool enable_dyncode_syscalls,
90                       bool enable_exception_handling,
91                       bool enable_crash_throttling,
92                       const pp::CompletionCallback& init_done_cb,
93                       const pp::CompletionCallback& crash_cb);
94
95   // Finish hooking interfaces up, after low-level initialization is
96   // complete.
97   bool LoadNaClModuleContinuationIntern();
98
99   // Continuation for starting SRPC/JSProxy services as appropriate.
100   // This is invoked as a callback when the NaCl module makes the
101   // init_done reverse RPC to tell us that low-level initialization
102   // such as ld.so processing is done.  That initialization requires
103   // that the main thread be free in order to do Pepper
104   // main-thread-only operations such as file processing.
105   bool LoadNaClModuleContinuation(int32_t pp_error);
106
107   // Load support.
108   // A helper SRPC NaCl module can be loaded given a DescWrapper.
109   // Blocks until the helper module signals initialization is done.
110   // Does not update nacl_module_origin().
111   // Returns NULL or the NaClSubprocess of the new helper NaCl module.
112   NaClSubprocess* LoadHelperNaClModule(const nacl::string& helper_url,
113                                        nacl::DescWrapper* wrapper,
114                                        int32_t manifest_id,
115                                        ErrorInfo* error_info);
116
117   enum LengthComputable {
118     LENGTH_IS_NOT_COMPUTABLE = 0,
119     LENGTH_IS_COMPUTABLE = 1
120   };
121   // Report successful loading of a module.
122   void ReportLoadSuccess(uint64_t loaded_bytes, uint64_t total_bytes);
123   // Report an error that was encountered while loading a module.
124   void ReportLoadError(const ErrorInfo& error_info);
125   // Report loading a module was aborted, typically due to user action.
126   void ReportLoadAbort();
127
128   // Dispatch a JavaScript event to indicate a key step in loading.
129   // |event_type| is a character string indicating which type of progress
130   // event (loadstart, progress, error, abort, load, loadend).  Events are
131   // enqueued on the JavaScript event loop, which then calls back through
132   // DispatchProgressEvent.
133   void EnqueueProgressEvent(PP_NaClEventType event_type,
134                             const nacl::string& url,
135                             LengthComputable length_computable,
136                             uint64_t loaded_bytes,
137                             uint64_t total_bytes);
138
139   // Report the error code that sel_ldr produces when starting a nexe.
140   void ReportSelLdrLoadStatus(int status);
141
142   nacl::DescWrapperFactory* wrapper_factory() const { return wrapper_factory_; }
143
144   // Requests a NaCl manifest download from a |url| relative to the page origin.
145   void RequestNaClManifest(const nacl::string& url);
146
147   // Called back by CallOnMainThread.  Dispatches the first enqueued progress
148   // event.
149   void DispatchProgressEvent(int32_t result);
150
151   // Requests a URL asynchronously resulting in a call to pp_callback with
152   // a PP_Error indicating status. On success an open file descriptor
153   // corresponding to the url body is recorded for further lookup.
154   bool StreamAsFile(const nacl::string& url,
155                     const pp::CompletionCallback& callback);
156
157   // Returns rich information for a file retrieved by StreamAsFile(). This info
158   // contains a file descriptor. The caller must take ownership of this
159   // descriptor.
160   struct NaClFileInfo GetFileInfo(const nacl::string& url);
161
162   // A helper function that indicates if |url| can be requested by the document
163   // under the same-origin policy. Strictly speaking, it may be possible for the
164   // document to request the URL using CORS even if this function returns false.
165   bool DocumentCanRequest(const std::string& url);
166
167   // set_exit_status may be called off the main thread.
168   void set_exit_status(int exit_status);
169
170   const PPB_NaCl_Private* nacl_interface() const { return nacl_interface_; }
171   pp::UMAPrivate& uma_interface() { return uma_interface_; }
172
173  private:
174   NACL_DISALLOW_COPY_AND_ASSIGN(Plugin);
175   // The browser will invoke the destructor via the pp::Instance
176   // pointer to this object, not from base's Delete().
177   ~Plugin();
178
179   // Shuts down socket connection, service runtime, and receive thread,
180   // in this order, for the main nacl subprocess.
181   void ShutDownSubprocesses();
182
183   // Access the service runtime for the main NaCl subprocess.
184   ServiceRuntime* main_service_runtime() const {
185     return main_subprocess_.service_runtime();
186   }
187
188   // Histogram helper functions, internal to Plugin so they can use
189   // uma_interface_ normally.
190   void HistogramTimeSmall(const std::string& name, int64_t ms);
191   void HistogramTimeMedium(const std::string& name, int64_t ms);
192   void HistogramTimeLarge(const std::string& name, int64_t ms);
193   void HistogramSizeKB(const std::string& name, int32_t sample);
194   void HistogramEnumerate(const std::string& name,
195                           int sample,
196                           int maximum,
197                           int out_of_range_replacement);
198   void HistogramEnumerateLoadStatus(PP_NaClError error_code);
199   void HistogramEnumerateSelLdrLoadStatus(NaClErrorCode error_code);
200   void HistogramHTTPStatusCode(const std::string& name, int status);
201
202   // Load a nacl module from the file specified in wrapper.
203   // Only to be used from a background (non-main) thread.
204   // This will fully initialize the |subprocess| if the load was successful.
205   bool LoadNaClModuleFromBackgroundThread(nacl::DescWrapper* wrapper,
206                                           NaClSubprocess* subprocess,
207                                           int32_t manifest_id,
208                                           const SelLdrStartParams& params);
209
210   // Start sel_ldr from the main thread, given the start params.
211   // |pp_error| is set by CallOnMainThread (should be PP_OK).
212   void StartSelLdrOnMainThread(int32_t pp_error,
213                                ServiceRuntime* service_runtime,
214                                const SelLdrStartParams& params,
215                                pp::CompletionCallback callback);
216
217   // Signals that StartSelLdr has finished.
218   void SignalStartSelLdrDone(int32_t pp_error,
219                              bool* started,
220                              ServiceRuntime* service_runtime);
221
222   void LoadNexeAndStart(int32_t pp_error,
223                         nacl::DescWrapper* wrapper,
224                         ServiceRuntime* service_runtime,
225                         const pp::CompletionCallback& crash_cb);
226
227   // Callback used when getting the URL for the .nexe file.  If the URL loading
228   // is successful, the file descriptor is opened and can be passed to sel_ldr
229   // with the sandbox on.
230   void NexeFileDidOpen(int32_t pp_error);
231   void NexeFileDidOpenContinuation(int32_t pp_error);
232
233   // Callback used when the reverse channel closes.  This is an
234   // asynchronous event that might turn into a JavaScript error or
235   // crash event -- this is controlled by the two state variables
236   // nacl_ready_state_ and nexe_error_reported_: If an error or crash
237   // had already been reported, no additional crash event is
238   // generated.  If no error has been reported but nacl_ready_state_
239   // is not DONE, then the loadend event has not been reported, and we
240   // enqueue an error event followed by loadend.  If nacl_ready_state_
241   // is DONE, then we are in the post-loadend (we need temporal
242   // predicate symbols), and we enqueue a crash event.
243   void NexeDidCrash(int32_t pp_error);
244
245   // Callback used when a .nexe is translated from bitcode.  If the translation
246   // is successful, the file descriptor is opened and can be passed to sel_ldr
247   // with the sandbox on.
248   void BitcodeDidTranslate(int32_t pp_error);
249   void BitcodeDidTranslateContinuation(int32_t pp_error);
250
251   // NaCl ISA selection manifest file support.  The manifest file is specified
252   // using the "nacl" attribute in the <embed> tag.  First, the manifest URL (or
253   // data: URI) is fetched, then the JSON is parsed.  Once a valid .nexe is
254   // chosen for the sandbox ISA, any current service runtime is shut down, the
255   // .nexe is loaded and run.
256
257   // Callback used when getting the manifest file as a local file descriptor.
258   void NaClManifestFileDidOpen(int32_t pp_error);
259
260   // Processes the JSON manifest string and starts loading the nexe.
261   void ProcessNaClManifest(const nacl::string& manifest_json);
262
263   // Parses the JSON in |manifest_json| and retains a Manifest in
264   // |manifest_| for use by subsequent resource lookups.
265   // On success, |true| is returned and |manifest_| is updated to
266   // contain a Manifest that is used by SelectNexeURLFromManifest.
267   // On failure, |false| is returned, and |manifest_| is unchanged.
268   bool SetManifestObject(const nacl::string& manifest_json);
269
270   // Logs timing information to a UMA histogram, and also logs the same timing
271   // information divided by the size of the nexe to another histogram.
272   void HistogramStartupTimeSmall(const std::string& name, float dt);
273   void HistogramStartupTimeMedium(const std::string& name, float dt);
274
275   // Callback used when loading a URL for SRPC-based StreamAsFile().
276   void UrlDidOpenForStreamAsFile(int32_t pp_error,
277                                  FileDownloader* url_downloader,
278                                  pp::CompletionCallback pp_callback);
279
280   // Open an app file by requesting a file descriptor from the browser. This
281   // method first checks that the url is for an installed file before making the
282   // request so it won't slow down non-installed file downloads.
283   bool OpenURLFast(const nacl::string& url, FileDownloader* downloader);
284
285   void SetExitStatusOnMainThread(int32_t pp_error, int exit_status);
286
287   // Keep track of the NaCl module subprocess that was spun up in the plugin.
288   NaClSubprocess main_subprocess_;
289
290   bool uses_nonsfi_mode_;
291
292   nacl::DescWrapperFactory* wrapper_factory_;
293
294   // File download support.  |nexe_downloader_| can be opened with a specific
295   // callback to run when the file has been downloaded and is opened for
296   // reading.  We use one downloader for all URL downloads to prevent issuing
297   // multiple GETs that might arrive out of order.  For example, this will
298   // prevent a GET of a NaCl manifest while a .nexe GET is pending.  Note that
299   // this will also prevent simultaneous handling of multiple .nexes on a page.
300   FileDownloader nexe_downloader_;
301   pp::CompletionCallbackFactory<Plugin> callback_factory_;
302
303   nacl::scoped_ptr<PnaclCoordinator> pnacl_coordinator_;
304
305   // Keep track of the FileDownloaders created to fetch urls.
306   std::set<FileDownloader*> url_downloaders_;
307   // Keep track of file descriptors opened by StreamAsFile().
308   // These are owned by the browser.
309   std::map<nacl::string, NaClFileInfoAutoCloser*> url_file_info_map_;
310
311   // Callback to receive .nexe and .dso download progress notifications.
312   static void UpdateDownloadProgress(
313       PP_Instance pp_instance,
314       PP_Resource pp_resource,
315       int64_t bytes_sent,
316       int64_t total_bytes_to_be_sent,
317       int64_t bytes_received,
318       int64_t total_bytes_to_be_received);
319
320   // Finds the file downloader which owns the given URL loader. This is used
321   // in UpdateDownloadProgress to map a url loader back to the URL being
322   // downloaded.
323   const FileDownloader* FindFileDownloader(PP_Resource url_loader) const;
324
325   int64_t time_of_last_progress_event_;
326   int exit_status_;
327
328   // Open times are in microseconds.
329   int64_t nexe_open_time_;
330
331   PP_Var manifest_data_var_;
332   int32_t manifest_id_;
333
334   const PPB_NaCl_Private* nacl_interface_;
335   pp::UMAPrivate uma_interface_;
336 };
337
338 }  // namespace plugin
339
340 #endif  // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PLUGIN_H_