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