diff options
Diffstat (limited to 'WebCore/plugins/PluginDatabase.cpp')
-rw-r--r-- | WebCore/plugins/PluginDatabase.cpp | 675 |
1 files changed, 0 insertions, 675 deletions
diff --git a/WebCore/plugins/PluginDatabase.cpp b/WebCore/plugins/PluginDatabase.cpp deleted file mode 100644 index b9e154a..0000000 --- a/WebCore/plugins/PluginDatabase.cpp +++ /dev/null @@ -1,675 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2008 Collabora, Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "PluginDatabase.h" - -#include "Frame.h" -#include "KURL.h" -#include "PluginPackage.h" -#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) -#include "FileSystem.h" -#endif -#include <stdlib.h> -#include <wtf/text/CString.h> - -#if PLATFORM(ANDROID) -#include "JavaSharedClient.h" -#include "PluginClient.h" -#endif - -namespace WebCore { - -typedef HashMap<String, RefPtr<PluginPackage> > PluginPackageByNameMap; - -#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) -static const size_t maximumPersistentPluginMetadataCacheSize = 32768; - -static bool gPersistentPluginMetadataCacheIsEnabled; - -String& persistentPluginMetadataCachePath() -{ - DEFINE_STATIC_LOCAL(String, cachePath, ()); - return cachePath; -} -#endif - -PluginDatabase::PluginDatabase() -#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) - : m_persistentMetadataCacheIsLoaded(false) -#endif -{ -} - -PluginDatabase* PluginDatabase::installedPlugins(bool populate) -{ - static PluginDatabase* plugins = 0; - - if (!plugins) { - plugins = new PluginDatabase; - - if (populate) { - plugins->setPluginDirectories(PluginDatabase::defaultPluginDirectories()); - plugins->refresh(); - } - } - - return plugins; -} - -bool PluginDatabase::isMIMETypeRegistered(const String& mimeType) -{ - if (mimeType.isNull()) - return false; - if (m_registeredMIMETypes.contains(mimeType)) - return true; - // No plugin was found, try refreshing the database and searching again - return (refresh() && m_registeredMIMETypes.contains(mimeType)); -} - -void PluginDatabase::addExtraPluginDirectory(const String& directory) -{ - m_pluginDirectories.append(directory); - refresh(); -} - -bool PluginDatabase::refresh() -{ -#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) - if (!m_persistentMetadataCacheIsLoaded) - loadPersistentMetadataCache(); -#endif - bool pluginSetChanged = false; - - if (!m_plugins.isEmpty()) { - PluginSet pluginsToUnload; - getDeletedPlugins(pluginsToUnload); - - // Unload plugins - PluginSet::const_iterator end = pluginsToUnload.end(); - for (PluginSet::const_iterator it = pluginsToUnload.begin(); it != end; ++it) - remove(it->get()); - - pluginSetChanged = !pluginsToUnload.isEmpty(); - } - - HashSet<String> paths; - getPluginPathsInDirectories(paths); - - HashMap<String, time_t> pathsWithTimes; - - // We should only skip unchanged files if we didn't remove any plugins above. If we did remove - // any plugins, we need to look at every plugin file so that, e.g., if the user has two versions - // of RealPlayer installed and just removed the newer one, we'll pick up the older one. - bool shouldSkipUnchangedFiles = !pluginSetChanged; - - HashSet<String>::const_iterator pathsEnd = paths.end(); - for (HashSet<String>::const_iterator it = paths.begin(); it != pathsEnd; ++it) { - time_t lastModified; - if (!getFileModificationTime(*it, lastModified)) - continue; - - pathsWithTimes.add(*it, lastModified); - - // If the path's timestamp hasn't changed since the last time we ran refresh(), we don't have to do anything. - if (shouldSkipUnchangedFiles && m_pluginPathsWithTimes.get(*it) == lastModified) - continue; - - if (RefPtr<PluginPackage> oldPackage = m_pluginsByPath.get(*it)) { - ASSERT(!shouldSkipUnchangedFiles || oldPackage->lastModified() != lastModified); - remove(oldPackage.get()); - } - - RefPtr<PluginPackage> package = PluginPackage::createPackage(*it, lastModified); - if (package && add(package.release())) - pluginSetChanged = true; - } - - // Cache all the paths we found with their timestamps for next time. - pathsWithTimes.swap(m_pluginPathsWithTimes); - - if (!pluginSetChanged) - return false; - -#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) - updatePersistentMetadataCache(); -#endif - - m_registeredMIMETypes.clear(); - - // Register plug-in MIME types - PluginSet::const_iterator end = m_plugins.end(); - for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) { - // Get MIME types - MIMEToDescriptionsMap::const_iterator map_it = (*it)->mimeToDescriptions().begin(); - MIMEToDescriptionsMap::const_iterator map_end = (*it)->mimeToDescriptions().end(); - for (; map_it != map_end; ++map_it) - m_registeredMIMETypes.add(map_it->first); - } - - return true; -} - -Vector<PluginPackage*> PluginDatabase::plugins() const -{ - Vector<PluginPackage*> result; - - PluginSet::const_iterator end = m_plugins.end(); - for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) - result.append((*it).get()); - - return result; -} - -int PluginDatabase::preferredPluginCompare(const void* a, const void* b) -{ - PluginPackage* pluginA = *static_cast<PluginPackage* const*>(a); - PluginPackage* pluginB = *static_cast<PluginPackage* const*>(b); - - return pluginA->compare(*pluginB); -} - -PluginPackage* PluginDatabase::pluginForMIMEType(const String& mimeType) -{ - if (mimeType.isEmpty()) - return 0; - - String key = mimeType.lower(); - PluginSet::const_iterator end = m_plugins.end(); - PluginPackage* preferredPlugin = m_preferredPlugins.get(key).get(); - if (preferredPlugin - && preferredPlugin->isEnabled() - && preferredPlugin->mimeToDescriptions().contains(key)) { - return preferredPlugin; - } - - Vector<PluginPackage*, 2> pluginChoices; - - for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) { - PluginPackage* plugin = (*it).get(); - - if (!plugin->isEnabled()) - continue; - - if (plugin->mimeToDescriptions().contains(key)) { -#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) - if (!plugin->ensurePluginLoaded()) - continue; -#endif - pluginChoices.append(plugin); - } - } - - if (pluginChoices.isEmpty()) - return 0; - - qsort(pluginChoices.data(), pluginChoices.size(), sizeof(PluginPackage*), PluginDatabase::preferredPluginCompare); - - return pluginChoices[0]; -} - -String PluginDatabase::MIMETypeForExtension(const String& extension) const -{ - if (extension.isEmpty()) - return String(); - - PluginSet::const_iterator end = m_plugins.end(); - String mimeType; - Vector<PluginPackage*, 2> pluginChoices; - HashMap<PluginPackage*, String> mimeTypeForPlugin; - - for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) { - if (!(*it)->isEnabled()) - continue; - - MIMEToExtensionsMap::const_iterator mime_end = (*it)->mimeToExtensions().end(); - - for (MIMEToExtensionsMap::const_iterator mime_it = (*it)->mimeToExtensions().begin(); mime_it != mime_end; ++mime_it) { - mimeType = mime_it->first; - PluginPackage* preferredPlugin = m_preferredPlugins.get(mimeType).get(); - const Vector<String>& extensions = mime_it->second; - bool foundMapping = false; - for (unsigned i = 0; i < extensions.size(); i++) { - if (equalIgnoringCase(extensions[i], extension)) { - PluginPackage* plugin = (*it).get(); - - if (preferredPlugin && PluginPackage::equal(*plugin, *preferredPlugin)) - return mimeType; - -#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) - if (!plugin->ensurePluginLoaded()) - continue; -#endif - pluginChoices.append(plugin); - mimeTypeForPlugin.add(plugin, mimeType); - foundMapping = true; - break; - } - } - if (foundMapping) - break; - } - } - - if (pluginChoices.isEmpty()) - return String(); - - qsort(pluginChoices.data(), pluginChoices.size(), sizeof(PluginPackage*), PluginDatabase::preferredPluginCompare); - - return mimeTypeForPlugin.get(pluginChoices[0]); -} - -PluginPackage* PluginDatabase::findPlugin(const KURL& url, String& mimeType) -{ - if (!mimeType.isEmpty()) - return pluginForMIMEType(mimeType); - - String filename = url.lastPathComponent(); - if (filename.endsWith("/")) - return 0; - - int extensionPos = filename.reverseFind('.'); - if (extensionPos == -1) - return 0; - - String mimeTypeForExtension = MIMETypeForExtension(filename.substring(extensionPos + 1)); - PluginPackage* plugin = pluginForMIMEType(mimeTypeForExtension); - if (!plugin) { - // FIXME: if no plugin could be found, query Windows for the mime type - // corresponding to the extension. - return 0; - } - - mimeType = mimeTypeForExtension; - return plugin; -} - -void PluginDatabase::setPreferredPluginForMIMEType(const String& mimeType, PluginPackage* plugin) -{ - if (!plugin || plugin->mimeToExtensions().contains(mimeType)) - m_preferredPlugins.set(mimeType.lower(), plugin); -} - -void PluginDatabase::getDeletedPlugins(PluginSet& plugins) const -{ - PluginSet::const_iterator end = m_plugins.end(); - for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) { - if (!fileExists((*it)->path())) - plugins.add(*it); - } -} - -bool PluginDatabase::add(PassRefPtr<PluginPackage> prpPackage) -{ - ASSERT_ARG(prpPackage, prpPackage); - - RefPtr<PluginPackage> package = prpPackage; - - if (!m_plugins.add(package).second) - return false; - - m_pluginsByPath.add(package->path(), package); - return true; -} - -void PluginDatabase::remove(PluginPackage* package) -{ - MIMEToExtensionsMap::const_iterator it = package->mimeToExtensions().begin(); - MIMEToExtensionsMap::const_iterator end = package->mimeToExtensions().end(); - for ( ; it != end; ++it) { - PluginPackageByNameMap::iterator packageInMap = m_preferredPlugins.find(it->first); - if (packageInMap != m_preferredPlugins.end() && packageInMap->second == package) - m_preferredPlugins.remove(packageInMap); - } - - m_plugins.remove(package); - m_pluginsByPath.remove(package->path()); -} - -void PluginDatabase::clear() -{ - m_plugins.clear(); - m_pluginsByPath.clear(); - m_pluginPathsWithTimes.clear(); - m_registeredMIMETypes.clear(); - m_preferredPlugins.clear(); -#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) - m_persistentMetadataCacheIsLoaded = false; -#endif -} - -#if (!OS(WINCE)) && (!OS(SYMBIAN)) && (!OS(WINDOWS) || !ENABLE(NETSCAPE_PLUGIN_API)) -// For Safari/Win the following three methods are implemented -// in PluginDatabaseWin.cpp, but if we can use WebCore constructs -// for the logic we should perhaps move it here under XP_WIN? - -Vector<String> PluginDatabase::defaultPluginDirectories() -{ - Vector<String> paths; - - // Add paths specific to each platform -#if defined(XP_UNIX) - String userPluginPath = homeDirectoryPath(); - userPluginPath.append(String("/.mozilla/plugins")); - paths.append(userPluginPath); - - userPluginPath = homeDirectoryPath(); - userPluginPath.append(String("/.netscape/plugins")); - paths.append(userPluginPath); - - paths.append("/usr/lib/browser/plugins"); - paths.append("/usr/local/lib/mozilla/plugins"); - paths.append("/usr/lib/firefox/plugins"); - paths.append("/usr/lib64/browser-plugins"); - paths.append("/usr/lib/browser-plugins"); - paths.append("/usr/lib/mozilla/plugins"); - paths.append("/usr/local/netscape/plugins"); - paths.append("/opt/mozilla/plugins"); - paths.append("/opt/mozilla/lib/plugins"); - paths.append("/opt/netscape/plugins"); - paths.append("/opt/netscape/communicator/plugins"); - paths.append("/usr/lib/netscape/plugins"); - paths.append("/usr/lib/netscape/plugins-libc5"); - paths.append("/usr/lib/netscape/plugins-libc6"); - paths.append("/usr/lib64/netscape/plugins"); - paths.append("/usr/lib64/mozilla/plugins"); - paths.append("/usr/lib/nsbrowser/plugins"); - paths.append("/usr/lib64/nsbrowser/plugins"); - - String mozHome(getenv("MOZILLA_HOME")); - mozHome.append("/plugins"); - paths.append(mozHome); - - Vector<String> mozPaths; - String mozPath(getenv("MOZ_PLUGIN_PATH")); - mozPath.split(UChar(':'), /* allowEmptyEntries */ false, mozPaths); - paths.append(mozPaths); -#elif defined(XP_MACOSX) - String userPluginPath = homeDirectoryPath(); - userPluginPath.append(String("/Library/Internet Plug-Ins")); - paths.append(userPluginPath); - paths.append("/Library/Internet Plug-Ins"); -#elif defined(XP_WIN) - String userPluginPath = homeDirectoryPath(); - userPluginPath.append(String("\\Application Data\\Mozilla\\plugins")); - paths.append(userPluginPath); -#endif - - // Add paths specific to each port -#if PLATFORM(QT) - Vector<String> qtPaths; - String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").constData()); - qtPath.split(UChar(':'), /* allowEmptyEntries */ false, qtPaths); - paths.append(qtPaths); -#endif - -#if PLATFORM(ANDROID) - if (android::JavaSharedClient::GetPluginClient()) - return android::JavaSharedClient::GetPluginClient()->getPluginDirectories(); -#endif - - return paths; -} - -bool PluginDatabase::isPreferredPluginDirectory(const String& path) -{ - String preferredPath = homeDirectoryPath(); - -#if defined(XP_UNIX) - preferredPath.append(String("/.mozilla/plugins")); -#elif defined(XP_MACOSX) - preferredPath.append(String("/Library/Internet Plug-Ins")); -#elif defined(XP_WIN) - preferredPath.append(String("\\Application Data\\Mozilla\\plugins")); -#endif - - // TODO: We should normalize the path before doing a comparison. - return path == preferredPath; -} - -void PluginDatabase::getPluginPathsInDirectories(HashSet<String>& paths) const -{ - // FIXME: This should be a case insensitive set. - HashSet<String> uniqueFilenames; - -#if defined(XP_UNIX) || defined(ANDROID) - String fileNameFilter("*.so"); -#else - String fileNameFilter(""); -#endif - - Vector<String>::const_iterator dirsEnd = m_pluginDirectories.end(); - for (Vector<String>::const_iterator dIt = m_pluginDirectories.begin(); dIt != dirsEnd; ++dIt) { - Vector<String> pluginPaths = listDirectory(*dIt, fileNameFilter); - Vector<String>::const_iterator pluginsEnd = pluginPaths.end(); - for (Vector<String>::const_iterator pIt = pluginPaths.begin(); pIt != pluginsEnd; ++pIt) { - if (!fileExists(*pIt)) - continue; - - paths.add(*pIt); - } - } -} - -#endif // !OS(SYMBIAN) && !OS(WINDOWS) - -#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) - -static void fillBufferWithContentsOfFile(PlatformFileHandle file, Vector<char>& buffer) -{ - size_t bufferSize = 0; - size_t bufferCapacity = 1024; - buffer.resize(bufferCapacity); - - do { - bufferSize += readFromFile(file, buffer.data() + bufferSize, bufferCapacity - bufferSize); - if (bufferSize == bufferCapacity) { - if (bufferCapacity < maximumPersistentPluginMetadataCacheSize) { - bufferCapacity *= 2; - buffer.resize(bufferCapacity); - } else { - buffer.clear(); - return; - } - } else - break; - } while (true); - - buffer.shrink(bufferSize); -} - -static bool readUTF8String(String& resultString, char*& start, const char* end) -{ - if (start >= end) - return false; - - int len = strlen(start); - resultString = String::fromUTF8(start, len); - start += len + 1; - - return true; -} - -static bool readTime(time_t& resultTime, char*& start, const char* end) -{ - if (start + sizeof(time_t) >= end) - return false; - - resultTime = *reinterpret_cast_ptr<time_t*>(start); - start += sizeof(time_t); - - return true; -} - -static const char schemaVersion = '1'; -static const char persistentPluginMetadataCacheFilename[] = "PluginMetadataCache.bin"; - -void PluginDatabase::loadPersistentMetadataCache() -{ - if (!isPersistentMetadataCacheEnabled() || persistentMetadataCachePath().isEmpty()) - return; - - PlatformFileHandle file; - String absoluteCachePath = pathByAppendingComponent(persistentMetadataCachePath(), persistentPluginMetadataCacheFilename); - file = openFile(absoluteCachePath, OpenForRead); - - if (!isHandleValid(file)) - return; - - // Mark cache as loaded regardless of success or failure. If - // there's error in the cache, we won't try to load it anymore. - m_persistentMetadataCacheIsLoaded = true; - - Vector<char> fileContents; - fillBufferWithContentsOfFile(file, fileContents); - closeFile(file); - - if (fileContents.size() < 2 || fileContents.first() != schemaVersion || fileContents.last() != '\0') { - LOG_ERROR("Unable to read plugin metadata cache: corrupt schema"); - deleteFile(absoluteCachePath); - return; - } - - char* bufferPos = fileContents.data() + 1; - char* end = fileContents.data() + fileContents.size(); - - PluginSet cachedPlugins; - HashMap<String, time_t> cachedPluginPathsWithTimes; - HashMap<String, RefPtr<PluginPackage> > cachedPluginsByPath; - - while (bufferPos < end) { - String path; - time_t lastModified; - String name; - String desc; - String mimeDesc; - if (!(readUTF8String(path, bufferPos, end) - && readTime(lastModified, bufferPos, end) - && readUTF8String(name, bufferPos, end) - && readUTF8String(desc, bufferPos, end) - && readUTF8String(mimeDesc, bufferPos, end))) { - LOG_ERROR("Unable to read plugin metadata cache: corrupt data"); - deleteFile(absoluteCachePath); - return; - } - - // Skip metadata that points to plugins from directories that - // are not part of plugin directory list anymore. - String pluginDirectoryName = directoryName(path); - if (m_pluginDirectories.find(pluginDirectoryName) == WTF::notFound) - continue; - - RefPtr<PluginPackage> package = PluginPackage::createPackageFromCache(path, lastModified, name, desc, mimeDesc); - - if (package && cachedPlugins.add(package).second) { - cachedPluginPathsWithTimes.add(package->path(), package->lastModified()); - cachedPluginsByPath.add(package->path(), package); - } - } - - m_plugins.swap(cachedPlugins); - m_pluginsByPath.swap(cachedPluginsByPath); - m_pluginPathsWithTimes.swap(cachedPluginPathsWithTimes); -} - -static bool writeUTF8String(PlatformFileHandle file, const String& string) -{ - CString utf8String = string.utf8(); - int length = utf8String.length() + 1; - return writeToFile(file, utf8String.data(), length) == length; -} - -static bool writeTime(PlatformFileHandle file, const time_t& time) -{ - return writeToFile(file, reinterpret_cast<const char*>(&time), sizeof(time_t)) == sizeof(time_t); -} - -void PluginDatabase::updatePersistentMetadataCache() -{ - if (!isPersistentMetadataCacheEnabled() || persistentMetadataCachePath().isEmpty()) - return; - - makeAllDirectories(persistentMetadataCachePath()); - String absoluteCachePath = pathByAppendingComponent(persistentMetadataCachePath(), persistentPluginMetadataCacheFilename); - deleteFile(absoluteCachePath); - - if (m_plugins.isEmpty()) - return; - - PlatformFileHandle file; - file = openFile(absoluteCachePath, OpenForWrite); - - if (!isHandleValid(file)) { - LOG_ERROR("Unable to open plugin metadata cache for saving"); - return; - } - - char localSchemaVersion = schemaVersion; - if (writeToFile(file, &localSchemaVersion, 1) != 1) { - LOG_ERROR("Unable to write plugin metadata cache schema"); - closeFile(file); - deleteFile(absoluteCachePath); - return; - } - - PluginSet::const_iterator end = m_plugins.end(); - for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) { - if (!(writeUTF8String(file, (*it)->path()) - && writeTime(file, (*it)->lastModified()) - && writeUTF8String(file, (*it)->name()) - && writeUTF8String(file, (*it)->description()) - && writeUTF8String(file, (*it)->fullMIMEDescription()))) { - LOG_ERROR("Unable to write plugin metadata to cache"); - closeFile(file); - deleteFile(absoluteCachePath); - return; - } - } - - closeFile(file); -} - -bool PluginDatabase::isPersistentMetadataCacheEnabled() -{ - return gPersistentPluginMetadataCacheIsEnabled; -} - -void PluginDatabase::setPersistentMetadataCacheEnabled(bool isEnabled) -{ - gPersistentPluginMetadataCacheIsEnabled = isEnabled; -} - -String PluginDatabase::persistentMetadataCachePath() -{ - return WebCore::persistentPluginMetadataCachePath(); -} - -void PluginDatabase::setPersistentMetadataCachePath(const String& persistentMetadataCachePath) -{ - WebCore::persistentPluginMetadataCachePath() = persistentMetadataCachePath; -} -#endif -} |