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 <string>
15
16#include "native_client/src/include/nacl_macros.h"
17#include "native_client/src/include/nacl_scoped_ptr.h"
18
19#include "ppapi/c/private/ppb_nacl_private.h"
20#include "ppapi/cpp/instance.h"
21#include "ppapi/cpp/private/uma_private.h"
22#include "ppapi/cpp/url_loader.h"
23#include "ppapi/cpp/var.h"
24#include "ppapi/cpp/view.h"
25
26#include "ppapi/native_client/src/trusted/plugin/nacl_subprocess.h"
27#include "ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h"
28#include "ppapi/native_client/src/trusted/plugin/service_runtime.h"
29#include "ppapi/native_client/src/trusted/plugin/utility.h"
30
31#include "ppapi/utility/completion_callback_factory.h"
32
33namespace nacl {
34class DescWrapper;
35class DescWrapperFactory;
36}  // namespace nacl
37
38namespace pp {
39class CompletionCallback;
40class URLLoader;
41class URLUtil_Dev;
42}
43
44namespace plugin {
45
46class ErrorInfo;
47class Manifest;
48
49int32_t ConvertFileDescriptor(PP_FileHandle handle);
50
51const PP_NaClFileInfo kInvalidNaClFileInfo = {
52  PP_kInvalidFileHandle,
53  0,  // token_lo
54  0,  // token_hi
55};
56
57class Plugin : public pp::Instance {
58 public:
59  explicit Plugin(PP_Instance instance);
60
61  // ----- Methods inherited from pp::Instance:
62
63  // Initializes this plugin with <embed/object ...> tag attribute count |argc|,
64  // names |argn| and values |argn|. Returns false on failure.
65  // Gets called by the browser right after New().
66  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
67
68  // Handles document load, when the plugin is a MIME type handler.
69  virtual bool HandleDocumentLoad(const pp::URLLoader& url_loader);
70
71  // Load support.
72  //
73  // Starts NaCl module but does not wait until low-level
74  // initialization (e.g. ld.so dynamic loading of manifest files) is
75  // done.  The module will become ready later, asynchronously.  Other
76  // event handlers should block until the module is ready before
77  // trying to communicate with it, i.e., until nacl_ready_state is
78  // DONE.
79  //
80  // NB: currently we do not time out, so if the untrusted code
81  // does not signal that it is ready, then we will deadlock the main
82  // thread of the renderer on this subsequent event delivery.  We
83  // should include a time-out at which point we declare the
84  // nacl_ready_state to be done, and let the normal crash detection
85  // mechanism(s) take over.
86  void LoadNaClModule(PP_NaClFileInfo file_info,
87                      bool uses_nonsfi_mode,
88                      bool enable_dyncode_syscalls,
89                      bool enable_exception_handling,
90                      bool enable_crash_throttling,
91                      const pp::CompletionCallback& init_done_cb);
92
93  // Finish hooking interfaces up, after low-level initialization is
94  // complete.
95  bool LoadNaClModuleContinuationIntern();
96
97  // Continuation for starting SRPC/JSProxy services as appropriate.
98  // This is invoked as a callback when the NaCl module makes the
99  // init_done reverse RPC to tell us that low-level initialization
100  // such as ld.so processing is done.  That initialization requires
101  // that the main thread be free in order to do Pepper
102  // main-thread-only operations such as file processing.
103  bool LoadNaClModuleContinuation(int32_t pp_error);
104
105  // Load support.
106  // A helper SRPC NaCl module can be loaded given a PP_NaClFileInfo.
107  // Blocks until the helper module signals initialization is done.
108  // Does not update nacl_module_origin().
109  // Returns NULL or the NaClSubprocess of the new helper NaCl module.
110  NaClSubprocess* LoadHelperNaClModule(const std::string& helper_url,
111                                       PP_NaClFileInfo file_info,
112                                       ErrorInfo* error_info);
113
114  // Report an error that was encountered while loading a module.
115  void ReportLoadError(const ErrorInfo& error_info);
116
117  nacl::DescWrapperFactory* wrapper_factory() const { return wrapper_factory_; }
118
119  const PPB_NaCl_Private* nacl_interface() const { return nacl_interface_; }
120  pp::UMAPrivate& uma_interface() { return uma_interface_; }
121
122 private:
123  NACL_DISALLOW_COPY_AND_ASSIGN(Plugin);
124  // The browser will invoke the destructor via the pp::Instance
125  // pointer to this object, not from base's Delete().
126  ~Plugin();
127
128  // Shuts down socket connection, service runtime, and receive thread,
129  // in this order, for the main nacl subprocess.
130  void ShutDownSubprocesses();
131
132  // Histogram helper functions, internal to Plugin so they can use
133  // uma_interface_ normally.
134  void HistogramTimeSmall(const std::string& name, int64_t ms);
135
136  // Loads and starts a helper (e.g. llc, ld) NaCl module.
137  // Only to be used from a background (non-main) thread for the PNaCl
138  // translator. This will fully initialize the |subprocess| if the load was
139  // successful.
140  bool LoadHelperNaClModuleInternal(NaClSubprocess* subprocess,
141                                    const SelLdrStartParams& params);
142
143  // Start sel_ldr from the main thread, given the start params.
144  // |pp_error| is set by CallOnMainThread (should be PP_OK).
145  void StartSelLdrOnMainThread(int32_t pp_error,
146                               ServiceRuntime* service_runtime,
147                               const SelLdrStartParams& params,
148                               pp::CompletionCallback callback);
149
150  // Signals that StartSelLdr has finished.
151  // This is invoked on the main thread.
152  void SignalStartSelLdrDone(int32_t pp_error,
153                             bool* started,
154                             ServiceRuntime* service_runtime);
155
156  // This is invoked on the main thread.
157  void StartNexe(int32_t pp_error, ServiceRuntime* service_runtime);
158
159  // Callback used when getting the URL for the .nexe file.  If the URL loading
160  // is successful, the file descriptor is opened and can be passed to sel_ldr
161  // with the sandbox on.
162  void NexeFileDidOpen(int32_t pp_error);
163  void NexeFileDidOpenContinuation(int32_t pp_error);
164
165  // Callback used when a .nexe is translated from bitcode.  If the translation
166  // is successful, the file descriptor is opened and can be passed to sel_ldr
167  // with the sandbox on.
168  void BitcodeDidTranslate(int32_t pp_error);
169  void BitcodeDidTranslateContinuation(int32_t pp_error);
170
171  // NaCl ISA selection manifest file support.  The manifest file is specified
172  // using the "nacl" attribute in the <embed> tag.  First, the manifest URL (or
173  // data: URI) is fetched, then the JSON is parsed.  Once a valid .nexe is
174  // chosen for the sandbox ISA, any current service runtime is shut down, the
175  // .nexe is loaded and run.
176
177  // Callback used when getting the manifest file as a local file descriptor.
178  void NaClManifestFileDidOpen(int32_t pp_error);
179
180  // Processes the JSON manifest string and starts loading the nexe.
181  void ProcessNaClManifest(const std::string& manifest_json);
182
183  // Keep track of the NaCl module subprocess that was spun up in the plugin.
184  NaClSubprocess main_subprocess_;
185
186  bool uses_nonsfi_mode_;
187
188  nacl::DescWrapperFactory* wrapper_factory_;
189
190  pp::CompletionCallbackFactory<Plugin> callback_factory_;
191
192  nacl::scoped_ptr<PnaclCoordinator> pnacl_coordinator_;
193
194  int exit_status_;
195
196  PP_NaClFileInfo nexe_file_info_;
197
198  const PPB_NaCl_Private* nacl_interface_;
199  pp::UMAPrivate uma_interface_;
200};
201
202}  // namespace plugin
203
204#endif  // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PLUGIN_H_
205