summaryrefslogtreecommitdiffstats
path: root/qt/qdbusintegrator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt/qdbusintegrator.cpp')
-rw-r--r--qt/qdbusintegrator.cpp85
1 files changed, 71 insertions, 14 deletions
diff --git a/qt/qdbusintegrator.cpp b/qt/qdbusintegrator.cpp
index bef8268d..3f907256 100644
--- a/qt/qdbusintegrator.cpp
+++ b/qt/qdbusintegrator.cpp
@@ -984,13 +984,14 @@ bool QDBusConnectionPrivate::activateInternalFilters(const ObjectTreeNode *node,
{
// object may be null
- if (msg.interface() == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE)) {
+ if (msg.interface().isEmpty() || msg.interface() == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE)) {
if (msg.method() == QLatin1String("Introspect") && msg.signature().isEmpty())
qDBusIntrospectObject(node, msg);
return true;
}
- if (node->obj && msg.interface() == QLatin1String(DBUS_INTERFACE_PROPERTIES)) {
+ if (node->obj && (msg.interface().isEmpty() ||
+ msg.interface() == QLatin1String(DBUS_INTERFACE_PROPERTIES))) {
if (msg.method() == QLatin1String("Get") && msg.signature() == QLatin1String("ss"))
qDBusPropertyGet(node, msg);
else if (msg.method() == QLatin1String("Set") && msg.signature() == QLatin1String("ssv"))
@@ -1053,25 +1054,26 @@ bool QDBusConnectionPrivate::activateObject(const ObjectTreeNode *node, const QD
return false;
}
-bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
+template<typename Func>
+static bool applyForObject(QDBusConnectionPrivate::ObjectTreeNode *root, const QString &fullpath,
+ Func& functor)
{
- QReadLocker locker(&lock);
-
// walk the object tree
- QStringList path = msg.path().split(QLatin1Char('/'));
+ QStringList path = fullpath.split(QLatin1Char('/'));
if (path.last().isEmpty())
path.removeLast(); // happens if path is "/"
int i = 1;
- ObjectTreeNode *node = &rootNode;
+ QDBusConnectionPrivate::ObjectTreeNode *node = root;
// try our own tree first
while (node && !(node->flags & QDBusConnection::ExportChildObjects) ) {
if (i == path.count()) {
// found our object
- return activateObject(node, msg);
+ functor(node);
+ return true;
}
- QVector<ObjectTreeNode::Data>::ConstIterator it =
+ QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::ConstIterator it =
qLowerBound(node->children.constBegin(), node->children.constEnd(), path.at(i));
if (it != node->children.constEnd() && it->name == path.at(i))
// match
@@ -1089,9 +1091,10 @@ bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
while (obj) {
if (i == path.count()) {
// we're at the correct level
- ObjectTreeNode fakenode(*node);
+ QDBusConnectionPrivate::ObjectTreeNode fakenode(*node);
fakenode.obj = obj;
- return activateObject(&fakenode, msg);
+ functor(&fakenode);
+ return true;
}
const QObjectList &children = obj->children();
@@ -1112,6 +1115,31 @@ bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
}
}
+ // object not found
+ return false;
+}
+
+struct qdbus_activateObject
+{
+ QDBusConnectionPrivate *self;
+ const QDBusMessage &msg;
+ bool returnVal;
+ inline qdbus_activateObject(QDBusConnectionPrivate *s, const QDBusMessage &m)
+ : self(s), msg(m)
+ { }
+
+ inline void operator()(QDBusConnectionPrivate::ObjectTreeNode *node)
+ { returnVal = self->activateObject(node, msg); }
+};
+
+bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
+{
+ QReadLocker locker(&lock);
+
+ qdbus_activateObject apply(this, msg);
+ if (applyForObject(&rootNode, msg.path(), apply))
+ return apply.returnVal;
+
qDebug("Call failed: no object found at %s", qPrintable(msg.path()));
return false;
}
@@ -1479,6 +1507,7 @@ QDBusConnectionPrivate::findInterface(const QString &service,
QString owner = getNameOwner(service);
if (connection && !owner.isEmpty() && QDBusUtil::isValidObjectPath(path) &&
(interface.isEmpty() || QDBusUtil::isValidInterfaceName(interface)))
+ // always call here with the unique connection name
mo = findMetaObject(owner, path, interface);
QDBusInterfacePrivate *p = new QDBusInterfacePrivate(QDBusConnection(name), this, owner, path, interface, mo);
@@ -1509,24 +1538,52 @@ QDBusConnectionPrivate::findInterface(const QString &service,
return p;
}
+struct qdbus_Introspect
+{
+ QString xml;
+ inline void operator()(QDBusConnectionPrivate::ObjectTreeNode *node)
+ { xml = qDBusIntrospectObject(node); }
+};
+
QDBusMetaObject *
QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &path,
const QString &interface)
{
+ // service must be a unique connection name
if (!interface.isEmpty()) {
QReadLocker locker(&lock);
QDBusMetaObject *mo = cachedMetaObjects.value(interface, 0);
if (mo)
return mo;
}
+ if (service == QString::fromUtf8(dbus_bus_get_unique_name(connection))) {
+ // it's one of our own
+ QWriteLocker locker(&lock);
+ QDBusMetaObject *mo = 0;
+ if (!interface.isEmpty())
+ mo = cachedMetaObjects.value(interface, 0);
+ if (mo)
+ // maybe it got created when we switched from read to write lock
+ return mo;
+
+ qdbus_Introspect apply;
+ if (!applyForObject(&rootNode, path, apply)) {
+ lastError = QDBusError(QDBusError::InvalidArgs,
+ QString(QLatin1String("No object at %1")).arg(path));
+ return 0; // no object at path
+ }
+
+ // release the lock and return
+ return QDBusMetaObject::createMetaObject(interface, apply.xml, cachedMetaObjects, lastError);
+ }
- // introspect the target object:
+ // not local: introspect the target object:
QDBusMessage msg = QDBusMessage::methodCall(service, path,
QLatin1String(DBUS_INTERFACE_INTROSPECTABLE),
QLatin1String("Introspect"));
- // we have to spin the event loop because the call could be targetting ourselves
- QDBusMessage reply = sendWithReply(msg, QDBusConnection::UseEventLoop);
+
+ QDBusMessage reply = sendWithReply(msg, QDBusConnection::NoUseEventLoop);
// it doesn't exist yet, we have to create it
QWriteLocker locker(&lock);