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 "native_client/src/include/nacl_macros.h"
15#include "native_client/src/include/nacl_scoped_ptr.h"
16#include "native_client/src/shared/platform/nacl_sync.h"
17#include "native_client/src/shared/srpc/nacl_srpc.h"
18#include "native_client/src/trusted/reverse_service/reverse_service.h"
19#include "native_client/src/trusted/weak_ref/weak_ref.h"
20
21#include "ppapi/cpp/completion_callback.h"
22#include "ppapi/native_client/src/trusted/plugin/utility.h"
23
24struct NaClFileInfo;
25
26namespace plugin {
27
28class ErrorInfo;
29class Plugin;
30class SelLdrLauncherChrome;
31class SrpcClient;
32class ServiceRuntime;
33
34// Struct of params used by StartSelLdr.  Use a struct so that callback
35// creation templates aren't overwhelmed with too many parameters.
36struct SelLdrStartParams {
37  SelLdrStartParams(const std::string& url,
38                    const PP_NaClFileInfo& file_info,
39                    bool uses_irt,
40                    bool uses_ppapi,
41                    bool enable_dyncode_syscalls,
42                    bool enable_exception_handling,
43                    bool enable_crash_throttling)
44      : url(url),
45        file_info(file_info),
46        uses_irt(uses_irt),
47        uses_ppapi(uses_ppapi),
48        enable_dyncode_syscalls(enable_dyncode_syscalls),
49        enable_exception_handling(enable_exception_handling),
50        enable_crash_throttling(enable_crash_throttling) {
51  }
52  std::string url;
53  PP_NaClFileInfo file_info;
54  bool uses_irt;
55  bool uses_ppapi;
56  bool enable_dev_interfaces;
57  bool enable_dyncode_syscalls;
58  bool enable_exception_handling;
59  bool enable_crash_throttling;
60};
61
62// Callback resources are essentially our continuation state.
63struct OpenManifestEntryResource {
64 public:
65  OpenManifestEntryResource(const std::string& target_url,
66                            struct NaClFileInfo* finfo,
67                            bool* op_complete)
68      : url(target_url),
69        file_info(finfo),
70        op_complete_ptr(op_complete) {}
71  ~OpenManifestEntryResource();
72
73  std::string url;
74  struct NaClFileInfo* file_info;
75  PP_NaClFileInfo pp_file_info;
76  bool* op_complete_ptr;
77};
78
79// Do not invoke from the main thread, since the main methods will
80// invoke CallOnMainThread and then wait on a condvar for the task to
81// complete: if invoked from the main thread, the main method not
82// returning (and thus unblocking the main thread) means that the
83// main-thread continuation methods will never get called, and thus
84// we'd get a deadlock.
85class PluginReverseInterface: public nacl::ReverseInterface {
86 public:
87  PluginReverseInterface(nacl::WeakRefAnchor* anchor,
88                         PP_Instance pp_instance,
89                         ServiceRuntime* service_runtime,
90                         pp::CompletionCallback init_done_cb);
91
92  virtual ~PluginReverseInterface();
93
94  void ShutDown();
95
96  virtual void DoPostMessage(std::string message);
97
98  virtual void StartupInitializationComplete();
99
100  virtual bool OpenManifestEntry(std::string url_key,
101                                 struct NaClFileInfo *info);
102
103  virtual void ReportCrash();
104
105  virtual void ReportExitStatus(int exit_status);
106
107  // TODO(teravest): Remove this method once it's gone from
108  // nacl::ReverseInterface.
109  virtual int64_t RequestQuotaForWrite(std::string file_id,
110                                       int64_t offset,
111                                       int64_t bytes_to_write);
112
113 protected:
114  virtual void OpenManifestEntry_MainThreadContinuation(
115      OpenManifestEntryResource* p,
116      int32_t err);
117
118  virtual void StreamAsFile_MainThreadContinuation(
119      OpenManifestEntryResource* p,
120      int32_t result);
121
122 private:
123  nacl::WeakRefAnchor* anchor_;  // holds a ref
124  // Should be used only in main thread in WeakRef-protected callbacks.
125  PP_Instance pp_instance_;
126  ServiceRuntime* service_runtime_;
127  NaClMutex mu_;
128  NaClCondVar cv_;
129  bool shutting_down_;
130
131  pp::CompletionCallback init_done_cb_;
132};
133
134//  ServiceRuntime abstracts a NativeClient sel_ldr instance.
135class ServiceRuntime {
136 public:
137  ServiceRuntime(Plugin* plugin,
138                 PP_Instance pp_instance,
139                 bool main_service_runtime,
140                 bool uses_nonsfi_mode,
141                 pp::CompletionCallback init_done_cb);
142  // The destructor terminates the sel_ldr process.
143  ~ServiceRuntime();
144
145  // Spawn the sel_ldr instance.
146  void StartSelLdr(const SelLdrStartParams& params,
147                   pp::CompletionCallback callback);
148
149  // If starting sel_ldr from a background thread, wait for sel_ldr to
150  // actually start. Returns |false| if timed out waiting for the process
151  // to start. Otherwise, returns |true| if StartSelLdr is complete
152  // (either successfully or unsuccessfully).
153  bool WaitForSelLdrStart();
154
155  // Signal to waiting threads that StartSelLdr is complete (either
156  // successfully or unsuccessfully).
157  void SignalStartSelLdrDone();
158
159  // If starting the nexe from a background thread, wait for the nexe to
160  // actually start. Returns |true| is the nexe started successfully.
161  bool WaitForNexeStart();
162
163  // Signal to waiting threads that LoadNexeAndStart is complete (either
164  // successfully or unsuccessfully).
165  void SignalNexeStarted(bool ok);
166
167  // Establish an SrpcClient to the sel_ldr instance and start the nexe.
168  // This function must be called on the main thread.
169  // This function must only be called once.
170  void StartNexe();
171
172  // Starts the application channel to the nexe.
173  SrpcClient* SetupAppChannel();
174
175  bool RemoteLog(int severity, const std::string& msg);
176  Plugin* plugin() const { return plugin_; }
177  void Shutdown();
178
179  bool main_service_runtime() const { return main_service_runtime_; }
180
181 private:
182  NACL_DISALLOW_COPY_AND_ASSIGN(ServiceRuntime);
183  bool StartNexeInternal();
184
185  bool SetupCommandChannel();
186  bool InitReverseService();
187  bool StartModule();
188  void ReapLogs();
189
190  void ReportLoadError(const ErrorInfo& error_info);
191
192  NaClSrpcChannel command_channel_;
193  Plugin* plugin_;
194  PP_Instance pp_instance_;
195  bool main_service_runtime_;
196  bool uses_nonsfi_mode_;
197  nacl::ReverseService* reverse_service_;
198  nacl::scoped_ptr<SelLdrLauncherChrome> subprocess_;
199
200  nacl::WeakRefAnchor* anchor_;
201
202  PluginReverseInterface* rev_interface_;
203
204  // Mutex and CondVar to protect start_sel_ldr_done_ and nexe_started_.
205  NaClMutex mu_;
206  NaClCondVar cond_;
207  bool start_sel_ldr_done_;
208  bool start_nexe_done_;
209  bool nexe_started_ok_;
210
211  NaClHandle bootstrap_channel_;
212};
213
214}  // namespace plugin
215
216#endif  // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
217