1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qwebviewfactory_p.h"
5#include "qwebviewplugin_p.h"
6#include <private/qfactoryloader_p.h>
7#include <QtCore/qglobal.h>
8
9QT_BEGIN_NAMESPACE
10
11Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, (QWebViewPluginInterface_iid, QLatin1String("/webview")))
12
13static QString getPluginName()
14{
15 static const QString name = !qEnvironmentVariableIsEmpty(varName: "QT_WEBVIEW_PLUGIN")
16 ? QString::fromLatin1(ba: qgetenv(varName: "QT_WEBVIEW_PLUGIN"))
17 : QStringLiteral("native");
18 return name;
19}
20
21class QNullWebViewSettings : public QAbstractWebViewSettings
22{
23public:
24 explicit QNullWebViewSettings(QObject *p) : QAbstractWebViewSettings(p) {}
25 bool localStorageEnabled() const override { return false; }
26 bool javaScriptEnabled() const override { return false; }
27 bool localContentCanAccessFileUrls() const override { return false; }
28 bool allowFileAccess() const override { return false; }
29 void setLocalContentCanAccessFileUrls(bool) override {}
30 void setJavaScriptEnabled(bool) override {}
31 void setLocalStorageEnabled(bool) override {}
32 void setAllowFileAccess(bool) override {}
33};
34
35class QNullWebView : public QAbstractWebView
36{
37public:
38 explicit QNullWebView(QObject *p = nullptr)
39 : QAbstractWebView(p)
40 , m_settings(new QNullWebViewSettings(this))
41 {}
42
43 QString httpUserAgent() const override { return QString(); }
44 void setHttpUserAgent(const QString &userAgent) override { Q_UNUSED(userAgent); }
45 void setUrl(const QUrl &url) override { Q_UNUSED(url); }
46 bool canGoBack() const override { return false; }
47 bool canGoForward() const override { return false; }
48 QString title() const override { return QString(); }
49 int loadProgress() const override { return 0; }
50 bool isLoading() const override { return false; }
51 void goBack() override { }
52 void goForward() override { }
53 void stop() override { }
54 void reload() override { }
55 void loadHtml(const QString &html, const QUrl &baseUrl) override
56 { Q_UNUSED(html); Q_UNUSED(baseUrl); }
57 void runJavaScriptPrivate(const QString &script, int callbackId) override
58 { Q_UNUSED(script); Q_UNUSED(callbackId); }
59 void setCookie(const QString &domain, const QString &name, const QString &value) override
60 { Q_UNUSED(domain); Q_UNUSED(name); Q_UNUSED(value); }
61 void deleteCookie(const QString &domain, const QString &name) override
62 { Q_UNUSED(domain); Q_UNUSED(name); }
63 void deleteAllCookies() override {}
64 QWindow *nativeWindow() const override { return nullptr; }
65
66protected:
67 QAbstractWebViewSettings *getSettings() const override
68 {
69 return m_settings;
70 }
71
72private:
73 QNullWebViewSettings *m_settings = nullptr;
74};
75
76QAbstractWebView *QWebViewFactory::createWebView()
77{
78 QAbstractWebView *wv = nullptr;
79 QWebViewPlugin *plugin = getPlugin();
80 if (plugin)
81 wv = plugin->create(QStringLiteral("webview"));
82
83 if (!wv || !plugin) {
84 qWarning(msg: "No WebView plug-in found!");
85 wv = new QNullWebView;
86 }
87
88 return wv;
89}
90
91bool QWebViewFactory::requiresExtraInitializationSteps()
92{
93 const QString pluginName = getPluginName();
94 const int index = pluginName.isEmpty() ? 0 : qMax<int>(a: 0, b: loader->indexOf(needle: pluginName));
95
96 const QList<QPluginParsedMetaData> metaDataList = loader->metaData();
97 if (metaDataList.isEmpty())
98 return false;
99
100 const auto &pluginMetaData = metaDataList.at(i: index);
101 Q_ASSERT(pluginMetaData.value(QtPluginMetaDataKeys::IID) == QLatin1String(QWebViewPluginInterface_iid));
102 const auto metaDataObject = pluginMetaData.value(k: QtPluginMetaDataKeys::MetaData).toMap();
103 return metaDataObject.value(key: QLatin1String("RequiresInit")).toBool();
104}
105
106QWebViewPlugin *QWebViewFactory::getPlugin()
107{
108 // Plugin loading logic:
109 // 1. Get plugin name - plugin name is either user specified or "native"
110 // - Exception: macOS, which will default to using "webengine" until the native plugin is matured.
111 // 2. If neither a user specified or "default" plugin exists, then the first available is used.
112 const QString pluginName = getPluginName();
113 const int index = pluginName.isEmpty() ? 0 : qMax<int>(a: 0, b: loader->indexOf(needle: pluginName));
114 return qobject_cast<QWebViewPlugin *>(object: loader->instance(index));
115}
116
117bool QWebViewFactory::loadedPluginHasKey(const QString key)
118{
119 const QString &pluginName = getPluginName();
120 // instead of creating multimap with QFactoryLoader::KeyMap and doing a search
121 // simply check if loded and key index matches
122 if (pluginName.isEmpty())
123 return false;
124 const int loadedIndex = qMax<int>(a: 0, b: loader->indexOf(needle: pluginName));
125 const int keyIndex = loader->indexOf(needle: key);
126 return keyIndex > -1 && loadedIndex == keyIndex;
127}
128
129QT_END_NAMESPACE
130

source code of qtwebview/src/webview/qwebviewfactory.cpp