summaryrefslogtreecommitdiff
path: root/qt/qdbusintegrator.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@trolltech.com>2006-04-29 12:44:31 +0000
committerJohn Palmieri <johnp@remedyz.boston.redhat.com>2006-06-28 08:15:15 -0400
commita92ae08214f2859f3cd3324e116cc6f89b2b681d (patch)
tree9d44d7917ee4943968eb46c5d9815b54a8d539a9 /qt/qdbusintegrator.cpp
parentb841326b891c15a34bd3d72fd17e001fc1ebd77d (diff)
* qt/qdbusinterface.h: Rename QDBusRef to QDBusInterfacePtr and disable the copy operators. (r533772, r534746)
* qt/qdbuserror.h: Remove the automatic cast to bool. (r533929) * qt/qdbusabstractinterface.cpp: * qt/qdbusabstractinterface.h: Change the default call mode to not use the event loop. Add convenience call() methods that take a CallMode parameter. (r534042) * qt/qdbusconnection.h: Change the default call mode to not use the event loop. (r534042) * qt/qdbusinterface.cpp: * qt/qdbusinterface.h: Add a method to tell us if the interface is valid (since we don't return a null pointer anymore) (r534099) * qt/qdbusinterface_p.h: Don't crash if metaObject is 0 (r534101) * qt/qdbusinternalfilters.cpp: Decouple the introspection function in two so taht we get the chance to introspect without having a QDBusMessage (r534102) * qt/qdbusbus.h: * qt/qdbusconnection.cpp: * qt/qdbusconnection_p.h: * qt/qdbusintegrator.cpp: Keep a list of our own names to avoid a round-trip to the server when attempting to introspect one of our own objects. Also make sure the filter functions match the empty interface as well. (r534108) Don't keep the connection names. Instead, trust the unique connection name (r534111) Remove event loop usage (r534112)
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 bef8268..3f90725 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);