From 0922baeab1134628d5898a21dbbd8973647caae0 Mon Sep 17 00:00:00 2001 From: "evan@chromium.org" Date: Thu, 27 Aug 2009 23:06:34 +0000 Subject: linux: scan more plugin directories, fix bugs We now scan more directories, sort file entries by mtime, use realpath() before loading plugins (fixes a Java bug), and de-duplicate multiple instances of the same plugin. This matches the Mozilla plugin loading code more closely. We also ignore xpcom-related errors while loading plugins, as that breaks layout tests. I encountered this while attempting to fix QuickTime (need to load the Totem plugins) but the fix overlaps with the Java one. I believe neither quite work yet, though. BUG=16787,19712 TEST=about:plugins should show more plugins Review URL: http://codereview.chromium.org/173550 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24691 0039d316-1c4b-4281-b951-d872f2087c98 --- base/native_library_linux.cc | 10 ++++- webkit/glue/plugins/plugin_list_linux.cc | 76 +++++++++++++++++++++++++++----- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/base/native_library_linux.cc b/base/native_library_linux.cc index 05050bd..2e5db88 100644 --- a/base/native_library_linux.cc +++ b/base/native_library_linux.cc @@ -16,8 +16,14 @@ namespace base { NativeLibrary LoadNativeLibrary(const FilePath& library_path) { void* dl = dlopen(library_path.value().c_str(), RTLD_LAZY); if (!dl) { - LOG(ERROR) << "dlopen failed when trying to open " << library_path.value() - << ": " << dlerror(); + std::string error_message = dlerror(); + // Some obsolete plugins depend on libxul or libxpcom. + // Ignore the error messages when failing to load these. + if (error_message.find("libxul.so") == std::string::npos && + error_message.find("libxpcom.so") == std::string::npos) { + LOG(ERROR) << "dlopen failed when trying to open " << library_path.value() + << ": " << error_message; + } } return dl; diff --git a/webkit/glue/plugins/plugin_list_linux.cc b/webkit/glue/plugins/plugin_list_linux.cc index 2a92bbd..661c142 100644 --- a/webkit/glue/plugins/plugin_list_linux.cc +++ b/webkit/glue/plugins/plugin_list_linux.cc @@ -7,6 +7,25 @@ #include "base/file_util.h" #include "base/path_service.h" +namespace { + +// We build up a list of files and mtimes so we can sort them. +typedef std::pair FileAndTime; +typedef std::vector FileTimeList; + +// Comparator used to sort by descending mtime then ascending filename. +bool CompareTime(const FileAndTime& a, const FileAndTime& b) { + if (a.second == b.second) { + // Fall back on filename sorting, just to make the predicate valid. + return a.first < b.first; + } + + // Sort by mtime, descending. + return a.second > b.second; +} + +} + namespace NPAPI { void PluginList::PlatformInit() { @@ -38,33 +57,68 @@ void PluginList::GetPluginDirectories(std::vector* plugin_dirs) { plugin_dirs->push_back(dir.Append("plugins")); // 4) NS_SYSTEM_PLUGINS_DIR: - // TODO(evanm): when we support 64-bit platforms, we'll need to fix this - // to be conditional. - COMPILE_ASSERT(sizeof(int)==4, fix_system_lib_path); + // This varies across different versions of Firefox, so check 'em all. plugin_dirs->push_back(FilePath("/usr/lib/mozilla/plugins")); + plugin_dirs->push_back(FilePath("/usr/lib/firefox/plugins")); + plugin_dirs->push_back(FilePath("/usr/lib/xulrunner-addons/plugins")); } void PluginList::LoadPluginsFromDir(const FilePath& path, std::vector* plugins) { + // See ScanPluginsDirectory near + // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginHostImpl.cpp#5052 + + // Construct and stat a list of all filenames under consideration, for + // later sorting by mtime. + FileTimeList files; file_util::FileEnumerator enumerator(path, false, // not recursive file_util::FileEnumerator::FILES); for (FilePath path = enumerator.Next(); !path.value().empty(); path = enumerator.Next()) { // Skip over Mozilla .xpt files. - if (!path.MatchesExtension(FILE_PATH_LITERAL(".xpt"))) - LoadPlugin(path, plugins); + if (path.MatchesExtension(FILE_PATH_LITERAL(".xpt"))) + continue; + + // Java doesn't like being loaded through a symlink, since it uses + // its path to find dependent data files. + // file_util::AbsolutePath calls through to realpath(), which resolves + // symlinks. + file_util::AbsolutePath(&path); + + // Get mtime. + file_util::FileInfo info; + if (!file_util::GetFileInfo(path, &info)) + continue; + + // Skip duplicates of the same file in our list. + bool skip = false; + for (size_t i = 0; i < plugins->size(); ++i) { + if (plugins->at(i).path == path) { + skip = true; + break; + } + } + if (skip) + continue; + + files.push_back(std::make_pair(path, info.last_modified)); + } + + // Sort the file list by time (and filename). + std::sort(files.begin(), files.end(), CompareTime); + + // Load the files in order. + for (FileTimeList::const_iterator i = files.begin(); i != files.end(); ++i) { + LoadPlugin(i->first, plugins); } } bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info, std::vector* plugins) { - // The equivalent Windows code verifies we haven't loaded a newer version - // of the same plugin, and then blacklists some known bad plugins. - // The equivalent Mac code verifies that plugins encountered first in the - // plugin list clobber later entries. - // TODO(evanm): figure out which behavior is appropriate for Linux. - // We don't need either yet as I'm just testing with Flash for now. + // TODO(evanm): blacklist nspluginwrapper here? + // TODO(evanm): prefer the newest version of flash here? + return true; } -- cgit v1.1