diff options
Diffstat (limited to 'src/dbus/qdbusmessage.cpp')
-rw-r--r-- | src/dbus/qdbusmessage.cpp | 126 |
1 files changed, 67 insertions, 59 deletions
diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp index fb3f8600e1..6ef762f225 100644 --- a/src/dbus/qdbusmessage.cpp +++ b/src/dbus/qdbusmessage.cpp @@ -36,22 +36,37 @@ static inline const char *data(const QByteArray &arr) } QDBusMessagePrivate::QDBusMessagePrivate() - : msg(nullptr), reply(nullptr), localReply(nullptr), ref(1), type(QDBusMessage::InvalidMessage), - delayedReply(false), localMessage(false), - parametersValidated(false), autoStartService(true), - interactiveAuthorizationAllowed(false) + : localReply(nullptr), ref(1), type(QDBusMessage::InvalidMessage), + delayedReply(false), parametersValidated(false), + localMessage(false), autoStartService(true), + interactiveAuthorizationAllowed(false), isReplyRequired(false) { } QDBusMessagePrivate::~QDBusMessagePrivate() { - if (msg) - q_dbus_message_unref(msg); - if (reply) - q_dbus_message_unref(reply); delete localReply; } +void QDBusMessagePrivate::createResponseLink(const QDBusMessagePrivate *call) +{ + if (Q_UNLIKELY(call->type != QDBusMessage::MethodCallMessage)) { + qWarning("QDBusMessage: replying to a message that isn't a method call"); + return; + } + + if (call->localMessage) { + localMessage = true; + call->localReply = new QDBusMessage(*this); // keep an internal copy + } else { + serial = call->serial; + service = call->service; + } + + // the reply must have a serial or be a local-loop optimization + Q_ASSERT(serial || localMessage); +} + /*! \since 4.3 Returns the human-readable message associated with the error that was received. @@ -113,8 +128,8 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB case QDBusMessage::ReplyMessage: msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); if (!d_ptr->localMessage) { - q_dbus_message_set_destination(msg, q_dbus_message_get_sender(d_ptr->reply)); - q_dbus_message_set_reply_serial(msg, q_dbus_message_get_serial(d_ptr->reply)); + q_dbus_message_set_destination(msg, data(d_ptr->service.toUtf8())); + q_dbus_message_set_reply_serial(msg, d_ptr->serial); } break; case QDBusMessage::ErrorMessage: @@ -126,8 +141,8 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_ERROR); q_dbus_message_set_error_name(msg, d_ptr->name.toUtf8()); if (!d_ptr->localMessage) { - q_dbus_message_set_destination(msg, q_dbus_message_get_sender(d_ptr->reply)); - q_dbus_message_set_reply_serial(msg, q_dbus_message_get_serial(d_ptr->reply)); + q_dbus_message_set_destination(msg, data(d_ptr->service.toUtf8())); + q_dbus_message_set_reply_serial(msg, d_ptr->serial); } break; case QDBusMessage::SignalMessage: @@ -155,14 +170,12 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB d_ptr->parametersValidated = true; QDBusMarshaller marshaller(capabilities); - QVariantList::ConstIterator it = d_ptr->arguments.constBegin(); - QVariantList::ConstIterator cend = d_ptr->arguments.constEnd(); q_dbus_message_iter_init_append(msg, &marshaller.iterator); if (!d_ptr->message.isEmpty()) // prepend the error message marshaller.append(d_ptr->message); - for ( ; it != cend; ++it) - marshaller.appendVariantInternal(*it); + for (const QVariant &argument : std::as_const(d_ptr->arguments)) + marshaller.appendVariantInternal(argument); // check if everything is ok if (marshaller.ok) @@ -206,6 +219,7 @@ QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnec return message; message.d_ptr->type = QDBusMessage::MessageType(q_dbus_message_get_type(dmsg)); + message.d_ptr->serial = q_dbus_message_get_serial(dmsg); message.d_ptr->path = QString::fromUtf8(q_dbus_message_get_path(dmsg)); message.d_ptr->interface = QString::fromUtf8(q_dbus_message_get_interface(dmsg)); message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ? @@ -214,7 +228,7 @@ QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnec message.d_ptr->service = QString::fromUtf8(q_dbus_message_get_sender(dmsg)); message.d_ptr->signature = QString::fromUtf8(q_dbus_message_get_signature(dmsg)); message.d_ptr->interactiveAuthorizationAllowed = q_dbus_message_get_allow_interactive_authorization(dmsg); - message.d_ptr->msg = q_dbus_message_ref(dmsg); + message.d_ptr->isReplyRequired = !q_dbus_message_get_no_reply(dmsg); QDBusDemarshaller demarshaller(capabilities); demarshaller.message = q_dbus_message_ref(dmsg); @@ -239,10 +253,8 @@ QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn, // determine if we are carrying any complex types QString computedSignature; - QVariantList::ConstIterator it = asSent.d_ptr->arguments.constBegin(); - QVariantList::ConstIterator end = asSent.d_ptr->arguments.constEnd(); - for ( ; it != end; ++it) { - QMetaType id = it->metaType(); + for (const QVariant &argument : std::as_const(asSent.d_ptr->arguments)) { + QMetaType id = argument.metaType(); const char *signature = QDBusMetaType::typeToSignature(id); if ((id.id() != QMetaType::QStringList && id.id() != QMetaType::QByteArray && qstrlen(signature) != 1) || id == QMetaType::fromType<QDBusVariant>()) { @@ -406,6 +418,7 @@ QDBusMessage QDBusMessage::createMethodCall(const QString &service, const QStrin message.d_ptr->path = path; message.d_ptr->interface = interface; message.d_ptr->name = method; + message.d_ptr->isReplyRequired = true; return message; } @@ -448,15 +461,7 @@ QDBusMessage QDBusMessage::createReply(const QVariantList &arguments) const QDBusMessage reply; reply.setArguments(arguments); reply.d_ptr->type = ReplyMessage; - if (d_ptr->msg) - reply.d_ptr->reply = q_dbus_message_ref(d_ptr->msg); - if (d_ptr->localMessage) { - reply.d_ptr->localMessage = true; - d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy - } - - // the reply must have a msg or be a local-loop optimization - Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage); + reply.d_ptr->createResponseLink(d_ptr); return reply; } @@ -467,15 +472,7 @@ QDBusMessage QDBusMessage::createReply(const QVariantList &arguments) const QDBusMessage QDBusMessage::createErrorReply(const QString &name, const QString &msg) const { QDBusMessage reply = QDBusMessage::createError(name, msg); - if (d_ptr->msg) - reply.d_ptr->reply = q_dbus_message_ref(d_ptr->msg); - if (d_ptr->localMessage) { - reply.d_ptr->localMessage = true; - d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy - } - - // the reply must have a msg or be a local-loop optimization - Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage); + reply.d_ptr->createResponseLink(d_ptr); return reply; } @@ -559,6 +556,8 @@ QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other) */ QString QDBusMessage::service() const { + if (d_ptr->type == ErrorMessage || d_ptr->type == ReplyMessage) + return QString(); // d_ptr->service holds the destination return d_ptr->service; } @@ -621,9 +620,9 @@ bool QDBusMessage::isReplyRequired() const if (d_ptr->type != QDBusMessage::MethodCallMessage) return false; - if (!d_ptr->msg) - return d_ptr->localMessage; // if it's a local message, reply is required - return !q_dbus_message_get_no_reply(d_ptr->msg); + if (d_ptr->localMessage) // if it's a local message, reply is required + return true; + return d_ptr->isReplyRequired; } /*! @@ -695,20 +694,26 @@ bool QDBusMessage::autoStartService() const } /*! - Sets the interactive authorization flag to \a enable. - This flag only makes sense for method call messages, where it - tells the D-Bus server that the caller of the method is prepared - to wait for interactive authorization to take place (for instance - via Polkit) before the actual method is processed. + Enables or disables the \c ALLOW_INTERACTIVE_AUTHORIZATION flag + in a message. + + This flag only makes sense for method call messages + (\l QDBusMessage::MethodCallMessage). If \a enable + is set to \c true, the flag indicates to the callee that the + caller of the method is prepared to wait for interactive authorization + to take place (for instance via Polkit) before the actual method + is processed. - By default this flag is false and the other end is expected to - make any authorization decisions non-interactively and promptly. + If \a enable is set to \c false, the flag is not + set, meaning that the other end is expected to make any authorization + decisions non-interactively and promptly. This is the default. The \c org.freedesktop.DBus.Error.InteractiveAuthorizationRequired error indicates that authorization failed, but could have succeeded if this flag had been set. - \sa isInteractiveAuthorizationAllowed() + \sa isInteractiveAuthorizationAllowed(), + QDBusAbstractInterface::setInteractiveAuthorizationAllowed() \since 5.12 */ @@ -718,12 +723,11 @@ void QDBusMessage::setInteractiveAuthorizationAllowed(bool enable) } /*! - Returns the interactive authorization allowed flag, as set by - setInteractiveAuthorizationAllowed(). By default this flag - is false and the other end is expected to make any authorization - decisions non-interactively and promptly. + Returns whether the message has the + \c ALLOW_INTERACTIVE_AUTHORIZATION flag set. - \sa setInteractiveAuthorizationAllowed() + \sa setInteractiveAuthorizationAllowed(), + QDBusAbstractInterface::isInteractiveAuthorizationAllowed() \since 5.12 */ @@ -763,6 +767,12 @@ QDBusMessage &QDBusMessage::operator<<(const QVariant &arg) return *this; } +QDBusMessage::QDBusMessage(QDBusMessagePrivate &dd) + : d_ptr(&dd) +{ + d_ptr->ref.ref(); +} + /*! Returns the message type. */ @@ -804,12 +814,10 @@ static QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t) static void debugVariantList(QDebug dbg, const QVariantList &list) { bool first = true; - QVariantList::ConstIterator it = list.constBegin(); - QVariantList::ConstIterator end = list.constEnd(); - for ( ; it != end; ++it) { + for (const QVariant &elem : list) { if (!first) dbg.nospace() << ", "; - dbg.nospace() << qPrintable(QDBusUtil::argumentToString(*it)); + dbg.nospace() << qPrintable(QDBusUtil::argumentToString(elem)); first = false; } } |