Changeset 561 for trunk/src/dbus/qdbusintegrator.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/dbus/qdbusintegrator.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information ([email protected]) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation ([email protected]) 5 6 ** 6 7 ** This file is part of the QtDBus module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you 37 ** @nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 75 75 if (th && !th->objectName().isEmpty()) 76 76 dbg.nospace() << ", name=" << th->objectName(); 77 dbg.nospace() << ")";77 dbg.nospace() << ; 78 78 return dbg.space(); 79 79 } … … 91 91 else 92 92 dbg.nospace() << conn->thread(); 93 dbg.nospace() << ")";93 dbg.nospace() << ; 94 94 return dbg.space(); 95 95 } … … 391 391 } // extern "C" 392 392 393 static QByteArray buildMatchRule(const QString &service, const QString & /*owner*/,393 static QByteArray buildMatchRule(const QString &service, 394 394 const QString &objectPath, const QString &interface, 395 const QString &member, const QString & /*signature*/)395 const QString &member, const QString & /*signature*/) 396 396 { 397 397 QString result = QLatin1String("type='signal',"); … … 406 406 if (!member.isEmpty()) 407 407 result += keyValue.arg(QLatin1String("member"), member); 408 409 410 411 412 413 414 415 408 416 409 417 result.chop(1); // remove ending comma … … 492 500 // object not found 493 501 return 0; 502 503 504 505 506 494 507 } 495 508 … … 566 579 QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator end = haystack.children.constEnd(); 567 580 for ( ; it != end; ++it) 568 huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1 String("/") + it->name);581 huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1) + it->name); 569 582 570 583 if (needle == haystack.obj) { … … 921 934 rootNode(QString(QLatin1Char('/'))) 922 935 { 923 static const bool threads = qDBusInitThreads(); 924 static const int debugging = ::isDebugging = qgetenv("QDBUS_DEBUG").toInt(); 936 static const bool threads = q_dbus_threads_init_default(); 937 static const int debugging = qgetenv("QDBUS_DEBUG").toInt(); 938 ::isDebugging = debugging; 925 939 Q_UNUSED(threads) 940 926 941 927 942 #ifdef QDBUS_THREAD_DEBUG … … 933 948 934 949 rootNode.flags = 0; 935 936 connect(this, SIGNAL(serviceOwnerChanged(QString,QString,QString)),937 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));938 950 } 939 951 … … 1103 1115 1104 1116 for (int i = 0; i < pendingWatches.size(); ++i) 1105 if (!q_dbus_watch_handle(pendingWatches[i], DBUS_WATCH_ READABLE))1117 if (!q_dbus_watch_handle(pendingWatches[i], DBUS_WATCH_ABLE)) 1106 1118 qDebug("OUT OF MEM"); 1107 1119 } … … 1126 1138 const QVariantList &args) 1127 1139 { 1128 int mciid = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE); 1129 Q_ASSERT(mciid != -1); 1130 1131 QMetaClassInfo mci = mo->classInfo(mciid); 1132 Q_ASSERT(mci.value()); 1133 const char *interface = mci.value(); 1140 QString interface = qDBusInterfaceFromMetaObject(mo); 1134 1141 1135 1142 QMetaMethod mm = mo->method(signalId); … … 1147 1154 1148 1155 QDBusReadLocker locker(RelaySignalAction, this); 1149 QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), QLatin1String(interface),1156 QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), , 1150 1157 QLatin1String(memberName)); 1158 1151 1159 message.setArguments(args); 1152 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message); 1160 QDBusError error; 1161 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error); 1153 1162 if (!msg) { 1154 qWarning("QDBusConnection: Could not emit signal %s.%s", interface, memberName.constData()); 1163 qWarning("QDBusConnection: Could not emit signal %s.%s: %s", qPrintable(interface), memberName.constData(), 1164 qPrintable(error.message())); 1165 lastError = error; 1155 1166 return; 1156 1167 } … … 1166 1177 const QString &oldOwner, const QString &newOwner) 1167 1178 { 1168 if (oldOwner == baseService) 1169 unregisterService(name); 1170 if (newOwner == baseService) 1171 registerService(name); 1172 1179 Q_UNUSED(oldOwner); 1173 1180 QDBusWriteLocker locker(UpdateSignalHookOwnerAction, this); 1174 QMutableHashIterator<QString, SignalHook> it(signalHooks); 1175 it.toFront(); 1176 while (it.hasNext()) 1177 if (it.next().value().service == name) 1178 it.value().owner = newOwner; 1181 WatchedServicesHash::Iterator it = watchedServices.find(name); 1182 if (it == watchedServices.end()) 1183 return; 1184 if (oldOwner != it->owner) 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; 1179 1190 } 1180 1191 … … 1194 1205 1195 1206 bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, 1196 const QString &service, const QString &owner,1207 const QString &service, 1197 1208 const QString &path, const QString &interface, const QString &name, 1209 1198 1210 QObject *receiver, const char *signal, int minMIdx, 1199 1211 bool buildSignature) … … 1212 1224 1213 1225 hook.service = service; 1214 hook.owner = owner; // we don't care if the service has an owner yet1215 1226 hook.path = path; 1216 1227 hook.obj = receiver; 1228 1217 1229 1218 1230 // build the D-Bus signal name and signature … … 1236 1248 } 1237 1249 1238 hook.matchRule = buildMatchRule(service, owner, path, interface, mname, hook.signature);1250 hook.matchRule = buildMatchRule(service, , hook.signature); 1239 1251 return true; // connect to this signal 1240 1252 } … … 1365 1377 if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots)) { 1366 1378 bool interfaceFound = true; 1367 if (!msg.interface().isEmpty()) { 1368 // check if the interface name matches anything in the class hierarchy 1369 const QMetaObject *mo = node.obj->metaObject(); 1370 for ( ; !interfaceFound && mo != &QObject::staticMetaObject; mo = mo->superClass()) 1371 interfaceFound = msg.interface() == qDBusInterfaceFromMetaObject(mo); 1372 } 1379 if (!msg.interface().isEmpty()) 1380 interfaceFound = qDBusInterfaceInObject(node.obj, msg.interface()); 1373 1381 1374 1382 if (interfaceFound) { … … 1483 1491 for ( ; it != end && it.key() == key; ++it) { 1484 1492 const SignalHook &hook = it.value(); 1485 if (!hook.owner.isEmpty() && hook.owner != msg.service()) 1486 continue; 1493 if (!hook.service.isEmpty()) { 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 } 1487 1501 if (!hook.path.isEmpty() && hook.path != msg.path()) 1488 1502 continue; … … 1491 1505 if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty()) 1492 1506 continue; 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1493 1525 1494 1526 activateSignal(hook, msg); … … 1625 1657 baseService = QString::fromUtf8(service); 1626 1658 } else { 1627 qWarning("QDBusConnectionPrivate::SetConnection: Unable to get base service"); 1628 } 1659 qWarning("QDBusConnectionPrivate::setConnection: Unable to get base service"); 1660 } 1661 1662 QString busService = QLatin1String(DBUS_SERVICE_DBUS); 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(), 1667 this, SLOT(registerService(QString))); 1668 connectSignal(busService, QString(), QString(), QLatin1String("NameLost"), QStringList(), QString(), 1669 this, SLOT(unregisterService(QString))); 1670 1629 1671 1630 1672 q_dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0); … … 1708 1750 // through the d_ptr->localReply link 1709 1751 1710 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message); 1752 QDBusError error; 1753 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error); 1711 1754 if (!msg) { 1712 1755 if (message.type() == QDBusMessage::MethodCallMessage) 1713 qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\" ",1756 qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"", 1714 1757 qPrintable(message.service()), qPrintable(message.path()), 1715 qPrintable(message.interface()), qPrintable(message.member())); 1758 qPrintable(message.interface()), qPrintable(message.member()), 1759 qPrintable(error.message())); 1716 1760 else if (message.type() == QDBusMessage::SignalMessage) 1717 qWarning("QDBusConnection: error: could not send signal path \"%s\" interface \"%s\" member \"%s\" ",1761 qWarning("QDBusConnection: error: could not send signal path \"%s\" interface \"%s\" member \"%s\"", 1718 1762 qPrintable(message.path()), qPrintable(message.interface()), 1719 qPrintable(message.member())); 1763 qPrintable(message.member()), 1764 qPrintable(error.message())); 1720 1765 else 1721 qWarning("QDBusConnection: error: could not send %s message to service \"%s\" ",1766 qWarning("QDBusConnection: error: could not send %s message to service \"%s\"", 1722 1767 message.type() == QDBusMessage::ReplyMessage ? "reply" : 1723 1768 message.type() == QDBusMessage::ErrorMessage ? "error" : 1724 "invalid", qPrintable(message.service())); 1769 "invalid", qPrintable(message.service()), 1770 qPrintable(error.message())); 1771 lastError = error; 1725 1772 return 0; 1726 1773 } … … 1749 1796 1750 1797 if (!QCoreApplication::instance() || sendMode == QDBus::Block) { 1751 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message); 1798 QDBusError err; 1799 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &err); 1752 1800 if (!msg) { 1753 qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\" ",1801 qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"", 1754 1802 qPrintable(message.service()), qPrintable(message.path()), 1755 qPrintable(message.interface()), qPrintable(message.member())); 1756 return QDBusMessage(); 1803 qPrintable(message.interface()), qPrintable(message.member()), 1804 qPrintable(err.message())); 1805 lastError = err; 1806 return QDBusMessage::createError(err); 1757 1807 } 1758 1808 … … 1764 1814 1765 1815 if (!!error) { 1766 QDBusError qe = error; 1767 lastError = qe; 1768 return QDBusMessage::createError(qe); 1816 lastError = err = error; 1817 return QDBusMessage::createError(err); 1769 1818 } 1770 1819 … … 1776 1825 } else { // use the event loop 1777 1826 QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout); 1778 if (!pcall) 1779 return QDBusMessage(); 1780 1781 pcall->watcherHelper = new QDBusPendingCallWatcherHelper; 1782 QEventLoop loop; 1783 loop.connect(pcall->watcherHelper, SIGNAL(reply(QDBusMessage)), SLOT(quit())); 1784 loop.connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), SLOT(quit())); 1785 1786 // enter the event loop and wait for a reply 1787 loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents); 1827 Q_ASSERT(pcall); 1828 1829 if (pcall->replyMessage.type() != QDBusMessage::InvalidMessage) { 1830 pcall->watcherHelper = new QDBusPendingCallWatcherHelper; 1831 QEventLoop loop; 1832 loop.connect(pcall->watcherHelper, SIGNAL(reply(QDBusMessage)), SLOT(quit())); 1833 loop.connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), SLOT(quit())); 1834 1835 // enter the event loop and wait for a reply 1836 loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents); 1837 } 1788 1838 1789 1839 QDBusMessage reply = pcall->replyMessage; … … 1841 1891 } 1842 1892 1843 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message);1844 if (!msg) {1845 qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",1846 qPrintable(message.service()), qPrintable(message.path()),1847 qPrintable(message.interface()), qPrintable(message.member()));1848 return 0;1849 }1850 1851 1893 checkThread(); 1852 qDBusDebug() << QThread::currentThread() << "sending message (async):" << message;1853 DBusPendingCall *pending = 0;1854 1894 QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate; 1855 1895 pcall->sentMessage = message; 1856 1896 pcall->ref = 0; 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1857 1912 1858 1913 QDBusDispatchLocker locker(SendWithReplyAsyncAction, this); … … 1868 1923 } else { 1869 1924 // we're probably disconnected at this point 1870 lastError = QDBusError(QDBusError::Disconnected, QLatin1String("Not connected to server"));1925 lastError = QDBusError(QDBusError::Disconnected, QLatin1String("Not connected to server")); 1871 1926 } 1872 1927 } else { 1873 lastError = QDBusError(QDBusError::NoMemory, QLatin1String("Out of memory"));1928 lastError = QDBusError(QDBusError::NoMemory, QLatin1String("Out of memory")); 1874 1929 } 1875 1930 1876 1931 q_dbus_message_unref(msg); 1877 pcall->replyMessage = QDBusMessage::createError( lastError);1932 pcall->replyMessage = QDBusMessage::createError(rror); 1878 1933 return pcall; 1879 1934 } … … 1884 1939 { 1885 1940 QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout); 1886 if (!pcall) 1887 return 0; 1941 Q_ASSERT(pcall); 1888 1942 1889 1943 // has it already finished (dispatched locally)? … … 1926 1980 } 1927 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 1928 2017 void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook &hook) 1929 2018 { 1930 2019 signalHooks.insertMulti(key, hook); 1931 2020 connect(hook.obj, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)), 1932 Qt:: DirectConnection);2021 Qt::); 1933 2022 1934 2023 MatchRefCountHash::iterator it = matchRefCounts.find(hook.matchRule); … … 1953 2042 qPrintable(qerror.name()), qPrintable(qerror.message())); 1954 2043 Q_ASSERT(false); 1955 } 1956 } 2044 } else { 2045 // Successfully connected the signal 2046 // Do we need to watch for this name? 2047 if (shouldWatchService(hook.service)) { 2048 WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; 2049 if (data.refcount) { 2050 // already watching 2051 ++data.refcount; 2052 } else { 2053 // we need to watch for this service changing 2054 QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); 2055 connectSignal(dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), 2056 QLatin1String("NameOwnerChanged"), QStringList() << hook.service, 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 << ")"; 2061 } 2062 } 2063 } 2064 } 2065 } 2066 2067 bool QDBusConnectionPrivate::disconnectSignal(const QString &service, 2068 const QString &path, const QString &interface, const QString &name, 2069 const QStringList &argumentMatch, const QString &signature, 2070 QObject *receiver, const char *slot) 2071 { 2072 // check the slot 2073 QDBusConnectionPrivate::SignalHook hook; 2074 QString key; 2075 QString name2 = name; 2076 if (name2.isNull()) 2077 name2.detach(); 2078 2079 hook.signature = signature; 2080 if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false)) 2081 return false; // don't disconnect 2082 2083 // avoid duplicating: 2084 QDBusConnectionPrivate::SignalHookHash::Iterator it = signalHooks.find(key); 2085 QDBusConnectionPrivate::SignalHookHash::Iterator end = signalHooks.end(); 2086 for ( ; it != end && it.key() == key; ++it) { 2087 const QDBusConnectionPrivate::SignalHook &entry = it.value(); 2088 if (entry.service == hook.service && 2089 entry.path == hook.path && 2090 entry.signature == hook.signature && 2091 entry.obj == hook.obj && 2092 entry.midx == hook.midx) { 2093 // no need to compare the parameters if it's the same slot 2094 disconnectSignal(it); 2095 return true; // it was there 2096 } 2097 } 2098 2099 // the slot was not found 2100 return false; 1957 2101 } 1958 2102 … … 1961 2105 { 1962 2106 const SignalHook &hook = it.value(); 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 1963 2120 1964 2121 bool erase = false; …