QDBusConnection::registorObject with interface
Currently QDBus relies on a key in QMetaClassInfo to understand the DBus interface name. This patch allows QDBus to also use a specified interface name in the registerObject call instead of relying on QMetaClassInfo that might not be there (if the QObject was created in QML or Javascript for example). Change-Id: Ie02b2c67e7deb07f43e35eb166c11833fcbf38f3 Task-number: QTBUG-44074 Reviewed-by: Kevron Rees <kevron.m.rees@intel.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
06ecd74db1
commit
0eec8c86b6
@ -761,6 +761,26 @@ bool QDBusConnection::disconnect(const QString &service, const QString &path, co
|
|||||||
was registered with QDBusConnection::ExportChildObjects.
|
was registered with QDBusConnection::ExportChildObjects.
|
||||||
*/
|
*/
|
||||||
bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options)
|
bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options)
|
||||||
|
{
|
||||||
|
return registerObject(path, QString(), object, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\overload
|
||||||
|
\since 5.5
|
||||||
|
|
||||||
|
Registers the object \a object at path \a path with interface name \a interface
|
||||||
|
and returns \c true if the registration was successful. The \a options parameter
|
||||||
|
specifies how much of the object \a object will be exposed through
|
||||||
|
D-Bus.
|
||||||
|
|
||||||
|
This function does not replace existing objects: if there is already an object registered at
|
||||||
|
path \a path, this function will return false. Use unregisterObject() to unregister it first.
|
||||||
|
|
||||||
|
You cannot register an object as a child object of an object that
|
||||||
|
was registered with QDBusConnection::ExportChildObjects.
|
||||||
|
*/
|
||||||
|
bool QDBusConnection::registerObject(const QString &path, const QString &interface, QObject *object, RegisterOptions options)
|
||||||
{
|
{
|
||||||
Q_ASSERT_X(QDBusUtil::isValidObjectPath(path), "QDBusConnection::registerObject",
|
Q_ASSERT_X(QDBusUtil::isValidObjectPath(path), "QDBusConnection::registerObject",
|
||||||
"Invalid object path given");
|
"Invalid object path given");
|
||||||
@ -793,6 +813,7 @@ bool QDBusConnection::registerObject(const QString &path, QObject *object, Regis
|
|||||||
// we can add the object here
|
// we can add the object here
|
||||||
node->obj = object;
|
node->obj = object;
|
||||||
node->flags = options;
|
node->flags = options;
|
||||||
|
node->interfaceName = interface;
|
||||||
|
|
||||||
d->registerObject(node);
|
d->registerObject(node);
|
||||||
//qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
|
//qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
|
||||||
|
@ -161,6 +161,8 @@ public:
|
|||||||
|
|
||||||
bool registerObject(const QString &path, QObject *object,
|
bool registerObject(const QString &path, QObject *object,
|
||||||
RegisterOptions options = ExportAdaptors);
|
RegisterOptions options = ExportAdaptors);
|
||||||
|
bool registerObject(const QString &path, const QString &interface, QObject *object,
|
||||||
|
RegisterOptions options = ExportAdaptors);
|
||||||
void unregisterObject(const QString &path, UnregisterMode mode = UnregisterNode);
|
void unregisterObject(const QString &path, UnregisterMode mode = UnregisterNode);
|
||||||
QObject *objectRegisteredAt(const QString &path) const;
|
QObject *objectRegisteredAt(const QString &path) const;
|
||||||
|
|
||||||
|
@ -152,6 +152,7 @@ public:
|
|||||||
{ return obj || !children.isEmpty(); }
|
{ return obj || !children.isEmpty(); }
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
|
QString interfaceName;
|
||||||
union {
|
union {
|
||||||
QObject *obj;
|
QObject *obj;
|
||||||
QDBusVirtualObject *treeNode;
|
QDBusVirtualObject *treeNode;
|
||||||
|
@ -1481,8 +1481,12 @@ void QDBusConnectionPrivate::activateObject(ObjectTreeNode &node, const QDBusMes
|
|||||||
if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots) ||
|
if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots) ||
|
||||||
node.flags & (QDBusConnection::ExportScriptableInvokables|QDBusConnection::ExportNonScriptableInvokables)) {
|
node.flags & (QDBusConnection::ExportScriptableInvokables|QDBusConnection::ExportNonScriptableInvokables)) {
|
||||||
bool interfaceFound = true;
|
bool interfaceFound = true;
|
||||||
if (!msg.interface().isEmpty())
|
if (!msg.interface().isEmpty()) {
|
||||||
interfaceFound = qDBusInterfaceInObject(node.obj, msg.interface());
|
if (!node.interfaceName.isEmpty())
|
||||||
|
interfaceFound = msg.interface() == node.interfaceName;
|
||||||
|
else
|
||||||
|
interfaceFound = qDBusInterfaceInObject(node.obj, msg.interface());
|
||||||
|
}
|
||||||
|
|
||||||
if (interfaceFound) {
|
if (interfaceFound) {
|
||||||
if (!activateCall(node.obj, node.flags, msg))
|
if (!activateCall(node.obj, node.flags, msg))
|
||||||
|
@ -134,7 +134,7 @@ QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node
|
|||||||
// create XML for the object itself
|
// create XML for the object itself
|
||||||
const QMetaObject *mo = node.obj->metaObject();
|
const QMetaObject *mo = node.obj->metaObject();
|
||||||
for ( ; mo != &QObject::staticMetaObject; mo = mo->superClass())
|
for ( ; mo != &QObject::staticMetaObject; mo = mo->superClass())
|
||||||
xml_data += qDBusGenerateMetaObjectXml(QString(), mo, mo->superClass(),
|
xml_data += qDBusGenerateMetaObjectXml(node.interfaceName, mo, mo->superClass(),
|
||||||
node.flags);
|
node.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,27 @@ void MyObject::method(const QDBusMessage &msg)
|
|||||||
//qDebug() << msg;
|
//qDebug() << msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MyObjectWithoutInterface: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public slots:
|
||||||
|
void method(const QDBusMessage &msg);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static QString path;
|
||||||
|
static QString interface;
|
||||||
|
int callCount;
|
||||||
|
MyObjectWithoutInterface(QObject *parent = 0) : QObject(parent), callCount(0) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void MyObjectWithoutInterface::method(const QDBusMessage &msg)
|
||||||
|
{
|
||||||
|
path = msg.path();
|
||||||
|
interface = msg.interface();
|
||||||
|
++callCount;
|
||||||
|
//qDebug() << msg;
|
||||||
|
}
|
||||||
|
|
||||||
class tst_QDBusConnection: public QObject
|
class tst_QDBusConnection: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -87,6 +108,8 @@ private slots:
|
|||||||
|
|
||||||
void registerObject_data();
|
void registerObject_data();
|
||||||
void registerObject();
|
void registerObject();
|
||||||
|
void registerObjectWithInterface_data();
|
||||||
|
void registerObjectWithInterface();
|
||||||
void registerObjectPeer_data();
|
void registerObjectPeer_data();
|
||||||
void registerObjectPeer();
|
void registerObjectPeer();
|
||||||
void registerObject2();
|
void registerObject2();
|
||||||
@ -112,6 +135,7 @@ private slots:
|
|||||||
public:
|
public:
|
||||||
QString serviceName() const { return "org.qtproject.Qt.Autotests.QDBusConnection"; }
|
QString serviceName() const { return "org.qtproject.Qt.Autotests.QDBusConnection"; }
|
||||||
bool callMethod(const QDBusConnection &conn, const QString &path);
|
bool callMethod(const QDBusConnection &conn, const QString &path);
|
||||||
|
bool callMethod(const QDBusConnection &conn, const QString &path, const QString &interface);
|
||||||
bool callMethodPeer(const QDBusConnection &conn, const QString &path);
|
bool callMethodPeer(const QDBusConnection &conn, const QString &path);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -379,6 +403,40 @@ void tst_QDBusConnection::registerObject()
|
|||||||
QVERIFY(!callMethod(con, path));
|
QVERIFY(!callMethod(con, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QDBusConnection::registerObjectWithInterface_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("path");
|
||||||
|
QTest::addColumn<QString>("interface");
|
||||||
|
|
||||||
|
QTest::newRow("/") << "/" << "org.foo";
|
||||||
|
QTest::newRow("/p1") << "/p1" << "org.foo";
|
||||||
|
QTest::newRow("/p2") << "/p2" << "org.foo";
|
||||||
|
QTest::newRow("/p1/q") << "/p1/q" << "org.foo";
|
||||||
|
QTest::newRow("/p1/q/r") << "/p1/q/r" << "org.foo";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QDBusConnection::registerObjectWithInterface()
|
||||||
|
{
|
||||||
|
QFETCH(QString, path);
|
||||||
|
QFETCH(QString, interface);
|
||||||
|
|
||||||
|
QDBusConnection con = QDBusConnection::sessionBus();
|
||||||
|
QVERIFY(con.isConnected());
|
||||||
|
|
||||||
|
{
|
||||||
|
// register one object at root:
|
||||||
|
MyObjectWithoutInterface obj;
|
||||||
|
QVERIFY(con.registerObject(path, interface, &obj, QDBusConnection::ExportAllSlots));
|
||||||
|
QCOMPARE(con.objectRegisteredAt(path), static_cast<QObject *>(&obj));
|
||||||
|
QVERIFY(callMethod(con, path, interface));
|
||||||
|
QCOMPARE(obj.path, path);
|
||||||
|
QCOMPARE(obj.interface, interface);
|
||||||
|
}
|
||||||
|
// make sure it's gone
|
||||||
|
QVERIFY(!callMethod(con, path, interface));
|
||||||
|
}
|
||||||
|
|
||||||
class MyServer : public QDBusServer
|
class MyServer : public QDBusServer
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -844,6 +902,16 @@ bool tst_QDBusConnection::callMethod(const QDBusConnection &conn, const QString
|
|||||||
return (MyObject::path == path);
|
return (MyObject::path == path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tst_QDBusConnection::callMethod(const QDBusConnection &conn, const QString &path, const QString &interface)
|
||||||
|
{
|
||||||
|
QDBusMessage msg = QDBusMessage::createMethodCall(conn.baseService(), path, interface, "method");
|
||||||
|
QDBusMessage reply = conn.call(msg, QDBus::Block/*WithGui*/);
|
||||||
|
if (reply.type() != QDBusMessage::ReplyMessage)
|
||||||
|
return false;
|
||||||
|
QTest::qCompare(MyObjectWithoutInterface::path, path, "MyObjectWithoutInterface::path", "path", __FILE__, __LINE__);
|
||||||
|
return (MyObjectWithoutInterface::path == path) && MyObjectWithoutInterface::interface == interface;
|
||||||
|
}
|
||||||
|
|
||||||
bool tst_QDBusConnection::callMethodPeer(const QDBusConnection &conn, const QString &path)
|
bool tst_QDBusConnection::callMethodPeer(const QDBusConnection &conn, const QString &path)
|
||||||
{
|
{
|
||||||
QDBusMessage msg = QDBusMessage::createMethodCall("", path, "", "method");
|
QDBusMessage msg = QDBusMessage::createMethodCall("", path, "", "method");
|
||||||
@ -1307,6 +1375,8 @@ void tst_QDBusConnection::callVirtualObjectLocal()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString MyObject::path;
|
QString MyObject::path;
|
||||||
|
QString MyObjectWithoutInterface::path;
|
||||||
|
QString MyObjectWithoutInterface::interface;
|
||||||
QTEST_MAIN(tst_QDBusConnection)
|
QTEST_MAIN(tst_QDBusConnection)
|
||||||
|
|
||||||
#include "tst_qdbusconnection.moc"
|
#include "tst_qdbusconnection.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user