1/*
2    Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com>
3
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17    Boston, MA 02110-1301, USA.
18*/
19
20#include "config.h"
21#include "qwebplugindatabase_p.h"
22
23#include "PluginDatabase.h"
24#include "PluginPackage.h"
25
26using namespace WebCore;
27
28/*!
29    \internal
30    \typedef QWebPluginInfo::MimeType
31    \since 4.6
32    \brief Represents a single MIME type supported by a plugin.
33*/
34
35/*!
36    \class QWebPluginInfo
37    \internal
38    \since 4.6
39    \brief The QWebPluginInfo class represents a single Netscape plugin.
40
41    A QWebPluginInfo object represents a Netscape plugin picked up by WebKit
42    and included in the plugin database. This class contains information about
43    the plugin, such as its name(), description(), a list of MIME types that it
44    supports (can be accessed with mimeTypes()) and the path of the plugin
45    file.
46
47    Plugins can be enabled and disabled with setEnabled(). If a plugin is
48    disabled, it will not be used by WebKit to handle supported MIME types. To
49    check if a plugin is enabled or not, use enabled().
50
51    \sa QWebPluginDatabase
52*/
53
54/*!
55    Constructs a null QWebPluginInfo.
56*/
57QWebPluginInfo::QWebPluginInfo()
58    : m_package(0)
59{
60}
61
62QWebPluginInfo::QWebPluginInfo(PluginPackage* package)
63    : m_package(package)
64{
65    if (m_package)
66        m_package->ref();
67}
68
69/*!
70    Contructs a copy of \a other.
71*/
72QWebPluginInfo::QWebPluginInfo(const QWebPluginInfo& other)
73    : m_package(other.m_package)
74{
75    if (m_package)
76        m_package->ref();
77}
78
79/*!
80    Destroys the plugin info.
81*/
82QWebPluginInfo::~QWebPluginInfo()
83{
84    if (m_package)
85        m_package->deref();
86}
87
88/*!
89    Returns the name of the plugin.
90
91    \sa description()
92*/
93QString QWebPluginInfo::name() const
94{
95    if (!m_package)
96        return QString();
97    return m_package->name();
98}
99
100/*!
101    Returns the description of the plugin.
102
103    \sa name()
104*/
105QString QWebPluginInfo::description() const
106{
107    if (!m_package)
108        return QString();
109    return m_package->description();
110}
111
112/*!
113    Returns a list of MIME types supported by the plugin.
114
115    \sa supportsMimeType()
116*/
117QList<QWebPluginInfo::MimeType> QWebPluginInfo::mimeTypes() const
118{
119    if (m_package && m_mimeTypes.isEmpty()) {
120        const MIMEToDescriptionsMap& mimeToDescriptions = m_package->mimeToDescriptions();
121        MIMEToDescriptionsMap::const_iterator end = mimeToDescriptions.end();
122
123        for (MIMEToDescriptionsMap::const_iterator it = mimeToDescriptions.begin(); it != end; ++it) {
124            MimeType mimeType;
125            mimeType.name = it->first;
126            mimeType.description = it->second;
127
128            QStringList fileExtensions;
129            Vector<String> extensions = m_package->mimeToExtensions().get(mimeType.name);
130
131            for (unsigned i = 0; i < extensions.size(); ++i)
132                fileExtensions.append(extensions[i]);
133
134            mimeType.fileExtensions = fileExtensions;
135            m_mimeTypes.append(mimeType);
136        }
137    }
138
139    return m_mimeTypes;
140}
141
142/*!
143    Returns true if the plugin supports a specific \a mimeType; otherwise
144    returns false.
145
146    \sa mimeTypes()
147*/
148bool QWebPluginInfo::supportsMimeType(const QString& mimeType) const
149{
150    if (!m_package)
151        return false;
152    return m_package->mimeToDescriptions().contains(mimeType);
153}
154
155/*!
156    Returns an absolute path to the plugin file.
157*/
158QString QWebPluginInfo::path() const
159{
160    if (!m_package)
161        return QString();
162    return m_package->path();
163}
164
165/*!
166    Returns true if the plugin is a null plugin; otherwise returns false.
167*/
168bool QWebPluginInfo::isNull() const
169{
170    return !m_package;
171}
172
173/*!
174    Enables or disables the plugin, depending on the \a enabled parameter.
175
176    Disabled plugins will not be picked up by WebKit when looking for a plugin
177    supporting a particular MIME type.
178
179    \sa isEnabled()
180*/
181void QWebPluginInfo::setEnabled(bool enabled)
182{
183    if (!m_package)
184        return;
185    m_package->setEnabled(enabled);
186}
187
188/*!
189    Returns true if the plugin is enabled; otherwise returns false.
190
191    \sa setEnabled()
192*/
193bool QWebPluginInfo::isEnabled() const
194{
195    if (!m_package)
196        return false;
197    return m_package->isEnabled();
198}
199
200/*!
201    Returns true if this plugin info is the same as the \a other plugin info.
202*/
203bool QWebPluginInfo::operator==(const QWebPluginInfo& other) const
204{
205    return m_package == other.m_package;
206}
207
208/*!
209    Returns true if this plugin info is different from the \a other plugin info.
210*/
211bool QWebPluginInfo::operator!=(const QWebPluginInfo& other) const
212{
213    return m_package != other.m_package;
214}
215
216/*!
217    Assigns the \a other plugin info to this plugin info, and returns a reference
218    to this plugin info.
219*/
220QWebPluginInfo &QWebPluginInfo::operator=(const QWebPluginInfo& other)
221{
222    if (this == &other)
223        return *this;
224
225    if (m_package)
226        m_package->deref();
227    m_package = other.m_package;
228    if (m_package)
229        m_package->ref();
230    m_mimeTypes = other.m_mimeTypes;
231
232    return *this;
233}
234
235/*!
236    \class QWebPluginDatabase
237    \internal
238    \since 4.6
239    \brief The QWebPluginDatabase class provides an interface for managing
240    Netscape plugins used by WebKit in QWebPages.
241
242    The QWebPluginDatabase class is a database of Netscape plugins that are used
243    by WebKit. The plugins are picked up by WebKit by looking up a set of search paths.
244    The default set can be accessed using defaultSearchPaths(). The search paths
245    can be changed, see searchPaths() and setSearchPaths(). Additional search paths
246    can also be added using addSearchPath().
247
248    The plugins that have been detected are exposed by the plugins() method.
249    The list contains QWebPlugin objects that hold both the metadata and the MIME
250    types that are supported by particular plugins.
251
252    WebKit specifies a plugin for a MIME type by looking for the first plugin that
253    supports the specific MIME type. To get a plugin, that is used by WebKit to
254    handle a specific MIME type, you can use the pluginForMimeType() function.
255
256    To change the way of resolving MIME types ambiguity, you can explicitly set
257    a preferred plugin for a specific MIME type, using setPreferredPluginForMimeType().
258
259    \sa QWebPluginInfo, QWebSettings::pluginDatabase()
260*/
261
262QWebPluginDatabase::QWebPluginDatabase(QObject* parent)
263    : QObject(parent)
264    , m_database(PluginDatabase::installedPlugins())
265{
266}
267
268QWebPluginDatabase::~QWebPluginDatabase()
269{
270}
271
272/*!
273    Returns a list of plugins installed in the search paths.
274
275    This list will contain disabled plugins, although they will not be used by
276    WebKit.
277
278    \sa pluginForMimeType()
279*/
280QList<QWebPluginInfo> QWebPluginDatabase::plugins() const
281{
282    QList<QWebPluginInfo> qwebplugins;
283    const Vector<PluginPackage*>& plugins = m_database->plugins();
284
285    for (unsigned int i = 0; i < plugins.size(); ++i) {
286        PluginPackage* plugin = plugins[i];
287#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)
288        if (!plugin->ensurePluginLoaded())
289            continue;
290#endif
291        qwebplugins.append(QWebPluginInfo(plugin));
292    }
293
294    return qwebplugins;
295}
296
297/*!
298    Returns a default set of search paths.
299
300    \sa searchPaths(), setSearchPaths()
301*/
302QStringList QWebPluginDatabase::defaultSearchPaths()
303{
304    QStringList paths;
305
306    const Vector<String>& directories = PluginDatabase::defaultPluginDirectories();
307    for (unsigned int i = 0; i < directories.size(); ++i)
308        paths.append(directories[i]);
309
310    return paths;
311}
312
313/*!
314    Returns a list of search paths that are used by WebKit to look for plugins.
315
316    \sa defaultSearchPaths(), setSearchPaths()
317*/
318QStringList QWebPluginDatabase::searchPaths() const
319{
320    QStringList paths;
321
322    const Vector<String>& directories = m_database->pluginDirectories();
323    for (unsigned int i = 0; i < directories.size(); ++i)
324        paths.append(directories[i]);
325
326    return paths;
327}
328
329/*!
330    Changes the search paths to \a paths.
331    The database is automatically refreshed.
332
333    \sa searchPaths(), defaultSearchPaths()
334*/
335void QWebPluginDatabase::setSearchPaths(const QStringList& paths)
336{
337    Vector<String> directories;
338
339    for (int i = 0; i < paths.count(); ++i)
340        directories.append(paths.at(i));
341
342    m_database->setPluginDirectories(directories);
343    // PluginDatabase::setPluginDirectories() does not refresh the database.
344    m_database->refresh();
345}
346
347/*!
348    Adds an additional \a path to the current set.
349    The database is automatically refreshed.
350
351    \sa searchPaths(), setSearchPaths()
352*/
353void QWebPluginDatabase::addSearchPath(const QString& path)
354{
355    m_database->addExtraPluginDirectory(path);
356    // PluginDatabase::addExtraPluginDirectory() does refresh the database.
357}
358
359/*!
360    Refreshes the plugin database, adds new plugins that have been found and removes
361    the ones that are no longer available in the search paths.
362
363    You can call this function when the set of plugins installed in the search paths
364    changes. You do not need to call this function when changing search paths,
365    in that case WebKit automatically refreshes the database.
366*/
367void QWebPluginDatabase::refresh()
368{
369    m_database->refresh();
370}
371
372/*!
373    Returns the plugin that is currently used by WebKit for a given \a mimeType.
374
375    \sa setPreferredPluginForMimeType()
376*/
377QWebPluginInfo QWebPluginDatabase::pluginForMimeType(const QString& mimeType)
378{
379    return QWebPluginInfo(m_database->pluginForMIMEType(mimeType));
380}
381
382/*!
383    Changes the preferred plugin for a given \a mimeType to \a plugin. The \a plugin
384    has to support the given \a mimeType, otherwise the setting will have no effect.
385
386    Calling the function with a null \a plugin resets the setting.
387
388    \sa pluginForMimeType()
389*/
390void QWebPluginDatabase::setPreferredPluginForMimeType(const QString& mimeType, const QWebPluginInfo& plugin)
391{
392    m_database->setPreferredPluginForMIMEType(mimeType, plugin.m_package);
393}
394