xref: /aosp_15_r20/external/cronet/components/nacl/renderer/plugin/plugin.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "components/nacl/renderer/plugin/plugin.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <sys/stat.h>
8*6777b538SAndroid Build Coastguard Worker #include <sys/types.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <string>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
13*6777b538SAndroid Build Coastguard Worker #include "components/nacl/renderer/plugin/nacl_subprocess.h"
14*6777b538SAndroid Build Coastguard Worker #include "components/nacl/renderer/plugin/plugin_error.h"
15*6777b538SAndroid Build Coastguard Worker #include "components/nacl/renderer/plugin/service_runtime.h"
16*6777b538SAndroid Build Coastguard Worker #include "components/nacl/renderer/ppb_nacl_private.h"
17*6777b538SAndroid Build Coastguard Worker #include "ppapi/c/pp_errors.h"
18*6777b538SAndroid Build Coastguard Worker #include "ppapi/cpp/module.h"
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker namespace {
21*6777b538SAndroid Build Coastguard Worker 
NoOpCallback(void * user_data,int32_t result)22*6777b538SAndroid Build Coastguard Worker void NoOpCallback(void* user_data, int32_t result) {
23*6777b538SAndroid Build Coastguard Worker }
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker }
26*6777b538SAndroid Build Coastguard Worker 
27*6777b538SAndroid Build Coastguard Worker namespace plugin {
28*6777b538SAndroid Build Coastguard Worker 
ShutDownSubprocesses()29*6777b538SAndroid Build Coastguard Worker void Plugin::ShutDownSubprocesses() {
30*6777b538SAndroid Build Coastguard Worker   // Shut down service runtime. This must be done before all other calls so
31*6777b538SAndroid Build Coastguard Worker   // they don't block forever when waiting for the upcall thread to exit.
32*6777b538SAndroid Build Coastguard Worker   main_subprocess_.Shutdown();
33*6777b538SAndroid Build Coastguard Worker }
34*6777b538SAndroid Build Coastguard Worker 
LoadNaClModule(PP_NaClFileInfo file_info,PP_NaClAppProcessType process_type)35*6777b538SAndroid Build Coastguard Worker void Plugin::LoadNaClModule(PP_NaClFileInfo file_info,
36*6777b538SAndroid Build Coastguard Worker                             PP_NaClAppProcessType process_type) {
37*6777b538SAndroid Build Coastguard Worker   CHECK(pp::Module::Get()->core()->IsMainThread());
38*6777b538SAndroid Build Coastguard Worker   // Before forking a new sel_ldr process, ensure that we do not leak
39*6777b538SAndroid Build Coastguard Worker   // the ServiceRuntime object for an existing subprocess, and that any
40*6777b538SAndroid Build Coastguard Worker   // associated listener threads do not go unjoined because if they
41*6777b538SAndroid Build Coastguard Worker   // outlive the Plugin object, they will not be memory safe.
42*6777b538SAndroid Build Coastguard Worker   ShutDownSubprocesses();
43*6777b538SAndroid Build Coastguard Worker   pp::Var manifest_base_url =
44*6777b538SAndroid Build Coastguard Worker       pp::Var(pp::PASS_REF,
45*6777b538SAndroid Build Coastguard Worker               nacl::PPBNaClPrivate::GetManifestBaseURL(pp_instance()));
46*6777b538SAndroid Build Coastguard Worker   std::string manifest_base_url_str = manifest_base_url.AsString();
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker   SelLdrStartParams params(manifest_base_url_str,
49*6777b538SAndroid Build Coastguard Worker                            file_info,
50*6777b538SAndroid Build Coastguard Worker                            process_type);
51*6777b538SAndroid Build Coastguard Worker   ErrorInfo error_info;
52*6777b538SAndroid Build Coastguard Worker   ServiceRuntime* service_runtime =
53*6777b538SAndroid Build Coastguard Worker       new ServiceRuntime(this, pp_instance(), /*main_service_runtime=*/true);
54*6777b538SAndroid Build Coastguard Worker   main_subprocess_.set_service_runtime(service_runtime);
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker   service_runtime->StartSelLdr(params,
57*6777b538SAndroid Build Coastguard Worker                                pp::CompletionCallback(NoOpCallback, NULL));
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker 
LoadHelperNaClModule(const std::string & helper_url,PP_NaClFileInfo file_info,NaClSubprocess * subprocess_to_init,pp::CompletionCallback callback)60*6777b538SAndroid Build Coastguard Worker void Plugin::LoadHelperNaClModule(const std::string& helper_url,
61*6777b538SAndroid Build Coastguard Worker                                   PP_NaClFileInfo file_info,
62*6777b538SAndroid Build Coastguard Worker                                   NaClSubprocess* subprocess_to_init,
63*6777b538SAndroid Build Coastguard Worker                                   pp::CompletionCallback callback) {
64*6777b538SAndroid Build Coastguard Worker   CHECK(pp::Module::Get()->core()->IsMainThread());
65*6777b538SAndroid Build Coastguard Worker   // Do not report UMA stats for translator-related nexes.
66*6777b538SAndroid Build Coastguard Worker   // TODO(sehr): define new UMA stats for translator related nexe events.
67*6777b538SAndroid Build Coastguard Worker   SelLdrStartParams params(helper_url,
68*6777b538SAndroid Build Coastguard Worker                            file_info,
69*6777b538SAndroid Build Coastguard Worker                            PP_PNACL_TRANSLATOR_PROCESS_TYPE);
70*6777b538SAndroid Build Coastguard Worker   ServiceRuntime* service_runtime =
71*6777b538SAndroid Build Coastguard Worker       new ServiceRuntime(this, pp_instance(),
72*6777b538SAndroid Build Coastguard Worker                          /*main_service_runtime=*/false);
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker   subprocess_to_init->set_service_runtime(service_runtime);
75*6777b538SAndroid Build Coastguard Worker   service_runtime->StartSelLdr(params, callback);
76*6777b538SAndroid Build Coastguard Worker }
77*6777b538SAndroid Build Coastguard Worker 
78*6777b538SAndroid Build Coastguard Worker // All failures of this function will show up as "Missing Plugin-in", so
79*6777b538SAndroid Build Coastguard Worker // there is no need to log to JS console that there was an initialization
80*6777b538SAndroid Build Coastguard Worker // failure. Note that module loading functions will log their own errors.
Init(uint32_t argc,const char * argn[],const char * argv[])81*6777b538SAndroid Build Coastguard Worker bool Plugin::Init(uint32_t argc, const char* argn[], const char* argv[]) {
82*6777b538SAndroid Build Coastguard Worker   nacl::PPBNaClPrivate::InitializePlugin(pp_instance(), argc, argn, argv);
83*6777b538SAndroid Build Coastguard Worker   pp::CompletionCallback open_cb =
84*6777b538SAndroid Build Coastguard Worker       callback_factory_.NewCallback(&Plugin::NaClManifestFileDidOpen);
85*6777b538SAndroid Build Coastguard Worker   nacl::PPBNaClPrivate::RequestNaClManifest(pp_instance(),
86*6777b538SAndroid Build Coastguard Worker                                             open_cb.pp_completion_callback());
87*6777b538SAndroid Build Coastguard Worker   return true;
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker 
Plugin(PP_Instance pp_instance)90*6777b538SAndroid Build Coastguard Worker Plugin::Plugin(PP_Instance pp_instance)
91*6777b538SAndroid Build Coastguard Worker     : pp::Instance(pp_instance), uma_interface_(this) {
92*6777b538SAndroid Build Coastguard Worker   callback_factory_.Initialize(this);
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker   // Notify PPBNaClPrivate that the instance is created before altering any
95*6777b538SAndroid Build Coastguard Worker   // state that it tracks.
96*6777b538SAndroid Build Coastguard Worker   nacl::PPBNaClPrivate::InstanceCreated(pp_instance);
97*6777b538SAndroid Build Coastguard Worker   nexe_file_info_ = kInvalidNaClFileInfo;
98*6777b538SAndroid Build Coastguard Worker }
99*6777b538SAndroid Build Coastguard Worker 
~Plugin()100*6777b538SAndroid Build Coastguard Worker Plugin::~Plugin() {
101*6777b538SAndroid Build Coastguard Worker   // Destroy the coordinator while the rest of the data is still there
102*6777b538SAndroid Build Coastguard Worker   pnacl_coordinator_.reset(NULL);
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker   nacl::PPBNaClPrivate::InstanceDestroyed(pp_instance());
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker   // ShutDownSubprocesses shuts down the main subprocess, which shuts
107*6777b538SAndroid Build Coastguard Worker   // down the main ServiceRuntime object, which kills the subprocess.
108*6777b538SAndroid Build Coastguard Worker   // As a side effect of the subprocess being killed, the reverse
109*6777b538SAndroid Build Coastguard Worker   // services thread(s) will get EOF on the reverse channel(s), and
110*6777b538SAndroid Build Coastguard Worker   // the thread(s) will exit.  In ServiceRuntime::Shutdown, we invoke
111*6777b538SAndroid Build Coastguard Worker   // ReverseService::WaitForServiceThreadsToExit(), so that there will
112*6777b538SAndroid Build Coastguard Worker   // not be an extent thread(s) hanging around.  This means that the
113*6777b538SAndroid Build Coastguard Worker   // ~Plugin will block until this happens.  This is a requirement,
114*6777b538SAndroid Build Coastguard Worker   // since the renderer should be free to unload the plugin code, and
115*6777b538SAndroid Build Coastguard Worker   // we cannot have threads running code that gets unloaded before
116*6777b538SAndroid Build Coastguard Worker   // they exit.
117*6777b538SAndroid Build Coastguard Worker   //
118*6777b538SAndroid Build Coastguard Worker   // By waiting for the threads here, we also ensure that the Plugin
119*6777b538SAndroid Build Coastguard Worker   // object and the subprocess and ServiceRuntime objects is not
120*6777b538SAndroid Build Coastguard Worker   // (fully) destroyed while the threads are running, so resources
121*6777b538SAndroid Build Coastguard Worker   // that are destroyed after ShutDownSubprocesses (below) are
122*6777b538SAndroid Build Coastguard Worker   // guaranteed to be live and valid for access from the service
123*6777b538SAndroid Build Coastguard Worker   // threads.
124*6777b538SAndroid Build Coastguard Worker   //
125*6777b538SAndroid Build Coastguard Worker   // The main_subprocess object, which wraps the main service_runtime
126*6777b538SAndroid Build Coastguard Worker   // object, is dtor'd implicitly after the explicit code below runs,
127*6777b538SAndroid Build Coastguard Worker   // so the main service runtime object will not have been dtor'd,
128*6777b538SAndroid Build Coastguard Worker   // though the Shutdown method may have been called, during the
129*6777b538SAndroid Build Coastguard Worker   // lifetime of the service threads.
130*6777b538SAndroid Build Coastguard Worker   ShutDownSubprocesses();
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker 
HandleDocumentLoad(const pp::URLLoader & url_loader)133*6777b538SAndroid Build Coastguard Worker bool Plugin::HandleDocumentLoad(const pp::URLLoader& url_loader) {
134*6777b538SAndroid Build Coastguard Worker   // We don't know if the plugin will handle the document load, but return
135*6777b538SAndroid Build Coastguard Worker   // true in order to give it a chance to respond once the proxy is started.
136*6777b538SAndroid Build Coastguard Worker   return true;
137*6777b538SAndroid Build Coastguard Worker }
138*6777b538SAndroid Build Coastguard Worker 
NexeFileDidOpen(int32_t pp_error)139*6777b538SAndroid Build Coastguard Worker void Plugin::NexeFileDidOpen(int32_t pp_error) {
140*6777b538SAndroid Build Coastguard Worker   if (pp_error != PP_OK)
141*6777b538SAndroid Build Coastguard Worker     return;
142*6777b538SAndroid Build Coastguard Worker   LoadNaClModule(nexe_file_info_, PP_NATIVE_NACL_PROCESS_TYPE);
143*6777b538SAndroid Build Coastguard Worker }
144*6777b538SAndroid Build Coastguard Worker 
BitcodeDidTranslate(int32_t pp_error)145*6777b538SAndroid Build Coastguard Worker void Plugin::BitcodeDidTranslate(int32_t pp_error) {
146*6777b538SAndroid Build Coastguard Worker   if (pp_error != PP_OK) {
147*6777b538SAndroid Build Coastguard Worker     // Error should have been reported by pnacl. Just return.
148*6777b538SAndroid Build Coastguard Worker     return;
149*6777b538SAndroid Build Coastguard Worker   }
150*6777b538SAndroid Build Coastguard Worker 
151*6777b538SAndroid Build Coastguard Worker   // Inform JavaScript that we successfully translated the bitcode to a nexe.
152*6777b538SAndroid Build Coastguard Worker   PP_FileHandle handle = pnacl_coordinator_->TakeTranslatedFileHandle();
153*6777b538SAndroid Build Coastguard Worker 
154*6777b538SAndroid Build Coastguard Worker   PP_NaClFileInfo info;
155*6777b538SAndroid Build Coastguard Worker   info.handle = handle;
156*6777b538SAndroid Build Coastguard Worker   info.token_lo = 0;
157*6777b538SAndroid Build Coastguard Worker   info.token_hi = 0;
158*6777b538SAndroid Build Coastguard Worker   LoadNaClModule(info, PP_PNACL_PROCESS_TYPE);
159*6777b538SAndroid Build Coastguard Worker }
160*6777b538SAndroid Build Coastguard Worker 
NaClManifestFileDidOpen(int32_t pp_error)161*6777b538SAndroid Build Coastguard Worker void Plugin::NaClManifestFileDidOpen(int32_t pp_error) {
162*6777b538SAndroid Build Coastguard Worker   if (pp_error != PP_OK)
163*6777b538SAndroid Build Coastguard Worker     return;
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker   PP_Var pp_program_url;
166*6777b538SAndroid Build Coastguard Worker   PP_PNaClOptions pnacl_options = {PP_FALSE, PP_FALSE, PP_FALSE, 2};
167*6777b538SAndroid Build Coastguard Worker   if (nacl::PPBNaClPrivate::GetManifestProgramURL(
168*6777b538SAndroid Build Coastguard Worker           pp_instance(), &pp_program_url, &pnacl_options)) {
169*6777b538SAndroid Build Coastguard Worker     std::string program_url = pp::Var(pp::PASS_REF, pp_program_url).AsString();
170*6777b538SAndroid Build Coastguard Worker     // TODO(teravest): Make ProcessNaClManifest take responsibility for more of
171*6777b538SAndroid Build Coastguard Worker     // this function.
172*6777b538SAndroid Build Coastguard Worker     nacl::PPBNaClPrivate::ProcessNaClManifest(pp_instance(),
173*6777b538SAndroid Build Coastguard Worker                                               program_url.c_str());
174*6777b538SAndroid Build Coastguard Worker     if (pnacl_options.translate) {
175*6777b538SAndroid Build Coastguard Worker       pp::CompletionCallback translate_callback =
176*6777b538SAndroid Build Coastguard Worker           callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate);
177*6777b538SAndroid Build Coastguard Worker       pnacl_coordinator_.reset(
178*6777b538SAndroid Build Coastguard Worker           PnaclCoordinator::BitcodeToNative(this,
179*6777b538SAndroid Build Coastguard Worker                                             program_url,
180*6777b538SAndroid Build Coastguard Worker                                             pnacl_options,
181*6777b538SAndroid Build Coastguard Worker                                             translate_callback));
182*6777b538SAndroid Build Coastguard Worker       return;
183*6777b538SAndroid Build Coastguard Worker     } else {
184*6777b538SAndroid Build Coastguard Worker       pp::CompletionCallback open_callback =
185*6777b538SAndroid Build Coastguard Worker           callback_factory_.NewCallback(&Plugin::NexeFileDidOpen);
186*6777b538SAndroid Build Coastguard Worker       // Will always call the callback on success or failure.
187*6777b538SAndroid Build Coastguard Worker       nacl::PPBNaClPrivate::DownloadNexe(
188*6777b538SAndroid Build Coastguard Worker           pp_instance(),
189*6777b538SAndroid Build Coastguard Worker           program_url.c_str(),
190*6777b538SAndroid Build Coastguard Worker           &nexe_file_info_,
191*6777b538SAndroid Build Coastguard Worker           open_callback.pp_completion_callback());
192*6777b538SAndroid Build Coastguard Worker       return;
193*6777b538SAndroid Build Coastguard Worker     }
194*6777b538SAndroid Build Coastguard Worker   }
195*6777b538SAndroid Build Coastguard Worker }
196*6777b538SAndroid Build Coastguard Worker 
ReportLoadError(const ErrorInfo & error_info)197*6777b538SAndroid Build Coastguard Worker void Plugin::ReportLoadError(const ErrorInfo& error_info) {
198*6777b538SAndroid Build Coastguard Worker   nacl::PPBNaClPrivate::ReportLoadError(pp_instance(),
199*6777b538SAndroid Build Coastguard Worker                                         error_info.error_code(),
200*6777b538SAndroid Build Coastguard Worker                                         error_info.message().c_str());
201*6777b538SAndroid Build Coastguard Worker }
202*6777b538SAndroid Build Coastguard Worker 
203*6777b538SAndroid Build Coastguard Worker }  // namespace plugin
204