diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-02 04:51:16 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-02 04:51:16 +0000 |
commit | cb7defb5f3b1ea748d037150f4099b0dbdc39243 (patch) | |
tree | 4fcc5076e7e1cca510bc3d7918834c7a3ce0d935 /chrome/common | |
parent | 3075f39b490ed83e41c802b250b6e4f68557304e (diff) | |
download | chromium_src-cb7defb5f3b1ea748d037150f4099b0dbdc39243.zip chromium_src-cb7defb5f3b1ea748d037150f4099b0dbdc39243.tar.gz chromium_src-cb7defb5f3b1ea748d037150f4099b0dbdc39243.tar.bz2 |
Set the name of the PPAPI plugin properly when running out of process. This
also does some refactoring of the plugin registry to make it more clear and to
avoid recomputilg the plugin list all the time.
Review URL: http://codereview.chromium.org/6246031
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73427 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r-- | chrome/common/pepper_plugin_registry.cc | 315 | ||||
-rw-r--r-- | chrome/common/pepper_plugin_registry.h | 50 |
2 files changed, 162 insertions, 203 deletions
diff --git a/chrome/common/pepper_plugin_registry.cc b/chrome/common/pepper_plugin_registry.cc index 26b6409..298fd22 100644 --- a/chrome/common/pepper_plugin_registry.cc +++ b/chrome/common/pepper_plugin_registry.cc @@ -15,68 +15,88 @@ #include "chrome/common/chrome_switches.h" #include "remoting/client/plugin/pepper_entrypoints.h" -const char* PepperPluginRegistry::kPDFPluginName = "Chrome PDF Viewer"; -const char* PepperPluginRegistry::kPDFPluginMimeType = "application/pdf"; -const char* PepperPluginRegistry::kPDFPluginExtension = "pdf"; -const char* PepperPluginRegistry::kPDFPluginDescription = - "Portable Document Format"; - -const char* PepperPluginRegistry::kNaClPluginName = "Chrome NaCl"; -const char* PepperPluginRegistry::kNaClPluginMimeType = - "application/x-nacl"; -const char* PepperPluginRegistry::kNaClPluginExtension = "nexe"; -const char* PepperPluginRegistry::kNaClPluginDescription = - "Native Client Executable"; - - -PepperPluginInfo::PepperPluginInfo() - : is_internal(false), - is_out_of_process(false) { -} - -PepperPluginInfo::~PepperPluginInfo() {} - -// static -PepperPluginRegistry* PepperPluginRegistry::GetInstance() { - static PepperPluginRegistry* registry = NULL; - // This object leaks. It is a temporary hack to work around a crash. - // http://code.google.com/p/chromium/issues/detail?id=63234 - if (!registry) - registry = new PepperPluginRegistry; - return registry; -} +namespace { + +const char* kPDFPluginName = "Chrome PDF Viewer"; +const char* kPDFPluginMimeType = "application/pdf"; +const char* kPDFPluginExtension = "pdf"; +const char* kPDFPluginDescription = "Portable Document Format"; + +const char* kNaClPluginName = "Chrome NaCl"; +const char* kNaClPluginMimeType = "application/x-nacl"; +const char* kNaClPluginExtension = "nexe"; +const char* kNaClPluginDescription = "Native Client Executable"; + +const char* kRemotingPluginMimeType = "pepper-application/x-chromoting"; + +// Appends the known built-in plugins to the given vector. Some built-in +// plugins are "internal" which means they are compiled into the Chrome binary, +// and some are extra shared libraries distributed with the browser (these are +// not marked internal, aside from being automatically registered, they're just +// regular plugins). +void ComputeBuiltInPlugins(std::vector<PepperPluginInfo>* plugins) { + // PDF. + // + // Once we're sandboxed, we can't know if the PDF plugin is available or not; + // but (on Linux) this function is always called once before we're sandboxed. + // So the first time through test if the file is available and then skip the + // check on subsequent calls if yes. + static bool skip_pdf_file_check = false; + FilePath path; + if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path)) { + if (skip_pdf_file_check || file_util::PathExists(path)) { + PepperPluginInfo pdf; + pdf.path = path; + pdf.name = kPDFPluginName; + pdf.mime_types.push_back(kPDFPluginMimeType); + pdf.file_extensions = kPDFPluginExtension; + pdf.type_descriptions = kPDFPluginDescription; + plugins->push_back(pdf); -// 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); + skip_pdf_file_check = true; + } } - GetPluginInfoFromSwitch(plugins); - GetExtraPlugins(plugins); -} + // Native client. + // + // Verify that we enable nacl on the command line. The name of the switch + // varies between the browser and renderer process. + if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path) && + file_util::PathExists(path)) { + PepperPluginInfo nacl; + nacl.path = path; + nacl.name = kNaClPluginName; + nacl.mime_types.push_back(kNaClPluginMimeType); + + // TODO(bbudge) Remove this mime type after NaCl tree has been updated. + const char* kNaClPluginOldMimeType = "application/x-ppapi-nacl-srpc"; + nacl.mime_types.push_back(kNaClPluginOldMimeType); + + nacl.file_extensions = kNaClPluginExtension; + nacl.type_descriptions = kNaClPluginDescription; + plugins->push_back(nacl); + } -// static -void PepperPluginRegistry::PreloadModules() { - std::vector<PepperPluginInfo> plugins; - GetList(&plugins); - for (size_t i = 0; i < plugins.size(); ++i) { - if (!plugins[i].is_internal && !plugins[i].is_out_of_process) { - base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path); - LOG_IF(WARNING, !library) << "Unable to load plugin " - << plugins[i].path.value(); - } + // Remoting. +#if defined(ENABLE_REMOTING) + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableRemoting)) { + PepperPluginInfo info; + info.is_internal = true; + info.path = FilePath(FILE_PATH_LITERAL("internal-chromoting")); + info.mime_types.push_back(kRemotingPluginMimeType); + info.internal_entry_points.get_interface = remoting::PPP_GetInterface; + info.internal_entry_points.initialize_module = + remoting::PPP_InitializeModule; + info.internal_entry_points.shutdown_module = remoting::PPP_ShutdownModule; + + plugins->push_back(info); } +#endif } -// static -void PepperPluginRegistry::GetPluginInfoFromSwitch( - std::vector<PepperPluginInfo>* plugins) { +// Appends any plugins from the command line to the given vector. +void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) { const std::string value = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kRegisterPepperPlugins); @@ -127,103 +147,56 @@ void PepperPluginRegistry::GetPluginInfoFromSwitch( } } -// static -void PepperPluginRegistry::GetExtraPlugins( - std::vector<PepperPluginInfo>* plugins) { - // Once we're sandboxed, we can't know if the PDF plugin is - // available or not; but (on Linux) this function is always called - // once before we're sandboxed. So the first time through test if - // the file is available and then skip the check on subsequent calls - // if yes. - static bool skip_pdf_file_check = false; - FilePath path; - if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path)) { - if (skip_pdf_file_check || file_util::PathExists(path)) { - PepperPluginInfo pdf; - pdf.path = path; - pdf.name = kPDFPluginName; - pdf.mime_types.push_back(kPDFPluginMimeType); - pdf.file_extensions = kPDFPluginExtension; - pdf.type_descriptions = kPDFPluginDescription; - plugins->push_back(pdf); +} // namespace - skip_pdf_file_check = true; - } - } +const char* PepperPluginRegistry::kPDFPluginName = ::kPDFPluginName; - static bool skip_nacl_file_check = false; - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaCl) - && PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) { - if (skip_nacl_file_check || file_util::PathExists(path)) { - PepperPluginInfo nacl; - nacl.path = path; - nacl.name = kNaClPluginName; - nacl.mime_types.push_back(kNaClPluginMimeType); - - // TODO(bbudge) Remove this mime type after NaCl tree has been updated. - const char* kNaClPluginOldMimeType = - "application/x-ppapi-nacl-srpc"; - nacl.mime_types.push_back(kNaClPluginOldMimeType); - - nacl.file_extensions = kNaClPluginExtension; - nacl.type_descriptions = kNaClPluginDescription; - plugins->push_back(nacl); - - skip_nacl_file_check = true; - } - } +PepperPluginInfo::PepperPluginInfo() + : is_internal(false), + is_out_of_process(false) { } -PepperPluginRegistry::InternalPluginInfo::InternalPluginInfo() { - is_internal = true; +PepperPluginInfo::~PepperPluginInfo() {} + +// static +PepperPluginRegistry* PepperPluginRegistry::GetInstance() { + static PepperPluginRegistry* registry = NULL; + // This object leaks. It is a temporary hack to work around a crash. + // http://code.google.com/p/chromium/issues/detail?id=63234 + if (!registry) + registry = new PepperPluginRegistry; + return registry; } // 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. Perhaps by construction of a singly linked list of - // plugin initializers that is built with static initializers? +void PepperPluginRegistry::ComputeList(std::vector<PepperPluginInfo>* plugins) { + ComputeBuiltInPlugins(plugins); + ComputePluginsFromCommandLine(plugins); +} -#if defined(ENABLE_REMOTING) - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableRemoting)) { - InternalPluginInfo info; - // Add the chromoting plugin. - DCHECK(info.is_internal); - 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); +// static +void PepperPluginRegistry::PreloadModules() { + std::vector<PepperPluginInfo> plugins; + ComputeList(&plugins); + for (size_t i = 0; i < plugins.size(); ++i) { + if (!plugins[i].is_internal && !plugins[i].is_out_of_process) { + base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path); + LOG_IF(WARNING, !library) << "Unable to load plugin " + << plugins[i].path.value(); + } } -#endif } -bool PepperPluginRegistry::RunOutOfProcessForPlugin( +const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin( const FilePath& path) const { - // TODO(brettw) don't recompute this every time. But since this Pepper - // switch is only for development, it's OK for now. - std::vector<PepperPluginInfo> plugins; - GetList(&plugins); - for (size_t i = 0; i < plugins.size(); ++i) { - if (path == plugins[i].path) - return plugins[i].is_out_of_process; + for (size_t i = 0; i < plugin_list_.size(); ++i) { + if (path == plugin_list_[i].path) + return &plugin_list_[i]; } - return false; + return NULL; } -webkit::ppapi::PluginModule* PepperPluginRegistry::GetModule( +webkit::ppapi::PluginModule* PepperPluginRegistry::GetLiveModule( const FilePath& path) { NonOwningModuleMap::iterator it = live_modules_.find(path); if (it == live_modules_.end()) @@ -261,46 +234,34 @@ PepperPluginRegistry::~PepperPluginRegistry() { } 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; - scoped_refptr<webkit::ppapi::PluginModule> module( - new webkit::ppapi::PluginModule(this)); - if (!module->InitAsInternalPlugin(it->entry_points)) { - DLOG(ERROR) << "Failed to load pepper module: " << path.value(); - continue; - } - module->set_name(it->name); - preloaded_modules_[path] = module; - AddLiveModule(path, module); - } - - // Add the modules specified on the command line last so that they can - // override the internal plugins. - std::vector<PepperPluginInfo> plugins; - GetPluginInfoFromSwitch(&plugins); - GetExtraPlugins(&plugins); - for (size_t i = 0; i < plugins.size(); ++i) { - if (plugins[i].is_out_of_process) - continue; // Only preload in-process plugins. - - const FilePath& path = plugins[i].path; - scoped_refptr<webkit::ppapi::PluginModule> module( - new webkit::ppapi::PluginModule(this)); - // Must call this before bailing out later since the PluginModule's - // destructor will call the corresponding Remove in the "continue" case. - AddLiveModule(path, module); - if (!module->InitAsLibrary(path)) { - DLOG(ERROR) << "Failed to load pepper module: " << path.value(); - continue; + ComputeList(&plugin_list_); + + // Note that in each case, AddLiveModule must be called before completing + // initialization. If we bail out (in the continue clauses) before saving + // the initialized module, it will still try to unregister itself in its + // destructor. + for (size_t i = 0; i < plugin_list_.size(); i++) { + const PepperPluginInfo& current = plugin_list_[i]; + if (current.is_out_of_process) + continue; // Out of process plugins need no special pre-initialization. + + scoped_refptr<webkit::ppapi::PluginModule> module = + new webkit::ppapi::PluginModule(current.name, this); + AddLiveModule(current.path, module); + if (current.is_internal) { + if (!module->InitAsInternalPlugin(current.internal_entry_points)) { + DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); + continue; + } + } else { + // Preload all external plugins we're not running out of process. + module = new webkit::ppapi::PluginModule(current.name, this); + AddLiveModule(current.path, module); + if (!module->InitAsLibrary(current.path)) { + DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); + continue; + } } - module->set_name(plugins[i].name); - preloaded_modules_[path] = module; + preloaded_modules_[current.path] = module; } } diff --git a/chrome/common/pepper_plugin_registry.h b/chrome/common/pepper_plugin_registry.h index 0dd8b15..18233ea 100644 --- a/chrome/common/pepper_plugin_registry.h +++ b/chrome/common/pepper_plugin_registry.h @@ -19,6 +19,8 @@ struct PepperPluginInfo { ~PepperPluginInfo(); // Indicates internal plugins for which there's not actually a library. + // These plugins are implemented in the Chrome binary using a separate set + // of entry points (see internal_entry_points below). // Defaults to false. bool is_internal; @@ -31,6 +33,10 @@ struct PepperPluginInfo { std::string description; std::string file_extensions; std::string type_descriptions; + + // When is_internal is set, this contains the function pointers to the + // entry points for the internal plugins. + webkit::ppapi::PluginModule::EntryPoints internal_entry_points; }; // This class holds references to all of the known pepper plugin modules. @@ -44,35 +50,32 @@ class PepperPluginRegistry ~PepperPluginRegistry(); static const char* kPDFPluginName; - static const char* kPDFPluginMimeType; - static const char* kPDFPluginExtension; - static const char* kPDFPluginDescription; - - static const char* kNaClPluginName; - static const char* kNaClPluginMimeType; - static const char* kNaClPluginExtension; - static const char* kNaClPluginDescription; static PepperPluginRegistry* GetInstance(); - // Returns the list of known pepper plugins. This method is static so that - // it can be used by the browser process, which has no need to load the - // pepper plugin modules. - static void GetList(std::vector<PepperPluginInfo>* plugins); + // Computes the list of known pepper plugins. + // + // This method is static so that it can be used by the browser process, which + // has no need to load the pepper plugin modules. It will re-compute the + // plugin list every time it is called. Generally, code in the registry should + // be using the cached plugin_list_ instead. + static void ComputeList(std::vector<PepperPluginInfo>* plugins); // Loads the (native) libraries but does not initialize them (i.e., does not // call PPP_InitializeModule). This is needed by the zygote on Linux to get // access to the plugins before entering the sandbox. static void PreloadModules(); - // Returns true if the given plugin is a pepper plugin that should be run - // out of process. - bool RunOutOfProcessForPlugin(const FilePath& path) const; + // Retrieves the information associated with the given plugin path. The + // return value will be NULL if there is no such plugin. + // + // The returned pointer is owned by the PluginRegistry. + const PepperPluginInfo* GetInfoForPlugin(const FilePath& path) const; // Returns an existing loaded module for the given path. It will search for // both preloaded in-process or currently active out-of-process plugins // matching the given name. Returns NULL if the plugin hasn't been loaded. - webkit::ppapi::PluginModule* GetModule(const FilePath& path); + webkit::ppapi::PluginModule* GetLiveModule(const FilePath& path); // Notifies the registry that a new non-preloaded module has been created. // This is normally called for out-of-process plugins. Once this is called, @@ -85,18 +88,13 @@ class PepperPluginRegistry webkit::ppapi::PluginModule* destroyed_module); private: - static void GetPluginInfoFromSwitch(std::vector<PepperPluginInfo>* plugins); - static void GetExtraPlugins(std::vector<PepperPluginInfo>* plugins); - - struct InternalPluginInfo : public PepperPluginInfo { - InternalPluginInfo(); // Sets |is_internal|. - webkit::ppapi::PluginModule::EntryPoints entry_points; - }; - typedef std::vector<InternalPluginInfo> InternalPluginInfoList; - static void GetInternalPluginInfo(InternalPluginInfoList* plugin_info); - PepperPluginRegistry(); + // All known pepper plugins. + std::vector<PepperPluginInfo> plugin_list_; + + // Plugins that have been preloaded so they can be executed in-process in + // the renderer (the sandbox prevents on-demand loading). typedef std::map<FilePath, scoped_refptr<webkit::ppapi::PluginModule> > OwningModuleMap; OwningModuleMap preloaded_modules_; |