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 <QtTest/QtTest>
21
22#include <qdir.h>
23#include <qwebframe.h>
24#include <qwebpage.h>
25#include <qwebplugindatabase.h>
26#include <qwebsettings.h>
27#include <qvariant.h>
28
29class tst_QWebPluginDatabase : public QObject
30{
31    Q_OBJECT
32
33private slots:
34    void installedPlugins();
35    void searchPaths();
36    void null_data();
37    void null();
38    void pluginForMimeType();
39    void enabled();
40    void operatorequal_data();
41    void operatorequal();
42    void preferredPlugin();
43    void operatorassign_data();
44    void operatorassign();
45};
46
47typedef QWebPluginInfo::MimeType MimeType;
48
49void tst_QWebPluginDatabase::installedPlugins()
50{
51    QWebPage page;
52    page.settings()->setAttribute(QWebSettings::PluginsEnabled, true);
53    QWebFrame* frame = page.mainFrame();
54
55    QVariantMap jsPluginsMap = frame->evaluateJavaScript("window.navigator.plugins").toMap();
56    QList<QWebPluginInfo> plugins = QWebSettings::pluginDatabase()->plugins();
57    QCOMPARE(plugins, QWebSettings::pluginDatabase()->plugins());
58
59    int length = jsPluginsMap["length"].toInt();
60    QCOMPARE(length, plugins.count());
61
62    for (int i = 0; i < length; ++i) {
63        QWebPluginInfo plugin = plugins.at(i);
64
65        QVariantMap jsPlugin = frame->evaluateJavaScript(QString("window.navigator.plugins[%1]").arg(i)).toMap();
66        QString name = jsPlugin["name"].toString();
67        QString description = jsPlugin["description"].toString();
68        QString fileName = jsPlugin["filename"].toString();
69
70        QCOMPARE(plugin.name(), name);
71        QCOMPARE(plugin.description(), description);
72        QCOMPARE(QFileInfo(plugin.path()).fileName(), fileName);
73
74        QList<MimeType> mimeTypes;
75        int mimeTypesCount = jsPlugin["length"].toInt();
76
77        for (int j = 0; j < mimeTypesCount; ++j) {
78            QVariantMap jsMimeType = frame->evaluateJavaScript(QString("window.navigator.plugins[%1][%2]").arg(i).arg(j)).toMap();
79
80            MimeType mimeType;
81            mimeType.name = jsMimeType["type"].toString();
82            mimeType.description = jsMimeType["description"].toString();
83            mimeType.fileExtensions = jsMimeType["suffixes"].toString().split(',', QString::SkipEmptyParts);
84
85            mimeTypes.append(mimeType);
86            QVERIFY(plugin.supportsMimeType(mimeType.name));
87        }
88
89        QCOMPARE(plugin.mimeTypes(), mimeTypes);
90
91        QVERIFY(!plugin.isNull());
92        QVERIFY(plugin.isEnabled());
93    }
94}
95
96void tst_QWebPluginDatabase::searchPaths()
97{
98    QWebPluginDatabase* database = QWebSettings::pluginDatabase();
99    QList<QWebPluginInfo> plugins = database->plugins();
100    QStringList directories = database->searchPaths();
101    QCOMPARE(QWebPluginDatabase::defaultSearchPaths(), directories);
102
103    database->setSearchPaths(directories);
104    QCOMPARE(QWebPluginDatabase::defaultSearchPaths(), directories);
105    QCOMPARE(database->searchPaths(), directories);
106    QCOMPARE(database->plugins(), plugins);
107    database->refresh();
108    QCOMPARE(database->plugins(), plugins);
109
110    database->setSearchPaths(QStringList());
111    QCOMPARE(QWebPluginDatabase::defaultSearchPaths(), directories);
112    QCOMPARE(database->searchPaths(), QStringList());
113    QCOMPARE(database->plugins().count(), 0);
114
115    database->setSearchPaths(directories);
116    QCOMPARE(database->searchPaths(), directories);
117    database->addSearchPath(QDir::tempPath());
118    QCOMPARE(database->searchPaths().count(), directories.count() + 1);
119    QVERIFY(database->searchPaths().contains(QDir::tempPath()));
120    directories.append(QDir::tempPath());
121    QCOMPARE(database->searchPaths(), directories);
122
123    // As an empty set of search paths has been set, the database has been rebuilt
124    // from scratch after bringing the old path set back.
125    // Because the QWebPlugins no longer point to the same PluginPackages,
126    // the list is also no longer equal to the older one, even though it contains
127    // the same information.
128    QCOMPARE(database->plugins().count(), plugins.count());
129    plugins = database->plugins();
130    QCOMPARE(database->plugins(), plugins);
131
132    for (int i = (directories.count() - 1); i >= 0; --i) {
133        QDir directory(directories.at(i));
134        if (!directory.exists() || !directory.count())
135            directories.removeAt(i);
136    }
137
138    database->setSearchPaths(directories);
139    QCOMPARE(database->plugins(), plugins);
140    database->refresh();
141    QCOMPARE(database->plugins(), plugins);
142
143    database->setSearchPaths(QWebPluginDatabase::defaultSearchPaths());
144    directories = QWebPluginDatabase::defaultSearchPaths();
145    QCOMPARE(QWebPluginDatabase::defaultSearchPaths(), directories);
146    QCOMPARE(database->searchPaths(), directories);
147    QCOMPARE(database->plugins(), plugins);
148}
149
150Q_DECLARE_METATYPE(QWebPluginInfo)
151void tst_QWebPluginDatabase::null_data()
152{
153    QTest::addColumn<QWebPluginInfo>("plugin");
154    QTest::addColumn<bool>("null");
155
156    QTest::newRow("null") << QWebPluginInfo() << true;
157    QTest::newRow("foo") << QWebSettings::pluginDatabase()->pluginForMimeType("foobarbaz") << true;
158
159    QList<QWebPluginInfo> plugins = QWebSettings::pluginDatabase()->plugins();
160    for (int i = 0; i < plugins.count(); ++i)
161        QTest::newRow(QString::number(i).toUtf8().constData()) << plugins.at(i) << false;
162}
163
164void tst_QWebPluginDatabase::null()
165{
166    QFETCH(QWebPluginInfo, plugin);
167    QFETCH(bool, null);
168
169    QCOMPARE(plugin.isNull(), null);
170}
171
172void tst_QWebPluginDatabase::pluginForMimeType()
173{
174    QMultiMap<QString, QWebPluginInfo> pluginsMap;
175    QWebPluginDatabase* database = QWebSettings::pluginDatabase();
176    QList<QWebPluginInfo> plugins = database->plugins();
177
178    for (int i = 0; i < plugins.count(); ++i) {
179        QWebPluginInfo plugin = plugins.at(i);
180
181        QList<MimeType> mimeTypes = plugin.mimeTypes();
182        for (int j = 0; j < mimeTypes.count(); ++j) {
183            QString mimeType = mimeTypes.at(j).name;
184            pluginsMap.insert(mimeType, plugin);
185            QVERIFY(plugin.supportsMimeType(mimeType));
186        }
187    }
188
189    for (int i = 0; i < plugins.count(); ++i) {
190        QWebPluginInfo plugin = plugins.at(i);
191
192        QList<MimeType> mimeTypes = plugin.mimeTypes();
193        for (int j = 0; j < mimeTypes.count(); ++j) {
194            QString mimeType = mimeTypes.at(j).name;
195
196            QVERIFY(pluginsMap.count(mimeType) > 0);
197            if (pluginsMap.count(mimeType) > 1)
198                continue;
199
200            QWebPluginInfo pluginForMimeType = database->pluginForMimeType(mimeType);
201            QCOMPARE(pluginForMimeType, plugin);
202            database->setSearchPaths(database->searchPaths());
203            QCOMPARE(pluginForMimeType, plugin);
204            QCOMPARE(pluginForMimeType, database->pluginForMimeType(mimeType.toUpper()));
205            QCOMPARE(pluginForMimeType, database->pluginForMimeType(mimeType.toLower()));
206            QVERIFY(plugin.supportsMimeType(mimeType));
207            QVERIFY(!pluginForMimeType.isNull());
208            QVERIFY(!plugin.isNull());
209        }
210    }
211}
212
213void tst_QWebPluginDatabase::enabled()
214{
215    QMultiMap<QString, QWebPluginInfo> pluginsMap;
216    QWebPluginDatabase* database = QWebSettings::pluginDatabase();
217    QList<QWebPluginInfo> plugins = database->plugins();
218
219    for (int i = 0; i < plugins.count(); ++i) {
220        QWebPluginInfo plugin = plugins.at(i);
221
222        QList<MimeType> mimeTypes = plugin.mimeTypes();
223        for (int j = 0; j < mimeTypes.count(); ++j) {
224            QString mimeType = mimeTypes.at(j).name;
225            pluginsMap.insert(mimeType, plugin);
226            QVERIFY(plugin.supportsMimeType(mimeType));
227        }
228    }
229
230    QMultiMap<QString, QWebPluginInfo>::iterator it = pluginsMap.begin();
231    while (it != pluginsMap.end()) {
232        QString mimeType = it.key();
233        QWebPluginInfo plugin = it.value();
234        QWebPluginInfo pluginForMimeType = database->pluginForMimeType(mimeType);
235
236        QVERIFY(pluginsMap.count(mimeType) > 0);
237
238        if (pluginsMap.count(mimeType) == 1) {
239            QCOMPARE(plugin, pluginForMimeType);
240
241            QVERIFY(plugin.isEnabled());
242            QVERIFY(pluginForMimeType.isEnabled());
243            plugin.setEnabled(false);
244            QVERIFY(!plugin.isEnabled());
245            QVERIFY(!pluginForMimeType.isEnabled());
246        } else {
247            QVERIFY(plugin.isEnabled());
248            QVERIFY(pluginForMimeType.isEnabled());
249            plugin.setEnabled(false);
250            QVERIFY(!plugin.isEnabled());
251        }
252
253        QVERIFY(!plugin.isNull());
254        QVERIFY(!pluginForMimeType.isNull());
255
256        QWebPluginInfo pluginForMimeType2 = database->pluginForMimeType(mimeType);
257        if (pluginsMap.count(mimeType) == 1) {
258            QVERIFY(pluginForMimeType2 != plugin);
259            QVERIFY(pluginForMimeType2.isNull());
260        } else {
261            QVERIFY(pluginForMimeType2 != plugin);
262            QVERIFY(!pluginForMimeType2.isNull());
263        }
264
265        plugin.setEnabled(true);
266
267        ++it;
268    }
269}
270
271void tst_QWebPluginDatabase::operatorequal_data()
272{
273    QTest::addColumn<QWebPluginInfo>("first");
274    QTest::addColumn<QWebPluginInfo>("second");
275    QTest::addColumn<bool>("equal");
276
277    QWebPluginDatabase* database = QWebSettings::pluginDatabase();
278    QTest::newRow("null") << QWebPluginInfo() << QWebPluginInfo() << true;
279    QTest::newRow("application/x-shockwave-flash") << database->pluginForMimeType("application/x-shockwave-flash")
280                                                   << database->pluginForMimeType("application/x-shockwave-flash") << true;
281    QTest::newRow("foo/bar-baz") << database->pluginForMimeType("foo/bar-baz")
282                                 << database->pluginForMimeType("foo/bar-baz") << true;
283
284    QList<QWebPluginInfo> plugins = database->plugins();
285    for (int i = 0; i < (plugins.count() - 1); ++i) {
286        QWebPluginInfo first = plugins.at(i);
287        QWebPluginInfo second = plugins.at(i + 1);
288
289        QTest::newRow(QString("%1==%2").arg(first.name(), second.name()).toUtf8().constData())
290                                    << first << second << false;
291    }
292}
293
294void tst_QWebPluginDatabase::operatorequal()
295{
296    QFETCH(QWebPluginInfo, first);
297    QFETCH(QWebPluginInfo, second);
298    QFETCH(bool, equal);
299
300    QCOMPARE(first == second, equal);
301}
302
303void tst_QWebPluginDatabase::preferredPlugin()
304{
305    QMultiMap<QString, QWebPluginInfo> pluginsMap;
306    QWebPluginDatabase* database = QWebSettings::pluginDatabase();
307    QList<QWebPluginInfo> plugins = database->plugins();
308
309    for (int i = 0; i < plugins.count(); ++i) {
310        QWebPluginInfo plugin = plugins.at(i);
311
312        QList<MimeType> mimeTypes = plugin.mimeTypes();
313        for (int j = 0; j < mimeTypes.count(); ++j) {
314            QString mimeType = mimeTypes.at(j).name;
315            pluginsMap.insert(mimeType, plugin);
316        }
317    }
318
319    QMultiMap<QString, QWebPluginInfo>::iterator it = pluginsMap.begin();
320    while (it != pluginsMap.end()) {
321        QString mimeType = it.key();
322
323        if (pluginsMap.count(mimeType) > 1) {
324            QList<QWebPluginInfo> pluginsForMimeType = pluginsMap.values(mimeType);
325            QWebPluginInfo plugin = database->pluginForMimeType(mimeType);
326            QVERIFY(plugin.supportsMimeType(mimeType));
327
328            pluginsForMimeType.removeAll(plugin);
329            for (int i = 0; i < pluginsForMimeType.count(); ++i) {
330                QWebPluginInfo anotherPlugin = pluginsForMimeType.at(i);
331                QVERIFY(plugin.supportsMimeType(mimeType));
332                QVERIFY(plugin != anotherPlugin);
333
334                QCOMPARE(database->pluginForMimeType(mimeType), plugin);
335                database->setPreferredPluginForMimeType(mimeType, anotherPlugin);
336                QCOMPARE(database->pluginForMimeType(mimeType), anotherPlugin);
337
338                anotherPlugin.setEnabled(false);
339                QCOMPARE(database->pluginForMimeType(mimeType), plugin);
340
341                anotherPlugin.setEnabled(true);
342                QCOMPARE(database->pluginForMimeType(mimeType), anotherPlugin);
343                database->setSearchPaths(database->searchPaths());
344                QCOMPARE(database->pluginForMimeType(mimeType), anotherPlugin);
345
346                database->setPreferredPluginForMimeType(mimeType, QWebPluginInfo());
347                QCOMPARE(database->pluginForMimeType(mimeType), plugin);
348            }
349        } else {
350            QWebPluginInfo plugin = database->pluginForMimeType(mimeType);
351            QCOMPARE(pluginsMap.value(mimeType), plugin);
352
353            database->setPreferredPluginForMimeType(mimeType, plugin);
354            QCOMPARE(database->pluginForMimeType(mimeType), plugin);
355
356            plugin.setEnabled(false);
357            QCOMPARE(database->pluginForMimeType(mimeType), QWebPluginInfo());
358            plugin.setEnabled(true);
359
360            database->setPreferredPluginForMimeType(mimeType, QWebPluginInfo());
361            QCOMPARE(database->pluginForMimeType(mimeType), plugin);
362        }
363
364        ++it;
365    }
366
367    if (pluginsMap.keys().count() >= 2) {
368        QStringList mimeTypes = pluginsMap.uniqueKeys();
369
370        QString mimeType1 = mimeTypes.at(0);
371        QString mimeType2 = mimeTypes.at(1);
372        QWebPluginInfo plugin1 = database->pluginForMimeType(mimeType1);
373        QWebPluginInfo plugin2 = database->pluginForMimeType(mimeType2);
374
375        int i = 2;
376        while (plugin2.supportsMimeType(mimeType1)
377               && !mimeType2.isEmpty()
378               && i < mimeTypes.count()) {
379            mimeType2 = mimeTypes.at(i);
380            plugin2 = database->pluginForMimeType(mimeType2);
381            ++i;
382        }
383
384        plugin1 = database->pluginForMimeType(mimeType1);
385        QVERIFY(plugin1.supportsMimeType(mimeType1));
386        QVERIFY(!plugin1.isNull());
387        plugin2 = database->pluginForMimeType(mimeType2);
388        QVERIFY(plugin2.supportsMimeType(mimeType2));
389        QVERIFY(!plugin2.isNull());
390
391        database->setPreferredPluginForMimeType(mimeType2, plugin1);
392        QVERIFY(!plugin1.supportsMimeType(mimeType2));
393        QCOMPARE(database->pluginForMimeType(mimeType2), plugin2);
394
395        database->setPreferredPluginForMimeType(mimeType1, plugin1);
396        QVERIFY(!plugin2.supportsMimeType(mimeType1));
397        QCOMPARE(database->pluginForMimeType(mimeType2), plugin2);
398    }
399}
400
401void tst_QWebPluginDatabase::operatorassign_data()
402{
403    QTest::addColumn<QWebPluginInfo>("first");
404    QTest::addColumn<QWebPluginInfo>("second");
405
406    QWebPluginDatabase* database = QWebSettings::pluginDatabase();
407    QTest::newRow("null") << QWebPluginInfo() << QWebPluginInfo();
408
409    QList<QWebPluginInfo> plugins = database->plugins();
410    for (int i = 0; i < (plugins.count() - 1); ++i) {
411        QWebPluginInfo first = plugins.at(i);
412        QWebPluginInfo second = plugins.at(i + 1);
413
414        QTest::newRow(QString("%1=%2").arg(first.name(), second.name()).toUtf8().constData()) << first << second;
415    }
416}
417
418void tst_QWebPluginDatabase::operatorassign()
419{
420    QFETCH(QWebPluginInfo, first);
421    QFETCH(QWebPluginInfo, second);
422
423    QWebPluginInfo info;
424    QCOMPARE(info.mimeTypes(), QList<MimeType>());
425    QCOMPARE(info = first, first);
426    QCOMPARE(info, first);
427    QCOMPARE(info.mimeTypes(), first.mimeTypes());
428    QCOMPARE(info = second, second);
429    QCOMPARE(info, second);
430    QCOMPARE(info.mimeTypes(), second.mimeTypes());
431    QCOMPARE(info = QWebPluginInfo(), QWebPluginInfo());
432    QCOMPARE(info.mimeTypes(), QList<MimeType>());
433}
434
435QTEST_MAIN(tst_QWebPluginDatabase)
436
437#include "tst_qwebplugindatabase.moc"
438