• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "content/renderer/pepper/plugin_module.h"
6 
7 #include <set>
8 
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/message_loop/message_loop_proxy.h"
15 #include "base/time/time.h"
16 #include "build/build_config.h"
17 #include "content/common/view_messages.h"
18 #include "content/public/renderer/content_renderer_client.h"
19 #include "content/renderer/pepper/common.h"
20 #include "content/renderer/pepper/host_dispatcher_wrapper.h"
21 #include "content/renderer/pepper/host_globals.h"
22 #include "content/renderer/pepper/pepper_hung_plugin_filter.h"
23 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
24 #include "content/renderer/pepper/pepper_plugin_registry.h"
25 #include "content/renderer/pepper/ppb_image_data_impl.h"
26 #include "content/renderer/pepper/ppb_proxy_impl.h"
27 #include "content/renderer/pepper/ppb_scrollbar_impl.h"
28 #include "content/renderer/pepper/ppb_uma_private_impl.h"
29 #include "content/renderer/pepper/ppb_var_deprecated_impl.h"
30 #include "content/renderer/pepper/ppb_video_decoder_impl.h"
31 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
32 #include "content/renderer/render_view_impl.h"
33 #include "ppapi/c/dev/ppb_alarms_dev.h"
34 #include "ppapi/c/dev/ppb_audio_input_dev.h"
35 #include "ppapi/c/dev/ppb_buffer_dev.h"
36 #include "ppapi/c/dev/ppb_char_set_dev.h"
37 #include "ppapi/c/dev/ppb_crypto_dev.h"
38 #include "ppapi/c/dev/ppb_cursor_control_dev.h"
39 #include "ppapi/c/dev/ppb_device_ref_dev.h"
40 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
41 #include "ppapi/c/dev/ppb_find_dev.h"
42 #include "ppapi/c/dev/ppb_font_dev.h"
43 #include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
44 #include "ppapi/c/dev/ppb_graphics_2d_dev.h"
45 #include "ppapi/c/dev/ppb_memory_dev.h"
46 #include "ppapi/c/dev/ppb_opengles2ext_dev.h"
47 #include "ppapi/c/dev/ppb_printing_dev.h"
48 #include "ppapi/c/dev/ppb_resource_array_dev.h"
49 #include "ppapi/c/dev/ppb_scrollbar_dev.h"
50 #include "ppapi/c/dev/ppb_text_input_dev.h"
51 #include "ppapi/c/dev/ppb_trace_event_dev.h"
52 #include "ppapi/c/dev/ppb_truetype_font_dev.h"
53 #include "ppapi/c/dev/ppb_url_util_dev.h"
54 #include "ppapi/c/dev/ppb_var_deprecated.h"
55 #include "ppapi/c/dev/ppb_var_resource_dev.h"
56 #include "ppapi/c/dev/ppb_video_capture_dev.h"
57 #include "ppapi/c/dev/ppb_video_decoder_dev.h"
58 #include "ppapi/c/dev/ppb_view_dev.h"
59 #include "ppapi/c/dev/ppb_widget_dev.h"
60 #include "ppapi/c/dev/ppb_zoom_dev.h"
61 #include "ppapi/c/extensions/dev/ppb_ext_socket_dev.h"
62 #include "ppapi/c/pp_module.h"
63 #include "ppapi/c/pp_resource.h"
64 #include "ppapi/c/pp_var.h"
65 #include "ppapi/c/ppb_audio.h"
66 #include "ppapi/c/ppb_audio_config.h"
67 #include "ppapi/c/ppb_console.h"
68 #include "ppapi/c/ppb_core.h"
69 #include "ppapi/c/ppb_file_io.h"
70 #include "ppapi/c/ppb_file_ref.h"
71 #include "ppapi/c/ppb_file_system.h"
72 #include "ppapi/c/ppb_fullscreen.h"
73 #include "ppapi/c/ppb_graphics_2d.h"
74 #include "ppapi/c/ppb_graphics_3d.h"
75 #include "ppapi/c/ppb_host_resolver.h"
76 #include "ppapi/c/ppb_image_data.h"
77 #include "ppapi/c/ppb_instance.h"
78 #include "ppapi/c/ppb_messaging.h"
79 #include "ppapi/c/ppb_mouse_cursor.h"
80 #include "ppapi/c/ppb_mouse_lock.h"
81 #include "ppapi/c/ppb_net_address.h"
82 #include "ppapi/c/ppb_network_list.h"
83 #include "ppapi/c/ppb_network_monitor.h"
84 #include "ppapi/c/ppb_network_proxy.h"
85 #include "ppapi/c/ppb_opengles2.h"
86 #include "ppapi/c/ppb_tcp_socket.h"
87 #include "ppapi/c/ppb_text_input_controller.h"
88 #include "ppapi/c/ppb_udp_socket.h"
89 #include "ppapi/c/ppb_url_loader.h"
90 #include "ppapi/c/ppb_url_request_info.h"
91 #include "ppapi/c/ppb_url_response_info.h"
92 #include "ppapi/c/ppb_var.h"
93 #include "ppapi/c/ppb_var_array.h"
94 #include "ppapi/c/ppb_var_array_buffer.h"
95 #include "ppapi/c/ppb_var_dictionary.h"
96 #include "ppapi/c/ppb_view.h"
97 #include "ppapi/c/ppp.h"
98 #include "ppapi/c/ppp_instance.h"
99 #include "ppapi/c/private/ppb_ext_crx_file_system_private.h"
100 #include "ppapi/c/private/ppb_file_io_private.h"
101 #include "ppapi/c/private/ppb_file_ref_private.h"
102 #include "ppapi/c/private/ppb_flash.h"
103 #include "ppapi/c/private/ppb_flash_clipboard.h"
104 #include "ppapi/c/private/ppb_flash_device_id.h"
105 #include "ppapi/c/private/ppb_flash_drm.h"
106 #include "ppapi/c/private/ppb_flash_file.h"
107 #include "ppapi/c/private/ppb_flash_font_file.h"
108 #include "ppapi/c/private/ppb_flash_fullscreen.h"
109 #include "ppapi/c/private/ppb_flash_menu.h"
110 #include "ppapi/c/private/ppb_flash_message_loop.h"
111 #include "ppapi/c/private/ppb_flash_print.h"
112 #include "ppapi/c/private/ppb_host_resolver_private.h"
113 #include "ppapi/c/private/ppb_instance_private.h"
114 #include "ppapi/c/private/ppb_isolated_file_system_private.h"
115 #include "ppapi/c/private/ppb_output_protection_private.h"
116 #include "ppapi/c/private/ppb_pdf.h"
117 #include "ppapi/c/private/ppb_proxy_private.h"
118 #include "ppapi/c/private/ppb_talk_private.h"
119 #include "ppapi/c/private/ppb_tcp_server_socket_private.h"
120 #include "ppapi/c/private/ppb_tcp_socket_private.h"
121 #include "ppapi/c/private/ppb_testing_private.h"
122 #include "ppapi/c/private/ppb_udp_socket_private.h"
123 #include "ppapi/c/private/ppb_uma_private.h"
124 #include "ppapi/c/private/ppb_video_destination_private.h"
125 #include "ppapi/c/private/ppb_video_source_private.h"
126 #include "ppapi/c/private/ppb_x509_certificate_private.h"
127 #include "ppapi/c/trusted/ppb_broker_trusted.h"
128 #include "ppapi/c/trusted/ppb_browser_font_trusted.h"
129 #include "ppapi/c/trusted/ppb_char_set_trusted.h"
130 #include "ppapi/c/trusted/ppb_file_chooser_trusted.h"
131 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
132 #include "ppapi/shared_impl/callback_tracker.h"
133 #include "ppapi/shared_impl/ppapi_preferences.h"
134 #include "ppapi/shared_impl/ppapi_switches.h"
135 #include "ppapi/shared_impl/ppb_input_event_shared.h"
136 #include "ppapi/shared_impl/ppb_opengles2_shared.h"
137 #include "ppapi/shared_impl/ppb_var_shared.h"
138 #include "ppapi/shared_impl/time_conversion.h"
139 #include "ppapi/thunk/enter.h"
140 #include "ppapi/thunk/ppb_graphics_2d_api.h"
141 #include "ppapi/thunk/thunk.h"
142 
143 #if defined(OS_CHROMEOS)
144 #include "ppapi/c/private/ppb_platform_verification_private.h"
145 #endif
146 
147 using ppapi::InputEventData;
148 using ppapi::PpapiGlobals;
149 using ppapi::TimeTicksToPPTimeTicks;
150 using ppapi::TimeToPPTime;
151 using ppapi::thunk::EnterResource;
152 using ppapi::thunk::PPB_Graphics2D_API;
153 using ppapi::thunk::PPB_InputEvent_API;
154 
155 namespace content {
156 
157 namespace {
158 
159 // Global tracking info for PPAPI plugins. This is lazily created before the
160 // first plugin is allocated, and leaked on shutdown.
161 //
162 // Note that we don't want a Singleton here since destroying this object will
163 // try to free some stuff that requires WebKit, and Singletons are destroyed
164 // after WebKit.
165 // TODO(raymes): I'm not sure if it is completely necessary to leak the
166 // HostGlobals. Figure out the shutdown sequence and find a way to do this
167 // more elegantly.
168 HostGlobals* host_globals = NULL;
169 
170 // Maintains all currently loaded plugin libs for validating PP_Module
171 // identifiers.
172 typedef std::set<PluginModule*> PluginModuleSet;
173 
GetLivePluginSet()174 PluginModuleSet* GetLivePluginSet() {
175   CR_DEFINE_STATIC_LOCAL(PluginModuleSet, live_plugin_libs, ());
176   return &live_plugin_libs;
177 }
178 
179 // PPB_Core --------------------------------------------------------------------
180 
AddRefResource(PP_Resource resource)181 void AddRefResource(PP_Resource resource) {
182   PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(resource);
183 }
184 
ReleaseResource(PP_Resource resource)185 void ReleaseResource(PP_Resource resource) {
186   PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(resource);
187 }
188 
GetTime()189 PP_Time GetTime() {
190   return TimeToPPTime(base::Time::Now());
191 }
192 
GetTickTime()193 PP_TimeTicks GetTickTime() {
194   return TimeTicksToPPTimeTicks(base::TimeTicks::Now());
195 }
196 
CallOnMainThread(int delay_in_msec,PP_CompletionCallback callback,int32_t result)197 void CallOnMainThread(int delay_in_msec,
198                       PP_CompletionCallback callback,
199                       int32_t result) {
200   if (callback.func) {
201     PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostDelayedTask(
202         FROM_HERE,
203         base::Bind(callback.func, callback.user_data, result),
204         base::TimeDelta::FromMilliseconds(delay_in_msec));
205   }
206 }
207 
IsMainThread()208 PP_Bool IsMainThread() {
209   return BoolToPPBool(PpapiGlobals::Get()->
210       GetMainThreadMessageLoop()->BelongsToCurrentThread());
211 }
212 
213 const PPB_Core core_interface = {
214   &AddRefResource,
215   &ReleaseResource,
216   &GetTime,
217   &GetTickTime,
218   &CallOnMainThread,
219   &IsMainThread
220 };
221 
222 // PPB_Testing -----------------------------------------------------------------
223 
ReadImageData(PP_Resource device_context_2d,PP_Resource image,const PP_Point * top_left)224 PP_Bool ReadImageData(PP_Resource device_context_2d,
225                       PP_Resource image,
226                       const PP_Point* top_left) {
227   EnterResource<PPB_Graphics2D_API> enter(device_context_2d, true);
228   if (enter.failed())
229     return PP_FALSE;
230   return BoolToPPBool(enter.object()->ReadImageData(image, top_left));
231 }
232 
RunMessageLoop(PP_Instance instance)233 void RunMessageLoop(PP_Instance instance) {
234   base::MessageLoop::ScopedNestableTaskAllower allow(
235       base::MessageLoop::current());
236   base::MessageLoop::current()->Run();
237 }
238 
QuitMessageLoop(PP_Instance instance)239 void QuitMessageLoop(PP_Instance instance) {
240   base::MessageLoop::current()->QuitNow();
241 }
242 
GetLiveObjectsForInstance(PP_Instance instance_id)243 uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) {
244   return HostGlobals::Get()->GetResourceTracker()->GetLiveObjectsForInstance(
245       instance_id);
246 }
247 
IsOutOfProcess()248 PP_Bool IsOutOfProcess() {
249   return PP_FALSE;
250 }
251 
SimulateInputEvent(PP_Instance instance,PP_Resource input_event)252 void SimulateInputEvent(PP_Instance instance, PP_Resource input_event) {
253   PepperPluginInstanceImpl* plugin_instance =
254       host_globals->GetInstance(instance);
255   if (!plugin_instance)
256     return;
257 
258   EnterResource<PPB_InputEvent_API> enter(input_event, false);
259   if (enter.failed())
260     return;
261 
262   const InputEventData& input_event_data = enter.object()->GetInputEventData();
263   plugin_instance->SimulateInputEvent(input_event_data);
264 }
265 
GetDocumentURL(PP_Instance instance,PP_URLComponents_Dev * components)266 PP_Var GetDocumentURL(PP_Instance instance, PP_URLComponents_Dev* components) {
267   PepperPluginInstanceImpl* plugin_instance =
268       host_globals->GetInstance(instance);
269   if (!plugin_instance)
270     return PP_MakeUndefined();
271   return plugin_instance->GetDocumentURL(instance, components);
272 }
273 
GetLiveVars(PP_Var live_vars[],uint32_t array_size)274 uint32_t GetLiveVars(PP_Var live_vars[], uint32_t array_size) {
275   std::vector<PP_Var> vars =
276       PpapiGlobals::Get()->GetVarTracker()->GetLiveVars();
277   for (size_t i = 0u;
278        i < std::min(static_cast<size_t>(array_size), vars.size());
279        ++i)
280     live_vars[i] = vars[i];
281   return vars.size();
282 }
283 
SetMinimumArrayBufferSizeForShmem(PP_Instance,uint32_t)284 void SetMinimumArrayBufferSizeForShmem(PP_Instance /*instance*/,
285                                        uint32_t /*threshold*/) {
286   // Does nothing. Not needed in-process.
287 }
288 
289 const PPB_Testing_Private testing_interface = {
290   &ReadImageData,
291   &RunMessageLoop,
292   &QuitMessageLoop,
293   &GetLiveObjectsForInstance,
294   &IsOutOfProcess,
295   &SimulateInputEvent,
296   &GetDocumentURL,
297   &GetLiveVars,
298   &SetMinimumArrayBufferSizeForShmem
299 };
300 
301 // GetInterface ----------------------------------------------------------------
302 
InternalGetInterface(const char * name)303 const void* InternalGetInterface(const char* name) {
304   // Allow custom interface factories first stab at the GetInterface call.
305   const void* custom_interface =
306       GetContentClient()->renderer()->CreatePPAPIInterface(name);
307   if (custom_interface)
308     return custom_interface;
309 
310   // TODO(brettw) put these in a hash map for better performance.
311   #define UNPROXIED_IFACE(api_name, iface_str, iface_struct) \
312       if (strcmp(name, iface_str) == 0) \
313         return ppapi::thunk::Get##iface_struct##_Thunk();
314   #define PROXIED_IFACE(api_name, iface_str, iface_struct) \
315       UNPROXIED_IFACE(api_name, iface_str, iface_struct)
316 
317   #include "ppapi/thunk/interfaces_ppb_public_stable.h"
318   #include "ppapi/thunk/interfaces_ppb_public_dev.h"
319   #include "ppapi/thunk/interfaces_ppb_private.h"
320   #include "ppapi/thunk/interfaces_ppb_private_no_permissions.h"
321   #include "ppapi/thunk/interfaces_ppb_private_flash.h"
322 
323   #undef UNPROXIED_API
324   #undef PROXIED_IFACE
325 
326   #define LEGACY_IFACE(iface_str, function_name) \
327       if (strcmp(name, iface_str) == 0) \
328         return function_name;
329 
330   #include "ppapi/thunk/interfaces_legacy.h"
331 
332   #undef LEGACY_IFACE
333 
334   // Only support the testing interface when the command line switch is
335   // specified. This allows us to prevent people from (ab)using this interface
336   // in production code.
337   if (CommandLine::ForCurrentProcess()->HasSwitch(
338           switches::kEnablePepperTesting)) {
339     if (strcmp(name, PPB_TESTING_PRIVATE_INTERFACE) == 0)
340       return &testing_interface;
341   }
342   return NULL;
343 }
344 
GetInterface(const char * name)345 const void* GetInterface(const char* name) {
346   // All interfaces should be used on the main thread.
347   CHECK(IsMainThread());
348 
349   return InternalGetInterface(name);
350 }
351 
352 // Gets the PPAPI entry points from the given library and places them into the
353 // given structure. Returns true on success.
LoadEntryPointsFromLibrary(const base::NativeLibrary & library,PepperPluginInfo::EntryPoints * entry_points)354 bool LoadEntryPointsFromLibrary(
355     const base::NativeLibrary& library,
356     PepperPluginInfo::EntryPoints* entry_points) {
357   entry_points->get_interface =
358       reinterpret_cast<PepperPluginInfo::GetInterfaceFunc>(
359           base::GetFunctionPointerFromNativeLibrary(library,
360                                                     "PPP_GetInterface"));
361   if (!entry_points->get_interface) {
362     LOG(WARNING) << "No PPP_GetInterface in plugin library";
363     return false;
364   }
365 
366   entry_points->initialize_module =
367       reinterpret_cast<PepperPluginInfo::PPP_InitializeModuleFunc>(
368           base::GetFunctionPointerFromNativeLibrary(library,
369                                                     "PPP_InitializeModule"));
370   if (!entry_points->initialize_module) {
371     LOG(WARNING) << "No PPP_InitializeModule in plugin library";
372     return false;
373   }
374 
375   // It's okay for PPP_ShutdownModule to not be defined and shutdown_module to
376   // be NULL.
377   entry_points->shutdown_module =
378       reinterpret_cast<PepperPluginInfo::PPP_ShutdownModuleFunc>(
379           base::GetFunctionPointerFromNativeLibrary(library,
380                                                     "PPP_ShutdownModule"));
381 
382   return true;
383 }
384 
CreateHostForInProcessModule(RenderFrameImpl * render_frame,PluginModule * module,const WebPluginInfo & webplugin_info)385 void CreateHostForInProcessModule(RenderFrameImpl* render_frame,
386                                   PluginModule* module,
387                                   const WebPluginInfo& webplugin_info) {
388   // First time an in-process plugin was used, make a host for it.
389   const PepperPluginInfo* info =
390       PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info);
391   DCHECK(!info->is_out_of_process);
392 
393   ppapi::PpapiPermissions perms(
394       PepperPluginRegistry::GetInstance()->GetInfoForPlugin(
395           webplugin_info)->permissions);
396   RendererPpapiHostImpl* host_impl =
397       RendererPpapiHostImpl::CreateOnModuleForInProcess(module, perms);
398   render_frame->PepperPluginCreated(host_impl);
399 }
400 
401 }  // namespace
402 
403 // PluginModule ----------------------------------------------------------------
404 
PluginModule(const std::string & name,const base::FilePath & path,const ppapi::PpapiPermissions & perms)405 PluginModule::PluginModule(const std::string& name,
406                            const base::FilePath& path,
407                            const ppapi::PpapiPermissions& perms)
408     : callback_tracker_(new ppapi::CallbackTracker),
409       is_in_destructor_(false),
410       is_crashed_(false),
411       broker_(NULL),
412       library_(NULL),
413       name_(name),
414       path_(path),
415       permissions_(perms),
416       reserve_instance_id_(NULL) {
417   // Ensure the globals object is created.
418   if (!host_globals)
419     host_globals = new HostGlobals;
420 
421   memset(&entry_points_, 0, sizeof(entry_points_));
422   pp_module_ = HostGlobals::Get()->AddModule(this);
423   GetLivePluginSet()->insert(this);
424 }
425 
~PluginModule()426 PluginModule::~PluginModule() {
427   // In the past there have been crashes reentering the plugin module
428   // destructor. Catch if that happens again earlier.
429   CHECK(!is_in_destructor_);
430   is_in_destructor_ = true;
431 
432   // When the module is being deleted, there should be no more instances still
433   // holding a reference to us.
434   DCHECK(instances_.empty());
435 
436   // Some resources and other stuff are hung off of the embedder state, which
437   // should be torn down before the routing stuff below.
438   renderer_ppapi_host_.reset();
439 
440   GetLivePluginSet()->erase(this);
441 
442   callback_tracker_->AbortAll();
443 
444   if (entry_points_.shutdown_module)
445     entry_points_.shutdown_module();
446 
447   if (library_)
448     base::UnloadNativeLibrary(library_);
449 
450   // Notifications that we've been deleted should be last.
451   HostGlobals::Get()->ModuleDeleted(pp_module_);
452   if (!is_crashed_) {
453     // When the plugin crashes, we immediately tell the lifetime delegate that
454     // we're gone, so we don't want to tell it again.
455     PepperPluginRegistry::GetInstance()->PluginModuleDead(this);
456   }
457 
458   // Don't add stuff here, the two notifications that the module object has
459   // been deleted should be last. This allows, for example,
460   // PPB_Proxy.IsInModuleDestructor to map PP_Module to this class during the
461   // previous parts of the destructor.
462 }
463 
SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl> host)464 void PluginModule::SetRendererPpapiHost(
465     scoped_ptr<RendererPpapiHostImpl> host) {
466   renderer_ppapi_host_ = host.Pass();
467 }
468 
InitAsInternalPlugin(const PepperPluginInfo::EntryPoints & entry_points)469 bool PluginModule::InitAsInternalPlugin(
470     const PepperPluginInfo::EntryPoints& entry_points) {
471   if (InitializeModule(entry_points)) {
472     entry_points_ = entry_points;
473     return true;
474   }
475   return false;
476 }
477 
InitAsLibrary(const base::FilePath & path)478 bool PluginModule::InitAsLibrary(const base::FilePath& path) {
479   base::NativeLibrary library = base::LoadNativeLibrary(path, NULL);
480   if (!library)
481     return false;
482 
483   PepperPluginInfo::EntryPoints entry_points;
484 
485   if (!LoadEntryPointsFromLibrary(library, &entry_points) ||
486       !InitializeModule(entry_points)) {
487     base::UnloadNativeLibrary(library);
488     return false;
489   }
490   entry_points_ = entry_points;
491   library_ = library;
492   return true;
493 }
494 
InitAsProxied(HostDispatcherWrapper * host_dispatcher_wrapper)495 void PluginModule::InitAsProxied(
496     HostDispatcherWrapper* host_dispatcher_wrapper) {
497   DCHECK(!host_dispatcher_wrapper_.get());
498   host_dispatcher_wrapper_.reset(host_dispatcher_wrapper);
499 }
500 
501 scoped_refptr<PluginModule>
CreateModuleForExternalPluginInstance()502     PluginModule::CreateModuleForExternalPluginInstance() {
503   // Create a new module, but don't set the lifetime delegate. This isn't a
504   // plugin in the usual sense, so it isn't tracked by the browser.
505   scoped_refptr<PluginModule> external_plugin_module(
506       new PluginModule(name_,
507                        path_,
508                        permissions_));
509   return external_plugin_module;
510 }
511 
InitAsProxiedExternalPlugin(PepperPluginInstanceImpl * instance)512 PP_ExternalPluginResult PluginModule::InitAsProxiedExternalPlugin(
513     PepperPluginInstanceImpl* instance) {
514   DCHECK(host_dispatcher_wrapper_.get());
515   // InitAsProxied (for the trusted/out-of-process case) initializes only the
516   // module, and one or more instances are added later. In this case, the
517   // PluginInstance was already created as in-process, so we missed the proxy
518   // AddInstance step and must do it now.
519   host_dispatcher_wrapper_->AddInstance(instance->pp_instance());
520   // For external plugins, we need to tell the instance to reset itself as
521   // proxied. This will clear cached interface pointers and send DidCreate (etc)
522   // to the plugin side of the proxy.
523   return instance->ResetAsProxied(this);
524 }
525 
IsProxied() const526 bool PluginModule::IsProxied() const {
527   return !!host_dispatcher_wrapper_;
528 }
529 
GetPeerProcessId()530 base::ProcessId PluginModule::GetPeerProcessId() {
531   if (host_dispatcher_wrapper_)
532     return host_dispatcher_wrapper_->peer_pid();
533   return base::kNullProcessId;
534 }
535 
GetPluginChildId()536 int PluginModule::GetPluginChildId() {
537   if (host_dispatcher_wrapper_)
538     return host_dispatcher_wrapper_->plugin_child_id();
539   return 0;
540 }
541 
542 // static
GetCore()543 const PPB_Core* PluginModule::GetCore() {
544   return &core_interface;
545 }
546 
547 // static
SupportsInterface(const char * name)548 bool PluginModule::SupportsInterface(const char* name) {
549   return !!InternalGetInterface(name);
550 }
551 
CreateInstance(RenderFrameImpl * render_frame,blink::WebPluginContainer * container,const GURL & plugin_url)552 PepperPluginInstanceImpl* PluginModule::CreateInstance(
553     RenderFrameImpl* render_frame,
554     blink::WebPluginContainer* container,
555     const GURL& plugin_url) {
556   PepperPluginInstanceImpl* instance = PepperPluginInstanceImpl::Create(
557       render_frame, this, container, plugin_url);
558   if (!instance) {
559     LOG(WARNING) << "Plugin doesn't support instance interface, failing.";
560     return NULL;
561   }
562   if (host_dispatcher_wrapper_)
563     host_dispatcher_wrapper_->AddInstance(instance->pp_instance());
564   return instance;
565 }
566 
GetSomeInstance() const567 PepperPluginInstanceImpl* PluginModule::GetSomeInstance() const {
568   // This will generally crash later if there is not actually any instance to
569   // return, so we force a crash now to make bugs easier to track down.
570   CHECK(!instances_.empty());
571   return *instances_.begin();
572 }
573 
GetPluginInterface(const char * name) const574 const void* PluginModule::GetPluginInterface(const char* name) const {
575   if (host_dispatcher_wrapper_)
576     return host_dispatcher_wrapper_->GetProxiedInterface(name);
577 
578   // In-process plugins.
579   if (!entry_points_.get_interface)
580     return NULL;
581   return entry_points_.get_interface(name);
582 }
583 
InstanceCreated(PepperPluginInstanceImpl * instance)584 void PluginModule::InstanceCreated(PepperPluginInstanceImpl* instance) {
585   instances_.insert(instance);
586 }
587 
InstanceDeleted(PepperPluginInstanceImpl * instance)588 void PluginModule::InstanceDeleted(PepperPluginInstanceImpl* instance) {
589   if (host_dispatcher_wrapper_)
590     host_dispatcher_wrapper_->RemoveInstance(instance->pp_instance());
591   instances_.erase(instance);
592 }
593 
GetCallbackTracker()594 scoped_refptr<ppapi::CallbackTracker> PluginModule::GetCallbackTracker() {
595   return callback_tracker_;
596 }
597 
PluginCrashed()598 void PluginModule::PluginCrashed() {
599   DCHECK(!is_crashed_);  // Should only get one notification.
600   is_crashed_ = true;
601 
602   // Notify all instances that they crashed.
603   for (PluginInstanceSet::iterator i = instances_.begin();
604        i != instances_.end(); ++i)
605     (*i)->InstanceCrashed();
606 
607   PepperPluginRegistry::GetInstance()->PluginModuleDead(this);
608 }
609 
SetReserveInstanceIDCallback(PP_Bool (* reserve)(PP_Module,PP_Instance))610 void PluginModule::SetReserveInstanceIDCallback(
611     PP_Bool (*reserve)(PP_Module, PP_Instance)) {
612   DCHECK(!reserve_instance_id_) << "Only expect one set.";
613   reserve_instance_id_ = reserve;
614 }
615 
ReserveInstanceID(PP_Instance instance)616 bool PluginModule::ReserveInstanceID(PP_Instance instance) {
617   if (reserve_instance_id_)
618     return PPBoolToBool(reserve_instance_id_(pp_module_, instance));
619   return true;  // Instance ID is usable.
620 }
621 
SetBroker(PepperBroker * broker)622 void PluginModule::SetBroker(PepperBroker* broker) {
623   DCHECK(!broker_ || !broker);
624   broker_ = broker;
625 }
626 
GetBroker()627 PepperBroker* PluginModule::GetBroker() {
628   return broker_;
629 }
630 
CreateOutOfProcessModule(RenderFrameImpl * render_frame,const base::FilePath & path,ppapi::PpapiPermissions permissions,const IPC::ChannelHandle & channel_handle,base::ProcessId peer_pid,int plugin_child_id,bool is_external)631 RendererPpapiHostImpl* PluginModule::CreateOutOfProcessModule(
632     RenderFrameImpl* render_frame,
633     const base::FilePath& path,
634     ppapi::PpapiPermissions permissions,
635     const IPC::ChannelHandle& channel_handle,
636     base::ProcessId peer_pid,
637     int plugin_child_id,
638     bool is_external) {
639   scoped_refptr<PepperHungPluginFilter> hung_filter(new PepperHungPluginFilter(
640       path, render_frame->GetRoutingID(), plugin_child_id));
641   scoped_ptr<HostDispatcherWrapper> dispatcher(
642       new HostDispatcherWrapper(this,
643                                 peer_pid,
644                                 plugin_child_id,
645                                 permissions,
646                                 is_external));
647   if (!dispatcher->Init(
648           channel_handle,
649           &GetInterface,
650           ppapi::Preferences(render_frame->render_view()->webkit_preferences()),
651           hung_filter.get()))
652     return NULL;
653 
654   RendererPpapiHostImpl* host_impl =
655       RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
656           this, dispatcher->dispatcher(), permissions);
657   render_frame->PepperPluginCreated(host_impl);
658 
659   InitAsProxied(dispatcher.release());
660   return host_impl;
661 }
662 
663 // static
ResetHostGlobalsForTest()664 void PluginModule::ResetHostGlobalsForTest() {
665   delete host_globals;
666   host_globals = NULL;
667 }
668 
InitializeModule(const PepperPluginInfo::EntryPoints & entry_points)669 bool PluginModule::InitializeModule(
670     const PepperPluginInfo::EntryPoints& entry_points) {
671   DCHECK(!host_dispatcher_wrapper_.get()) << "Don't call for proxied modules.";
672   DCHECK(entry_points.initialize_module != NULL);
673   int retval = entry_points.initialize_module(pp_module(), &GetInterface);
674   if (retval != 0) {
675     LOG(WARNING) << "PPP_InitializeModule returned failure " << retval;
676     return false;
677   }
678   return true;
679 }
680 
Create(RenderFrameImpl * render_frame,const WebPluginInfo & webplugin_info,bool * pepper_plugin_was_registered)681 scoped_refptr<PluginModule> PluginModule::Create(
682     RenderFrameImpl* render_frame,
683     const WebPluginInfo& webplugin_info,
684     bool* pepper_plugin_was_registered) {
685   *pepper_plugin_was_registered = true;
686 
687   // See if a module has already been loaded for this plugin.
688   base::FilePath path(webplugin_info.path);
689   scoped_refptr<PluginModule> module =
690       PepperPluginRegistry::GetInstance()->GetLiveModule(path);
691   if (module.get()) {
692     if (!module->renderer_ppapi_host()) {
693       // If the module exists and no embedder state was associated with it,
694       // then the module was one of the ones preloaded and is an in-process
695       // plugin. We need to associate our host state with it.
696       CreateHostForInProcessModule(render_frame, module.get(), webplugin_info);
697     }
698     return module;
699   }
700 
701   // In-process plugins will have always been created up-front to avoid the
702   // sandbox restrictions. So getting here implies it doesn't exist or should
703   // be out of process.
704   const PepperPluginInfo* info =
705       PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info);
706   if (!info) {
707     *pepper_plugin_was_registered = false;
708     return scoped_refptr<PluginModule>();
709   } else if (!info->is_out_of_process) {
710     // In-process plugin not preloaded, it probably couldn't be initialized.
711     return scoped_refptr<PluginModule>();
712   }
713 
714   ppapi::PpapiPermissions permissions =
715       ppapi::PpapiPermissions::GetForCommandLine(info->permissions);
716 
717   // Out of process: have the browser start the plugin process for us.
718   IPC::ChannelHandle channel_handle;
719   base::ProcessId peer_pid;
720   int plugin_child_id = 0;
721   render_frame->Send(new ViewHostMsg_OpenChannelToPepperPlugin(
722       path, &channel_handle, &peer_pid, &plugin_child_id));
723   if (channel_handle.name.empty()) {
724     // Couldn't be initialized.
725     return scoped_refptr<PluginModule>();
726   }
727 
728   // AddLiveModule must be called before any early returns since the
729   // module's destructor will remove itself.
730   module = new PluginModule(info->name, path, permissions);
731   PepperPluginRegistry::GetInstance()->AddLiveModule(path, module.get());
732 
733   if (!module->CreateOutOfProcessModule(render_frame,
734                                         path,
735                                         permissions,
736                                         channel_handle,
737                                         peer_pid,
738                                         plugin_child_id,
739                                         false))  // is_external = false
740     return scoped_refptr<PluginModule>();
741 
742   return module;
743 }
744 
745 }  // namespace content
746