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.
5 #include "content/renderer/pepper/plugin_module.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/time/time.h"
15 #include "build/build_config.h"
16 #include "content/common/frame_messages.h"
17 #include "content/public/renderer/content_renderer_client.h"
18 #include "content/renderer/pepper/host_dispatcher_wrapper.h"
19 #include "content/renderer/pepper/host_globals.h"
20 #include "content/renderer/pepper/pepper_hung_plugin_filter.h"
21 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
22 #include "content/renderer/pepper/pepper_plugin_registry.h"
23 #include "content/renderer/pepper/plugin_instance_throttler_impl.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_var_deprecated_impl.h"
28 #include "content/renderer/pepper/ppb_video_decoder_impl.h"
29 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
30 #include "content/renderer/render_view_impl.h"
31 #include "ppapi/c/dev/ppb_audio_input_dev.h"
32 #include "ppapi/c/dev/ppb_buffer_dev.h"
33 #include "ppapi/c/dev/ppb_char_set_dev.h"
34 #include "ppapi/c/dev/ppb_crypto_dev.h"
35 #include "ppapi/c/dev/ppb_cursor_control_dev.h"
36 #include "ppapi/c/dev/ppb_device_ref_dev.h"
37 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
38 #include "ppapi/c/dev/ppb_font_dev.h"
39 #include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
40 #include "ppapi/c/dev/ppb_memory_dev.h"
41 #include "ppapi/c/dev/ppb_opengles2ext_dev.h"
42 #include "ppapi/c/dev/ppb_printing_dev.h"
43 #include "ppapi/c/dev/ppb_text_input_dev.h"
44 #include "ppapi/c/dev/ppb_trace_event_dev.h"
45 #include "ppapi/c/dev/ppb_truetype_font_dev.h"
46 #include "ppapi/c/dev/ppb_url_util_dev.h"
47 #include "ppapi/c/dev/ppb_var_deprecated.h"
48 #include "ppapi/c/dev/ppb_video_capture_dev.h"
49 #include "ppapi/c/dev/ppb_video_decoder_dev.h"
50 #include "ppapi/c/dev/ppb_view_dev.h"
51 #include "ppapi/c/pp_module.h"
52 #include "ppapi/c/pp_resource.h"
53 #include "ppapi/c/pp_var.h"
54 #include "ppapi/c/ppb_audio.h"
55 #include "ppapi/c/ppb_audio_buffer.h"
56 #include "ppapi/c/ppb_audio_config.h"
57 #include "ppapi/c/ppb_audio_encoder.h"
58 #include "ppapi/c/ppb_compositor.h"
59 #include "ppapi/c/ppb_compositor_layer.h"
60 #include "ppapi/c/ppb_console.h"
61 #include "ppapi/c/ppb_core.h"
62 #include "ppapi/c/ppb_file_io.h"
63 #include "ppapi/c/ppb_file_ref.h"
64 #include "ppapi/c/ppb_file_system.h"
65 #include "ppapi/c/ppb_fullscreen.h"
66 #include "ppapi/c/ppb_graphics_2d.h"
67 #include "ppapi/c/ppb_graphics_3d.h"
68 #include "ppapi/c/ppb_host_resolver.h"
69 #include "ppapi/c/ppb_image_data.h"
70 #include "ppapi/c/ppb_instance.h"
71 #include "ppapi/c/ppb_media_stream_audio_track.h"
72 #include "ppapi/c/ppb_media_stream_video_track.h"
73 #include "ppapi/c/ppb_messaging.h"
74 #include "ppapi/c/ppb_mouse_cursor.h"
75 #include "ppapi/c/ppb_mouse_lock.h"
76 #include "ppapi/c/ppb_net_address.h"
77 #include "ppapi/c/ppb_network_list.h"
78 #include "ppapi/c/ppb_network_monitor.h"
79 #include "ppapi/c/ppb_network_proxy.h"
80 #include "ppapi/c/ppb_opengles2.h"
81 #include "ppapi/c/ppb_tcp_socket.h"
82 #include "ppapi/c/ppb_text_input_controller.h"
83 #include "ppapi/c/ppb_udp_socket.h"
84 #include "ppapi/c/ppb_url_loader.h"
85 #include "ppapi/c/ppb_url_request_info.h"
86 #include "ppapi/c/ppb_url_response_info.h"
87 #include "ppapi/c/ppb_var.h"
88 #include "ppapi/c/ppb_var_array.h"
89 #include "ppapi/c/ppb_var_array_buffer.h"
90 #include "ppapi/c/ppb_var_dictionary.h"
91 #include "ppapi/c/ppb_video_decoder.h"
92 #include "ppapi/c/ppb_video_encoder.h"
93 #include "ppapi/c/ppb_video_frame.h"
94 #include "ppapi/c/ppb_view.h"
95 #include "ppapi/c/ppp.h"
96 #include "ppapi/c/ppp_instance.h"
97 #include "ppapi/c/private/ppb_camera_capabilities_private.h"
98 #include "ppapi/c/private/ppb_camera_device_private.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_find_private.h"
103 #include "ppapi/c/private/ppb_flash.h"
104 #include "ppapi/c/private/ppb_flash_clipboard.h"
105 #include "ppapi/c/private/ppb_flash_device_id.h"
106 #include "ppapi/c/private/ppb_flash_drm.h"
107 #include "ppapi/c/private/ppb_flash_file.h"
108 #include "ppapi/c/private/ppb_flash_font_file.h"
109 #include "ppapi/c/private/ppb_flash_fullscreen.h"
110 #include "ppapi/c/private/ppb_flash_menu.h"
111 #include "ppapi/c/private/ppb_flash_message_loop.h"
112 #include "ppapi/c/private/ppb_flash_print.h"
113 #include "ppapi/c/private/ppb_host_resolver_private.h"
114 #include "ppapi/c/private/ppb_instance_private.h"
115 #include "ppapi/c/private/ppb_isolated_file_system_private.h"
116 #include "ppapi/c/private/ppb_output_protection_private.h"
117 #include "ppapi/c/private/ppb_pdf.h"
118 #include "ppapi/c/private/ppb_proxy_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/dictionary_var.h"
134 #include "ppapi/shared_impl/ppapi_preferences.h"
135 #include "ppapi/shared_impl/ppapi_switches.h"
136 #include "ppapi/shared_impl/ppb_input_event_shared.h"
137 #include "ppapi/shared_impl/ppb_opengles2_shared.h"
138 #include "ppapi/shared_impl/ppb_var_shared.h"
139 #include "ppapi/shared_impl/time_conversion.h"
140 #include "ppapi/thunk/enter.h"
141 #include "ppapi/thunk/ppb_graphics_2d_api.h"
142 #include "ppapi/thunk/thunk.h"
144 #if defined(OS_CHROMEOS)
145 #include "ppapi/c/private/ppb_platform_verification_private.h"
148 using ppapi::InputEventData
;
149 using ppapi::PpapiGlobals
;
150 using ppapi::TimeTicksToPPTimeTicks
;
151 using ppapi::TimeToPPTime
;
152 using ppapi::thunk::EnterResource
;
153 using ppapi::thunk::PPB_Graphics2D_API
;
154 using ppapi::thunk::PPB_InputEvent_API
;
160 // Global tracking info for PPAPI plugins. This is lazily created before the
161 // first plugin is allocated, and leaked on shutdown.
163 // Note that we don't want a Singleton here since destroying this object will
164 // try to free some stuff that requires WebKit, and Singletons are destroyed
166 // TODO(raymes): I'm not sure if it is completely necessary to leak the
167 // HostGlobals. Figure out the shutdown sequence and find a way to do this
169 HostGlobals
* host_globals
= NULL
;
171 // Maintains all currently loaded plugin libs for validating PP_Module
173 typedef std::set
<PluginModule
*> PluginModuleSet
;
175 PluginModuleSet
* GetLivePluginSet() {
176 CR_DEFINE_STATIC_LOCAL(PluginModuleSet
, live_plugin_libs
, ());
177 return &live_plugin_libs
;
180 class PowerSaverTestPluginDelegate
: public PluginInstanceThrottler::Observer
{
182 explicit PowerSaverTestPluginDelegate(PluginInstanceThrottlerImpl
* throttler
)
183 : throttler_(throttler
) {
184 throttler_
->AddObserver(this);
185 PostPowerSaverStatusToJavaScript("initial");
188 virtual ~PowerSaverTestPluginDelegate() { throttler_
->RemoveObserver(this); }
190 static void PostPowerSaverStatusToJavaScript(
191 PepperPluginInstanceImpl
* instance
,
192 const std::string
& source
) {
195 bool is_hidden_for_placeholder
= false;
196 bool is_peripheral
= false;
197 bool is_throttled
= false;
199 if (instance
->throttler()) {
200 PluginInstanceThrottlerImpl
* throttler
= instance
->throttler();
201 is_hidden_for_placeholder
= throttler
->IsHiddenForPlaceholder();
202 is_peripheral
= throttler
->power_saver_enabled();
203 is_throttled
= throttler
->IsThrottled();
206 // Refcounted by the returned PP_Var.
207 ppapi::DictionaryVar
* dictionary
= new ppapi::DictionaryVar
;
208 dictionary
->Set(ppapi::StringVar::StringToPPVar("source"),
209 ppapi::StringVar::StringToPPVar(source
));
210 dictionary
->Set(ppapi::StringVar::StringToPPVar("isHiddenForPlaceholder"),
211 PP_MakeBool(PP_FromBool(is_hidden_for_placeholder
)));
212 dictionary
->Set(ppapi::StringVar::StringToPPVar("isPeripheral"),
213 PP_MakeBool(PP_FromBool(is_peripheral
)));
214 dictionary
->Set(ppapi::StringVar::StringToPPVar("isThrottled"),
215 PP_MakeBool(PP_FromBool(is_throttled
)));
217 instance
->PostMessageToJavaScript(dictionary
->GetPPVar());
221 void OnThrottleStateChange() override
{
222 PostPowerSaverStatusToJavaScript("throttleStatusChange");
225 void OnPeripheralStateChange() override
{
226 PostPowerSaverStatusToJavaScript("peripheralStatusChange");
229 void OnHiddenForPlaceholder(bool hidden
) override
{
230 PostPowerSaverStatusToJavaScript("hiddenForPlaceholderStatusChange");
233 void OnThrottlerDestroyed() override
{ delete this; }
235 void PostPowerSaverStatusToJavaScript(const std::string
& source
) {
236 if (!throttler_
->GetWebPlugin() || !throttler_
->GetWebPlugin()->instance())
238 PostPowerSaverStatusToJavaScript(throttler_
->GetWebPlugin()->instance(),
242 // Non-owning pointer.
243 PluginInstanceThrottlerImpl
* const throttler_
;
246 // PPB_Core --------------------------------------------------------------------
248 void AddRefResource(PP_Resource resource
) {
249 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(resource
);
252 void ReleaseResource(PP_Resource resource
) {
253 PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(resource
);
256 PP_Time
GetTime() { return TimeToPPTime(base::Time::Now()); }
258 PP_TimeTicks
GetTickTime() {
259 return TimeTicksToPPTimeTicks(base::TimeTicks::Now());
262 void CallOnMainThread(int delay_in_msec
,
263 PP_CompletionCallback callback
,
266 PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostDelayedTask(
268 base::Bind(callback
.func
, callback
.user_data
, result
),
269 base::TimeDelta::FromMilliseconds(delay_in_msec
));
273 PP_Bool
IsMainThread() {
274 return PP_FromBool(PpapiGlobals::Get()
275 ->GetMainThreadMessageLoop()
276 ->BelongsToCurrentThread());
279 const PPB_Core core_interface
= {&AddRefResource
, &ReleaseResource
,
280 &GetTime
, &GetTickTime
,
281 &CallOnMainThread
, &IsMainThread
};
283 // PPB_Testing -----------------------------------------------------------------
285 PP_Bool
ReadImageData(PP_Resource device_context_2d
,
287 const PP_Point
* top_left
) {
288 EnterResource
<PPB_Graphics2D_API
> enter(device_context_2d
, true);
291 return PP_FromBool(enter
.object()->ReadImageData(image
, top_left
));
294 void RunMessageLoop(PP_Instance instance
) {
295 base::MessageLoop::ScopedNestableTaskAllower
allow(
296 base::MessageLoop::current());
297 base::MessageLoop::current()->Run();
300 void QuitMessageLoop(PP_Instance instance
) {
301 base::MessageLoop::current()->QuitNow();
304 uint32_t GetLiveObjectsForInstance(PP_Instance instance_id
) {
305 return HostGlobals::Get()->GetResourceTracker()->GetLiveObjectsForInstance(
309 PP_Bool
IsOutOfProcess() { return PP_FALSE
; }
311 void PostPowerSaverStatus(PP_Instance instance_id
) {
312 PepperPluginInstanceImpl
* plugin_instance
=
313 host_globals
->GetInstance(instance_id
);
314 if (!plugin_instance
)
317 PowerSaverTestPluginDelegate::PostPowerSaverStatusToJavaScript(
318 plugin_instance
, "getPowerSaverStatusResponse");
321 void SubscribeToPowerSaverNotifications(PP_Instance instance_id
) {
322 PepperPluginInstanceImpl
* plugin_instance
=
323 host_globals
->GetInstance(instance_id
);
324 if (!plugin_instance
)
327 if (plugin_instance
->throttler()) {
328 // Manages its own lifetime.
329 new PowerSaverTestPluginDelegate(plugin_instance
->throttler());
331 // Just send an initial status. This status will never be updated.
332 PowerSaverTestPluginDelegate::PostPowerSaverStatusToJavaScript(
333 plugin_instance
, "initial");
337 void SimulateInputEvent(PP_Instance instance
, PP_Resource input_event
) {
338 PepperPluginInstanceImpl
* plugin_instance
=
339 host_globals
->GetInstance(instance
);
340 if (!plugin_instance
)
343 EnterResource
<PPB_InputEvent_API
> enter(input_event
, false);
347 const InputEventData
& input_event_data
= enter
.object()->GetInputEventData();
348 plugin_instance
->SimulateInputEvent(input_event_data
);
351 PP_Var
GetDocumentURL(PP_Instance instance
, PP_URLComponents_Dev
* components
) {
352 PepperPluginInstanceImpl
* plugin_instance
=
353 host_globals
->GetInstance(instance
);
354 if (!plugin_instance
)
355 return PP_MakeUndefined();
356 return plugin_instance
->GetDocumentURL(instance
, components
);
359 uint32_t GetLiveVars(PP_Var live_vars
[], uint32_t array_size
) {
360 std::vector
<PP_Var
> vars
=
361 PpapiGlobals::Get()->GetVarTracker()->GetLiveVars();
363 i
< std::min(static_cast<size_t>(array_size
), vars
.size());
365 live_vars
[i
] = vars
[i
];
369 void SetMinimumArrayBufferSizeForShmem(PP_Instance
/*instance*/,
370 uint32_t /*threshold*/) {
371 // Does nothing. Not needed in-process.
374 void RunV8GC(PP_Instance instance
) {
375 content::PepperPluginInstance::Get(instance
)->GetIsolate()->
376 RequestGarbageCollectionForTesting(v8::Isolate::kFullGarbageCollection
);
379 const PPB_Testing_Private testing_interface
= {
383 &GetLiveObjectsForInstance
,
385 &PostPowerSaverStatus
,
386 &SubscribeToPowerSaverNotifications
,
390 &SetMinimumArrayBufferSizeForShmem
,
393 // GetInterface ----------------------------------------------------------------
395 const void* InternalGetInterface(const char* name
) {
396 // Allow custom interface factories first stab at the GetInterface call.
397 const void* custom_interface
=
398 GetContentClient()->renderer()->CreatePPAPIInterface(name
);
399 if (custom_interface
)
400 return custom_interface
;
402 // TODO(brettw) put these in a hash map for better performance.
403 #define PROXIED_IFACE(iface_str, iface_struct) \
404 if (strcmp(name, iface_str) == 0) \
405 return ppapi::thunk::Get##iface_struct##_Thunk();
407 #include "ppapi/thunk/interfaces_ppb_private.h"
408 #include "ppapi/thunk/interfaces_ppb_private_flash.h"
409 #include "ppapi/thunk/interfaces_ppb_private_no_permissions.h"
410 #include "ppapi/thunk/interfaces_ppb_public_dev.h"
411 #include "ppapi/thunk/interfaces_ppb_public_dev_channel.h"
412 #include "ppapi/thunk/interfaces_ppb_public_stable.h"
416 #define LEGACY_IFACE(iface_str, function_name) \
417 if (strcmp(name, iface_str) == 0) \
418 return function_name;
420 #include "ppapi/thunk/interfaces_legacy.h"
424 // Only support the testing interface when the command line switch is
425 // specified. This allows us to prevent people from (ab)using this interface
426 // in production code.
427 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
428 switches::kEnablePepperTesting
)) {
429 if (strcmp(name
, PPB_TESTING_PRIVATE_INTERFACE
) == 0)
430 return &testing_interface
;
435 const void* GetInterface(const char* name
) {
436 // All interfaces should be used on the main thread.
437 CHECK(IsMainThread());
439 return InternalGetInterface(name
);
442 // Gets the PPAPI entry points from the given library and places them into the
443 // given structure. Returns true on success.
444 bool LoadEntryPointsFromLibrary(const base::NativeLibrary
& library
,
445 PepperPluginInfo::EntryPoints
* entry_points
) {
446 entry_points
->get_interface
=
447 reinterpret_cast<PepperPluginInfo::GetInterfaceFunc
>(
448 base::GetFunctionPointerFromNativeLibrary(library
,
449 "PPP_GetInterface"));
450 if (!entry_points
->get_interface
) {
451 LOG(WARNING
) << "No PPP_GetInterface in plugin library";
455 entry_points
->initialize_module
=
456 reinterpret_cast<PepperPluginInfo::PPP_InitializeModuleFunc
>(
457 base::GetFunctionPointerFromNativeLibrary(library
,
458 "PPP_InitializeModule"));
459 if (!entry_points
->initialize_module
) {
460 LOG(WARNING
) << "No PPP_InitializeModule in plugin library";
464 // It's okay for PPP_ShutdownModule to not be defined and shutdown_module to
466 entry_points
->shutdown_module
=
467 reinterpret_cast<PepperPluginInfo::PPP_ShutdownModuleFunc
>(
468 base::GetFunctionPointerFromNativeLibrary(library
,
469 "PPP_ShutdownModule"));
474 void CreateHostForInProcessModule(RenderFrameImpl
* render_frame
,
475 PluginModule
* module
,
476 const WebPluginInfo
& webplugin_info
) {
477 // First time an in-process plugin was used, make a host for it.
478 const PepperPluginInfo
* info
=
479 PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info
);
480 DCHECK(!info
->is_out_of_process
);
482 ppapi::PpapiPermissions
perms(PepperPluginRegistry::GetInstance()
483 ->GetInfoForPlugin(webplugin_info
)
485 RendererPpapiHostImpl
* host_impl
=
486 RendererPpapiHostImpl::CreateOnModuleForInProcess(module
, perms
);
487 render_frame
->PepperPluginCreated(host_impl
);
492 // PluginModule ----------------------------------------------------------------
494 PluginModule::PluginModule(const std::string
& name
,
495 const std::string
& version
,
496 const base::FilePath
& path
,
497 const ppapi::PpapiPermissions
& perms
)
498 : callback_tracker_(new ppapi::CallbackTracker
),
499 is_in_destructor_(false),
506 permissions_(ppapi::PpapiPermissions::GetForCommandLine(perms
.GetBits())),
507 reserve_instance_id_(NULL
) {
508 // Ensure the globals object is created.
510 host_globals
= new HostGlobals
;
512 memset(&entry_points_
, 0, sizeof(entry_points_
));
513 pp_module_
= HostGlobals::Get()->AddModule(this);
514 GetLivePluginSet()->insert(this);
517 PluginModule::~PluginModule() {
518 // In the past there have been crashes reentering the plugin module
519 // destructor. Catch if that happens again earlier.
520 CHECK(!is_in_destructor_
);
521 is_in_destructor_
= true;
523 // When the module is being deleted, there should be no more instances still
524 // holding a reference to us.
525 DCHECK(instances_
.empty());
527 // Some resources and other stuff are hung off of the embedder state, which
528 // should be torn down before the routing stuff below.
529 renderer_ppapi_host_
.reset();
531 GetLivePluginSet()->erase(this);
533 callback_tracker_
->AbortAll();
535 if (entry_points_
.shutdown_module
)
536 entry_points_
.shutdown_module();
539 base::UnloadNativeLibrary(library_
);
541 // Notifications that we've been deleted should be last.
542 HostGlobals::Get()->ModuleDeleted(pp_module_
);
544 // When the plugin crashes, we immediately tell the lifetime delegate that
545 // we're gone, so we don't want to tell it again.
546 PepperPluginRegistry::GetInstance()->PluginModuleDead(this);
549 // Don't add stuff here, the two notifications that the module object has
550 // been deleted should be last. This allows, for example,
551 // PPB_Proxy.IsInModuleDestructor to map PP_Module to this class during the
552 // previous parts of the destructor.
555 void PluginModule::SetRendererPpapiHost(
556 scoped_ptr
<RendererPpapiHostImpl
> host
) {
557 renderer_ppapi_host_
= host
.Pass();
560 bool PluginModule::InitAsInternalPlugin(
561 const PepperPluginInfo::EntryPoints
& entry_points
) {
562 if (InitializeModule(entry_points
)) {
563 entry_points_
= entry_points
;
569 bool PluginModule::InitAsLibrary(const base::FilePath
& path
) {
570 base::NativeLibrary library
= base::LoadNativeLibrary(path
, NULL
);
574 PepperPluginInfo::EntryPoints entry_points
;
576 if (!LoadEntryPointsFromLibrary(library
, &entry_points
) ||
577 !InitializeModule(entry_points
)) {
578 base::UnloadNativeLibrary(library
);
581 entry_points_
= entry_points
;
586 void PluginModule::InitAsProxied(
587 HostDispatcherWrapper
* host_dispatcher_wrapper
) {
588 DCHECK(!host_dispatcher_wrapper_
.get());
589 host_dispatcher_wrapper_
.reset(host_dispatcher_wrapper
);
592 scoped_refptr
<PluginModule
>
593 PluginModule::CreateModuleForExternalPluginInstance() {
594 // Create a new module, but don't set the lifetime delegate. This isn't a
595 // plugin in the usual sense, so it isn't tracked by the browser.
596 scoped_refptr
<PluginModule
> external_plugin_module(
597 new PluginModule(name_
, version_
, path_
, permissions_
));
598 return external_plugin_module
;
601 PP_ExternalPluginResult
PluginModule::InitAsProxiedExternalPlugin(
602 PepperPluginInstanceImpl
* instance
) {
603 DCHECK(host_dispatcher_wrapper_
.get());
604 // InitAsProxied (for the trusted/out-of-process case) initializes only the
605 // module, and one or more instances are added later. In this case, the
606 // PluginInstance was already created as in-process, so we missed the proxy
607 // AddInstance step and must do it now.
608 host_dispatcher_wrapper_
->AddInstance(instance
->pp_instance());
609 // For external plugins, we need to tell the instance to reset itself as
610 // proxied. This will clear cached interface pointers and send DidCreate (etc)
611 // to the plugin side of the proxy.
612 return instance
->ResetAsProxied(this);
615 bool PluginModule::IsProxied() const { return !!host_dispatcher_wrapper_
; }
617 base::ProcessId
PluginModule::GetPeerProcessId() {
618 if (host_dispatcher_wrapper_
)
619 return host_dispatcher_wrapper_
->peer_pid();
620 return base::kNullProcessId
;
623 int PluginModule::GetPluginChildId() {
624 if (host_dispatcher_wrapper_
)
625 return host_dispatcher_wrapper_
->plugin_child_id();
630 const PPB_Core
* PluginModule::GetCore() { return &core_interface
; }
633 bool PluginModule::SupportsInterface(const char* name
) {
634 return !!InternalGetInterface(name
);
637 PepperPluginInstanceImpl
* PluginModule::CreateInstance(
638 RenderFrameImpl
* render_frame
,
639 blink::WebPluginContainer
* container
,
640 const GURL
& plugin_url
) {
641 PepperPluginInstanceImpl
* instance
= PepperPluginInstanceImpl::Create(
642 render_frame
, this, container
, plugin_url
);
644 LOG(WARNING
) << "Plugin doesn't support instance interface, failing.";
647 if (host_dispatcher_wrapper_
)
648 host_dispatcher_wrapper_
->AddInstance(instance
->pp_instance());
652 PepperPluginInstanceImpl
* PluginModule::GetSomeInstance() const {
653 // This will generally crash later if there is not actually any instance to
654 // return, so we force a crash now to make bugs easier to track down.
655 CHECK(!instances_
.empty());
656 return *instances_
.begin();
659 const void* PluginModule::GetPluginInterface(const char* name
) const {
660 if (host_dispatcher_wrapper_
)
661 return host_dispatcher_wrapper_
->GetProxiedInterface(name
);
663 // In-process plugins.
664 if (!entry_points_
.get_interface
)
666 return entry_points_
.get_interface(name
);
669 void PluginModule::InstanceCreated(PepperPluginInstanceImpl
* instance
) {
670 instances_
.insert(instance
);
673 void PluginModule::InstanceDeleted(PepperPluginInstanceImpl
* instance
) {
674 if (host_dispatcher_wrapper_
)
675 host_dispatcher_wrapper_
->RemoveInstance(instance
->pp_instance());
676 instances_
.erase(instance
);
679 scoped_refptr
<ppapi::CallbackTracker
> PluginModule::GetCallbackTracker() {
680 return callback_tracker_
;
683 void PluginModule::PluginCrashed() {
684 DCHECK(!is_crashed_
); // Should only get one notification.
687 // Notify all instances that they crashed.
688 for (PluginInstanceSet::iterator i
= instances_
.begin();
689 i
!= instances_
.end();
691 (*i
)->InstanceCrashed();
693 PepperPluginRegistry::GetInstance()->PluginModuleDead(this);
696 void PluginModule::SetReserveInstanceIDCallback(
697 PP_Bool (*reserve
)(PP_Module
, PP_Instance
)) {
698 DCHECK(!reserve_instance_id_
) << "Only expect one set.";
699 reserve_instance_id_
= reserve
;
702 bool PluginModule::ReserveInstanceID(PP_Instance instance
) {
703 if (reserve_instance_id_
)
704 return PP_ToBool(reserve_instance_id_(pp_module_
, instance
));
705 return true; // Instance ID is usable.
708 void PluginModule::SetBroker(PepperBroker
* broker
) {
709 DCHECK(!broker_
|| !broker
);
713 PepperBroker
* PluginModule::GetBroker() { return broker_
; }
715 RendererPpapiHostImpl
* PluginModule::CreateOutOfProcessModule(
716 RenderFrameImpl
* render_frame
,
717 const base::FilePath
& path
,
718 ppapi::PpapiPermissions permissions
,
719 const IPC::ChannelHandle
& channel_handle
,
720 base::ProcessId peer_pid
,
723 scoped_refptr
<PepperHungPluginFilter
> hung_filter(new PepperHungPluginFilter(
724 path
, render_frame
->GetRoutingID(), plugin_child_id
));
725 scoped_ptr
<HostDispatcherWrapper
> dispatcher(new HostDispatcherWrapper(
726 this, peer_pid
, plugin_child_id
, permissions
, is_external
));
727 if (!dispatcher
->Init(channel_handle
,
729 ppapi::Preferences(PpapiPreferencesBuilder::Build(
730 render_frame
->render_view()->webkit_preferences())),
734 RendererPpapiHostImpl
* host_impl
=
735 RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
736 this, dispatcher
->dispatcher(), permissions
);
737 render_frame
->PepperPluginCreated(host_impl
);
739 InitAsProxied(dispatcher
.release());
744 void PluginModule::ResetHostGlobalsForTest() {
749 bool PluginModule::InitializeModule(
750 const PepperPluginInfo::EntryPoints
& entry_points
) {
751 DCHECK(!host_dispatcher_wrapper_
.get()) << "Don't call for proxied modules.";
752 DCHECK(entry_points
.initialize_module
!= NULL
);
753 int retval
= entry_points
.initialize_module(pp_module(), &GetInterface
);
755 #if !defined(DISABLE_NACL)
756 LOG(WARNING
) << "PPP_InitializeModule returned failure " << retval
;
757 #endif // !defined(DISABLE_NACL)
763 scoped_refptr
<PluginModule
> PluginModule::Create(
764 RenderFrameImpl
* render_frame
,
765 const WebPluginInfo
& webplugin_info
,
766 bool* pepper_plugin_was_registered
) {
767 *pepper_plugin_was_registered
= true;
769 // See if a module has already been loaded for this plugin.
770 base::FilePath
path(webplugin_info
.path
);
771 scoped_refptr
<PluginModule
> module
=
772 PepperPluginRegistry::GetInstance()->GetLiveModule(path
);
774 if (!module
->renderer_ppapi_host()) {
775 // If the module exists and no embedder state was associated with it,
776 // then the module was one of the ones preloaded and is an in-process
777 // plugin. We need to associate our host state with it.
778 CreateHostForInProcessModule(render_frame
, module
.get(), webplugin_info
);
783 // In-process plugins will have always been created up-front to avoid the
784 // sandbox restrictions. So getting here implies it doesn't exist or should
785 // be out of process.
786 const PepperPluginInfo
* info
=
787 PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info
);
789 *pepper_plugin_was_registered
= false;
790 return scoped_refptr
<PluginModule
>();
791 } else if (!info
->is_out_of_process
) {
792 // In-process plugin not preloaded, it probably couldn't be initialized.
793 return scoped_refptr
<PluginModule
>();
796 // Out of process: have the browser start the plugin process for us.
797 IPC::ChannelHandle channel_handle
;
798 base::ProcessId peer_pid
= 0;
799 int plugin_child_id
= 0;
800 render_frame
->Send(new FrameHostMsg_OpenChannelToPepperPlugin(
801 path
, &channel_handle
, &peer_pid
, &plugin_child_id
));
802 if (channel_handle
.name
.empty()) {
803 // Couldn't be initialized.
804 return scoped_refptr
<PluginModule
>();
807 ppapi::PpapiPermissions
permissions(info
->permissions
);
809 // AddLiveModule must be called before any early returns since the
810 // module's destructor will remove itself.
811 module
= new PluginModule(info
->name
, info
->version
, path
, permissions
);
812 PepperPluginRegistry::GetInstance()->AddLiveModule(path
, module
.get());
814 if (!module
->CreateOutOfProcessModule(render_frame
,
820 false)) // is_external = false
821 return scoped_refptr
<PluginModule
>();
826 } // namespace content