2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #include "PluginInfoStore.h"
29 #include "PluginModuleInfo.h"
30 #include <WebCore/KURL.h>
31 #include <WebCore/MIMETypeRegistry.h>
33 #include <wtf/ListHashSet.h>
34 #include <wtf/StdLibExtras.h>
37 using namespace WebCore;
41 PluginInfoStore::PluginInfoStore()
42 : m_pluginListIsUpToDate(false)
46 void PluginInfoStore::setAdditionalPluginsDirectories(const Vector<String>& directories)
48 m_additionalPluginsDirectories = directories;
52 void PluginInfoStore::refresh()
54 m_pluginListIsUpToDate = false;
57 template <typename T, typename U>
58 static void addFromVector(T& hashSet, const U& vector)
60 for (size_t i = 0; i < vector.size(); ++i)
61 hashSet.add(vector[i]);
64 // We use a ListHashSet so that plugins will be loaded from the additional plugins directories first
65 // (which in turn means those plugins will be preferred if two plugins claim the same MIME type).
67 typedef ListHashSet<String, 32, CaseFoldingHash> PathHashSet;
69 typedef ListHashSet<String, 32> PathHashSet;
72 void PluginInfoStore::loadPluginsIfNecessary()
74 if (m_pluginListIsUpToDate)
77 PathHashSet uniquePluginPaths;
79 // First, load plug-ins from the additional plug-ins directories specified.
80 for (size_t i = 0; i < m_additionalPluginsDirectories.size(); ++i)
81 addFromVector(uniquePluginPaths, pluginPathsInDirectory(m_additionalPluginsDirectories[i]));
83 // Then load plug-ins from the standard plug-ins directories.
84 Vector<String> directories = pluginsDirectories();
85 for (size_t i = 0; i < directories.size(); ++i)
86 addFromVector(uniquePluginPaths, pluginPathsInDirectory(directories[i]));
88 // Then load plug-ins that are not in the standard plug-ins directories.
89 addFromVector(uniquePluginPaths, individualPluginPaths());
91 Vector<PluginModuleInfo> plugins;
93 PathHashSet::const_iterator end = uniquePluginPaths.end();
94 for (PathHashSet::const_iterator it = uniquePluginPaths.begin(); it != end; ++it)
95 loadPlugin(plugins, *it);
97 m_plugins.swap(plugins);
98 m_pluginListIsUpToDate = true;
101 void PluginInfoStore::loadPlugin(Vector<PluginModuleInfo>& plugins, const String& pluginPath)
103 PluginModuleInfo plugin;
105 if (!getPluginInfo(pluginPath, plugin))
108 if (!shouldUsePlugin(plugins, plugin))
111 plugins.append(plugin);
114 Vector<PluginModuleInfo> PluginInfoStore::plugins()
116 loadPluginsIfNecessary();
118 Vector<PluginModuleInfo> plugins(m_plugins);
123 PluginModuleInfo PluginInfoStore::findPluginForMIMEType(const String& mimeType) const
125 ASSERT(!mimeType.isNull());
127 for (size_t i = 0; i < m_plugins.size(); ++i) {
128 const PluginModuleInfo& plugin = m_plugins[i];
130 for (size_t j = 0; j < plugin.info.mimes.size(); ++j) {
131 const MimeClassInfo& mimeClassInfo = plugin.info.mimes[j];
132 if (mimeClassInfo.type == mimeType)
137 return PluginModuleInfo();
140 PluginModuleInfo PluginInfoStore::findPluginForExtension(const String& extension, String& mimeType) const
142 ASSERT(!extension.isNull());
144 for (size_t i = 0; i < m_plugins.size(); ++i) {
145 const PluginModuleInfo& plugin = m_plugins[i];
147 for (size_t j = 0; j < plugin.info.mimes.size(); ++j) {
148 const MimeClassInfo& mimeClassInfo = plugin.info.mimes[j];
150 const Vector<String>& extensions = mimeClassInfo.extensions;
152 if (find(extensions.begin(), extensions.end(), extension) != extensions.end()) {
153 // We found a supported extension, set the correct MIME type.
154 mimeType = mimeClassInfo.type;
160 return PluginModuleInfo();
163 static inline String pathExtension(const KURL& url)
166 String filename = url.lastPathComponent();
167 if (!filename.endsWith("/")) {
168 int extensionPos = filename.reverseFind('.');
169 if (extensionPos != -1)
170 extension = filename.substring(extensionPos + 1);
177 String PluginInfoStore::getMIMETypeForExtension(const String& extension)
179 return MIMETypeRegistry::getMIMETypeForExtension(extension);
183 PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const KURL& url)
185 loadPluginsIfNecessary();
187 // First, check if we can get the plug-in based on its MIME type.
188 if (!mimeType.isNull()) {
189 PluginModuleInfo plugin = findPluginForMIMEType(mimeType);
190 if (!plugin.path.isNull())
194 // Next, check if any plug-ins claim to support the URL extension.
195 String extension = pathExtension(url).lower();
196 if (!extension.isNull() && mimeType.isEmpty()) {
197 PluginModuleInfo plugin = findPluginForExtension(extension, mimeType);
198 if (!plugin.path.isNull())
201 // Finally, try to get the MIME type from the extension in a platform specific manner and use that.
202 String extensionMimeType = getMIMETypeForExtension(extension);
203 if (!extensionMimeType.isNull()) {
204 PluginModuleInfo plugin = findPluginForMIMEType(extensionMimeType);
205 if (!plugin.path.isNull()) {
206 mimeType = extensionMimeType;
212 return PluginModuleInfo();
215 PluginModuleInfo PluginInfoStore::infoForPluginWithPath(const String& pluginPath) const
217 for (size_t i = 0; i < m_plugins.size(); ++i) {
218 if (m_plugins[i].path == pluginPath)
222 ASSERT_NOT_REACHED();
223 return PluginModuleInfo();
226 } // namespace WebKit