Changeset 561 for trunk/src/dbus/qdbusabstractinterface.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/qdbusabstractinterface.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 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 have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 45 45 #include "qdbusargument.h" 46 46 #include "qdbuspendingcall.h" 47 #include "qdbusmessage_p.h" 47 48 #include "qdbusmetaobject_p.h" 48 49 #include "qdbusmetatype_p.h" … … 52 53 53 54 QT_BEGIN_NAMESPACE 55 56 static QDBusError checkIfValid(const QString &service, const QString &path, 57 const QString &interface, bool isDynamic) 58 { 59 // We should be throwing exceptions here... oh well 60 QDBusError error; 61 62 // dynamic interfaces (QDBusInterface) can have empty interfaces, but not service and object paths 63 // non-dynamic is the opposite: service and object paths can be empty, but not the interface 64 if (!isDynamic) { 65 // use assertion here because this should never happen, at all 66 Q_ASSERT_X(!interface.isEmpty(), "QDBusAbstractInterface", "Interface name cannot be empty"); 67 } 68 if (!QDBusUtil::checkBusName(service, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error)) 69 return error; 70 if (!QDBusUtil::checkObjectPath(path, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error)) 71 return error; 72 if (!QDBusUtil::checkInterfaceName(interface, QDBusUtil::EmptyAllowed, &error)) 73 return error; 74 75 // no error 76 return QDBusError(); 77 } 54 78 55 79 QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv, … … 58 82 const QDBusConnection& con, 59 83 bool isDynamic) 60 : connection(con), service(serv), path(p), interface(iface), isValid(true) 61 { 62 if (isDynamic) { 63 // QDBusInterface: service and object path can't be empty, but interface can 64 #if 0 65 Q_ASSERT_X(QDBusUtil::isValidBusName(service), 66 "QDBusInterface::QDBusInterface", "Invalid service name"); 67 Q_ASSERT_X(QDBusUtil::isValidObjectPath(path), 68 "QDBusInterface::QDBusInterface", "Invalid object path given"); 69 Q_ASSERT_X(interface.isEmpty() || QDBusUtil::isValidInterfaceName(interface), 70 "QDBusInterface::QDBusInterface", "Invalid interface name"); 71 #else 72 if (!QDBusUtil::isValidBusName(service)) { 73 lastError = QDBusError(QDBusError::Disconnected, 74 QLatin1String("Invalid service name")); 75 isValid = false; 76 } else if (!QDBusUtil::isValidObjectPath(path)) { 77 lastError = QDBusError(QDBusError::Disconnected, 78 QLatin1String("Invalid object name given")); 79 isValid = false; 80 } else if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface)) { 81 lastError = QDBusError(QDBusError::Disconnected, 82 QLatin1String("Invalid interface name")); 83 isValid = false; 84 } 85 #endif 86 } else { 87 // all others: service and path can be empty here, but interface can't 88 #if 0 89 Q_ASSERT_X(service.isEmpty() || QDBusUtil::isValidBusName(service), 90 "QDBusAbstractInterface::QDBusAbstractInterface", "Invalid service name"); 91 Q_ASSERT_X(path.isEmpty() || QDBusUtil::isValidObjectPath(path), 92 "QDBusAbstractInterface::QDBusAbstractInterface", "Invalid object path given"); 93 Q_ASSERT_X(QDBusUtil::isValidInterfaceName(interface), 94 "QDBusAbstractInterface::QDBusAbstractInterface", "Invalid interface class!"); 95 #else 96 if (!service.isEmpty() && !QDBusUtil::isValidBusName(service)) { 97 lastError = QDBusError(QDBusError::Disconnected, 98 QLatin1String("Invalid service name")); 99 isValid = false; 100 } else if (!path.isEmpty() && !QDBusUtil::isValidObjectPath(path)) { 101 lastError = QDBusError(QDBusError::Disconnected, 102 QLatin1String("Invalid object path given")); 103 isValid = false; 104 } else if (!QDBusUtil::isValidInterfaceName(interface)) { 105 lastError = QDBusError(QDBusError::Disconnected, 106 QLatin1String("Invalid interface class")); 107 isValid = false; 108 } 109 #endif 110 } 111 84 : connection(con), service(serv), path(p), interface(iface), 85 lastError(checkIfValid(serv, p, iface, isDynamic)), 86 isValid(!lastError.isValid()) 87 { 112 88 if (!isValid) 113 89 return; … … 116 92 lastError = QDBusError(QDBusError::Disconnected, 117 93 QLatin1String("Not connected to D-Bus server")); 118 isValid = false;119 94 } else if (!service.isEmpty()) { 120 95 currentOwner = connectionPrivate()->getNameOwner(service); // verify the name owner 121 96 if (currentOwner.isEmpty()) { 122 isValid = false;123 97 lastError = connectionPrivate()->lastError; 124 98 } … … 126 100 } 127 101 128 QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const 129 { 130 if (!connection.isConnected()) // not connected 131 return QVariant(); 102 bool QDBusAbstractInterfacePrivate::canMakeCalls() const 103 { 104 // recheck only if we have a wildcard (i.e. empty) service or path 105 // if any are empty, set the error message according to QDBusUtil 106 if (service.isEmpty()) 107 return QDBusUtil::checkBusName(service, QDBusUtil::EmptyNotAllowed, &lastError); 108 if (path.isEmpty()) 109 return QDBusUtil::checkObjectPath(path, QDBusUtil::EmptyNotAllowed, &lastError); 110 return true; 111 } 112 113 void QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp, QVariant &where) const 114 { 115 if (!isValid || !canMakeCalls()) { // can't make calls 116 where.clear(); 117 return; 118 } 132 119 133 120 // is this metatype registered? 134 int mid; 135 const char *expectedSignature; 136 if (mp.type() == QVariant::LastType) { 137 // We're asking to read a QVariant 138 mid = qMetaTypeId<QDBusVariant>(); 139 expectedSignature = "v"; 140 } else { 141 mid = QMetaType::type(mp.typeName()); 142 expectedSignature = QDBusMetaType::typeToSignature(mid); 121 const char *expectedSignature = ""; 122 if (mp.type() != 0xff) { 123 expectedSignature = QDBusMetaType::typeToSignature(where.userType()); 143 124 if (expectedSignature == 0) { 144 125 qWarning("QDBusAbstractInterface: type %s must be registered with QtDBus before it can be " 145 126 "used to read property %s.%s", 146 127 mp.typeName(), qPrintable(interface), mp.name()); 147 return QVariant(); 128 lastError = QDBusError(QDBusError::Failed, 129 QString::fromLatin1("Unregistered type %1 cannot be handled") 130 .arg(QLatin1String(mp.typeName()))); 131 where.clear(); 132 return; 148 133 } 149 134 } … … 153 138 QLatin1String(DBUS_INTERFACE_PROPERTIES), 154 139 QLatin1String("Get")); 140 QDBusMessagePrivate::setParametersValidated(msg, true); 155 141 msg << interface << QString::fromUtf8(mp.name()); 156 142 QDBusMessage reply = connection.call(msg, QDBus::Block); … … 158 144 if (reply.type() != QDBusMessage::ReplyMessage) { 159 145 lastError = reply; 160 return QVariant(); 146 where.clear(); 147 return; 161 148 } 162 149 if (reply.signature() != QLatin1String("v")) { … … 164 151 DBUS_INTERFACE_PROPERTIES); 165 152 lastError = QDBusError(QDBusError::InvalidSignature, errmsg.arg(reply.signature())); 166 return QVariant(); 153 where.clear(); 154 return; 167 155 } 168 156 … … 171 159 QVariant value = qvariant_cast<QDBusVariant>(reply.arguments().at(0)).variant(); 172 160 173 if (value.userType() == mid) 174 return value; // simple match 161 if (value.userType() == where.userType() || mp.type() == 0xff 162 || (expectedSignature[0] == 'v' && expectedSignature[1] == '\0')) { 163 // simple match 164 where = value; 165 return; 166 } 175 167 176 168 if (value.userType() == qMetaTypeId<QDBusArgument>()) { … … 180 172 foundSignature = arg.currentSignature().toLatin1(); 181 173 if (foundSignature == expectedSignature) { 182 void *null = 0; 183 QVariant result(mid, null); 184 QDBusMetaType::demarshall(arg, mid, result.data()); 185 186 if (mp.type() == QVariant::LastType) 187 // special case: QVariant 188 return qvariant_cast<QDBusVariant>(result).variant(); 189 return result; 174 // signatures match, we can demarshall 175 QDBusMetaType::demarshall(arg, where.userType(), where.data()); 176 return; 190 177 } 191 178 } else { … … 204 191 QString::fromLatin1(mp.typeName()), 205 192 QString::fromLatin1(expectedSignature))); 206 return QVariant(); 207 } 208 209 void QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value) 210 { 211 if (!connection.isConnected()) // not connected 212 return; 193 where.clear(); 194 return; 195 } 196 197 bool QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value) 198 { 199 if (!isValid || !canMakeCalls()) // can't make calls 200 return false; 213 201 214 202 // send the value … … 216 204 QLatin1String(DBUS_INTERFACE_PROPERTIES), 217 205 QLatin1String("Set")); 206 QDBusMessagePrivate::setParametersValidated(msg, true); 218 207 msg << interface << QString::fromUtf8(mp.name()) << qVariantFromValue(QDBusVariant(value)); 219 208 QDBusMessage reply = connection.call(msg, QDBus::Block); 220 209 221 if (reply.type() != QDBusMessage::ReplyMessage) 210 if (reply.type() != QDBusMessage::ReplyMessage) { 222 211 lastError = reply; 212 return false; 213 } 214 return true; 223 215 } 224 216 … … 231 223 if (name == service) { 232 224 currentOwner = newOwner; 233 isValid = !newOwner.isEmpty(); 234 } 235 } 236 225 } 226 } 227 228 QDBusAbstractInterfaceBase::QDBusAbstractInterfaceBase(QDBusAbstractInterfacePrivate &d, QObject *parent) 229 : QObject(d, parent) 230 { 231 } 232 233 int QDBusAbstractInterfaceBase::qt_metacall(QMetaObject::Call _c, int _id, void **_a) 234 { 235 int saved_id = _id; 236 _id = QObject::qt_metacall(_c, _id, _a); 237 if (_id < 0) 238 return _id; 239 240 if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty) { 241 QMetaProperty mp = metaObject()->property(saved_id); 242 int &status = *reinterpret_cast<int *>(_a[2]); 243 QVariant &variant = *reinterpret_cast<QVariant *>(_a[1]); 244 245 if (_c == QMetaObject::WriteProperty) { 246 status = d_func()->setProperty(mp, variant) ? 1 : 0; 247 } else { 248 d_func()->property(mp, variant); 249 status = variant.isValid() ? 1 : 0; 250 } 251 _id = -1; 252 } 253 return _id; 254 } 237 255 238 256 /*! … … 259 277 */ 260 278 QDBusAbstractInterface::QDBusAbstractInterface(QDBusAbstractInterfacePrivate &d, QObject *parent) 261 : Q Object(d, parent)279 : QDBusAbstractInterfaceBase(d, parent) 262 280 { 263 281 // keep track of the service owner 264 if (d_func()->isValid) 265 QObject::connect(d_func()->connectionPrivate(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), 266 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); 282 if (d.isValid && 283 d.connection.isConnected() 284 && !d.service.isEmpty() 285 && !d.service.startsWith(QLatin1Char(':'))) 286 d_func()->connection.connect(QLatin1String(DBUS_SERVICE_DBUS), // service 287 QString(), // path 288 QLatin1String(DBUS_INTERFACE_DBUS), // interface 289 QLatin1String("NameOwnerChanged"), 290 QStringList() << d.service, 291 QString(), // signature 292 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); 267 293 } 268 294 … … 275 301 const char *interface, const QDBusConnection &con, 276 302 QObject *parent) 277 : Q Object(*new QDBusAbstractInterfacePrivate(service, path, QString::fromLatin1(interface),303 : QDBusAbstractInterfaceBase(*new QDBusAbstractInterfacePrivate(service, path, QString::fromLatin1(interface), 278 304 con, false), parent) 279 305 { 280 306 // keep track of the service owner 281 if (d_func()->connection.isConnected()) 282 QObject::connect(d_func()->connectionPrivate(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), 283 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); 307 if (d_func()->isValid && 308 d_func()->connection.isConnected() 309 && !service.isEmpty() 310 && !service.startsWith(QLatin1Char(':'))) 311 d_func()->connection.connect(QLatin1String(DBUS_SERVICE_DBUS), // service 312 QString(), // path 313 QLatin1String(DBUS_INTERFACE_DBUS), // interface 314 QLatin1String("NameOwnerChanged"), 315 QStringList() << service, 316 QString(), //signature 317 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); 284 318 } 285 319 … … 301 335 bool QDBusAbstractInterface::isValid() const 302 336 { 303 return d_func()->isValid;337 return !d_func()->currentOwner.isEmpty(); 304 338 } 305 339 … … 367 401 { 368 402 Q_D(QDBusAbstractInterface); 403 404 if (!d->isValid || !d->canMakeCalls()) 405 return QDBusMessage::createError(d->lastError); 369 406 370 407 QString m = method; … … 398 435 // qDebug() << "QDBusAbstractInterface" << "Service" << service() << "Path:" << path(); 399 436 QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), m); 437 QDBusMessagePrivate::setParametersValidated(msg, true); 400 438 msg.setArguments(args); 401 439 … … 426 464 Q_D(QDBusAbstractInterface); 427 465 466 if (!d->isValid || !d->canMakeCalls()) 467 return QDBusPendingCall::fromError(d->lastError); 468 428 469 QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), method); 470 QDBusMessagePrivate::setParametersValidated(msg, true); 429 471 msg.setArguments(args); 430 472 return d->connection.asyncCall(msg); … … 441 483 This function returns true if the queueing succeeds. It does 442 484 not indicate that the executed call succeeded. If it fails, 443 the \a errorMethod is called. 485 the \a errorMethod is called. If the queueing failed, this 486 function returns false and no slot will be called. 444 487 445 488 The \a returnMethod must have as its parameters the types returned … … 454 497 const QList<QVariant> &args, 455 498 QObject *receiver, 456 499 const char *returnMethod, 457 500 const char *errorMethod) 458 501 { 459 502 Q_D(QDBusAbstractInterface); 460 503 504 if (!d->isValid || !d->canMakeCalls()) 505 return false; 506 461 507 QDBusMessage msg = QDBusMessage::createMethodCall(service(), 462 path(), 463 interface(), 464 method); 508 path(), 509 interface(), 510 method); 511 QDBusMessagePrivate::setParametersValidated(msg, true); 465 512 msg.setArguments(args); 466 513 467 514 d->lastError = 0; 468 515 return d->connection.callWithCallback(msg, 469 470 471 516 receiver, 517 returnMethod, 518 errorMethod); 472 519 } 473 520 … … 493 540 const QList<QVariant> &args, 494 541 QObject *receiver, 495 542 const char *slot) 496 543 { 497 544 return callWithCallback(method, args, receiver, slot, 0); … … 504 551 void QDBusAbstractInterface::connectNotify(const char *signal) 505 552 { 553 // someone connecting to one of our signals 554 Q_D(QDBusAbstractInterface); 555 if (!d->isValid) 556 return; 557 506 558 // we end up recursing here, so optimise away 507 559 if (qstrcmp(signal + 1, "destroyed(QObject*)") == 0) 508 560 return; 509 561 510 // someone connecting to one of our signals 562 QDBusConnectionPrivate *conn = d->connectionPrivate(); 563 if (conn) { 564 conn->connectRelay(d->service, d->path, d->interface, 565 this, signal); 566 } 567 } 568 569 /*! 570 \internal 571 Catch signal disconnections. 572 */ 573 void QDBusAbstractInterface::disconnectNotify(const char *signal) 574 { 575 // someone disconnecting from one of our signals 511 576 Q_D(QDBusAbstractInterface); 577 if (!d->isValid) 578 return; 512 579 513 580 QDBusConnectionPrivate *conn = d->connectionPrivate(); 514 581 if (conn) 515 conn->connectRelay(d->service, d->currentOwner, d->path, d->interface, 516 this, signal); 517 } 518 519 /*! 520 \internal 521 Catch signal disconnections. 522 */ 523 void QDBusAbstractInterface::disconnectNotify(const char *signal) 524 { 525 // someone disconnecting from one of our signals 526 Q_D(QDBusAbstractInterface); 527 528 QDBusConnectionPrivate *conn = d->connectionPrivate(); 529 if (conn) 530 conn->disconnectRelay(d->service, d->currentOwner, d->path, d->interface, 582 conn->disconnectRelay(d->service, d->path, d->interface, 531 583 this, signal); 532 584 } … … 541 593 // we're only called from generated code anyways 542 594 543 int idx = metaObject()->indexOfProperty(propname); 544 if (idx != -1) 545 return d_func()->property(metaObject()->property(idx)); 546 qWarning("QDBusAbstractInterface::internalPropGet called with unknown property '%s'", propname); 547 return QVariant(); // error 595 return property(propname); 548 596 } 549 597 … … 554 602 void QDBusAbstractInterface::internalPropSet(const char *propname, const QVariant &value) 555 603 { 556 Q_D(QDBusAbstractInterface); 557 558 // assume this property exists and is writeable 559 // we're only called from generated code anyways 560 561 int idx = metaObject()->indexOfProperty(propname); 562 if (idx != -1) 563 d->setProperty(metaObject()->property(idx), value); 564 else 565 qWarning("QDBusAbstractInterface::internalPropGet called with unknown property '%s'", propname); 604 setProperty(propname, value); 566 605 } 567 606
Note:
See TracChangeset
for help on using the changeset viewer.