[Android] Implement 3-way sensor fallback for Device Orientation.
[chromium-blink-merge.git] / content / renderer / pepper / plugin_module.cc
blobf97fdf683909bfc69f7f52fac76b78b47fdf57df
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"
7 #include <set>
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/time/time.h"
15 #include "build/build_config.h"
16 #include "content/common/view_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_compositor.h"
58 #include "ppapi/c/ppb_compositor_layer.h"
59 #include "ppapi/c/ppb_console.h"
60 #include "ppapi/c/ppb_core.h"
61 #include "ppapi/c/ppb_file_io.h"
62 #include "ppapi/c/ppb_file_ref.h"
63 #include "ppapi/c/ppb_file_system.h"
64 #include "ppapi/c/ppb_fullscreen.h"
65 #include "ppapi/c/ppb_graphics_2d.h"
66 #include "ppapi/c/ppb_graphics_3d.h"
67 #include "ppapi/c/ppb_host_resolver.h"
68 #include "ppapi/c/ppb_image_data.h"
69 #include "ppapi/c/ppb_instance.h"
70 #include "ppapi/c/ppb_media_stream_audio_track.h"
71 #include "ppapi/c/ppb_media_stream_video_track.h"
72 #include "ppapi/c/ppb_messaging.h"
73 #include "ppapi/c/ppb_mouse_cursor.h"
74 #include "ppapi/c/ppb_mouse_lock.h"
75 #include "ppapi/c/ppb_net_address.h"
76 #include "ppapi/c/ppb_network_list.h"
77 #include "ppapi/c/ppb_network_monitor.h"
78 #include "ppapi/c/ppb_network_proxy.h"
79 #include "ppapi/c/ppb_opengles2.h"
80 #include "ppapi/c/ppb_tcp_socket.h"
81 #include "ppapi/c/ppb_text_input_controller.h"
82 #include "ppapi/c/ppb_udp_socket.h"
83 #include "ppapi/c/ppb_url_loader.h"
84 #include "ppapi/c/ppb_url_request_info.h"
85 #include "ppapi/c/ppb_url_response_info.h"
86 #include "ppapi/c/ppb_var.h"
87 #include "ppapi/c/ppb_var_array.h"
88 #include "ppapi/c/ppb_var_array_buffer.h"
89 #include "ppapi/c/ppb_var_dictionary.h"
90 #include "ppapi/c/ppb_video_decoder.h"
91 #include "ppapi/c/ppb_video_encoder.h"
92 #include "ppapi/c/ppb_video_frame.h"
93 #include "ppapi/c/ppb_view.h"
94 #include "ppapi/c/ppp.h"
95 #include "ppapi/c/ppp_instance.h"
96 #include "ppapi/c/private/ppb_camera_capabilities_private.h"
97 #include "ppapi/c/private/ppb_camera_device_private.h"
98 #include "ppapi/c/private/ppb_ext_crx_file_system_private.h"
99 #include "ppapi/c/private/ppb_file_io_private.h"
100 #include "ppapi/c/private/ppb_file_ref_private.h"
101 #include "ppapi/c/private/ppb_find_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_tcp_server_socket_private.h"
119 #include "ppapi/c/private/ppb_tcp_socket_private.h"
120 #include "ppapi/c/private/ppb_testing_private.h"
121 #include "ppapi/c/private/ppb_udp_socket_private.h"
122 #include "ppapi/c/private/ppb_uma_private.h"
123 #include "ppapi/c/private/ppb_video_destination_private.h"
124 #include "ppapi/c/private/ppb_video_source_private.h"
125 #include "ppapi/c/private/ppb_x509_certificate_private.h"
126 #include "ppapi/c/trusted/ppb_broker_trusted.h"
127 #include "ppapi/c/trusted/ppb_browser_font_trusted.h"
128 #include "ppapi/c/trusted/ppb_char_set_trusted.h"
129 #include "ppapi/c/trusted/ppb_file_chooser_trusted.h"
130 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
131 #include "ppapi/shared_impl/callback_tracker.h"
132 #include "ppapi/shared_impl/dictionary_var.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"
143 #if defined(OS_CHROMEOS)
144 #include "ppapi/c/private/ppb_platform_verification_private.h"
145 #endif
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;
155 namespace content {
157 namespace {
159 // Global tracking info for PPAPI plugins. This is lazily created before the
160 // first plugin is allocated, and leaked on shutdown.
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;
170 // Maintains all currently loaded plugin libs for validating PP_Module
171 // identifiers.
172 typedef std::set<PluginModule*> PluginModuleSet;
174 PluginModuleSet* GetLivePluginSet() {
175 CR_DEFINE_STATIC_LOCAL(PluginModuleSet, live_plugin_libs, ());
176 return &live_plugin_libs;
179 class PowerSaverTestPluginDelegate : public PluginInstanceThrottler::Observer {
180 public:
181 explicit PowerSaverTestPluginDelegate(PluginInstanceThrottlerImpl* throttler)
182 : throttler_(throttler) {
183 throttler_->AddObserver(this);
184 PostPowerSaverStatusToJavaScript("initial");
187 virtual ~PowerSaverTestPluginDelegate() { throttler_->RemoveObserver(this); }
189 static void PostPowerSaverStatusToJavaScript(
190 PepperPluginInstanceImpl* instance,
191 const std::string& source) {
192 DCHECK(instance);
194 bool is_hidden_for_placeholder = false;
195 bool is_peripheral = false;
196 bool is_throttled = false;
198 if (instance->throttler()) {
199 PluginInstanceThrottlerImpl* throttler = instance->throttler();
200 is_hidden_for_placeholder = throttler->IsHiddenForPlaceholder();
201 is_peripheral = throttler->power_saver_enabled();
202 is_throttled = throttler->IsThrottled();
205 // Refcounted by the returned PP_Var.
206 ppapi::DictionaryVar* dictionary = new ppapi::DictionaryVar;
207 dictionary->Set(ppapi::StringVar::StringToPPVar("source"),
208 ppapi::StringVar::StringToPPVar(source));
209 dictionary->Set(ppapi::StringVar::StringToPPVar("isHiddenForPlaceholder"),
210 PP_MakeBool(PP_FromBool(is_hidden_for_placeholder)));
211 dictionary->Set(ppapi::StringVar::StringToPPVar("isPeripheral"),
212 PP_MakeBool(PP_FromBool(is_peripheral)));
213 dictionary->Set(ppapi::StringVar::StringToPPVar("isThrottled"),
214 PP_MakeBool(PP_FromBool(is_throttled)));
216 instance->PostMessageToJavaScript(dictionary->GetPPVar());
219 private:
220 void OnThrottleStateChange() override {
221 PostPowerSaverStatusToJavaScript("throttleStatusChange");
224 void OnPeripheralStateChange() override {
225 PostPowerSaverStatusToJavaScript("peripheralStatusChange");
228 void OnHiddenForPlaceholder(bool hidden) override {
229 PostPowerSaverStatusToJavaScript("hiddenForPlaceholderStatusChange");
232 void OnThrottlerDestroyed() override { delete this; }
234 void PostPowerSaverStatusToJavaScript(const std::string& source) {
235 if (!throttler_->GetWebPlugin() || !throttler_->GetWebPlugin()->instance())
236 return;
237 PostPowerSaverStatusToJavaScript(throttler_->GetWebPlugin()->instance(),
238 source);
241 // Non-owning pointer.
242 PluginInstanceThrottlerImpl* const throttler_;
245 // PPB_Core --------------------------------------------------------------------
247 void AddRefResource(PP_Resource resource) {
248 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(resource);
251 void ReleaseResource(PP_Resource resource) {
252 PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(resource);
255 PP_Time GetTime() { return TimeToPPTime(base::Time::Now()); }
257 PP_TimeTicks GetTickTime() {
258 return TimeTicksToPPTimeTicks(base::TimeTicks::Now());
261 void CallOnMainThread(int delay_in_msec,
262 PP_CompletionCallback callback,
263 int32_t result) {
264 if (callback.func) {
265 PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostDelayedTask(
266 FROM_HERE,
267 base::Bind(callback.func, callback.user_data, result),
268 base::TimeDelta::FromMilliseconds(delay_in_msec));
272 PP_Bool IsMainThread() {
273 return PP_FromBool(PpapiGlobals::Get()
274 ->GetMainThreadMessageLoop()
275 ->BelongsToCurrentThread());
278 const PPB_Core core_interface = {&AddRefResource, &ReleaseResource,
279 &GetTime, &GetTickTime,
280 &CallOnMainThread, &IsMainThread};
282 // PPB_Testing -----------------------------------------------------------------
284 PP_Bool ReadImageData(PP_Resource device_context_2d,
285 PP_Resource image,
286 const PP_Point* top_left) {
287 EnterResource<PPB_Graphics2D_API> enter(device_context_2d, true);
288 if (enter.failed())
289 return PP_FALSE;
290 return PP_FromBool(enter.object()->ReadImageData(image, top_left));
293 void RunMessageLoop(PP_Instance instance) {
294 base::MessageLoop::ScopedNestableTaskAllower allow(
295 base::MessageLoop::current());
296 base::MessageLoop::current()->Run();
299 void QuitMessageLoop(PP_Instance instance) {
300 base::MessageLoop::current()->QuitNow();
303 uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) {
304 return HostGlobals::Get()->GetResourceTracker()->GetLiveObjectsForInstance(
305 instance_id);
308 PP_Bool IsOutOfProcess() { return PP_FALSE; }
310 void PostPowerSaverStatus(PP_Instance instance_id) {
311 PepperPluginInstanceImpl* plugin_instance =
312 host_globals->GetInstance(instance_id);
313 if (!plugin_instance)
314 return;
316 PowerSaverTestPluginDelegate::PostPowerSaverStatusToJavaScript(
317 plugin_instance, "getPowerSaverStatusResponse");
320 void SubscribeToPowerSaverNotifications(PP_Instance instance_id) {
321 PepperPluginInstanceImpl* plugin_instance =
322 host_globals->GetInstance(instance_id);
323 if (!plugin_instance)
324 return;
326 if (plugin_instance->throttler()) {
327 // Manages its own lifetime.
328 new PowerSaverTestPluginDelegate(plugin_instance->throttler());
329 } else {
330 // Just send an initial status. This status will never be updated.
331 PowerSaverTestPluginDelegate::PostPowerSaverStatusToJavaScript(
332 plugin_instance, "initial");
336 void SimulateInputEvent(PP_Instance instance, PP_Resource input_event) {
337 PepperPluginInstanceImpl* plugin_instance =
338 host_globals->GetInstance(instance);
339 if (!plugin_instance)
340 return;
342 EnterResource<PPB_InputEvent_API> enter(input_event, false);
343 if (enter.failed())
344 return;
346 const InputEventData& input_event_data = enter.object()->GetInputEventData();
347 plugin_instance->SimulateInputEvent(input_event_data);
350 PP_Var GetDocumentURL(PP_Instance instance, PP_URLComponents_Dev* components) {
351 PepperPluginInstanceImpl* plugin_instance =
352 host_globals->GetInstance(instance);
353 if (!plugin_instance)
354 return PP_MakeUndefined();
355 return plugin_instance->GetDocumentURL(instance, components);
358 uint32_t GetLiveVars(PP_Var live_vars[], uint32_t array_size) {
359 std::vector<PP_Var> vars =
360 PpapiGlobals::Get()->GetVarTracker()->GetLiveVars();
361 for (size_t i = 0u;
362 i < std::min(static_cast<size_t>(array_size), vars.size());
363 ++i)
364 live_vars[i] = vars[i];
365 return vars.size();
368 void SetMinimumArrayBufferSizeForShmem(PP_Instance /*instance*/,
369 uint32_t /*threshold*/) {
370 // Does nothing. Not needed in-process.
373 void RunV8GC(PP_Instance instance) {
374 content::PepperPluginInstance::Get(instance)->GetIsolate()->
375 RequestGarbageCollectionForTesting(v8::Isolate::kFullGarbageCollection);
378 const PPB_Testing_Private testing_interface = {
379 &ReadImageData,
380 &RunMessageLoop,
381 &QuitMessageLoop,
382 &GetLiveObjectsForInstance,
383 &IsOutOfProcess,
384 &PostPowerSaverStatus,
385 &SubscribeToPowerSaverNotifications,
386 &SimulateInputEvent,
387 &GetDocumentURL,
388 &GetLiveVars,
389 &SetMinimumArrayBufferSizeForShmem,
390 &RunV8GC};
392 // GetInterface ----------------------------------------------------------------
394 const void* InternalGetInterface(const char* name) {
395 // Allow custom interface factories first stab at the GetInterface call.
396 const void* custom_interface =
397 GetContentClient()->renderer()->CreatePPAPIInterface(name);
398 if (custom_interface)
399 return custom_interface;
401 // TODO(brettw) put these in a hash map for better performance.
402 #define PROXIED_IFACE(iface_str, iface_struct) \
403 if (strcmp(name, iface_str) == 0) \
404 return ppapi::thunk::Get##iface_struct##_Thunk();
406 #include "ppapi/thunk/interfaces_ppb_private.h"
407 #include "ppapi/thunk/interfaces_ppb_private_flash.h"
408 #include "ppapi/thunk/interfaces_ppb_private_no_permissions.h"
409 #include "ppapi/thunk/interfaces_ppb_public_dev.h"
410 #include "ppapi/thunk/interfaces_ppb_public_dev_channel.h"
411 #include "ppapi/thunk/interfaces_ppb_public_stable.h"
413 #undef PROXIED_IFACE
415 #define LEGACY_IFACE(iface_str, function_name) \
416 if (strcmp(name, iface_str) == 0) \
417 return function_name;
419 #include "ppapi/thunk/interfaces_legacy.h"
421 #undef LEGACY_IFACE
423 // Only support the testing interface when the command line switch is
424 // specified. This allows us to prevent people from (ab)using this interface
425 // in production code.
426 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
427 switches::kEnablePepperTesting)) {
428 if (strcmp(name, PPB_TESTING_PRIVATE_INTERFACE) == 0)
429 return &testing_interface;
431 return NULL;
434 const void* GetInterface(const char* name) {
435 // All interfaces should be used on the main thread.
436 CHECK(IsMainThread());
438 return InternalGetInterface(name);
441 // Gets the PPAPI entry points from the given library and places them into the
442 // given structure. Returns true on success.
443 bool LoadEntryPointsFromLibrary(const base::NativeLibrary& library,
444 PepperPluginInfo::EntryPoints* entry_points) {
445 entry_points->get_interface =
446 reinterpret_cast<PepperPluginInfo::GetInterfaceFunc>(
447 base::GetFunctionPointerFromNativeLibrary(library,
448 "PPP_GetInterface"));
449 if (!entry_points->get_interface) {
450 LOG(WARNING) << "No PPP_GetInterface in plugin library";
451 return false;
454 entry_points->initialize_module =
455 reinterpret_cast<PepperPluginInfo::PPP_InitializeModuleFunc>(
456 base::GetFunctionPointerFromNativeLibrary(library,
457 "PPP_InitializeModule"));
458 if (!entry_points->initialize_module) {
459 LOG(WARNING) << "No PPP_InitializeModule in plugin library";
460 return false;
463 // It's okay for PPP_ShutdownModule to not be defined and shutdown_module to
464 // be NULL.
465 entry_points->shutdown_module =
466 reinterpret_cast<PepperPluginInfo::PPP_ShutdownModuleFunc>(
467 base::GetFunctionPointerFromNativeLibrary(library,
468 "PPP_ShutdownModule"));
470 return true;
473 void CreateHostForInProcessModule(RenderFrameImpl* render_frame,
474 PluginModule* module,
475 const WebPluginInfo& webplugin_info) {
476 // First time an in-process plugin was used, make a host for it.
477 const PepperPluginInfo* info =
478 PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info);
479 DCHECK(!info->is_out_of_process);
481 ppapi::PpapiPermissions perms(PepperPluginRegistry::GetInstance()
482 ->GetInfoForPlugin(webplugin_info)
483 ->permissions);
484 RendererPpapiHostImpl* host_impl =
485 RendererPpapiHostImpl::CreateOnModuleForInProcess(module, perms);
486 render_frame->PepperPluginCreated(host_impl);
489 } // namespace
491 // PluginModule ----------------------------------------------------------------
493 PluginModule::PluginModule(const std::string& name,
494 const std::string& version,
495 const base::FilePath& path,
496 const ppapi::PpapiPermissions& perms)
497 : callback_tracker_(new ppapi::CallbackTracker),
498 is_in_destructor_(false),
499 is_crashed_(false),
500 broker_(NULL),
501 library_(NULL),
502 name_(name),
503 version_(version),
504 path_(path),
505 permissions_(ppapi::PpapiPermissions::GetForCommandLine(perms.GetBits())),
506 reserve_instance_id_(NULL) {
507 // Ensure the globals object is created.
508 if (!host_globals)
509 host_globals = new HostGlobals;
511 memset(&entry_points_, 0, sizeof(entry_points_));
512 pp_module_ = HostGlobals::Get()->AddModule(this);
513 GetLivePluginSet()->insert(this);
516 PluginModule::~PluginModule() {
517 // In the past there have been crashes reentering the plugin module
518 // destructor. Catch if that happens again earlier.
519 CHECK(!is_in_destructor_);
520 is_in_destructor_ = true;
522 // When the module is being deleted, there should be no more instances still
523 // holding a reference to us.
524 DCHECK(instances_.empty());
526 // Some resources and other stuff are hung off of the embedder state, which
527 // should be torn down before the routing stuff below.
528 renderer_ppapi_host_.reset();
530 GetLivePluginSet()->erase(this);
532 callback_tracker_->AbortAll();
534 if (entry_points_.shutdown_module)
535 entry_points_.shutdown_module();
537 if (library_)
538 base::UnloadNativeLibrary(library_);
540 // Notifications that we've been deleted should be last.
541 HostGlobals::Get()->ModuleDeleted(pp_module_);
542 if (!is_crashed_) {
543 // When the plugin crashes, we immediately tell the lifetime delegate that
544 // we're gone, so we don't want to tell it again.
545 PepperPluginRegistry::GetInstance()->PluginModuleDead(this);
548 // Don't add stuff here, the two notifications that the module object has
549 // been deleted should be last. This allows, for example,
550 // PPB_Proxy.IsInModuleDestructor to map PP_Module to this class during the
551 // previous parts of the destructor.
554 void PluginModule::SetRendererPpapiHost(
555 scoped_ptr<RendererPpapiHostImpl> host) {
556 renderer_ppapi_host_ = host.Pass();
559 bool PluginModule::InitAsInternalPlugin(
560 const PepperPluginInfo::EntryPoints& entry_points) {
561 if (InitializeModule(entry_points)) {
562 entry_points_ = entry_points;
563 return true;
565 return false;
568 bool PluginModule::InitAsLibrary(const base::FilePath& path) {
569 base::NativeLibrary library = base::LoadNativeLibrary(path, NULL);
570 if (!library)
571 return false;
573 PepperPluginInfo::EntryPoints entry_points;
575 if (!LoadEntryPointsFromLibrary(library, &entry_points) ||
576 !InitializeModule(entry_points)) {
577 base::UnloadNativeLibrary(library);
578 return false;
580 entry_points_ = entry_points;
581 library_ = library;
582 return true;
585 void PluginModule::InitAsProxied(
586 HostDispatcherWrapper* host_dispatcher_wrapper) {
587 DCHECK(!host_dispatcher_wrapper_.get());
588 host_dispatcher_wrapper_.reset(host_dispatcher_wrapper);
591 scoped_refptr<PluginModule>
592 PluginModule::CreateModuleForExternalPluginInstance() {
593 // Create a new module, but don't set the lifetime delegate. This isn't a
594 // plugin in the usual sense, so it isn't tracked by the browser.
595 scoped_refptr<PluginModule> external_plugin_module(
596 new PluginModule(name_, version_, path_, permissions_));
597 return external_plugin_module;
600 PP_ExternalPluginResult PluginModule::InitAsProxiedExternalPlugin(
601 PepperPluginInstanceImpl* instance) {
602 DCHECK(host_dispatcher_wrapper_.get());
603 // InitAsProxied (for the trusted/out-of-process case) initializes only the
604 // module, and one or more instances are added later. In this case, the
605 // PluginInstance was already created as in-process, so we missed the proxy
606 // AddInstance step and must do it now.
607 host_dispatcher_wrapper_->AddInstance(instance->pp_instance());
608 // For external plugins, we need to tell the instance to reset itself as
609 // proxied. This will clear cached interface pointers and send DidCreate (etc)
610 // to the plugin side of the proxy.
611 return instance->ResetAsProxied(this);
614 bool PluginModule::IsProxied() const { return !!host_dispatcher_wrapper_; }
616 base::ProcessId PluginModule::GetPeerProcessId() {
617 if (host_dispatcher_wrapper_)
618 return host_dispatcher_wrapper_->peer_pid();
619 return base::kNullProcessId;
622 int PluginModule::GetPluginChildId() {
623 if (host_dispatcher_wrapper_)
624 return host_dispatcher_wrapper_->plugin_child_id();
625 return 0;
628 // static
629 const PPB_Core* PluginModule::GetCore() { return &core_interface; }
631 // static
632 bool PluginModule::SupportsInterface(const char* name) {
633 return !!InternalGetInterface(name);
636 PepperPluginInstanceImpl* PluginModule::CreateInstance(
637 RenderFrameImpl* render_frame,
638 blink::WebPluginContainer* container,
639 const GURL& plugin_url) {
640 PepperPluginInstanceImpl* instance = PepperPluginInstanceImpl::Create(
641 render_frame, this, container, plugin_url);
642 if (!instance) {
643 LOG(WARNING) << "Plugin doesn't support instance interface, failing.";
644 return NULL;
646 if (host_dispatcher_wrapper_)
647 host_dispatcher_wrapper_->AddInstance(instance->pp_instance());
648 return instance;
651 PepperPluginInstanceImpl* PluginModule::GetSomeInstance() const {
652 // This will generally crash later if there is not actually any instance to
653 // return, so we force a crash now to make bugs easier to track down.
654 CHECK(!instances_.empty());
655 return *instances_.begin();
658 const void* PluginModule::GetPluginInterface(const char* name) const {
659 if (host_dispatcher_wrapper_)
660 return host_dispatcher_wrapper_->GetProxiedInterface(name);
662 // In-process plugins.
663 if (!entry_points_.get_interface)
664 return NULL;
665 return entry_points_.get_interface(name);
668 void PluginModule::InstanceCreated(PepperPluginInstanceImpl* instance) {
669 instances_.insert(instance);
672 void PluginModule::InstanceDeleted(PepperPluginInstanceImpl* instance) {
673 if (host_dispatcher_wrapper_)
674 host_dispatcher_wrapper_->RemoveInstance(instance->pp_instance());
675 instances_.erase(instance);
678 scoped_refptr<ppapi::CallbackTracker> PluginModule::GetCallbackTracker() {
679 return callback_tracker_;
682 void PluginModule::PluginCrashed() {
683 DCHECK(!is_crashed_); // Should only get one notification.
684 is_crashed_ = true;
686 // Notify all instances that they crashed.
687 for (PluginInstanceSet::iterator i = instances_.begin();
688 i != instances_.end();
689 ++i)
690 (*i)->InstanceCrashed();
692 PepperPluginRegistry::GetInstance()->PluginModuleDead(this);
695 void PluginModule::SetReserveInstanceIDCallback(
696 PP_Bool (*reserve)(PP_Module, PP_Instance)) {
697 DCHECK(!reserve_instance_id_) << "Only expect one set.";
698 reserve_instance_id_ = reserve;
701 bool PluginModule::ReserveInstanceID(PP_Instance instance) {
702 if (reserve_instance_id_)
703 return PP_ToBool(reserve_instance_id_(pp_module_, instance));
704 return true; // Instance ID is usable.
707 void PluginModule::SetBroker(PepperBroker* broker) {
708 DCHECK(!broker_ || !broker);
709 broker_ = broker;
712 PepperBroker* PluginModule::GetBroker() { return broker_; }
714 RendererPpapiHostImpl* PluginModule::CreateOutOfProcessModule(
715 RenderFrameImpl* render_frame,
716 const base::FilePath& path,
717 ppapi::PpapiPermissions permissions,
718 const IPC::ChannelHandle& channel_handle,
719 base::ProcessId peer_pid,
720 int plugin_child_id,
721 bool is_external) {
722 scoped_refptr<PepperHungPluginFilter> hung_filter(new PepperHungPluginFilter(
723 path, render_frame->GetRoutingID(), plugin_child_id));
724 scoped_ptr<HostDispatcherWrapper> dispatcher(new HostDispatcherWrapper(
725 this, peer_pid, plugin_child_id, permissions, is_external));
726 if (!dispatcher->Init(channel_handle,
727 &GetInterface,
728 ppapi::Preferences(PpapiPreferencesBuilder::Build(
729 render_frame->render_view()->webkit_preferences())),
730 hung_filter.get()))
731 return NULL;
733 RendererPpapiHostImpl* host_impl =
734 RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
735 this, dispatcher->dispatcher(), permissions);
736 render_frame->PepperPluginCreated(host_impl);
738 InitAsProxied(dispatcher.release());
739 return host_impl;
742 // static
743 void PluginModule::ResetHostGlobalsForTest() {
744 delete host_globals;
745 host_globals = NULL;
748 bool PluginModule::InitializeModule(
749 const PepperPluginInfo::EntryPoints& entry_points) {
750 DCHECK(!host_dispatcher_wrapper_.get()) << "Don't call for proxied modules.";
751 DCHECK(entry_points.initialize_module != NULL);
752 int retval = entry_points.initialize_module(pp_module(), &GetInterface);
753 if (retval != 0) {
754 #if !defined(DISABLE_NACL)
755 LOG(WARNING) << "PPP_InitializeModule returned failure " << retval;
756 #endif // !defined(DISABLE_NACL)
757 return false;
759 return true;
762 scoped_refptr<PluginModule> PluginModule::Create(
763 RenderFrameImpl* render_frame,
764 const WebPluginInfo& webplugin_info,
765 bool* pepper_plugin_was_registered) {
766 *pepper_plugin_was_registered = true;
768 // See if a module has already been loaded for this plugin.
769 base::FilePath path(webplugin_info.path);
770 scoped_refptr<PluginModule> module =
771 PepperPluginRegistry::GetInstance()->GetLiveModule(path);
772 if (module.get()) {
773 if (!module->renderer_ppapi_host()) {
774 // If the module exists and no embedder state was associated with it,
775 // then the module was one of the ones preloaded and is an in-process
776 // plugin. We need to associate our host state with it.
777 CreateHostForInProcessModule(render_frame, module.get(), webplugin_info);
779 return module;
782 // In-process plugins will have always been created up-front to avoid the
783 // sandbox restrictions. So getting here implies it doesn't exist or should
784 // be out of process.
785 const PepperPluginInfo* info =
786 PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info);
787 if (!info) {
788 *pepper_plugin_was_registered = false;
789 return scoped_refptr<PluginModule>();
790 } else if (!info->is_out_of_process) {
791 // In-process plugin not preloaded, it probably couldn't be initialized.
792 return scoped_refptr<PluginModule>();
795 // Out of process: have the browser start the plugin process for us.
796 IPC::ChannelHandle channel_handle;
797 base::ProcessId peer_pid = 0;
798 int plugin_child_id = 0;
799 render_frame->Send(new ViewHostMsg_OpenChannelToPepperPlugin(
800 path, &channel_handle, &peer_pid, &plugin_child_id));
801 if (channel_handle.name.empty()) {
802 // Couldn't be initialized.
803 return scoped_refptr<PluginModule>();
806 ppapi::PpapiPermissions permissions(info->permissions);
808 // AddLiveModule must be called before any early returns since the
809 // module's destructor will remove itself.
810 module = new PluginModule(info->name, info->version, path, permissions);
811 PepperPluginRegistry::GetInstance()->AddLiveModule(path, module.get());
813 if (!module->CreateOutOfProcessModule(render_frame,
814 path,
815 permissions,
816 channel_handle,
817 peer_pid,
818 plugin_child_id,
819 false)) // is_external = false
820 return scoped_refptr<PluginModule>();
822 return module;
825 } // namespace content