| Index: webkit/plugins/npapi/plugin_list_posix.cc
|
| ===================================================================
|
| --- webkit/plugins/npapi/plugin_list_posix.cc (revision 212369)
|
| +++ webkit/plugins/npapi/plugin_list_posix.cc (working copy)
|
| @@ -1,595 +0,0 @@
|
| -// Copyright (c) 2011 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 "webkit/plugins/npapi/plugin_list.h"
|
| -
|
| -#include <algorithm>
|
| -#include <dlfcn.h>
|
| -#if defined(OS_OPENBSD)
|
| -#include <sys/exec_elf.h>
|
| -#else
|
| -#include <elf.h>
|
| -#endif
|
| -#include <fcntl.h>
|
| -#include <sys/stat.h>
|
| -#include <sys/types.h>
|
| -#include <unistd.h>
|
| -
|
| -#include "base/cpu.h"
|
| -#include "base/file_util.h"
|
| -#include "base/files/file_enumerator.h"
|
| -#include "base/native_library.h"
|
| -#include "base/path_service.h"
|
| -#include "base/posix/eintr_wrapper.h"
|
| -#include "base/sha1.h"
|
| -#include "base/strings/string_split.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/strings/stringprintf.h"
|
| -#include "base/strings/sys_string_conversions.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "build/build_config.h"
|
| -#include "third_party/npapi/bindings/nphostapi.h"
|
| -
|
| -// These headers must be included in this order to make the declaration gods
|
| -// happy.
|
| -#include "base/third_party/nspr/prcpucfg_linux.h"
|
| -
|
| -namespace webkit {
|
| -namespace npapi {
|
| -
|
| -namespace {
|
| -
|
| -// We build up a list of files and mtimes so we can sort them.
|
| -typedef std::pair<base::FilePath, base::Time> FileAndTime;
|
| -typedef std::vector<FileAndTime> FileTimeList;
|
| -
|
| -enum PluginQuirk {
|
| - // No quirks - plugin is outright banned.
|
| - PLUGIN_QUIRK_NONE = 0,
|
| - // Plugin is using SSE2 instructions without checking for SSE2 instruction
|
| - // support. Ban the plugin if the system has no SSE2 support.
|
| - PLUGIN_QUIRK_MISSING_SSE2_CHECK = 1 << 0,
|
| -};
|
| -
|
| -// Copied from nsplugindefs.h instead of including the file since it has a bunch
|
| -// of dependencies.
|
| -enum nsPluginVariable {
|
| - nsPluginVariable_NameString = 1,
|
| - nsPluginVariable_DescriptionString = 2
|
| -};
|
| -
|
| -// 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;
|
| -}
|
| -
|
| -// Checks to see if the current environment meets any of the condtions set in
|
| -// |quirks|. Returns true if any of the conditions are met, or if |quirks| is
|
| -// PLUGIN_QUIRK_NONE.
|
| -bool CheckQuirks(PluginQuirk quirks) {
|
| - if (quirks == PLUGIN_QUIRK_NONE)
|
| - return true;
|
| -
|
| - if ((quirks & PLUGIN_QUIRK_MISSING_SSE2_CHECK) != 0) {
|
| - base::CPU cpu;
|
| - if (!cpu.has_sse2())
|
| - return true;
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -// Return true if |path| matches a known (file size, sha1sum) pair.
|
| -// Also check against any PluginQuirks the bad plugin may have.
|
| -// The use of the file size is an optimization so we don't have to read in
|
| -// the entire file unless we have to.
|
| -bool IsBlacklistedBySha1sumAndQuirks(const base::FilePath& path) {
|
| - const struct BadEntry {
|
| - int64 size;
|
| - std::string sha1;
|
| - PluginQuirk quirks;
|
| - } bad_entries[] = {
|
| - // Flash 9 r31 - http://crbug.com/29237
|
| - { 7040080, "fa5803061125ca47846713b34a26a42f1f1e98bb", PLUGIN_QUIRK_NONE },
|
| - // Flash 9 r48 - http://crbug.com/29237
|
| - { 7040036, "0c4b3768a6d4bfba003088e4b9090d381de1af2b", PLUGIN_QUIRK_NONE },
|
| - // Flash 11.2.202.236, 32-bit - http://crbug.com/140086
|
| - { 17406436, "1e07eac912faf9426c52a288c76c3b6238f90b6b",
|
| - PLUGIN_QUIRK_MISSING_SSE2_CHECK },
|
| - // Flash 11.2.202.238, 32-bit - http://crbug.com/140086
|
| - { 17410532, "e9401097e97c8443a7d9156be62184ffe1addd5c",
|
| - PLUGIN_QUIRK_MISSING_SSE2_CHECK },
|
| - };
|
| -
|
| - int64 size;
|
| - if (!file_util::GetFileSize(path, &size))
|
| - return false;
|
| - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(bad_entries); i++) {
|
| - if (bad_entries[i].size != size)
|
| - continue;
|
| -
|
| - std::string file_content;
|
| - if (!file_util::ReadFileToString(path, &file_content))
|
| - continue;
|
| - std::string sha1 = base::SHA1HashString(file_content);
|
| - std::string sha1_readable;
|
| - for (size_t j = 0; j < sha1.size(); j++)
|
| - base::StringAppendF(&sha1_readable, "%02x", sha1[j] & 0xFF);
|
| - if (bad_entries[i].sha1 == sha1_readable)
|
| - return CheckQuirks(bad_entries[i].quirks);
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -// Some plugins are shells around other plugins; we prefer to use the
|
| -// real plugin directly, if it's available. This function returns
|
| -// true if we should prefer other plugins over this one. We'll still
|
| -// use a "undesirable" plugin if no other option is available.
|
| -bool IsUndesirablePlugin(const WebPluginInfo& info) {
|
| - std::string filename = info.path.BaseName().value();
|
| - const char* kUndesiredPlugins[] = {
|
| - "npcxoffice", // Crossover
|
| - "npwrapper", // nspluginwrapper
|
| - };
|
| - for (size_t i = 0; i < arraysize(kUndesiredPlugins); i++) {
|
| - if (filename.find(kUndesiredPlugins[i]) != std::string::npos) {
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -// Return true if we shouldn't load a plugin at all.
|
| -// This is an ugly hack to blacklist Adobe Acrobat due to not supporting
|
| -// its Xt-based mainloop.
|
| -// http://code.google.com/p/chromium/issues/detail?id=38229
|
| -bool IsBlacklistedPlugin(const base::FilePath& path) {
|
| - const char* kBlackListedPlugins[] = {
|
| - "nppdf.so", // Adobe PDF
|
| - };
|
| - std::string filename = path.BaseName().value();
|
| - for (size_t i = 0; i < arraysize(kBlackListedPlugins); i++) {
|
| - if (filename.find(kBlackListedPlugins[i]) != std::string::npos) {
|
| - return true;
|
| - }
|
| - }
|
| - return IsBlacklistedBySha1sumAndQuirks(path);
|
| -}
|
| -
|
| -// Read the ELF header and return true if it is usable on
|
| -// the current architecture (e.g. 32-bit ELF on 32-bit build).
|
| -// Returns false on other errors as well.
|
| -bool ELFMatchesCurrentArchitecture(const base::FilePath& filename) {
|
| - // First make sure we can open the file and it is in fact, a regular file.
|
| - struct stat stat_buf;
|
| - // Open with O_NONBLOCK so we don't block on pipes.
|
| - int fd = open(filename.value().c_str(), O_RDONLY|O_NONBLOCK);
|
| - if (fd < 0)
|
| - return false;
|
| - bool ret = (fstat(fd, &stat_buf) >= 0 && S_ISREG(stat_buf.st_mode));
|
| - if (HANDLE_EINTR(close(fd)) < 0)
|
| - return false;
|
| - if (!ret)
|
| - return false;
|
| -
|
| - const size_t kELFBufferSize = 5;
|
| - char buffer[kELFBufferSize];
|
| - if (!file_util::ReadFile(filename, buffer, kELFBufferSize))
|
| - return false;
|
| -
|
| - if (buffer[0] != ELFMAG0 ||
|
| - buffer[1] != ELFMAG1 ||
|
| - buffer[2] != ELFMAG2 ||
|
| - buffer[3] != ELFMAG3) {
|
| - // Not an ELF file, perhaps?
|
| - return false;
|
| - }
|
| -
|
| - int elf_class = buffer[EI_CLASS];
|
| -#if defined(ARCH_CPU_32_BITS)
|
| - if (elf_class == ELFCLASS32)
|
| - return true;
|
| -#elif defined(ARCH_CPU_64_BITS)
|
| - if (elf_class == ELFCLASS64)
|
| - return true;
|
| -#endif
|
| -
|
| - return false;
|
| -}
|
| -
|
| -// This structure matches enough of nspluginwrapper's NPW_PluginInfo
|
| -// for us to extract the real plugin path.
|
| -struct __attribute__((packed)) NSPluginWrapperInfo {
|
| - char ident[32]; // NSPluginWrapper magic identifier (includes version).
|
| - char path[PATH_MAX]; // Path to wrapped plugin.
|
| -};
|
| -
|
| -// Test a plugin for whether it's been wrapped by NSPluginWrapper, and
|
| -// if so attempt to unwrap it. Pass in an opened plugin handle; on
|
| -// success, |dl| and |unwrapped_path| will be filled in with the newly
|
| -// opened plugin. On failure, params are left unmodified.
|
| -void UnwrapNSPluginWrapper(void **dl, base::FilePath* unwrapped_path) {
|
| - NSPluginWrapperInfo* info =
|
| - reinterpret_cast<NSPluginWrapperInfo*>(dlsym(*dl, "NPW_Plugin"));
|
| - if (!info)
|
| - return; // Not a NSPW plugin.
|
| -
|
| - // Here we could check the NSPW ident field for the versioning
|
| - // information, but the path field is available in all versions
|
| - // anyway.
|
| -
|
| - // Grab the path to the wrapped plugin. Just in case the structure
|
| - // format changes, protect against the path not being null-terminated.
|
| - char* path_end = static_cast<char*>(memchr(info->path, '\0',
|
| - sizeof(info->path)));
|
| - if (!path_end)
|
| - path_end = info->path + sizeof(info->path);
|
| - base::FilePath path = base::FilePath(
|
| - std::string(info->path, path_end - info->path));
|
| -
|
| - if (!ELFMatchesCurrentArchitecture(path)) {
|
| - LOG(WARNING) << path.value() << " is nspluginwrapper wrapping a "
|
| - << "plugin for a different architecture; it will "
|
| - << "work better if you instead use a native plugin.";
|
| - return;
|
| - }
|
| -
|
| - std::string error;
|
| - void* newdl = base::LoadNativeLibrary(path, &error);
|
| - if (!newdl) {
|
| - // We couldn't load the unwrapped plugin for some reason, despite
|
| - // being able to load the wrapped one. Just use the wrapped one.
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Could not use unwrapped nspluginwrapper plugin "
|
| - << unwrapped_path->value() << " (" << error << "), "
|
| - << "using the wrapped one.";
|
| - return;
|
| - }
|
| -
|
| - // Unload the wrapped plugin, and use the wrapped plugin instead.
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Using unwrapped version " << unwrapped_path->value()
|
| - << " of nspluginwrapper-wrapped plugin.";
|
| - base::UnloadNativeLibrary(*dl);
|
| - *dl = newdl;
|
| - *unwrapped_path = path;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -bool PluginList::ReadWebPluginInfo(const base::FilePath& filename,
|
| - WebPluginInfo* info) {
|
| - // The file to reference is:
|
| - // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUnix.cpp
|
| -
|
| - // Skip files that aren't appropriate for our architecture.
|
| - if (!ELFMatchesCurrentArchitecture(filename)) {
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Skipping plugin " << filename.value()
|
| - << " because it doesn't match the current architecture.";
|
| - return false;
|
| - }
|
| -
|
| - std::string error;
|
| - void* dl = base::LoadNativeLibrary(filename, &error);
|
| - if (!dl) {
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "While reading plugin info, unable to load library "
|
| - << filename.value() << " (" << error << "), skipping.";
|
| - return false;
|
| - }
|
| -
|
| - info->path = filename;
|
| -
|
| - // Attempt to swap in the wrapped plugin if this is nspluginwrapper.
|
| - UnwrapNSPluginWrapper(&dl, &info->path);
|
| -
|
| - // See comments in plugin_lib_mac regarding this symbol.
|
| - typedef const char* (*NP_GetMimeDescriptionType)();
|
| - NP_GetMimeDescriptionType NP_GetMIMEDescription =
|
| - reinterpret_cast<NP_GetMimeDescriptionType>(
|
| - dlsym(dl, "NP_GetMIMEDescription"));
|
| - const char* mime_description = NULL;
|
| - if (!NP_GetMIMEDescription) {
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Plugin " << filename.value() << " doesn't have a "
|
| - << "NP_GetMIMEDescription symbol";
|
| - return false;
|
| - }
|
| - mime_description = NP_GetMIMEDescription();
|
| -
|
| - if (!mime_description) {
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "MIME description for " << filename.value() << " is empty";
|
| - return false;
|
| - }
|
| - ParseMIMEDescription(mime_description, &info->mime_types);
|
| -
|
| - // The plugin name and description live behind NP_GetValue calls.
|
| - typedef NPError (*NP_GetValueType)(void* unused,
|
| - nsPluginVariable variable,
|
| - void* value_out);
|
| - NP_GetValueType NP_GetValue =
|
| - reinterpret_cast<NP_GetValueType>(dlsym(dl, "NP_GetValue"));
|
| - if (NP_GetValue) {
|
| - const char* name = NULL;
|
| - NP_GetValue(NULL, nsPluginVariable_NameString, &name);
|
| - if (name) {
|
| - info->name = UTF8ToUTF16(name);
|
| - ExtractVersionString(name, info);
|
| - }
|
| -
|
| - const char* description = NULL;
|
| - NP_GetValue(NULL, nsPluginVariable_DescriptionString, &description);
|
| - if (description) {
|
| - info->desc = UTF8ToUTF16(description);
|
| - if (info->version.empty())
|
| - ExtractVersionString(description, info);
|
| - }
|
| -
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Got info for plugin " << filename.value()
|
| - << " Name = \"" << UTF16ToUTF8(info->name)
|
| - << "\", Description = \"" << UTF16ToUTF8(info->desc)
|
| - << "\", Version = \"" << UTF16ToUTF8(info->version)
|
| - << "\".";
|
| - } else {
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Plugin " << filename.value()
|
| - << " has no GetValue() and probably won't work.";
|
| - }
|
| -
|
| - // Intentionally not unloading the plugin here, it can lead to crashes.
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// static
|
| -void PluginList::ParseMIMEDescription(
|
| - const std::string& description,
|
| - std::vector<WebPluginMimeType>* mime_types) {
|
| - // We parse the description here into WebPluginMimeType structures.
|
| - // Naively from the NPAPI docs you'd think you could use
|
| - // string-splitting, but the Firefox parser turns out to do something
|
| - // different: find the first colon, then the second, then a semi.
|
| - //
|
| - // See ParsePluginMimeDescription near
|
| - // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUtils.h#53
|
| -
|
| - std::string::size_type ofs = 0;
|
| - for (;;) {
|
| - WebPluginMimeType mime_type;
|
| -
|
| - std::string::size_type end = description.find(':', ofs);
|
| - if (end == std::string::npos)
|
| - break;
|
| - mime_type.mime_type = description.substr(ofs, end - ofs);
|
| - ofs = end + 1;
|
| -
|
| - end = description.find(':', ofs);
|
| - if (end == std::string::npos)
|
| - break;
|
| - const std::string extensions = description.substr(ofs, end - ofs);
|
| - base::SplitString(extensions, ',', &mime_type.file_extensions);
|
| - ofs = end + 1;
|
| -
|
| - end = description.find(';', ofs);
|
| - // It's ok for end to run off the string here. If there's no
|
| - // trailing semicolon we consume the remainder of the string.
|
| - if (end != std::string::npos) {
|
| - mime_type.description = UTF8ToUTF16(description.substr(ofs, end - ofs));
|
| - } else {
|
| - mime_type.description = UTF8ToUTF16(description.substr(ofs));
|
| - }
|
| - mime_types->push_back(mime_type);
|
| - if (end == std::string::npos)
|
| - break;
|
| - ofs = end + 1;
|
| - }
|
| -}
|
| -
|
| -// static
|
| -void PluginList::ExtractVersionString(const std::string& desc,
|
| - WebPluginInfo* info) {
|
| - // This matching works by extracting a version substring, along the lines of:
|
| - // No postfix: second match in .*<prefix>.*$
|
| - // With postfix: second match .*<prefix>.*<postfix>
|
| - static const struct {
|
| - const char* kPrefix;
|
| - const char* kPostfix;
|
| - } kPrePostFixes[] = {
|
| - { "Shockwave Flash ", 0 },
|
| - { "Java(TM) Plug-in ", 0 },
|
| - { "(using IcedTea-Web ", " " },
|
| - { 0, 0 }
|
| - };
|
| - std::string version;
|
| - for (size_t i = 0; kPrePostFixes[i].kPrefix; ++i) {
|
| - size_t pos;
|
| - if ((pos = desc.find(kPrePostFixes[i].kPrefix)) != std::string::npos) {
|
| - version = desc.substr(pos + strlen(kPrePostFixes[i].kPrefix));
|
| - pos = std::string::npos;
|
| - if (kPrePostFixes[i].kPostfix)
|
| - pos = version.find(kPrePostFixes[i].kPostfix);
|
| - if (pos != std::string::npos)
|
| - version = version.substr(0, pos);
|
| - break;
|
| - }
|
| - }
|
| - if (!version.empty()) {
|
| - info->version = UTF8ToUTF16(version);
|
| - }
|
| -}
|
| -
|
| -void PluginList::GetPluginDirectories(std::vector<base::FilePath>* plugin_dirs) {
|
| - // See http://groups.google.com/group/chromium-dev/browse_thread/thread/7a70e5fcbac786a9
|
| - // for discussion.
|
| - // We first consult Chrome-specific dirs, then fall back on the logic
|
| - // Mozilla uses.
|
| -
|
| - if (PluginList::plugins_discovery_disabled_)
|
| - return;
|
| -
|
| - // Note: "extra" plugin dirs and paths are examined before these.
|
| - // "Extra" are those added by PluginList::AddExtraPluginDir() and
|
| - // PluginList::AddExtraPluginPath().
|
| -
|
| - // The Chrome binary dir + "plugins/".
|
| - base::FilePath dir;
|
| - PathService::Get(base::DIR_EXE, &dir);
|
| - plugin_dirs->push_back(dir.Append("plugins"));
|
| -
|
| - // Chrome OS only loads plugins from /opt/google/chrome/plugins.
|
| -#if !defined(OS_CHROMEOS)
|
| - // Mozilla code to reference:
|
| - // http://mxr.mozilla.org/firefox/ident?i=NS_APP_PLUGINS_DIR_LIST
|
| - // and tens of accompanying files (mxr is very helpful).
|
| - // This code carefully matches their behavior for compat reasons.
|
| -
|
| - // 1) MOZ_PLUGIN_PATH env variable.
|
| - const char* moz_plugin_path = getenv("MOZ_PLUGIN_PATH");
|
| - if (moz_plugin_path) {
|
| - std::vector<std::string> paths;
|
| - base::SplitString(moz_plugin_path, ':', &paths);
|
| - for (size_t i = 0; i < paths.size(); ++i)
|
| - plugin_dirs->push_back(base::FilePath(paths[i]));
|
| - }
|
| -
|
| - // 2) NS_USER_PLUGINS_DIR: ~/.mozilla/plugins.
|
| - // This is a de-facto standard, so even though we're not Mozilla, let's
|
| - // look in there too.
|
| - base::FilePath home = file_util::GetHomeDir();
|
| - if (!home.empty())
|
| - plugin_dirs->push_back(home.Append(".mozilla/plugins"));
|
| -
|
| - // 3) NS_SYSTEM_PLUGINS_DIR:
|
| - // This varies across different browsers and versions, so check 'em all.
|
| - plugin_dirs->push_back(base::FilePath("/usr/lib/browser-plugins"));
|
| - plugin_dirs->push_back(base::FilePath("/usr/lib/mozilla/plugins"));
|
| - plugin_dirs->push_back(base::FilePath("/usr/lib/firefox/plugins"));
|
| - plugin_dirs->push_back(base::FilePath("/usr/lib/xulrunner-addons/plugins"));
|
| -
|
| -#if defined(ARCH_CPU_64_BITS)
|
| - // On my Ubuntu system, /usr/lib64 is a symlink to /usr/lib.
|
| - // But a user reported on their Fedora system they are separate.
|
| - plugin_dirs->push_back(base::FilePath("/usr/lib64/browser-plugins"));
|
| - plugin_dirs->push_back(base::FilePath("/usr/lib64/mozilla/plugins"));
|
| - plugin_dirs->push_back(base::FilePath("/usr/lib64/firefox/plugins"));
|
| - plugin_dirs->push_back(base::FilePath("/usr/lib64/xulrunner-addons/plugins"));
|
| -#endif // defined(ARCH_CPU_64_BITS)
|
| -#endif // !defined(OS_CHROMEOS)
|
| -}
|
| -
|
| -void PluginList::GetPluginsInDir(
|
| - const base::FilePath& dir_path, std::vector<base::FilePath>* 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;
|
| - base::FileEnumerator enumerator(dir_path,
|
| - false, // not recursive
|
| - base::FileEnumerator::FILES);
|
| - for (base::FilePath path = enumerator.Next(); !path.value().empty();
|
| - path = enumerator.Next()) {
|
| - // Skip over Mozilla .xpt files.
|
| - 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.
|
| - // MakeAbsoluteFilePath calls through to realpath(), which resolves
|
| - // symlinks.
|
| - base::FilePath orig_path = path;
|
| - path = base::MakeAbsoluteFilePath(path);
|
| - if (path.empty())
|
| - path = orig_path;
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Resolved " << orig_path.value() << " -> " << path.value();
|
| -
|
| - if (std::find(plugins->begin(), plugins->end(), path) != plugins->end()) {
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Skipping duplicate instance of " << path.value();
|
| - continue;
|
| - }
|
| -
|
| - if (IsBlacklistedPlugin(path)) {
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Skipping blacklisted plugin " << path.value();
|
| - continue;
|
| - }
|
| -
|
| - // Flash stops working if the containing directory involves 'netscape'.
|
| - // No joke. So use the other path if it's better.
|
| - static const char kFlashPlayerFilename[] = "libflashplayer.so";
|
| - static const char kNetscapeInPath[] = "/netscape/";
|
| - if (path.BaseName().value() == kFlashPlayerFilename &&
|
| - path.value().find(kNetscapeInPath) != std::string::npos) {
|
| - if (orig_path.value().find(kNetscapeInPath) == std::string::npos) {
|
| - // Go back to the old path.
|
| - path = orig_path;
|
| - } else {
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Flash misbehaves when used from a directory containing "
|
| - << kNetscapeInPath << ", so skipping " << orig_path.value();
|
| - continue;
|
| - }
|
| - }
|
| -
|
| - // Get mtime.
|
| - base::PlatformFileInfo info;
|
| - if (!file_util::GetFileInfo(path, &info))
|
| - 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) {
|
| - plugins->push_back(i->first);
|
| - }
|
| -}
|
| -
|
| -bool PluginList::ShouldLoadPluginUsingPluginList(
|
| - const WebPluginInfo& info, std::vector<webkit::WebPluginInfo>* plugins) {
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Considering " << info.path.value() << " (" << info.name << ")";
|
| -
|
| - if (IsUndesirablePlugin(info)) {
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << info.path.value() << " is undesirable.";
|
| -
|
| - // See if we have a better version of this plugin.
|
| - for (size_t j = 0; j < plugins->size(); ++j) {
|
| - if ((*plugins)[j].name == info.name &&
|
| - !IsUndesirablePlugin((*plugins)[j])) {
|
| - // Skip the current undesirable one so we can use the better one
|
| - // we just found.
|
| - LOG_IF(ERROR, PluginList::DebugPluginLoading())
|
| - << "Skipping " << info.path.value() << ", preferring "
|
| - << (*plugins)[j].path.value();
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // TODO(evanm): prefer the newest version of flash, etc. here?
|
| -
|
| - VLOG_IF(1, PluginList::DebugPluginLoading()) << "Using " << info.path.value();
|
| -
|
| - return true;
|
| -}
|
| -
|
| -} // namespace npapi
|
| -} // namespace webkit
|
|
|