OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/nacl/renderer/plugin/plugin.h" | 5 #include "components/nacl/renderer/plugin/plugin.h" |
6 | 6 |
7 #include <sys/stat.h> | 7 #include <sys/stat.h> |
8 #include <sys/types.h> | 8 #include <sys/types.h> |
9 | 9 |
10 #include <string> | 10 #include <string> |
(...skipping 20 matching lines...) Expand all Loading... |
31 static_cast<void*>(this))); | 31 static_cast<void*>(this))); |
32 | 32 |
33 // Shut down service runtime. This must be done before all other calls so | 33 // Shut down service runtime. This must be done before all other calls so |
34 // they don't block forever when waiting for the upcall thread to exit. | 34 // they don't block forever when waiting for the upcall thread to exit. |
35 main_subprocess_.Shutdown(); | 35 main_subprocess_.Shutdown(); |
36 | 36 |
37 PLUGIN_PRINTF(("Plugin::ShutDownSubprocess (this=%p, return)\n", | 37 PLUGIN_PRINTF(("Plugin::ShutDownSubprocess (this=%p, return)\n", |
38 static_cast<void*>(this))); | 38 static_cast<void*>(this))); |
39 } | 39 } |
40 | 40 |
41 bool Plugin::LoadHelperNaClModuleInternal(NaClSubprocess* subprocess, | 41 void Plugin::StartSelLdr(ServiceRuntime* service_runtime, |
42 const SelLdrStartParams& params) { | 42 const SelLdrStartParams& params, |
43 CHECK(!pp::Module::Get()->core()->IsMainThread()); | 43 pp::CompletionCallback callback) { |
44 ServiceRuntime* service_runtime = | |
45 new ServiceRuntime(this, | |
46 pp_instance(), | |
47 false, // No main_service_runtime. | |
48 false); // No non-SFI mode (i.e. in SFI-mode). | |
49 | |
50 // Now start the SelLdr instance. This must be created on the main thread. | |
51 bool service_runtime_started = false; | |
52 pp::CompletionCallback sel_ldr_callback = | |
53 callback_factory_.NewCallback(&Plugin::SignalStartSelLdrDone, | |
54 &service_runtime_started, | |
55 service_runtime); | |
56 pp::CompletionCallback callback = | |
57 callback_factory_.NewCallback(&Plugin::StartSelLdrOnMainThread, | |
58 service_runtime, params, | |
59 sel_ldr_callback); | |
60 pp::Module::Get()->core()->CallOnMainThread(0, callback, 0); | |
61 if (!service_runtime->WaitForSelLdrStart()) { | |
62 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule " | |
63 "WaitForSelLdrStart timed out!\n")); | |
64 service_runtime->Shutdown(); | |
65 // Don't delete service_runtime here; it could still be used by the pending | |
66 // SignalStartSelLdrDone callback. | |
67 return false; | |
68 } | |
69 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule (service_runtime_started=%d)\n", | |
70 service_runtime_started)); | |
71 if (!service_runtime_started) { | |
72 service_runtime->Shutdown(); | |
73 delete service_runtime; | |
74 return false; | |
75 } | |
76 | |
77 // Now actually start the nexe. | |
78 // | |
79 // We can't use pp::BlockUntilComplete() inside an in-process plugin, so we | |
80 // have to roll our own blocking logic, similar to WaitForSelLdrStart() | |
81 // above, except without timeout logic. | |
82 pp::Module::Get()->core()->CallOnMainThread( | |
83 0, | |
84 callback_factory_.NewCallback(&Plugin::StartNexe, service_runtime)); | |
85 if (!service_runtime->WaitForNexeStart()) { | |
86 service_runtime->Shutdown(); | |
87 delete service_runtime; | |
88 return false; | |
89 } | |
90 subprocess->set_service_runtime(service_runtime); | |
91 return true; | |
92 } | |
93 | |
94 void Plugin::StartSelLdrOnMainThread(int32_t pp_error, | |
95 ServiceRuntime* service_runtime, | |
96 const SelLdrStartParams& params, | |
97 pp::CompletionCallback callback) { | |
98 CHECK(pp_error == PP_OK); | |
99 service_runtime->StartSelLdr(params, callback); | 44 service_runtime->StartSelLdr(params, callback); |
100 } | 45 } |
101 | 46 |
102 void Plugin::SignalStartSelLdrDone(int32_t pp_error, | |
103 bool* started, | |
104 ServiceRuntime* service_runtime) { | |
105 if (service_runtime->SelLdrWaitTimedOut()) { | |
106 delete service_runtime; | |
107 } else { | |
108 *started = (pp_error == PP_OK); | |
109 service_runtime->SignalStartSelLdrDone(); | |
110 } | |
111 } | |
112 | |
113 void Plugin::LoadNaClModule(PP_NaClFileInfo file_info, | 47 void Plugin::LoadNaClModule(PP_NaClFileInfo file_info, |
114 bool uses_nonsfi_mode, | 48 bool uses_nonsfi_mode, |
115 PP_NaClAppProcessType process_type) { | 49 PP_NaClAppProcessType process_type) { |
116 CHECK(pp::Module::Get()->core()->IsMainThread()); | 50 CHECK(pp::Module::Get()->core()->IsMainThread()); |
117 // Before forking a new sel_ldr process, ensure that we do not leak | 51 // Before forking a new sel_ldr process, ensure that we do not leak |
118 // the ServiceRuntime object for an existing subprocess, and that any | 52 // the ServiceRuntime object for an existing subprocess, and that any |
119 // associated listener threads do not go unjoined because if they | 53 // associated listener threads do not go unjoined because if they |
120 // outlive the Plugin object, they will not be memory safe. | 54 // outlive the Plugin object, they will not be memory safe. |
121 ShutDownSubprocesses(); | 55 ShutDownSubprocesses(); |
122 pp::Var manifest_base_url = | 56 pp::Var manifest_base_url = |
(...skipping 12 matching lines...) Expand all Loading... |
135 PP_NACL_ERROR_SEL_LDR_INIT, | 69 PP_NACL_ERROR_SEL_LDR_INIT, |
136 "sel_ldr init failure " + main_subprocess_.description()); | 70 "sel_ldr init failure " + main_subprocess_.description()); |
137 ReportLoadError(error_info); | 71 ReportLoadError(error_info); |
138 return; | 72 return; |
139 } | 73 } |
140 | 74 |
141 // We don't take any action once nexe loading has completed, so pass an empty | 75 // We don't take any action once nexe loading has completed, so pass an empty |
142 // callback here for |callback|. | 76 // callback here for |callback|. |
143 pp::CompletionCallback callback = callback_factory_.NewCallback( | 77 pp::CompletionCallback callback = callback_factory_.NewCallback( |
144 &Plugin::StartNexe, service_runtime); | 78 &Plugin::StartNexe, service_runtime); |
145 StartSelLdrOnMainThread( | 79 StartSelLdr(service_runtime, params, callback); |
146 static_cast<int32_t>(PP_OK), service_runtime, params, callback); | |
147 } | 80 } |
148 | 81 |
149 void Plugin::StartNexe(int32_t pp_error, ServiceRuntime* service_runtime) { | 82 void Plugin::StartNexe(int32_t pp_error, ServiceRuntime* service_runtime) { |
150 CHECK(pp::Module::Get()->core()->IsMainThread()); | 83 CHECK(pp::Module::Get()->core()->IsMainThread()); |
151 if (pp_error != PP_OK) | 84 if (pp_error != PP_OK) |
152 return; | 85 return; |
153 service_runtime->StartNexe(); | 86 service_runtime->StartNexe(); |
154 } | 87 } |
155 | 88 |
156 NaClSubprocess* Plugin::LoadHelperNaClModule(const std::string& helper_url, | 89 void Plugin::LoadHelperNaClModule(const std::string& helper_url, |
157 PP_NaClFileInfo file_info, | 90 PP_NaClFileInfo file_info, |
158 ErrorInfo* error_info) { | 91 NaClSubprocess* subprocess_to_init, |
159 nacl::scoped_ptr<NaClSubprocess> nacl_subprocess( | 92 pp::CompletionCallback callback) { |
160 new NaClSubprocess("helper module", NULL, NULL)); | 93 CHECK(pp::Module::Get()->core()->IsMainThread()); |
161 if (NULL == nacl_subprocess.get()) { | |
162 error_info->SetReport(PP_NACL_ERROR_SEL_LDR_INIT, | |
163 "unable to allocate helper subprocess."); | |
164 return NULL; | |
165 } | |
166 | |
167 // Do not report UMA stats for translator-related nexes. | 94 // Do not report UMA stats for translator-related nexes. |
168 // TODO(sehr): define new UMA stats for translator related nexe events. | 95 // TODO(sehr): define new UMA stats for translator related nexe events. |
169 // NOTE: The PNaCl translator nexes are not built to use the IRT. This is | |
170 // done to save on address space and swap space. | |
171 SelLdrStartParams params(helper_url, | 96 SelLdrStartParams params(helper_url, |
172 file_info, | 97 file_info, |
173 PP_PNACL_TRANSLATOR_PROCESS_TYPE); | 98 PP_PNACL_TRANSLATOR_PROCESS_TYPE); |
| 99 ServiceRuntime* service_runtime = |
| 100 new ServiceRuntime(this, pp_instance(), |
| 101 false, // Not main_service_runtime. |
| 102 false); // No non-SFI mode (i.e. in SFI-mode). |
| 103 subprocess_to_init->set_service_runtime(service_runtime); |
| 104 pp::CompletionCallback sel_ldr_callback = callback_factory_.NewCallback( |
| 105 &Plugin::StartHelperNexe, subprocess_to_init, callback); |
| 106 StartSelLdr(service_runtime, params, sel_ldr_callback); |
| 107 } |
174 | 108 |
175 // Helper NaCl modules always use the PNaCl manifest, as there is no | 109 void Plugin::StartHelperNexe(int32_t pp_error, |
176 // corresponding NMF. | 110 NaClSubprocess* subprocess_to_init, |
177 if (!LoadHelperNaClModuleInternal(nacl_subprocess.get(), params)) | 111 pp::CompletionCallback callback) { |
178 return NULL; | 112 CHECK(pp::Module::Get()->core()->IsMainThread()); |
179 | 113 if (pp_error != PP_OK) { |
180 // We can block here in StartSrpcServices, since helper NaCl | 114 callback.RunAndClear(pp_error); |
181 // modules are spawned from a private thread. | 115 return; |
182 // | |
183 // TODO(bsy): if helper module crashes, we should abort. | |
184 // crash_cb is not used here, so we are relying on crashes | |
185 // being detected in StartSrpcServices or later. | |
186 // | |
187 // NB: More refactoring might be needed, however, if helper | |
188 // NaCl modules have their own manifest. Currently the | |
189 // manifest is a per-plugin-instance object, not a per | |
190 // NaClSubprocess object. | |
191 if (!nacl_subprocess->StartSrpcServices()) { | |
192 error_info->SetReport(PP_NACL_ERROR_SRPC_CONNECTION_FAIL, | |
193 "SRPC connection failure for " + | |
194 nacl_subprocess->description()); | |
195 return NULL; | |
196 } | 116 } |
197 | 117 // TODO(jvoung): This operation blocks. That's bad because this is the |
198 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule (%s, %s)\n", | 118 // main thread. However, we could make it so that StartHelperNexe isn't |
199 helper_url.c_str(), | 119 // called until the blocking is minimized. There is a hook in |
200 nacl_subprocess.get()->detailed_description().c_str())); | 120 // sel_main_chrome which indicates when the nexe load is done. If we hook |
201 | 121 // up that hook to StartSelLdr's callback, then we'll only |
202 return nacl_subprocess.release(); | 122 // call StartNexe once the nexe load is done instead of blocking here |
| 123 // until the nexe load is done. |
| 124 subprocess_to_init->service_runtime()->StartNexe(); |
| 125 callback.RunAndClear(PP_OK); |
203 } | 126 } |
204 | 127 |
205 // All failures of this function will show up as "Missing Plugin-in", so | 128 // All failures of this function will show up as "Missing Plugin-in", so |
206 // there is no need to log to JS console that there was an initialization | 129 // there is no need to log to JS console that there was an initialization |
207 // failure. Note that module loading functions will log their own errors. | 130 // failure. Note that module loading functions will log their own errors. |
208 bool Plugin::Init(uint32_t argc, const char* argn[], const char* argv[]) { | 131 bool Plugin::Init(uint32_t argc, const char* argn[], const char* argv[]) { |
209 nacl_interface_->InitializePlugin(pp_instance(), argc, argn, argv); | 132 nacl_interface_->InitializePlugin(pp_instance(), argc, argn, argv); |
210 wrapper_factory_ = new nacl::DescWrapperFactory(); | 133 wrapper_factory_ = new nacl::DescWrapperFactory(); |
211 pp::CompletionCallback open_cb = | 134 pp::CompletionCallback open_cb = |
212 callback_factory_.NewCallback(&Plugin::NaClManifestFileDidOpen); | 135 callback_factory_.NewCallback(&Plugin::NaClManifestFileDidOpen); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 } | 264 } |
342 } | 265 } |
343 | 266 |
344 void Plugin::ReportLoadError(const ErrorInfo& error_info) { | 267 void Plugin::ReportLoadError(const ErrorInfo& error_info) { |
345 nacl_interface_->ReportLoadError(pp_instance(), | 268 nacl_interface_->ReportLoadError(pp_instance(), |
346 error_info.error_code(), | 269 error_info.error_code(), |
347 error_info.message().c_str()); | 270 error_info.message().c_str()); |
348 } | 271 } |
349 | 272 |
350 } // namespace plugin | 273 } // namespace plugin |
OLD | NEW |