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 147using ppapi::InputEventData; 148using ppapi::PpapiGlobals; 149using ppapi::TimeTicksToPPTimeTicks; 150using ppapi::TimeToPPTime; 151using ppapi::thunk::EnterResource; 152using ppapi::thunk::PPB_Graphics2D_API; 153using ppapi::thunk::PPB_InputEvent_API; 154 155namespace content { 156 157namespace { 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. 168HostGlobals* host_globals = NULL; 169 170// Maintains all currently loaded plugin libs for validating PP_Module 171// identifiers. 172typedef std::set<PluginModule*> PluginModuleSet; 173 174PluginModuleSet* GetLivePluginSet() { 175 CR_DEFINE_STATIC_LOCAL(PluginModuleSet, live_plugin_libs, ()); 176 return &live_plugin_libs; 177} 178 179// PPB_Core -------------------------------------------------------------------- 180 181void AddRefResource(PP_Resource resource) { 182 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(resource); 183} 184 185void ReleaseResource(PP_Resource resource) { 186 PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(resource); 187} 188 189PP_Time GetTime() { 190 return TimeToPPTime(base::Time::Now()); 191} 192 193PP_TimeTicks GetTickTime() { 194 return TimeTicksToPPTimeTicks(base::TimeTicks::Now()); 195} 196 197void 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 208PP_Bool IsMainThread() { 209 return BoolToPPBool(PpapiGlobals::Get()-> 210 GetMainThreadMessageLoop()->BelongsToCurrentThread()); 211} 212 213const PPB_Core core_interface = { 214 &AddRefResource, 215 &ReleaseResource, 216 &GetTime, 217 &GetTickTime, 218 &CallOnMainThread, 219 &IsMainThread 220}; 221 222// PPB_Testing ----------------------------------------------------------------- 223 224PP_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 233void RunMessageLoop(PP_Instance instance) { 234 base::MessageLoop::ScopedNestableTaskAllower allow( 235 base::MessageLoop::current()); 236 base::MessageLoop::current()->Run(); 237} 238 239void QuitMessageLoop(PP_Instance instance) { 240 base::MessageLoop::current()->QuitNow(); 241} 242 243uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) { 244 return HostGlobals::Get()->GetResourceTracker()->GetLiveObjectsForInstance( 245 instance_id); 246} 247 248PP_Bool IsOutOfProcess() { 249 return PP_FALSE; 250} 251 252void 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 266PP_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 274uint32_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 284void SetMinimumArrayBufferSizeForShmem(PP_Instance /*instance*/, 285 uint32_t /*threshold*/) { 286 // Does nothing. Not needed in-process. 287} 288 289const 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 303const 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 345const 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. 354bool 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 385void 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 405PluginModule::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 426PluginModule::~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 464void PluginModule::SetRendererPpapiHost( 465 scoped_ptr<RendererPpapiHostImpl> host) { 466 renderer_ppapi_host_ = host.Pass(); 467} 468 469bool 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 478bool 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 495void PluginModule::InitAsProxied( 496 HostDispatcherWrapper* host_dispatcher_wrapper) { 497 DCHECK(!host_dispatcher_wrapper_.get()); 498 host_dispatcher_wrapper_.reset(host_dispatcher_wrapper); 499} 500 501scoped_refptr<PluginModule> 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 512PP_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 526bool PluginModule::IsProxied() const { 527 return !!host_dispatcher_wrapper_; 528} 529 530base::ProcessId PluginModule::GetPeerProcessId() { 531 if (host_dispatcher_wrapper_) 532 return host_dispatcher_wrapper_->peer_pid(); 533 return base::kNullProcessId; 534} 535 536int PluginModule::GetPluginChildId() { 537 if (host_dispatcher_wrapper_) 538 return host_dispatcher_wrapper_->plugin_child_id(); 539 return 0; 540} 541 542// static 543const PPB_Core* PluginModule::GetCore() { 544 return &core_interface; 545} 546 547// static 548bool PluginModule::SupportsInterface(const char* name) { 549 return !!InternalGetInterface(name); 550} 551 552PepperPluginInstanceImpl* 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 567PepperPluginInstanceImpl* 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 574const 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 584void PluginModule::InstanceCreated(PepperPluginInstanceImpl* instance) { 585 instances_.insert(instance); 586} 587 588void PluginModule::InstanceDeleted(PepperPluginInstanceImpl* instance) { 589 if (host_dispatcher_wrapper_) 590 host_dispatcher_wrapper_->RemoveInstance(instance->pp_instance()); 591 instances_.erase(instance); 592} 593 594scoped_refptr<ppapi::CallbackTracker> PluginModule::GetCallbackTracker() { 595 return callback_tracker_; 596} 597 598void 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 610void 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 616bool 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 622void PluginModule::SetBroker(PepperBroker* broker) { 623 DCHECK(!broker_ || !broker); 624 broker_ = broker; 625} 626 627PepperBroker* PluginModule::GetBroker() { 628 return broker_; 629} 630 631RendererPpapiHostImpl* 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 664void PluginModule::ResetHostGlobalsForTest() { 665 delete host_globals; 666 host_globals = NULL; 667} 668 669bool 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 681scoped_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