1177 void QDBusConnectionPrivate::_q_serviceOwnerChanged(const QString &name, |
1176 void QDBusConnectionPrivate::_q_serviceOwnerChanged(const QString &name, |
1178 const QString &oldOwner, const QString &newOwner) |
1177 const QString &oldOwner, const QString &newOwner) |
1179 { |
1178 { |
1180 Q_UNUSED(oldOwner); |
1179 Q_UNUSED(oldOwner); |
1181 QDBusWriteLocker locker(UpdateSignalHookOwnerAction, this); |
1180 QDBusWriteLocker locker(UpdateSignalHookOwnerAction, this); |
1182 QMutableHashIterator<QString, SignalHook> it(signalHooks); |
1181 WatchedServicesHash::Iterator it = watchedServices.find(name); |
1183 it.toFront(); |
1182 if (it == watchedServices.end()) |
1184 while (it.hasNext()) |
1183 return; |
1185 if (it.next().value().service == name) |
1184 if (oldOwner != it->owner) |
1186 it.value().owner = newOwner; |
1185 qWarning("QDBusConnection: name '%s' had owner '%s' but we thought it was '%s'", |
|
1186 qPrintable(name), qPrintable(oldOwner), qPrintable(it->owner)); |
|
1187 |
|
1188 qDBusDebug() << this << "Updating name" << name << "from" << oldOwner << "to" << newOwner; |
|
1189 it->owner = newOwner; |
1187 } |
1190 } |
1188 |
1191 |
1189 int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedName, |
1192 int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedName, |
1190 QList<int> ¶ms) |
1193 QList<int> ¶ms) |
1191 { |
1194 { |
1486 SignalHookHash::const_iterator end = signalHooks.constEnd(); |
1488 SignalHookHash::const_iterator end = signalHooks.constEnd(); |
1487 //qDebug("looking for: %s", path.toLocal8Bit().constData()); |
1489 //qDebug("looking for: %s", path.toLocal8Bit().constData()); |
1488 //qDBusDebug() << signalHooks.keys(); |
1490 //qDBusDebug() << signalHooks.keys(); |
1489 for ( ; it != end && it.key() == key; ++it) { |
1491 for ( ; it != end && it.key() == key; ++it) { |
1490 const SignalHook &hook = it.value(); |
1492 const SignalHook &hook = it.value(); |
1491 if (!hook.owner.isNull() && hook.owner != msg.service()) |
1493 if (!hook.service.isEmpty()) { |
1492 continue; |
1494 const QString owner = |
|
1495 shouldWatchService(hook.service) ? |
|
1496 watchedServices.value(hook.service).owner : |
|
1497 hook.service; |
|
1498 if (owner != msg.service()) |
|
1499 continue; |
|
1500 } |
1493 if (!hook.path.isEmpty() && hook.path != msg.path()) |
1501 if (!hook.path.isEmpty() && hook.path != msg.path()) |
1494 continue; |
1502 continue; |
1495 if (!hook.signature.isEmpty() && hook.signature != msg.signature()) |
1503 if (!hook.signature.isEmpty() && hook.signature != msg.signature()) |
1496 continue; |
1504 continue; |
1497 if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty()) |
1505 if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty()) |
1650 } else { |
1658 } else { |
1651 qWarning("QDBusConnectionPrivate::setConnection: Unable to get base service"); |
1659 qWarning("QDBusConnectionPrivate::setConnection: Unable to get base service"); |
1652 } |
1660 } |
1653 |
1661 |
1654 QString busService = QLatin1String(DBUS_SERVICE_DBUS); |
1662 QString busService = QLatin1String(DBUS_SERVICE_DBUS); |
1655 connectSignal(busService, QString(), QString(), QString(), QLatin1String("NameAcquired"), QStringList(), QString(), |
1663 WatchedServicesHash::mapped_type &bus = watchedServices[busService]; |
|
1664 bus.refcount = 1; |
|
1665 bus.owner = getNameOwnerNoCache(busService); |
|
1666 connectSignal(busService, QString(), QString(), QLatin1String("NameAcquired"), QStringList(), QString(), |
1656 this, SLOT(registerService(QString))); |
1667 this, SLOT(registerService(QString))); |
1657 connectSignal(busService, QString(), QString(), QString(), QLatin1String("NameLost"), QStringList(), QString(), |
1668 connectSignal(busService, QString(), QString(), QLatin1String("NameLost"), QStringList(), QString(), |
1658 this, SLOT(unregisterService(QString))); |
1669 this, SLOT(unregisterService(QString))); |
1659 |
1670 |
1660 |
1671 |
1661 q_dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0); |
1672 q_dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0); |
1662 |
1673 |
1663 //qDebug("base service: %s", service); |
1674 qDBusDebug() << this << ": connected successfully"; |
1664 |
1675 |
1665 // schedule a dispatch: |
1676 // schedule a dispatch: |
1666 QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection); |
1677 QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection); |
1667 } |
1678 } |
1668 |
1679 |
1806 return QDBusMessage::createError(err); |
1817 return QDBusMessage::createError(err); |
1807 } |
1818 } |
1808 |
1819 |
1809 QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply); |
1820 QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply); |
1810 q_dbus_message_unref(reply); |
1821 q_dbus_message_unref(reply); |
1811 qDBusDebug() << QThread::currentThread() << "got message reply (blocking):" << amsg; |
1822 qDBusDebug() << this << "got message reply (blocking):" << amsg; |
1812 |
1823 |
1813 return amsg; |
1824 return amsg; |
1814 } else { // use the event loop |
1825 } else { // use the event loop |
1815 QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout); |
1826 QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout); |
1816 Q_ASSERT(pcall); |
1827 Q_ASSERT(pcall); |
1817 |
1828 |
1818 if (pcall->replyMessage.type() != QDBusMessage::InvalidMessage) { |
1829 if (pcall->replyMessage.type() == QDBusMessage::InvalidMessage) { |
1819 pcall->watcherHelper = new QDBusPendingCallWatcherHelper; |
1830 pcall->watcherHelper = new QDBusPendingCallWatcherHelper; |
1820 QEventLoop loop; |
1831 QEventLoop loop; |
1821 loop.connect(pcall->watcherHelper, SIGNAL(reply(QDBusMessage)), SLOT(quit())); |
1832 loop.connect(pcall->watcherHelper, SIGNAL(reply(QDBusMessage)), SLOT(quit())); |
1822 loop.connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), SLOT(quit())); |
1833 loop.connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), SLOT(quit())); |
1823 |
1834 |
1979 QString name2 = name; |
1990 QString name2 = name; |
1980 if (name2.isNull()) |
1991 if (name2.isNull()) |
1981 name2.detach(); |
1992 name2.detach(); |
1982 |
1993 |
1983 hook.signature = signature; |
1994 hook.signature = signature; |
1984 if (!prepareHook(hook, key, service, owner, path, interface, name, argumentMatch, receiver, slot, 0, false)) |
1995 if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false)) |
1985 return false; // don't connect |
1996 return false; // don't connect |
1986 |
1997 |
1987 // avoid duplicating: |
1998 // avoid duplicating: |
1988 QDBusConnectionPrivate::SignalHookHash::ConstIterator it = signalHooks.find(key); |
1999 QDBusConnectionPrivate::SignalHookHash::ConstIterator it = signalHooks.find(key); |
1989 QDBusConnectionPrivate::SignalHookHash::ConstIterator end = signalHooks.constEnd(); |
2000 QDBusConnectionPrivate::SignalHookHash::ConstIterator end = signalHooks.constEnd(); |
1990 for ( ; it != end && it.key() == key; ++it) { |
2001 for ( ; it != end && it.key() == key; ++it) { |
1991 const QDBusConnectionPrivate::SignalHook &entry = it.value(); |
2002 const QDBusConnectionPrivate::SignalHook &entry = it.value(); |
1992 if (entry.service == hook.service && |
2003 if (entry.service == hook.service && |
1993 entry.owner == hook.owner && |
|
1994 entry.path == hook.path && |
2004 entry.path == hook.path && |
1995 entry.signature == hook.signature && |
2005 entry.signature == hook.signature && |
1996 entry.obj == hook.obj && |
2006 entry.obj == hook.obj && |
1997 entry.midx == hook.midx) { |
2007 entry.midx == hook.midx) { |
1998 // no need to compare the parameters if it's the same slot |
2008 // no need to compare the parameters if it's the same slot |
2033 Q_ASSERT(false); |
2043 Q_ASSERT(false); |
2034 } else { |
2044 } else { |
2035 // Successfully connected the signal |
2045 // Successfully connected the signal |
2036 // Do we need to watch for this name? |
2046 // Do we need to watch for this name? |
2037 if (shouldWatchService(hook.service)) { |
2047 if (shouldWatchService(hook.service)) { |
2038 WatchedServicesHash::Iterator it = watchedServiceNames.find(hook.service); |
2048 WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; |
2039 if (it != watchedServiceNames.end()) { |
2049 if (data.refcount) { |
2040 // already watching |
2050 // already watching |
2041 ++it.value(); |
2051 ++data.refcount; |
2042 } else { |
2052 } else { |
2043 // we need to watch for this service changing |
2053 // we need to watch for this service changing |
2044 QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); |
2054 QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); |
2045 connectSignal(dbusServerService, dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), |
2055 connectSignal(dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), |
2046 QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), |
2056 QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), |
2047 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); |
2057 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); |
|
2058 data.owner = getNameOwnerNoCache(hook.service); |
|
2059 qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" |
|
2060 << data.owner << ")"; |
2048 } |
2061 } |
2049 } |
2062 } |
2050 } |
2063 } |
2051 } |
2064 } |
2052 } |
2065 } |
2062 QString name2 = name; |
2075 QString name2 = name; |
2063 if (name2.isNull()) |
2076 if (name2.isNull()) |
2064 name2.detach(); |
2077 name2.detach(); |
2065 |
2078 |
2066 hook.signature = signature; |
2079 hook.signature = signature; |
2067 if (!prepareHook(hook, key, service, QString(), path, interface, name, argumentMatch, receiver, slot, 0, false)) |
2080 if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false)) |
2068 return false; // don't disconnect |
2081 return false; // don't disconnect |
2069 |
2082 |
2070 // avoid duplicating: |
2083 // avoid duplicating: |
2071 QDBusConnectionPrivate::SignalHookHash::Iterator it = signalHooks.find(key); |
2084 QDBusConnectionPrivate::SignalHookHash::Iterator it = signalHooks.find(key); |
2072 QDBusConnectionPrivate::SignalHookHash::Iterator end = signalHooks.end(); |
2085 QDBusConnectionPrivate::SignalHookHash::Iterator end = signalHooks.end(); |
2073 for ( ; it != end && it.key() == key; ++it) { |
2086 for ( ; it != end && it.key() == key; ++it) { |
2074 const QDBusConnectionPrivate::SignalHook &entry = it.value(); |
2087 const QDBusConnectionPrivate::SignalHook &entry = it.value(); |
2075 if (entry.service == hook.service && |
2088 if (entry.service == hook.service && |
2076 //entry.owner == hook.owner && |
|
2077 entry.path == hook.path && |
2089 entry.path == hook.path && |
2078 entry.signature == hook.signature && |
2090 entry.signature == hook.signature && |
2079 entry.obj == hook.obj && |
2091 entry.obj == hook.obj && |
2080 entry.midx == hook.midx) { |
2092 entry.midx == hook.midx) { |
2081 // no need to compare the parameters if it's the same slot |
2093 // no need to compare the parameters if it's the same slot |
2091 QDBusConnectionPrivate::SignalHookHash::Iterator |
2103 QDBusConnectionPrivate::SignalHookHash::Iterator |
2092 QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it) |
2104 QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it) |
2093 { |
2105 { |
2094 const SignalHook &hook = it.value(); |
2106 const SignalHook &hook = it.value(); |
2095 |
2107 |
2096 WatchedServicesHash::Iterator sit = watchedServiceNames.find(hook.service); |
2108 WatchedServicesHash::Iterator sit = watchedServices.find(hook.service); |
2097 if (sit != watchedServiceNames.end()) { |
2109 if (sit != watchedServices.end()) { |
2098 if (sit.value() == 1) { |
2110 if (sit.value().refcount == 1) { |
2099 watchedServiceNames.erase(sit); |
2111 watchedServices.erase(sit); |
2100 QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); |
2112 QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); |
2101 disconnectSignal(dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), |
2113 disconnectSignal(dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), |
2102 QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), |
2114 QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), |
2103 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); |
2115 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); |
2104 } else { |
2116 } else { |
2105 --sit.value(); |
2117 --sit.value().refcount; |
2106 } |
2118 } |
2107 } |
2119 } |
2108 |
2120 |
2109 bool erase = false; |
2121 bool erase = false; |
2110 MatchRefCountHash::iterator i = matchRefCounts.find(hook.matchRule); |
2122 MatchRefCountHash::iterator i = matchRefCounts.find(hook.matchRule); |
2152 this, SLOT(relaySignal(QObject*,const QMetaObject*,int,QVariantList)), |
2164 this, SLOT(relaySignal(QObject*,const QMetaObject*,int,QVariantList)), |
2153 Qt::DirectConnection); |
2165 Qt::DirectConnection); |
2154 } |
2166 } |
2155 } |
2167 } |
2156 |
2168 |
2157 void QDBusConnectionPrivate::connectRelay(const QString &service, const QString &owner, |
2169 void QDBusConnectionPrivate::connectRelay(const QString &service, |
2158 const QString &path, const QString &interface, |
2170 const QString &path, const QString &interface, |
2159 QDBusAbstractInterface *receiver, |
2171 QDBusAbstractInterface *receiver, |
2160 const char *signal) |
2172 const char *signal) |
2161 { |
2173 { |
2162 // this function is called by QDBusAbstractInterface when one of its signals is connected |
2174 // this function is called by QDBusAbstractInterface when one of its signals is connected |
2163 // we set up a relay from D-Bus into it |
2175 // we set up a relay from D-Bus into it |
2164 SignalHook hook; |
2176 SignalHook hook; |
2165 QString key; |
2177 QString key; |
2166 |
2178 |
2167 if (!prepareHook(hook, key, service, owner, path, interface, QString(), QStringList(), receiver, signal, |
2179 if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, signal, |
2168 QDBusAbstractInterface::staticMetaObject.methodCount(), true)) |
2180 QDBusAbstractInterface::staticMetaObject.methodCount(), true)) |
2169 return; // don't connect |
2181 return; // don't connect |
2170 |
2182 |
2171 // add it to our list: |
2183 // add it to our list: |
2172 QDBusWriteLocker locker(ConnectRelayAction, this); |
2184 QDBusWriteLocker locker(ConnectRelayAction, this); |
2173 SignalHookHash::ConstIterator it = signalHooks.find(key); |
2185 SignalHookHash::ConstIterator it = signalHooks.find(key); |
2174 SignalHookHash::ConstIterator end = signalHooks.constEnd(); |
2186 SignalHookHash::ConstIterator end = signalHooks.constEnd(); |
2175 for ( ; it != end && it.key() == key; ++it) { |
2187 for ( ; it != end && it.key() == key; ++it) { |
2176 const SignalHook &entry = it.value(); |
2188 const SignalHook &entry = it.value(); |
2177 if (entry.service == hook.service && |
2189 if (entry.service == hook.service && |
2178 entry.owner == hook.owner && |
|
2179 entry.path == hook.path && |
2190 entry.path == hook.path && |
2180 entry.signature == hook.signature && |
2191 entry.signature == hook.signature && |
2181 entry.obj == hook.obj && |
2192 entry.obj == hook.obj && |
2182 entry.midx == hook.midx) |
2193 entry.midx == hook.midx) |
2183 return; // already there, no need to re-add |
2194 return; // already there, no need to re-add |
2184 } |
2195 } |
2185 |
2196 |
2186 connectSignal(key, hook); |
2197 connectSignal(key, hook); |
2187 } |
2198 } |
2188 |
2199 |
2189 void QDBusConnectionPrivate::disconnectRelay(const QString &service, const QString &owner, |
2200 void QDBusConnectionPrivate::disconnectRelay(const QString &service, |
2190 const QString &path, const QString &interface, |
2201 const QString &path, const QString &interface, |
2191 QDBusAbstractInterface *receiver, |
2202 QDBusAbstractInterface *receiver, |
2192 const char *signal) |
2203 const char *signal) |
2193 { |
2204 { |
2194 // this function is called by QDBusAbstractInterface when one of its signals is disconnected |
2205 // this function is called by QDBusAbstractInterface when one of its signals is disconnected |
2195 // we remove relay from D-Bus into it |
2206 // we remove relay from D-Bus into it |
2196 SignalHook hook; |
2207 SignalHook hook; |
2197 QString key; |
2208 QString key; |
2198 |
2209 |
2199 if (!prepareHook(hook, key, service, owner, path, interface, QString(), QStringList(), receiver, signal, |
2210 if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, signal, |
2200 QDBusAbstractInterface::staticMetaObject.methodCount(), true)) |
2211 QDBusAbstractInterface::staticMetaObject.methodCount(), true)) |
2201 return; // don't connect |
2212 return; // don't connect |
2202 |
2213 |
2203 // remove it from our list: |
2214 // remove it from our list: |
2204 QDBusWriteLocker locker(DisconnectRelayAction, this); |
2215 QDBusWriteLocker locker(DisconnectRelayAction, this); |
2205 SignalHookHash::Iterator it = signalHooks.find(key); |
2216 SignalHookHash::Iterator it = signalHooks.find(key); |
2206 SignalHookHash::Iterator end = signalHooks.end(); |
2217 SignalHookHash::Iterator end = signalHooks.end(); |
2207 for ( ; it != end && it.key() == key; ++it) { |
2218 for ( ; it != end && it.key() == key; ++it) { |
2208 const SignalHook &entry = it.value(); |
2219 const SignalHook &entry = it.value(); |
2209 if (entry.service == hook.service && |
2220 if (entry.service == hook.service && |
2210 entry.owner == hook.owner && |
|
2211 entry.path == hook.path && |
2221 entry.path == hook.path && |
2212 entry.signature == hook.signature && |
2222 entry.signature == hook.signature && |
2213 entry.obj == hook.obj && |
2223 entry.obj == hook.obj && |
2214 entry.midx == hook.midx) { |
2224 entry.midx == hook.midx) { |
2215 // found it |
2225 // found it |