PluginInfoStore.cpp [plain text]
#include "config.h"
#include "PluginInfoStore.h"
#include "PluginModuleInfo.h"
#include <WebCore/KURL.h>
#include <WebCore/MIMETypeRegistry.h>
#include <algorithm>
#include <wtf/ListHashSet.h>
#include <wtf/StdLibExtras.h>
using namespace std;
using namespace WebCore;
namespace WebKit {
PluginInfoStore::PluginInfoStore()
: m_pluginListIsUpToDate(false)
, m_client(0)
{
}
void PluginInfoStore::setAdditionalPluginsDirectories(const Vector<String>& directories)
{
m_additionalPluginsDirectories = directories;
refresh();
}
void PluginInfoStore::refresh()
{
m_pluginListIsUpToDate = false;
}
template <typename T, typename U>
static void addFromVector(T& hashSet, const U& vector)
{
for (size_t i = 0; i < vector.size(); ++i)
hashSet.add(vector[i]);
}
#if OS(WINDOWS)
typedef ListHashSet<String, 32, CaseFoldingHash> PathHashSet;
#else
typedef ListHashSet<String, 32> PathHashSet;
#endif
static inline Vector<PluginModuleInfo> deepIsolatedCopyPluginInfoVector(const Vector<PluginModuleInfo>& vector)
{
Vector<PluginModuleInfo> copy;
copy.reserveCapacity(vector.size());
for (unsigned i = 0; i < vector.size(); ++i)
copy.append(vector[i].isolatedCopy());
return copy;
}
void PluginInfoStore::loadPluginsIfNecessary()
{
if (m_pluginListIsUpToDate)
return;
PathHashSet uniquePluginPaths;
for (size_t i = 0; i < m_additionalPluginsDirectories.size(); ++i)
addFromVector(uniquePluginPaths, pluginPathsInDirectory(m_additionalPluginsDirectories[i]));
Vector<String> directories = pluginsDirectories();
for (size_t i = 0; i < directories.size(); ++i)
addFromVector(uniquePluginPaths, pluginPathsInDirectory(directories[i]));
addFromVector(uniquePluginPaths, individualPluginPaths());
Vector<PluginModuleInfo> plugins;
PathHashSet::const_iterator end = uniquePluginPaths.end();
for (PathHashSet::const_iterator it = uniquePluginPaths.begin(); it != end; ++it)
loadPlugin(plugins, *it);
m_plugins = deepIsolatedCopyPluginInfoVector(plugins);
m_pluginListIsUpToDate = true;
if (m_client)
m_client->pluginInfoStoreDidLoadPlugins(this, m_plugins);
}
void PluginInfoStore::loadPlugin(Vector<PluginModuleInfo>& plugins, const String& pluginPath)
{
PluginModuleInfo plugin;
if (!getPluginInfo(pluginPath, plugin))
return;
if (!shouldUsePlugin(plugins, plugin))
return;
plugins.append(plugin);
}
Vector<PluginModuleInfo> PluginInfoStore::plugins()
{
MutexLocker locker(m_pluginsLock);
loadPluginsIfNecessary();
return deepIsolatedCopyPluginInfoVector(m_plugins);
}
PluginModuleInfo PluginInfoStore::findPluginForMIMEType(const String& mimeType) const
{
MutexLocker locker(m_pluginsLock);
ASSERT(!mimeType.isNull());
for (size_t i = 0; i < m_plugins.size(); ++i) {
const PluginModuleInfo& plugin = m_plugins[i];
for (size_t j = 0; j < plugin.info.mimes.size(); ++j) {
const MimeClassInfo& mimeClassInfo = plugin.info.mimes[j];
if (mimeClassInfo.type == mimeType)
return plugin;
}
}
return PluginModuleInfo();
}
PluginModuleInfo PluginInfoStore::findPluginForExtension(const String& extension, String& mimeType) const
{
MutexLocker locker(m_pluginsLock);
ASSERT(!extension.isNull());
for (size_t i = 0; i < m_plugins.size(); ++i) {
const PluginModuleInfo& plugin = m_plugins[i];
for (size_t j = 0; j < plugin.info.mimes.size(); ++j) {
const MimeClassInfo& mimeClassInfo = plugin.info.mimes[j];
const Vector<String>& extensions = mimeClassInfo.extensions;
if (find(extensions.begin(), extensions.end(), extension) != extensions.end()) {
mimeType = mimeClassInfo.type;
return plugin;
}
}
}
return PluginModuleInfo();
}
static inline String pathExtension(const KURL& url)
{
String extension;
String filename = url.lastPathComponent();
if (!filename.endsWith('/')) {
int extensionPos = filename.reverseFind('.');
if (extensionPos != -1)
extension = filename.substring(extensionPos + 1);
}
return extension;
}
#if !PLATFORM(MAC)
PluginModuleLoadPolicy PluginInfoStore::policyForPlugin(const PluginModuleInfo&)
{
return PluginModuleLoadNormally;
}
bool PluginInfoStore::reactivateInactivePlugin(const PluginModuleInfo&)
{
return false;
}
String PluginInfoStore::getMIMETypeForExtension(const String& extension)
{
return MIMETypeRegistry::getMIMETypeForExtension(extension);
}
PluginModuleInfo PluginInfoStore::findPluginWithBundleIdentifier(const String&)
{
ASSERT_NOT_REACHED();
return PluginModuleInfo();
}
#endif
PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const KURL& url)
{
{
MutexLocker locker(m_pluginsLock);
loadPluginsIfNecessary();
}
if (!mimeType.isNull()) {
PluginModuleInfo plugin = findPluginForMIMEType(mimeType);
if (!plugin.path.isNull())
return plugin;
}
String extension = pathExtension(url).lower();
if (!extension.isNull() && mimeType.isEmpty()) {
PluginModuleInfo plugin = findPluginForExtension(extension, mimeType);
if (!plugin.path.isNull())
return plugin;
String extensionMimeType = getMIMETypeForExtension(extension);
if (!extensionMimeType.isNull()) {
PluginModuleInfo plugin = findPluginForMIMEType(extensionMimeType);
if (!plugin.path.isNull()) {
mimeType = extensionMimeType;
return plugin;
}
}
}
return PluginModuleInfo();
}
PluginModuleInfo PluginInfoStore::infoForPluginWithPath(const String& pluginPath) const
{
MutexLocker locker(m_pluginsLock);
for (size_t i = 0; i < m_plugins.size(); ++i) {
if (m_plugins[i].path == pluginPath)
return m_plugins[i];
}
ASSERT_NOT_REACHED();
return PluginModuleInfo();
}
}