2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "PluginDatabase.h"
32 #include "PluginPackage.h"
37 PluginDatabase* PluginDatabase::installedPlugins()
39 static PluginDatabase* plugins = 0;
42 plugins = new PluginDatabase;
43 plugins->setPluginPaths(PluginDatabase::defaultPluginPaths());
50 bool PluginDatabase::isMIMETypeRegistered(const String& mimeType)
52 if (mimeType.isNull())
54 if (m_registeredMIMETypes.contains(mimeType))
56 // No plugin was found, try refreshing the database and searching again
57 return (refresh() && m_registeredMIMETypes.contains(mimeType));
60 void PluginDatabase::addExtraPluginPath(const String& path)
62 m_pluginPaths.append(path);
66 bool PluginDatabase::refresh()
70 bool pluginSetChanged = false;
72 // Create a new set of plugins
73 newPlugins = getPluginsInPaths();
75 if (!m_plugins.isEmpty()) {
76 m_registeredMIMETypes.clear();
78 PluginSet pluginsToUnload = m_plugins;
80 PluginSet::const_iterator end = newPlugins.end();
81 for (PluginSet::const_iterator it = newPlugins.begin(); it != end; ++it)
82 pluginsToUnload.remove(*it);
84 end = m_plugins.end();
85 for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it)
86 newPlugins.remove(*it);
89 end = pluginsToUnload.end();
90 for (PluginSet::const_iterator it = pluginsToUnload.begin(); it != end; ++it)
91 m_plugins.remove(*it);
94 end = newPlugins.end();
95 for (PluginSet::const_iterator it = newPlugins.begin(); it != end; ++it)
98 pluginSetChanged = !pluginsToUnload.isEmpty() || !newPlugins.isEmpty();
100 m_plugins = newPlugins;
101 PluginSet::const_iterator end = newPlugins.end();
102 for (PluginSet::const_iterator it = newPlugins.begin(); it != end; ++it)
105 pluginSetChanged = !newPlugins.isEmpty();
108 // Register plug-in MIME types
109 PluginSet::const_iterator end = m_plugins.end();
110 for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) {
112 MIMEToDescriptionsMap::const_iterator map_end = (*it)->mimeToDescriptions().end();
113 for (MIMEToDescriptionsMap::const_iterator map_it = (*it)->mimeToDescriptions().begin(); map_it != map_end; ++map_it) {
114 m_registeredMIMETypes.add(map_it->first);
118 return pluginSetChanged;
121 Vector<PluginPackage*> PluginDatabase::plugins() const
123 Vector<PluginPackage*> result;
125 PluginSet::const_iterator end = m_plugins.end();
126 for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it)
127 result.append((*it).get());
132 int PluginDatabase::preferredPluginCompare(const void* a, const void* b)
134 PluginPackage* pluginA = *static_cast<PluginPackage* const*>(a);
135 PluginPackage* pluginB = *static_cast<PluginPackage* const*>(b);
137 return pluginA->compare(*pluginB);
140 PluginPackage* PluginDatabase::pluginForMIMEType(const String& mimeType)
142 if (mimeType.isEmpty())
145 String key = mimeType.lower();
146 PluginSet::const_iterator end = m_plugins.end();
148 Vector<PluginPackage*, 2> pluginChoices;
150 for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) {
151 if ((*it)->mimeToDescriptions().contains(key))
152 pluginChoices.append((*it).get());
155 if (pluginChoices.isEmpty())
158 qsort(pluginChoices.data(), pluginChoices.size(), sizeof(PluginPackage*), PluginDatabase::preferredPluginCompare);
160 return pluginChoices[0];
163 String PluginDatabase::MIMETypeForExtension(const String& extension) const
165 if (extension.isEmpty())
168 PluginSet::const_iterator end = m_plugins.end();
170 Vector<PluginPackage*, 2> pluginChoices;
171 HashMap<PluginPackage*, String> mimeTypeForPlugin;
173 for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) {
174 MIMEToExtensionsMap::const_iterator mime_end = (*it)->mimeToExtensions().end();
176 for (MIMEToExtensionsMap::const_iterator mime_it = (*it)->mimeToExtensions().begin(); mime_it != mime_end; ++mime_it) {
177 const Vector<String>& extensions = mime_it->second;
178 bool foundMapping = false;
179 for (unsigned i = 0; i < extensions.size(); i++) {
180 if (equalIgnoringCase(extensions[i], extension)) {
181 PluginPackage* plugin = (*it).get();
182 pluginChoices.append(plugin);
183 mimeTypeForPlugin.add(plugin, mime_it->first);
193 if (pluginChoices.isEmpty())
196 qsort(pluginChoices.data(), pluginChoices.size(), sizeof(PluginPackage*), PluginDatabase::preferredPluginCompare);
198 return mimeTypeForPlugin.get(pluginChoices[0]);
201 PluginPackage* PluginDatabase::findPlugin(const KURL& url, String& mimeType)
203 PluginPackage* plugin = pluginForMIMEType(mimeType);
204 String filename = url.string();
207 String filename = url.lastPathComponent();
208 if (!filename.endsWith("/")) {
209 int extensionPos = filename.reverseFind('.');
210 if (extensionPos != -1) {
211 String extension = filename.substring(extensionPos + 1);
213 mimeType = MIMETypeForExtension(extension);
214 plugin = pluginForMIMEType(mimeType);
219 // FIXME: if no plugin could be found, query Windows for the mime type
220 // corresponding to the extension.