diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-23 23:32:55 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-23 23:32:55 +0000 |
commit | 19215f85f0e477936a13c77450d0b12e40d7839c (patch) | |
tree | 95e4791d7a1e9bb1bd9736b2f3ec4cd0d1e5608a | |
parent | 4dd33d2a1bf4bff8c1c637bf38dda3f6d7882af5 (diff) | |
download | chromium_src-19215f85f0e477936a13c77450d0b12e40d7839c.zip chromium_src-19215f85f0e477936a13c77450d0b12e40d7839c.tar.gz chromium_src-19215f85f0e477936a13c77450d0b12e40d7839c.tar.bz2 |
Add in support for internal pepper plugins into the PepperPluginRegistry and pepper::PluginModule.
Used Chromoting's plugin as the first attempt at using this interface.
BUG=none
TEST=compiles
Review URL: http://codereview.chromium.org/2843018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50667 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/chrome_common.gypi | 5 | ||||
-rw-r--r-- | chrome/common/DEPS | 1 | ||||
-rw-r--r-- | chrome/common/pepper_plugin_registry.cc | 66 | ||||
-rw-r--r-- | chrome/common/pepper_plugin_registry.h | 11 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_plugin.cc | 27 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_plugin.h | 16 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_entrypoints.cc | 233 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_entrypoints.h | 20 | ||||
-rw-r--r-- | remoting/remoting.gyp | 85 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_module.cc | 109 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_module.h | 41 |
11 files changed, 510 insertions, 104 deletions
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index f4a8e6e..e178607 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -311,6 +311,11 @@ 'common/sandbox_policy.cc', ], }], + ['remoting==1', { + 'dependencies': [ + '../remoting/remoting.gyp:chromoting_plugin', + ], + }], ], 'export_dependent_settings': [ '../app/app.gyp:app_base', diff --git a/chrome/common/DEPS b/chrome/common/DEPS index c3db484..75629ca 100644 --- a/chrome/common/DEPS +++ b/chrome/common/DEPS @@ -3,6 +3,7 @@ include_rules = [ "+grit", # For generated headers "+libxml", "+media/audio", + "+remoting/client/plugin", "+sandbox/src", "+skia/include", "+webkit/default_plugin", diff --git a/chrome/common/pepper_plugin_registry.cc b/chrome/common/pepper_plugin_registry.cc index 0a23eca..e7771c4 100644 --- a/chrome/common/pepper_plugin_registry.cc +++ b/chrome/common/pepper_plugin_registry.cc @@ -7,6 +7,7 @@ #include "base/command_line.h" #include "base/string_util.h" #include "chrome/common/chrome_switches.h" +#include "remoting/client/plugin/pepper_entrypoints.h" // static PepperPluginRegistry* PepperPluginRegistry::GetInstance() { @@ -16,6 +17,21 @@ PepperPluginRegistry* PepperPluginRegistry::GetInstance() { // static void PepperPluginRegistry::GetList(std::vector<PepperPluginInfo>* plugins) { + InternalPluginInfoList internal_plugin_info; + GetInternalPluginInfo(&internal_plugin_info); + for (InternalPluginInfoList::const_iterator it = + internal_plugin_info.begin(); + it != internal_plugin_info.end(); + ++it) { + plugins->push_back(*it); + } + + GetPluginInfoFromSwitch(plugins); +} + +// static +void PepperPluginRegistry::GetPluginInfoFromSwitch( + std::vector<PepperPluginInfo>* plugins) { const std::wstring& value = CommandLine::ForCurrentProcess()->GetSwitchValue( switches::kRegisterPepperPlugins); if (value.empty()) @@ -44,6 +60,35 @@ void PepperPluginRegistry::GetList(std::vector<PepperPluginInfo>* plugins) { } } +// static +void PepperPluginRegistry::GetInternalPluginInfo( + InternalPluginInfoList* plugin_info) { + // Currently, to centralize the internal plugin registration logic, we + // hardcode the list of plugins, mimetypes, and registration information + // in this function. This is gross, but because the GetList() function is + // called from both the renderer and browser the other option is to force a + // special register function for each plugin to be called by both + // RendererMain() and BrowserMain(). This seemed like the better tradeoff. + // + // TODO(ajwong): Think up a better way to maintain the plugin registration + // information. Pehraps by construction of a singly linked list of + // plugin initializers that is built with static initializers? + +#if defined(ENABLE_REMOTING) + InternalPluginInfo info; + // Add the chromoting plugin. + info.path = + FilePath(FILE_PATH_LITERAL("internal-chromoting")); + info.mime_types.push_back("pepper-application/x-chromoting"); + info.entry_points.get_interface = remoting::PPP_GetInterface; + info.entry_points.initialize_module = remoting::PPP_InitializeModule; + info.entry_points.shutdown_module = remoting::PPP_ShutdownModule; + + plugin_info->push_back(info); +#endif + +} + pepper::PluginModule* PepperPluginRegistry::GetModule( const FilePath& path) const { ModuleMap::const_iterator it = modules_.find(path); @@ -53,8 +98,27 @@ pepper::PluginModule* PepperPluginRegistry::GetModule( } PepperPluginRegistry::PepperPluginRegistry() { + InternalPluginInfoList internal_plugin_info; + GetInternalPluginInfo(&internal_plugin_info); + // Register modules for these suckers. + for (InternalPluginInfoList::const_iterator it = + internal_plugin_info.begin(); + it != internal_plugin_info.end(); + ++it) { + const FilePath& path = it->path; + ModuleHandle module = + pepper::PluginModule::CreateInternalModule(it->entry_points); + if (!module) { + DLOG(ERROR) << "Failed to load pepper module: " << path.value(); + continue; + } + modules_[path] = module; + } + + // Add the modules specified on the command line last so that they can + // override the internal plugins. std::vector<PepperPluginInfo> plugins; - GetList(&plugins); + GetPluginInfoFromSwitch(&plugins); for (size_t i = 0; i < plugins.size(); ++i) { const FilePath& path = plugins[i].path; ModuleHandle module = pepper::PluginModule::CreateModule(path); diff --git a/chrome/common/pepper_plugin_registry.h b/chrome/common/pepper_plugin_registry.h index 940a1ba..9949ed4 100644 --- a/chrome/common/pepper_plugin_registry.h +++ b/chrome/common/pepper_plugin_registry.h @@ -7,11 +7,12 @@ #include <string> #include <map> +#include <vector> #include "webkit/glue/plugins/pepper_plugin_module.h" struct PepperPluginInfo { - FilePath path; + FilePath path; // Internal plugins are of the form "internal-[name]". std::vector<std::string> mime_types; }; @@ -28,6 +29,14 @@ class PepperPluginRegistry { pepper::PluginModule* GetModule(const FilePath& path) const; private: + static void GetPluginInfoFromSwitch(std::vector<PepperPluginInfo>* plugins); + + struct InternalPluginInfo : public PepperPluginInfo { + pepper::PluginModule::EntryPoints entry_points; + }; + typedef std::vector<InternalPluginInfo> InternalPluginInfoList; + static void GetInternalPluginInfo(InternalPluginInfoList* plugin_info); + PepperPluginRegistry(); typedef scoped_refptr<pepper::PluginModule> ModuleHandle; diff --git a/remoting/client/plugin/chromoting_plugin.cc b/remoting/client/plugin/chromoting_plugin.cc index 1657e20..9bc6fc2 100644 --- a/remoting/client/plugin/chromoting_plugin.cc +++ b/remoting/client/plugin/chromoting_plugin.cc @@ -23,13 +23,15 @@ using std::vector; namespace remoting { -const char* ChromotingPlugin::kMimeType = - "pepper-application/x-chromoting-plugin::Chromoting"; - -ChromotingPlugin::ChromotingPlugin(PP_Instance instance) - : pp::Instance(instance), - width_(0), - height_(0) { +const char* ChromotingPlugin::kMimeType = "pepper-application/x-chromoting"; + +ChromotingPlugin::ChromotingPlugin(PP_Instance pp_instance, + const PPB_Instance* ppb_instance_funcs) + : width_(0), + height_(0), + drawing_context_(NULL), + pp_instance_(pp_instance), + ppb_instance_funcs_(ppb_instance_funcs) { } ChromotingPlugin::~ChromotingPlugin() { @@ -47,7 +49,8 @@ ChromotingPlugin::~ChromotingPlugin() { main_thread_->Stop(); } -bool ChromotingPlugin::Init(uint32_t argc, const char* argn[], const char* argv[]) { +bool ChromotingPlugin::Init(uint32_t argc, const char* argn[], + const char* argv[]) { LOG(INFO) << "Started ChromotingPlugin::Init"; // Extract the URL from the arguments. @@ -112,8 +115,13 @@ void ChromotingPlugin::ViewChanged(const PP_Rect& position, width_ = position.size.width; height_ = position.size.height; + /* + * TODO(ajwong): Reenable this code once we fingure out how we want to + * abstract away the C-api for DeviceContext2D. device_context_ = pp::DeviceContext2D(width_, height_, false); - if (!BindGraphicsDeviceContext(device_context_)) { + if (!ppb_instance_funcs_->BindGraphicsDeviceContext( + pp_instance_, + device_context_.pp_resource())) { LOG(ERROR) << "Couldn't bind the device context."; return; } @@ -130,6 +138,7 @@ void ChromotingPlugin::ViewChanged(const PP_Rect& position, } else { LOG(ERROR) << "Unable to allocate image."; } + */ //client_->SetViewport(0, 0, width_, height_); //client_->Repaint(); diff --git a/remoting/client/plugin/chromoting_plugin.h b/remoting/client/plugin/chromoting_plugin.h index d19b612..757e038 100644 --- a/remoting/client/plugin/chromoting_plugin.h +++ b/remoting/client/plugin/chromoting_plugin.h @@ -11,8 +11,11 @@ #include "base/scoped_ptr.h" #include "remoting/client/host_connection.h" #include "testing/gtest/include/gtest/gtest_prod.h" -#include "third_party/ppapi/cpp/device_context_2d.h" -#include "third_party/ppapi/cpp/instance.h" +#include "third_party/ppapi/c/pp_event.h" +#include "third_party/ppapi/c/pp_instance.h" +#include "third_party/ppapi/c/pp_rect.h" +#include "third_party/ppapi/c/pp_resource.h" +#include "third_party/ppapi/c/ppb_instance.h" namespace base { class Thread; @@ -27,7 +30,7 @@ class PepperView; class ChromotingClient; -class ChromotingPlugin : public pp::Instance { +class ChromotingPlugin { public: // The mimetype for which this plugin is registered. // @@ -35,7 +38,7 @@ class ChromotingPlugin : public pp::Instance { // point. I think we should handle a special protocol (eg., chromotocol://) static const char *kMimeType; - ChromotingPlugin(PP_Instance instance); + ChromotingPlugin(PP_Instance instance, const PPB_Instance* instance_funcs); virtual ~ChromotingPlugin(); virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); @@ -55,7 +58,10 @@ class ChromotingPlugin : public pp::Instance { int width_; int height_; - pp::DeviceContext2D device_context_; + PP_Resource drawing_context_; + + PP_Instance pp_instance_; + const PPB_Instance* ppb_instance_funcs_; scoped_ptr<base::Thread> main_thread_; scoped_ptr<JingleThread> network_thread_; diff --git a/remoting/client/plugin/pepper_entrypoints.cc b/remoting/client/plugin/pepper_entrypoints.cc new file mode 100644 index 0000000..0ca7a06 --- /dev/null +++ b/remoting/client/plugin/pepper_entrypoints.cc @@ -0,0 +1,233 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/client/plugin/pepper_entrypoints.h" + +#include "remoting/client/plugin/chromoting_plugin.h" +#include "third_party/ppapi/c/pp_instance.h" +#include "third_party/ppapi/c/pp_module.h" +#include "third_party/ppapi/c/ppp_instance.h" +#include "third_party/ppapi/cpp/instance.h" +#include "third_party/ppapi/cpp/module.h" + +static const int kModuleInitSuccess = 0; +static const int kModuleInitFailure = 1; + +namespace remoting { + +// Fork of ppapi::Module +// +// TODO(ajwong): Generalize this into something that other internal plugins can +// use. Either that, or attempt to refactor the external ppapi C++ wrapper to +// make it friendly for multiple Modules in one process. I think we can do this +// by: +// 1) Moving the singleton Module instance + C-bindings into another class +// (eg., ModuleExporter) under a different gyp targe. +// 2) Extracting the idea of a "Browser" out of the module that returns +// PPB_Core, etc. This can be a singleton per process regardless of +// module. +// 3) Migrate all PPB related objects to get data out of Browser interface +// instead of Module::Get(). +class ChromotingModule { + public: + ChromotingModule() {} + + // This function will be automatically called after the object is created. + // This is where you can put functions that rely on other parts of the API, + // now that the module has been created. + virtual bool Init() { return true; } + + PP_Module pp_module() const { return pp_module_; } + const PPB_Core& core() const { return *core_; } + + // Implements GetInterface for the browser to get plugin interfaces. Override + // if you need to implement your own interface types that this wrapper + // doesn't support. + virtual const void* GetInstanceInterface(const char* interface_name) { + if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) + return &instance_interface_; + + return NULL; + } + + // Returns an interface in the browser. + const void* GetBrowserInterface(const char* interface_name) { + return get_browser_interface_(interface_name); + } + + // Returns the object associated with this PP_Instance, or NULL if one is + // not found. + ChromotingPlugin* InstanceForPPInstance(PP_Instance instance) { + InstanceMap::iterator found = current_instances_.find(instance); + if (found == current_instances_.end()) + return NULL; + return found->second; + } + + // Sets the browser interface and calls the regular init function that + // can be overridden by the base classes. + // + // TODO(brettw) make this private when I can figure out how to make the + // initialize function a friend. + bool InternalInit(PP_Module mod, + PPB_GetInterface get_browser_interface) { + pp_module_ = mod; + get_browser_interface_ = get_browser_interface; + core_ = reinterpret_cast<const PPB_Core*>(GetBrowserInterface( + PPB_CORE_INTERFACE)); + if (!core_) + return false; // Can't run without the core interface. + + return Init(); + } + + // Implementation of Global PPP functions --------------------------------- + static int PPP_InitializeModule(PP_Module module_id, + PPB_GetInterface get_browser_interface) { + ChromotingModule* module = new ChromotingModule(); + if (!module) + return kModuleInitFailure; + + if (!module->InternalInit(module_id, get_browser_interface)) { + delete module; + return kModuleInitFailure; + } + + module_singleton_ = module; + return kModuleInitSuccess; + } + + static void PPP_ShutdownModule() { + delete module_singleton_; + module_singleton_ = NULL; + } + + static const void* PPP_GetInterface(const char* interface_name) { + if (!module_singleton_) + return NULL; + return module_singleton_->GetInstanceInterface(interface_name); + } + + protected: + virtual ChromotingPlugin* CreateInstance(PP_Instance instance) { + const PPB_Instance* ppb_instance_funcs = + reinterpret_cast<const PPB_Instance *>( + module_singleton_->GetBrowserInterface(PPB_INSTANCE_INTERFACE)); + return new ChromotingPlugin(instance, ppb_instance_funcs); + } + + private: + static bool Instance_New(PP_Instance instance) { + if (!module_singleton_) + return false; + ChromotingPlugin* obj = module_singleton_->CreateInstance(instance); + if (obj) { + module_singleton_->current_instances_[instance] = obj; + return true; + } + return false; + } + + static void Instance_Delete(PP_Instance instance) { + if (!module_singleton_) + return; + ChromotingModule::InstanceMap::iterator found = + module_singleton_->current_instances_.find(instance); + if (found == module_singleton_->current_instances_.end()) + return; + + // Remove it from the map before deleting to try to catch reentrancy. + ChromotingPlugin* obj = found->second; + module_singleton_->current_instances_.erase(found); + delete obj; + } + + static bool Instance_Initialize(PP_Instance pp_instance, + uint32_t argc, + const char* argn[], + const char* argv[]) { + if (!module_singleton_) + return false; + ChromotingPlugin* instance = + module_singleton_->InstanceForPPInstance(pp_instance); + if (!instance) + return false; + return instance->Init(argc, argn, argv); + } + + static bool Instance_HandleEvent(PP_Instance pp_instance, + const PP_Event* event) { + if (!module_singleton_) + return false; + ChromotingPlugin* instance = + module_singleton_->InstanceForPPInstance(pp_instance); + if (!instance) + return false; + return instance->HandleEvent(*event); + } + + static PP_Var Instance_GetInstanceObject(PP_Instance pp_instance) { + PP_Var var; + var.type = PP_VarType_Void; + return var; + } + + static void Instance_ViewChanged(PP_Instance pp_instance, + const PP_Rect* position, + const PP_Rect* clip) { + if (!module_singleton_) + return; + ChromotingPlugin* instance = + module_singleton_->InstanceForPPInstance(pp_instance); + if (!instance) + return; + instance->ViewChanged(*position, *clip); + } + + // Bindings and identifiers to and from the browser. + PP_Module pp_module_; + PPB_GetInterface get_browser_interface_; + PPB_Core const* core_; + + // Instance tracking. + typedef std::map<PP_Instance, ChromotingPlugin*> InstanceMap; + InstanceMap current_instances_; + + // Static members for the ppapi C-bridge. + static PPP_Instance instance_interface_; + static ChromotingModule* module_singleton_; + + DISALLOW_COPY_AND_ASSIGN(ChromotingModule); +}; + +ChromotingModule* ChromotingModule::module_singleton_ = NULL; + +PPP_Instance ChromotingModule::instance_interface_ = { + &ChromotingModule::Instance_New, + &ChromotingModule::Instance_Delete, + &ChromotingModule::Instance_Initialize, + &ChromotingModule::Instance_HandleEvent, + &ChromotingModule::Instance_GetInstanceObject, + &ChromotingModule::Instance_ViewChanged, +}; + +// Implementation of Global PPP functions --------------------------------- +// +// TODO(ajwong): This is to get around friending issues. Fix it after we decide +// whether or not ChromotingModule should be generalized. +int PPP_InitializeModule(PP_Module module_id, + PPB_GetInterface get_browser_interface) { + return ChromotingModule::PPP_InitializeModule(module_id, + get_browser_interface); +} + +void PPP_ShutdownModule() { + return ChromotingModule::PPP_ShutdownModule(); +} + +const void* PPP_GetInterface(const char* interface_name) { + return ChromotingModule::PPP_GetInterface(interface_name); +} + +} // namespace remoting diff --git a/remoting/client/plugin/pepper_entrypoints.h b/remoting/client/plugin/pepper_entrypoints.h new file mode 100644 index 0000000..ab6de20 --- /dev/null +++ b/remoting/client/plugin/pepper_entrypoints.h @@ -0,0 +1,20 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_CLIENT_PLUGIN_PEPPER_ENTRYPOINTS_ +#define REMOTING_CLIENT_PLUGIN_PEPPER_ENTRYPOINTS_ + +#include "third_party/ppapi/c/pp_module.h" +#include "third_party/ppapi/c/ppb.h" + +namespace remoting { + +int PPP_InitializeModule(PP_Module module_id, + PPB_GetInterface get_browser_interface); +void PPP_ShutdownModule(); +const void* PPP_GetInterface(const char* interface_name); + +} // namespace remoting + +#endif // REMOTING_CLIENT_PLUGIN_PEPPER_ENTRYPOINTS_ diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 47dc6ea..818fbd3 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -16,46 +16,8 @@ }, 'conditions': [ - # Chromoting Client targets ['OS=="linux" or OS=="mac"', { 'targets': [ - { - 'target_name': 'chromoting_client_plugin', - 'type': 'static_library', - 'defines': [ - 'HAVE_STDINT_H', # Required by on2_integer.h - ], - 'dependencies': [ - 'chromoting_base', - 'chromoting_client', - 'chromoting_jingle_glue', - '../third_party/ppapi/ppapi.gyp:ppapi_cpp', - '../third_party/zlib/zlib.gyp:zlib', - ], - 'sources': [ - 'client/plugin/chromoting_plugin.cc', - 'client/plugin/chromoting_plugin.h', - 'client/plugin/pepper_view.cc', - 'client/plugin/pepper_view.h', - '../media/base/yuv_convert.cc', - '../media/base/yuv_convert.h', - '../media/base/yuv_row.h', - '../media/base/yuv_row_posix.cc', - '../media/base/yuv_row_table.cc', - ], - 'conditions': [ - ['OS=="win"', { - 'sources': [ - '../media/base/yuv_row_win.cc', - ], - }], - ['OS=="linux" and target_arch=="x64" and linux_fpic!=1', { - # Shared libraries need -fPIC on x86-64 - 'cflags': ['-fPIC'], - }], - ], # end of 'conditions' - }, # end of target 'chromoting_client_plugin' - # Simple webserver for testing chromoting client plugin. { 'target_name': 'chromoting_client_test_webserver', @@ -63,13 +25,13 @@ 'sources': [ 'tools/client_webserver/main.c', ], - }, # end of target 'chromoting_client_test_webserver' - - ], # end of Client targets - }], # end of OS conditions for Client targets + } + ], # end of target 'chromoting_client_test_webserver' + }], # TODO(hclam): Enable this target for mac. ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', { + 'targets': [ { 'target_name': 'chromoting_x11_client', @@ -100,6 +62,45 @@ 'targets': [ { + 'target_name': 'chromoting_plugin', + 'type': 'static_library', + 'defines': [ + 'HAVE_STDINT_H', # Required by on2_integer.h + ], + 'dependencies': [ + 'chromoting_base', + 'chromoting_client', + 'chromoting_jingle_glue', + '../third_party/ppapi/ppapi.gyp:ppapi_c', + '../third_party/zlib/zlib.gyp:zlib', + ], + 'sources': [ + 'client/plugin/chromoting_plugin.cc', + 'client/plugin/chromoting_plugin.h', + 'client/plugin/pepper_entrypoints.cc', + 'client/plugin/pepper_entrypoints.h', + 'client/plugin/pepper_view.cc', + 'client/plugin/pepper_view.h', + '../media/base/yuv_convert.cc', + '../media/base/yuv_convert.h', + '../media/base/yuv_row.h', + '../media/base/yuv_row_table.cc', + ], + 'conditions': [ + ['OS=="win"', { + 'sources': [ + '../media/base/yuv_row_win.cc', + ], + }], + ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="mac"', { + 'sources': [ + '../media/base/yuv_row_posix.cc', + ], + }], + ], # end of 'conditions' + }, # end of target 'chromoting_plugin' + + { 'target_name': 'chromoting_base', 'type': '<(library)', 'dependencies': [ diff --git a/webkit/glue/plugins/pepper_plugin_module.cc b/webkit/glue/plugins/pepper_plugin_module.cc index 22a9eb2..26cef2c 100644 --- a/webkit/glue/plugins/pepper_plugin_module.cc +++ b/webkit/glue/plugins/pepper_plugin_module.cc @@ -31,9 +31,6 @@ #include "webkit/glue/plugins/pepper_resource_tracker.h" #include "webkit/glue/plugins/pepper_var.h" -typedef bool (*PPP_InitializeModuleFunc)(PP_Module, PPB_GetInterface); -typedef void (*PPP_ShutdownModuleFunc)(); - namespace pepper { namespace { @@ -158,11 +155,9 @@ const void* GetInterface(const char* name) { } // namespace -PluginModule::PluginModule(const FilePath& filename) - : filename_(filename), - initialized_(false), - library_(0), - ppp_get_interface_(NULL) { +PluginModule::PluginModule() + : initialized_(false), + library_(NULL) { GetMainThreadMessageLoop(); // Initialize the main thread message loop. GetLivePluginSet()->insert(this); } @@ -174,25 +169,31 @@ PluginModule::~PluginModule() { GetLivePluginSet()->erase(this); - if (library_) { - PPP_ShutdownModuleFunc shutdown_module = - reinterpret_cast<PPP_ShutdownModuleFunc>( - base::GetFunctionPointerFromNativeLibrary(library_, - "PPP_ShutdownModule")); - if (shutdown_module) - shutdown_module(); + if (entry_points_.shutdown_module) + entry_points_.shutdown_module(); + + if (library_) base::UnloadNativeLibrary(library_); - } } // static scoped_refptr<PluginModule> PluginModule::CreateModule( - const FilePath& filename) { + const FilePath& path) { // FIXME(brettw) do uniquifying of the plugin here like the NPAPI one. - scoped_refptr<PluginModule> lib(new PluginModule(filename)); - if (!lib->Load()) - lib = NULL; + scoped_refptr<PluginModule> lib(new PluginModule()); + if (!lib->InitFromFile(path)) + return NULL; + + return lib; +} + +scoped_refptr<PluginModule> PluginModule::CreateInternalModule( + EntryPoints entry_points) { + scoped_refptr<PluginModule> lib(new PluginModule()); + if (!lib->InitFromEntryPoints(entry_points)) + return NULL; + return lib; } @@ -204,39 +205,71 @@ PluginModule* PluginModule::FromPPModule(PP_Module module) { return lib; } -bool PluginModule::Load() { +bool PluginModule::InitFromEntryPoints(const EntryPoints& entry_points) { if (initialized_) return true; + + // Attempt to run the initialization funciton. + int retval = entry_points.initialize_module(GetPPModule(), &GetInterface); + if (retval != 0) { + LOG(WARNING) << "PPP_InitializeModule returned failure " << retval; + return false; + } + + entry_points_ = entry_points; initialized_ = true; + return true; +} - library_ = base::LoadNativeLibrary(filename_); - if (!library_) +bool PluginModule::InitFromFile(const FilePath& path) { + if (initialized_) + return true; + + base::NativeLibrary library = base::LoadNativeLibrary(path); + if (!library) return false; - // Save the GetInterface function pointer for later. - ppp_get_interface_ = + EntryPoints entry_points; + if (!LoadEntryPoints(library, &entry_points) || + !InitFromEntryPoints(entry_points)) { + base::UnloadNativeLibrary(library); + return false; + } + + // We let InitFromEntryPoints() handle setting the all the internal state + // of the object other than the |library_| reference. + library_ = library; + return true; +} + +// static +bool PluginModule::LoadEntryPoints(const base::NativeLibrary& library, + EntryPoints* entry_points) { + + entry_points->get_interface = reinterpret_cast<PPP_GetInterfaceFunc>( - base::GetFunctionPointerFromNativeLibrary(library_, + base::GetFunctionPointerFromNativeLibrary(library, "PPP_GetInterface")); - if (!ppp_get_interface_) { + if (!entry_points->get_interface) { LOG(WARNING) << "No PPP_GetInterface in plugin library"; return false; } - // Call the plugin initialize function. - PPP_InitializeModuleFunc initialize_module = + entry_points->initialize_module = reinterpret_cast<PPP_InitializeModuleFunc>( - base::GetFunctionPointerFromNativeLibrary(library_, + base::GetFunctionPointerFromNativeLibrary(library, "PPP_InitializeModule")); - if (!initialize_module) { + if (!entry_points->initialize_module) { LOG(WARNING) << "No PPP_InitializeModule in plugin library"; return false; } - int retval = initialize_module(GetPPModule(), &GetInterface); - if (retval != 0) { - LOG(WARNING) << "PPP_InitializeModule returned failure " << retval; - return false; - } + + // It's okay for PPP_ShutdownModule to not be defined and shutdown_module to + // be NULL. + entry_points->shutdown_module = + reinterpret_cast<PPP_ShutdownModuleFunc>( + base::GetFunctionPointerFromNativeLibrary(library, + "PPP_ShutdownModule")); return true; } @@ -264,9 +297,9 @@ PluginInstance* PluginModule::GetSomeInstance() const { } const void* PluginModule::GetPluginInterface(const char* name) const { - if (!ppp_get_interface_) + if (!entry_points_.get_interface) return NULL; - return ppp_get_interface_(name); + return entry_points_.get_interface(name); } void PluginModule::InstanceCreated(PluginInstance* instance) { diff --git a/webkit/glue/plugins/pepper_plugin_module.h b/webkit/glue/plugins/pepper_plugin_module.h index 0498c45..1b2d9fb 100644 --- a/webkit/glue/plugins/pepper_plugin_module.h +++ b/webkit/glue/plugins/pepper_plugin_module.h @@ -12,6 +12,7 @@ #include "base/native_library.h" #include "base/ref_counted.h" #include "third_party/ppapi/c/pp_module.h" +#include "third_party/ppapi/c/ppb.h" namespace pepper { @@ -20,9 +21,27 @@ class PluginInstance; class PluginModule : public base::RefCounted<PluginModule> { public: + typedef const void* (*PPP_GetInterfaceFunc)(const char*); + typedef int (*PPP_InitializeModuleFunc)(PP_Module, PPB_GetInterface); + typedef void (*PPP_ShutdownModuleFunc)(); + + struct EntryPoints { + EntryPoints() + : get_interface(NULL), + initialize_module(NULL), + shutdown_module(NULL) { + } + + PPP_GetInterfaceFunc get_interface; + PPP_InitializeModuleFunc initialize_module; + PPP_ShutdownModuleFunc shutdown_module; + }; + ~PluginModule(); - static scoped_refptr<PluginModule> CreateModule(const FilePath& filename); + static scoped_refptr<PluginModule> CreateModule(const FilePath& path); + static scoped_refptr<PluginModule> CreateInternalModule( + EntryPoints entry_points); // Converts the given module ID to an actual module object. Will return NULL // if the module is invalid. @@ -47,18 +66,24 @@ class PluginModule : public base::RefCounted<PluginModule> { void InstanceDeleted(PluginInstance* instance); private: - typedef const void* (*PPP_GetInterfaceFunc)(const char*); - - explicit PluginModule(const FilePath& filename); + PluginModule(); - bool Load(); - - FilePath filename_; + bool InitFromEntryPoints(const EntryPoints& entry_points); + bool InitFromFile(const FilePath& path); + static bool LoadEntryPoints(const base::NativeLibrary& library, + EntryPoints* entry_points); bool initialized_; + + // Holds a reference to the base::NativeLibrary handle if this PluginModule + // instance wraps functions loaded from a library. Can be NULL. If + // |library_| is non-NULL, PluginModule will attempt to unload the library + // during destruction. base::NativeLibrary library_; - PPP_GetInterfaceFunc ppp_get_interface_; + // Contains pointers to the entry points of the actual plugin + // implementation. + EntryPoints entry_points_; // Non-owning pointers to all instances associated with this module. When // there are no more instances, this object should be deleted. |