Chromium Code Reviews| 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 operations blocks. That's bad because this is the |
|
Derek Schuff
2015/05/08 22:45:59
this operation, or these operations
jvoung (off chromium)
2015/05/08 23:59:31
Done.
| |
| 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 |