summaryrefslogtreecommitdiffstats
path: root/src/corelib/plugin
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/plugin')
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp92
-rw-r--r--src/corelib/plugin/qfactoryloader_p.h38
-rw-r--r--src/corelib/plugin/qlibrary.cpp21
-rw-r--r--src/corelib/plugin/qlibrary_p.h10
-rw-r--r--src/corelib/plugin/qplugin_p.h10
-rw-r--r--src/corelib/plugin/qpluginloader.cpp17
6 files changed, 110 insertions, 78 deletions
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 02c9cafbed..824bf60f7d 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -46,8 +46,12 @@
#include "private/qcoreapplication_p.h"
#include "private/qduplicatetracker_p.h"
#include "private/qobject_p.h"
+#include "qcborarray.h"
#include "qcbormap.h"
#include "qcborvalue.h"
+#include "qcborvalue.h"
+#include "qdir.h"
+#include "qfileinfo.h"
#include "qjsonarray.h"
#include "qjsondocument.h"
#include "qjsonobject.h"
@@ -57,63 +61,61 @@
#include "qplugin.h"
#include "qplugin_p.h"
#include "qpluginloader.h"
-#include <qdebug.h>
-#include <qdir.h>
+
+#if QT_CONFIG(library)
+# include "qlibrary_p.h"
+#endif
#include <qtcore_tracepoints_p.h>
QT_BEGIN_NAMESPACE
-QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QString *errMsg)
+bool QPluginParsedMetaData::parse(QByteArrayView raw)
{
- // extract the keys not stored in CBOR
QPluginMetaData::Header header;
- Q_ASSERT(size >= qsizetype(sizeof(header)));
- memcpy(&header, raw, sizeof(header));
- if (Q_UNLIKELY(header.version > QPluginMetaData::CurrentMetaDataVersion)) {
- *errMsg = QStringLiteral("Invalid metadata version");
- return QJsonDocument();
- }
-
- raw += sizeof(header);
- size -= sizeof(header);
- QByteArray ba = QByteArray::fromRawData(raw, int(size));
+ Q_ASSERT(raw.size() >= qsizetype(sizeof(header)));
+ memcpy(&header, raw.data(), sizeof(header));
+ if (Q_UNLIKELY(header.version > QPluginMetaData::CurrentMetaDataVersion))
+ return setError(QFactoryLoader::tr("Invalid metadata version"));
+
+ // use fromRawData to keep QCborStreamReader from copying
+ raw = raw.sliced(sizeof(header));
+ QByteArray ba = QByteArray::fromRawData(raw.data(), raw.size());
QCborParserError err;
QCborValue metadata = QCborValue::fromCbor(ba, &err);
- if (err.error != QCborError::NoError) {
- *errMsg = QLatin1String("Metadata parsing error: ") + err.error.toString();
- return QJsonDocument();
- }
-
- if (!metadata.isMap()) {
- *errMsg = QStringLiteral("Unexpected metadata contents");
- return QJsonDocument();
- }
+ if (err.error != QCborError::NoError)
+ return setError(QFactoryLoader::tr("Metadata parsing error: %1").arg(err.error.toString()));
+ if (!metadata.isMap())
+ return setError(QFactoryLoader::tr("Unexpected metadata contents"));
+ QCborMap map = metadata.toMap();
+ metadata = {};
DecodedArchRequirements archReq =
header.version == 0 ? decodeVersion0ArchRequirements(header.plugin_arch_requirements)
: decodeVersion1ArchRequirements(header.plugin_arch_requirements);
- QJsonObject o;
- o.insert(QLatin1String("version"),
- QT_VERSION_CHECK(header.qt_major_version, header.qt_minor_version, 0));
- o.insert(QLatin1String("debug"), archReq.isDebug);
- o.insert(QLatin1String("archlevel"), archReq.level);
+ // insert the keys not stored in the top-level CBOR map
+ map[int(QtPluginMetaDataKeys::QtVersion)] =
+ QT_VERSION_CHECK(header.qt_major_version, header.qt_minor_version, 0);
+ map[int(QtPluginMetaDataKeys::IsDebug)] = archReq.isDebug;
+ map[int(QtPluginMetaDataKeys::Requirements)] = archReq.level;
+
+ data = std::move(map);
+ return true;
+}
- // convert the top-level map integer keys
- for (auto it : metadata.toMap()) {
+QJsonObject QPluginParsedMetaData::toJson() const
+{
+ // convert from the internal CBOR representation to an external JSON one
+ QJsonObject o;
+ for (auto it : data.toMap()) {
QString key;
if (it.first.isInteger()) {
switch (it.first.toInteger()) {
#define CONVERT_TO_STRING(IntKey, StringKey, Description) \
case int(IntKey): key = QStringLiteral(StringKey); break;
QT_PLUGIN_FOREACH_METADATA(CONVERT_TO_STRING)
-#undef CONVERT_TO_STRING
-
- case int(QtPluginMetaDataKeys::Requirements):
- // ignore, handled above
- break;
}
} else {
key = it.first.toString();
@@ -122,7 +124,7 @@ QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QStri
if (!key.isEmpty())
o.insert(key, it.second.toJsonValue());
}
- return QJsonDocument(o);
+ return o;
}
class QFactoryLoaderPrivate : public QObjectPrivate
@@ -227,12 +229,12 @@ void QFactoryLoader::update()
QStringList keys;
bool metaDataOk = false;
- QString iid = library->metaData.value(QLatin1String("IID")).toString();
+ QString iid = library->metaData.value(QtPluginMetaDataKeys::IID).toString();
if (iid == QLatin1String(d->iid.constData(), d->iid.size())) {
- QJsonObject object = library->metaData.value(QLatin1String("MetaData")).toObject();
+ QCborMap object = library->metaData.value(QtPluginMetaDataKeys::MetaData).toMap();
metaDataOk = true;
- QJsonArray k = object.value(QLatin1String("Keys")).toArray();
+ QCborArray k = object.value(QLatin1String("Keys")).toArray();
for (int i = 0; i < k.size(); ++i)
keys += d->cs ? k.at(i).toString() : k.at(i).toString().toLower();
}
@@ -251,14 +253,14 @@ void QFactoryLoader::update()
// library was built with a future Qt version,
// whereas the new one has a Qt version that fits
// better
+ constexpr int QtVersionNoPatch = QT_VERSION_CHECK(QT_VERSION_MAJOR, QT_VERSION_MINOR, 0);
const QString &key = keys.at(k);
QLibraryPrivate *previous = d->keyMap.value(key);
int prev_qt_version = 0;
- if (previous) {
- prev_qt_version = (int)previous->metaData.value(QLatin1String("version")).toDouble();
- }
- int qt_version = (int)library->metaData.value(QLatin1String("version")).toDouble();
- if (!previous || (prev_qt_version > QT_VERSION && qt_version <= QT_VERSION)) {
+ if (previous)
+ prev_qt_version = int(previous->metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger());
+ int qt_version = int(library->metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger());
+ if (!previous || (prev_qt_version > QtVersionNoPatch && qt_version <= QtVersionNoPatch)) {
d->keyMap[key] = library;
++keyUsageCount;
}
@@ -339,7 +341,7 @@ QList<QJsonObject> QFactoryLoader::metaData() const
#if QT_CONFIG(library)
QMutexLocker locker(&d->mutex);
for (int i = 0; i < d->libraryList.size(); ++i)
- metaData.append(d->libraryList.at(i)->metaData);
+ metaData.append(d->libraryList.at(i)->metaData.toJson());
#endif
const auto staticPlugins = QPluginLoader::staticPlugins();
diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h
index 0ad62cc525..b7536d0349 100644
--- a/src/corelib/plugin/qfactoryloader_p.h
+++ b/src/corelib/plugin/qfactoryloader_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -54,19 +55,44 @@
#include "QtCore/qglobal.h"
#ifndef QT_NO_QOBJECT
+#include "QtCore/private/qplugin_p.h"
+#include "QtCore/qcbormap.h"
+#include "QtCore/qcborvalue.h"
#include "QtCore/qmap.h"
#include "QtCore/qobject.h"
-
-#if QT_CONFIG(library)
-# include "qlibrary_p.h"
-#endif
+#include "QtCore/qplugin.h"
QT_BEGIN_NAMESPACE
class QJsonDocument;
class QJsonObject;
+class QLibraryPrivate;
+
+class QPluginParsedMetaData
+{
+ QCborValue data;
+ bool setError(const QString &errorString) Q_DECL_COLD_FUNCTION
+ {
+ data = errorString;
+ return false;
+ }
+public:
+ QPluginParsedMetaData() = default;
+ QPluginParsedMetaData(QByteArrayView input) { parse(input); }
+
+ bool isError() const { return !data.isMap(); }
+ QString errorString() const { return data.toString(); }
+
+ bool parse(QByteArrayView input);
+ bool parse(QPluginMetaData metaData)
+ { return parse(QByteArrayView(reinterpret_cast<const char *>(metaData.data), metaData.size)); }
-QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QString *errMsg);
+ QJsonObject toJson() const;
+
+ // if data is not a map, toMap() returns empty, so shall these functions
+ QCborMap toCbor() const { return data.toMap(); }
+ QCborValue value(QtPluginMetaDataKeys k) const { return toCbor()[int(k)]; }
+};
class QFactoryLoaderPrivate;
class Q_CORE_EXPORT QFactoryLoader : public QObject
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 432b232d27..4eea6f0002 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -270,13 +270,13 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
QString errMsg = library;
QLibraryScanResult r = qt_find_pattern(filedata, fdlen, &errMsg);
if (r.length) {
- QJsonDocument doc = qJsonFromRawLibraryMetaData(filedata + r.pos, r.length, &errMsg);
- if (doc.isNull()) {
+ if (!lib->metaData.parse(QByteArrayView(filedata + r.pos, r.length))) {
+ errMsg = lib->metaData.errorString();
qWarning("Found invalid metadata in lib %ls: %ls",
qUtf16Printable(library), qUtf16Printable(errMsg));
} else {
- lib->metaData = doc.object();
if (qt_debug_component()) {
+ QJsonDocument doc(lib->metaData.toJson());
qWarning("Found metadata in lib %s, metadata=\n%s\n",
library.toLocal8Bit().constData(), doc.toJson().constData());
}
@@ -711,13 +711,10 @@ static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg)
if (metaData.size < sizeof(QPluginMetaData::Header))
return error(QLibrary::tr("metadata too small"));
- QJsonDocument doc = qJsonFromRawLibraryMetaData(reinterpret_cast<const char *>(metaData.data),
- metaData.size, errMsg);
- if (doc.isNull())
- return false; // error message already set
-
- priv->metaData = doc.object();
- return true;
+ if (priv->metaData.parse(metaData))
+ return true;
+ *errMsg = priv->metaData.errorString();
+ return false;
}
bool QLibraryPrivate::isPlugin()
@@ -773,8 +770,8 @@ void QLibraryPrivate::updatePluginState()
pluginState = IsNotAPlugin; // be pessimistic
- uint qt_version = (uint)metaData.value(QLatin1String("version")).toDouble();
- bool debug = metaData.value(QLatin1String("debug")).toBool();
+ uint qt_version = uint(metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger());
+ bool debug = metaData.value(QtPluginMetaDataKeys::IsDebug).toBool();
if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) {
if (qt_debug_component()) {
qWarning("In %s:\n"
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
index b42816a469..3c43d79e25 100644
--- a/src/corelib/plugin/qlibrary_p.h
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -52,9 +52,9 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
-
#include "QtCore/qlibrary.h"
+
+#include "QtCore/private/qfactoryloader_p.h"
#include "QtCore/qmutex.h"
#include "QtCore/qplugin.h"
#include "QtCore/qpointer.h"
@@ -111,7 +111,7 @@ public:
// the mutex protects the fields below
QMutex mutex;
QPointer<QObject> inst; // used by QFactoryLoader
- QJsonObject metaData;
+ QPluginParsedMetaData metaData;
QString errorString;
QString qualifiedFileName;
diff --git a/src/corelib/plugin/qplugin_p.h b/src/corelib/plugin/qplugin_p.h
index 80ee02e761..026992ba97 100644
--- a/src/corelib/plugin/qplugin_p.h
+++ b/src/corelib/plugin/qplugin_p.h
@@ -61,7 +61,8 @@ enum class QtPluginMetaDataKeys {
IID,
ClassName,
MetaData,
- URI
+ URI,
+ IsDebug,
};
// F(IntKey, StringKey, Description)
@@ -70,7 +71,12 @@ enum class QtPluginMetaDataKeys {
F(QtPluginMetaDataKeys::IID, "IID", "Plugin's Interface ID") \
F(QtPluginMetaDataKeys::ClassName, "className", "Plugin class name") \
F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data") \
- F(QtPluginMetaDataKeys::URI, "URI", "Plugin URI")
+ F(QtPluginMetaDataKeys::URI, "URI", "Plugin URI") \
+ /* not output by moc in CBOR */ \
+ F(QtPluginMetaDataKeys::QtVersion, "version", "Qt version") \
+ F(QtPluginMetaDataKeys::Requirements, "archlevel", "Architectural level") \
+ F(QtPluginMetaDataKeys::IsDebug, "debug", "Debug-mode plugin") \
+ /**/
namespace {
struct DecodedArchRequirements
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index 9afdf0e537..eca85eb82e 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -47,6 +47,10 @@
#include "qfileinfo.h"
#include "qjsondocument.h"
+#if QT_CONFIG(library)
+# include "qlibrary_p.h"
+#endif
+
QT_BEGIN_NAMESPACE
#if QT_CONFIG(library)
@@ -185,7 +189,7 @@ QJsonObject QPluginLoader::metaData() const
{
if (!d)
return QJsonObject();
- return d->metaData;
+ return d->metaData.toJson();
}
/*!
@@ -477,13 +481,10 @@ QList<QStaticPlugin> QPluginLoader::staticPlugins()
*/
QJsonObject QStaticPlugin::metaData() const
{
- auto ptr = static_cast<const char *>(rawMetaData);
-
- QString errMsg;
- QJsonDocument doc = qJsonFromRawLibraryMetaData(ptr, rawMetaDataSize, &errMsg);
- Q_ASSERT(doc.isObject());
- Q_ASSERT(errMsg.isEmpty());
- return doc.object();
+ QByteArrayView data(static_cast<const char *>(rawMetaData), rawMetaDataSize);
+ QPluginParsedMetaData parsed(data);
+ Q_ASSERT(!parsed.isError());
+ return parsed.toJson();
}
QT_END_NAMESPACE