d743df975d
This flag was introduced to serve as a replacement for a dedicated "interactive" boolean argument in method calls guarded by Polkit. Change-Id: Ida91c9872e70f8ca6672563d0ca6642f38c498ab Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
883 lines
29 KiB
C++
883 lines
29 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
** Copyright (C) 2016 Intel Corporation.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtDBus module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 3 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 3 requirements
|
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 2.0 or (at your option) the GNU General
|
|
** Public license version 3 or any later version approved by the KDE Free
|
|
** Qt Foundation. The licenses are as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "qdbusmessage.h"
|
|
#include "qdbusmessage_p.h"
|
|
|
|
#include <qdebug.h>
|
|
#include <qstringlist.h>
|
|
|
|
#include "qdbus_symbols_p.h"
|
|
|
|
#include "qdbusargument_p.h"
|
|
#include "qdbuserror.h"
|
|
#include "qdbusmetatype.h"
|
|
#include "qdbusconnection_p.h"
|
|
#include "qdbusutil_p.h"
|
|
|
|
#ifndef QT_NO_DBUS
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
Q_STATIC_ASSERT(QDBusMessage::InvalidMessage == DBUS_MESSAGE_TYPE_INVALID);
|
|
Q_STATIC_ASSERT(QDBusMessage::MethodCallMessage == DBUS_MESSAGE_TYPE_METHOD_CALL);
|
|
Q_STATIC_ASSERT(QDBusMessage::ReplyMessage == DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
|
Q_STATIC_ASSERT(QDBusMessage::ErrorMessage == DBUS_MESSAGE_TYPE_ERROR);
|
|
Q_STATIC_ASSERT(QDBusMessage::SignalMessage == DBUS_MESSAGE_TYPE_SIGNAL);
|
|
|
|
static inline const char *data(const QByteArray &arr)
|
|
{
|
|
return arr.isEmpty() ? 0 : arr.constData();
|
|
}
|
|
|
|
QDBusMessagePrivate::QDBusMessagePrivate()
|
|
: msg(0), reply(0), localReply(0), ref(1), type(QDBusMessage::InvalidMessage),
|
|
delayedReply(false), localMessage(false),
|
|
parametersValidated(false), autoStartService(true),
|
|
interactiveAuthorizationAllowed(false)
|
|
{
|
|
}
|
|
|
|
QDBusMessagePrivate::~QDBusMessagePrivate()
|
|
{
|
|
if (msg)
|
|
q_dbus_message_unref(msg);
|
|
if (reply)
|
|
q_dbus_message_unref(reply);
|
|
delete localReply;
|
|
}
|
|
|
|
/*!
|
|
\since 4.3
|
|
Returns the human-readable message associated with the error that was received.
|
|
*/
|
|
QString QDBusMessage::errorMessage() const
|
|
{
|
|
if (d_ptr->type == ErrorMessage) {
|
|
if (!d_ptr->message.isEmpty())
|
|
return d_ptr->message;
|
|
if (!d_ptr->arguments.isEmpty())
|
|
return d_ptr->arguments.at(0).toString();
|
|
}
|
|
return QString();
|
|
}
|
|
|
|
/*!
|
|
\internal
|
|
Constructs a DBusMessage object from \a message. The returned value must be de-referenced
|
|
with q_dbus_message_unref. The \a capabilities flags indicates which capabilities to use.
|
|
|
|
The \a error object is set to indicate the error if anything went wrong with the
|
|
marshalling. Usually, this error message will be placed in the reply, as if the call failed.
|
|
The \a error pointer must not be null.
|
|
*/
|
|
DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDBusConnection::ConnectionCapabilities capabilities,
|
|
QDBusError *error)
|
|
{
|
|
if (!qdbus_loadLibDBus()) {
|
|
*error = QDBusError(QDBusError::Failed, QLatin1String("Could not open lidbus-1 library"));
|
|
return 0;
|
|
}
|
|
|
|
DBusMessage *msg = 0;
|
|
const QDBusMessagePrivate *d_ptr = message.d_ptr;
|
|
|
|
switch (d_ptr->type) {
|
|
case QDBusMessage::InvalidMessage:
|
|
//qDebug() << "QDBusMessagePrivate::toDBusMessage" << "message is invalid";
|
|
break;
|
|
case QDBusMessage::MethodCallMessage:
|
|
// only service and interface can be empty -> path and name must not be empty
|
|
if (!d_ptr->parametersValidated) {
|
|
if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error))
|
|
return 0;
|
|
if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
|
|
return 0;
|
|
if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
|
|
return 0;
|
|
if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method"))
|
|
return 0;
|
|
}
|
|
|
|
msg = q_dbus_message_new_method_call(data(d_ptr->service.toUtf8()), d_ptr->path.toUtf8(),
|
|
data(d_ptr->interface.toUtf8()), d_ptr->name.toUtf8());
|
|
q_dbus_message_set_auto_start( msg, d_ptr->autoStartService );
|
|
q_dbus_message_set_allow_interactive_authorization(msg, d_ptr->interactiveAuthorizationAllowed);
|
|
|
|
break;
|
|
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));
|
|
}
|
|
break;
|
|
case QDBusMessage::ErrorMessage:
|
|
// error name can't be empty
|
|
if (!d_ptr->parametersValidated
|
|
&& !QDBusUtil::checkErrorName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error))
|
|
return 0;
|
|
|
|
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));
|
|
}
|
|
break;
|
|
case QDBusMessage::SignalMessage:
|
|
// only the service name can be empty here
|
|
if (!d_ptr->parametersValidated) {
|
|
if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error))
|
|
return 0;
|
|
if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
|
|
return 0;
|
|
if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
|
|
return 0;
|
|
if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method"))
|
|
return 0;
|
|
}
|
|
|
|
msg = q_dbus_message_new_signal(d_ptr->path.toUtf8(), d_ptr->interface.toUtf8(),
|
|
d_ptr->name.toUtf8());
|
|
q_dbus_message_set_destination(msg, data(d_ptr->service.toUtf8()));
|
|
break;
|
|
}
|
|
|
|
// if we got here, the parameters validated
|
|
// and since the message parameters cannot be changed once the message is created
|
|
// we can record this fact
|
|
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);
|
|
|
|
// check if everything is ok
|
|
if (marshaller.ok)
|
|
return msg;
|
|
|
|
// not ok;
|
|
q_dbus_message_unref(msg);
|
|
*error = QDBusError(QDBusError::Failed, QLatin1String("Marshalling failed: ") + marshaller.errorString);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
struct DBusMessage
|
|
{
|
|
DBusAtomic refcount;
|
|
DBusHeader header;
|
|
DBusString body;
|
|
char byte_order;
|
|
unsigned int locked : 1;
|
|
DBUS_DISABLE_CHECKS
|
|
unsigned int in_cache : 1;
|
|
#endif
|
|
DBusList *size_counters;
|
|
long size_counter_delta;
|
|
dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS;
|
|
DBusDataSlotList slot_list;
|
|
#ifndef DBUS_DISABLE_CHECKS
|
|
int generation;
|
|
#endif
|
|
};
|
|
*/
|
|
|
|
/*!
|
|
\internal
|
|
Constructs a QDBusMessage by parsing the given DBusMessage object.
|
|
*/
|
|
QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnection::ConnectionCapabilities capabilities)
|
|
{
|
|
QDBusMessage message;
|
|
if (!dmsg)
|
|
return message;
|
|
|
|
message.d_ptr->type = QDBusMessage::MessageType(q_dbus_message_get_type(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 ?
|
|
QString::fromUtf8(q_dbus_message_get_error_name(dmsg)) :
|
|
QString::fromUtf8(q_dbus_message_get_member(dmsg));
|
|
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);
|
|
|
|
QDBusDemarshaller demarshaller(capabilities);
|
|
demarshaller.message = q_dbus_message_ref(dmsg);
|
|
if (q_dbus_message_iter_init(demarshaller.message, &demarshaller.iterator))
|
|
while (!demarshaller.atEnd())
|
|
message << demarshaller.toVariantInternal();
|
|
return message;
|
|
}
|
|
|
|
bool QDBusMessagePrivate::isLocal(const QDBusMessage &message)
|
|
{
|
|
return message.d_ptr->localMessage;
|
|
}
|
|
|
|
QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn,
|
|
const QDBusMessage &asSent)
|
|
{
|
|
// simulate the message being sent to the bus and then received back
|
|
// the only field that the bus sets when delivering the message
|
|
// (as opposed to the message as we send it), is the sender
|
|
// so we simply set the sender to our unique name
|
|
|
|
// 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) {
|
|
int id = it->userType();
|
|
const char *signature = QDBusMetaType::typeToSignature(id);
|
|
if ((id != QVariant::StringList && id != QVariant::ByteArray &&
|
|
qstrlen(signature) != 1) || id == qMetaTypeId<QDBusVariant>()) {
|
|
// yes, we are
|
|
// we must marshall and demarshall again so as to create QDBusArgument
|
|
// entries for the complex types
|
|
QDBusError error;
|
|
DBusMessage *message = toDBusMessage(asSent, conn.capabilities, &error);
|
|
if (!message) {
|
|
// failed to marshall, so it's a call error
|
|
return QDBusMessage::createError(error);
|
|
}
|
|
|
|
q_dbus_message_set_sender(message, conn.baseService.toUtf8());
|
|
|
|
QDBusMessage retval = fromDBusMessage(message, conn.capabilities);
|
|
retval.d_ptr->localMessage = true;
|
|
q_dbus_message_unref(message);
|
|
if (retval.d_ptr->service.isEmpty())
|
|
retval.d_ptr->service = conn.baseService;
|
|
return retval;
|
|
} else {
|
|
computedSignature += QLatin1String(signature);
|
|
}
|
|
}
|
|
|
|
// no complex types seen
|
|
// optimize by using the variant list itself
|
|
QDBusMessage retval;
|
|
QDBusMessagePrivate *d = retval.d_ptr;
|
|
d->arguments = asSent.d_ptr->arguments;
|
|
d->path = asSent.d_ptr->path;
|
|
d->interface = asSent.d_ptr->interface;
|
|
d->name = asSent.d_ptr->name;
|
|
d->message = asSent.d_ptr->message;
|
|
d->type = asSent.d_ptr->type;
|
|
|
|
d->service = conn.baseService;
|
|
d->signature = computedSignature;
|
|
d->localMessage = true;
|
|
return retval;
|
|
}
|
|
|
|
QDBusMessage QDBusMessagePrivate::makeLocalReply(const QDBusConnectionPrivate &conn,
|
|
const QDBusMessage &callMsg)
|
|
{
|
|
// simulate the reply (return or error) message being sent to the bus and
|
|
// then received back.
|
|
if (callMsg.d_ptr->localReply)
|
|
return makeLocal(conn, *callMsg.d_ptr->localReply);
|
|
return QDBusMessage(); // failed
|
|
}
|
|
|
|
/*!
|
|
\class QDBusMessage
|
|
\inmodule QtDBus
|
|
\since 4.2
|
|
|
|
\brief The QDBusMessage class represents one message sent or
|
|
received over the D-Bus bus.
|
|
|
|
This object can represent any of the four different types of
|
|
messages (MessageType) that can occur on the bus:
|
|
|
|
\list
|
|
\li Method calls
|
|
\li Method return values
|
|
\li Signal emissions
|
|
\li Error codes
|
|
\endlist
|
|
|
|
Objects of this type are created with the static createError(),
|
|
createMethodCall() and createSignal() functions. Use the
|
|
QDBusConnection::send() function to send the messages.
|
|
*/
|
|
|
|
/*!
|
|
\enum QDBusMessage::MessageType
|
|
The possible message types:
|
|
|
|
\value MethodCallMessage a message representing an outgoing or incoming method call
|
|
\value SignalMessage a message representing an outgoing or incoming signal emission
|
|
\value ReplyMessage a message representing the return values of a method call
|
|
\value ErrorMessage a message representing an error condition in response to a method call
|
|
\value InvalidMessage an invalid message: this is never set on messages received from D-Bus
|
|
*/
|
|
|
|
/*!
|
|
Constructs a new DBus message with the given \a path, \a interface
|
|
and \a name, representing a signal emission.
|
|
|
|
A DBus signal is emitted from one application and is received by
|
|
all applications that are listening for that signal from that
|
|
interface.
|
|
|
|
The QDBusMessage object that is returned can be sent using the
|
|
QDBusConnection::send() function.
|
|
*/
|
|
QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &interface,
|
|
const QString &name)
|
|
{
|
|
QDBusMessage message;
|
|
message.d_ptr->type = SignalMessage;
|
|
message.d_ptr->path = path;
|
|
message.d_ptr->interface = interface;
|
|
message.d_ptr->name = name;
|
|
|
|
return message;
|
|
}
|
|
|
|
/*!
|
|
\since 5.6
|
|
|
|
Constructs a new DBus message with the given \a path, \a interface
|
|
and \a name, representing a signal emission to a specific destination.
|
|
|
|
A DBus signal is emitted from one application and is received only by
|
|
the application owning the destination \a service name.
|
|
|
|
The QDBusMessage object that is returned can be sent using the
|
|
QDBusConnection::send() function.
|
|
*/
|
|
QDBusMessage QDBusMessage::createTargetedSignal(const QString &service, const QString &path,
|
|
const QString &interface, const QString &name)
|
|
{
|
|
QDBusMessage message;
|
|
message.d_ptr->type = SignalMessage;
|
|
message.d_ptr->service = service;
|
|
message.d_ptr->path = path;
|
|
message.d_ptr->interface = interface;
|
|
message.d_ptr->name = name;
|
|
|
|
return message;
|
|
}
|
|
|
|
/*!
|
|
Constructs a new DBus message representing a method call.
|
|
A method call always informs its destination address
|
|
(\a service, \a path, \a interface and \a method).
|
|
|
|
The DBus bus allows calling a method on a given remote object without specifying the
|
|
destination interface, if the method name is unique. However, if two interfaces on the
|
|
remote object export the same method name, the result is undefined (one of the two may be
|
|
called or an error may be returned).
|
|
|
|
When using DBus in a peer-to-peer context (i.e., not on a bus), the \a service parameter is
|
|
optional.
|
|
|
|
The QDBusInterface class provides a simpler abstraction to synchronous
|
|
method calling.
|
|
|
|
This function returns a QDBusMessage object that can be sent with
|
|
QDBusConnection::call().
|
|
*/
|
|
QDBusMessage QDBusMessage::createMethodCall(const QString &service, const QString &path,
|
|
const QString &interface, const QString &method)
|
|
{
|
|
QDBusMessage message;
|
|
message.d_ptr->type = MethodCallMessage;
|
|
message.d_ptr->service = service;
|
|
message.d_ptr->path = path;
|
|
message.d_ptr->interface = interface;
|
|
message.d_ptr->name = method;
|
|
|
|
return message;
|
|
}
|
|
|
|
/*!
|
|
Constructs a new DBus message representing an error,
|
|
with the given \a name and \a msg.
|
|
*/
|
|
QDBusMessage QDBusMessage::createError(const QString &name, const QString &msg)
|
|
{
|
|
QDBusMessage error;
|
|
error.d_ptr->type = ErrorMessage;
|
|
error.d_ptr->name = name;
|
|
error.d_ptr->message = msg;
|
|
|
|
return error;
|
|
}
|
|
|
|
/*!
|
|
\fn QDBusMessage QDBusMessage::createError(const QDBusError &error)
|
|
|
|
Constructs a new DBus message representing the given \a error.
|
|
*/
|
|
|
|
/*!
|
|
\fn QDBusMessage QDBusMessage::createError(QDBusError::ErrorType type, const QString &msg)
|
|
|
|
Constructs a new DBus message for the error type \a type using
|
|
the message \a msg. Returns the DBus message.
|
|
*/
|
|
|
|
/*!
|
|
\fn QDBusMessage QDBusMessage::createReply(const QList<QVariant> &arguments) const
|
|
|
|
Constructs a new DBus message representing a reply, with the given
|
|
\a arguments.
|
|
*/
|
|
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);
|
|
return reply;
|
|
}
|
|
|
|
/*!
|
|
Constructs a new DBus message representing an error reply message,
|
|
with the given \a name and \a msg.
|
|
*/
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
|
QDBusMessage QDBusMessage::createErrorReply(const QString &name, const QString &msg) const
|
|
#else
|
|
QDBusMessage QDBusMessage::createErrorReply(const QString name, const QString &msg) const
|
|
#endif
|
|
{
|
|
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);
|
|
return reply;
|
|
}
|
|
|
|
/*!
|
|
\fn QDBusMessage QDBusMessage::createReply(const QVariant &argument) const
|
|
|
|
Constructs a new DBus message representing a reply, with the
|
|
given \a argument.
|
|
*/
|
|
|
|
/*!
|
|
\fn QDBusMessage QDBusMessage::createErrorReply(const QDBusError &error) const
|
|
|
|
Constructs a new DBus message representing an error reply message,
|
|
from the given \a error object.
|
|
*/
|
|
|
|
/*!
|
|
\fn QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType type, const QString &msg) const
|
|
|
|
Constructs a new DBus reply message for the error type \a type using
|
|
the message \a msg. Returns the DBus message.
|
|
*/
|
|
QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType atype, const QString &amsg) const
|
|
{
|
|
QDBusMessage msg = createErrorReply(QDBusError::errorString(atype), amsg);
|
|
msg.d_ptr->parametersValidated = true;
|
|
return msg;
|
|
}
|
|
|
|
|
|
/*!
|
|
Constructs an empty, invalid QDBusMessage object.
|
|
|
|
\sa createError(), createMethodCall(), createSignal()
|
|
*/
|
|
QDBusMessage::QDBusMessage()
|
|
{
|
|
d_ptr = new QDBusMessagePrivate;
|
|
}
|
|
|
|
/*!
|
|
Constructs a copy of the object given by \a other.
|
|
|
|
Note: QDBusMessage objects are shared. Modifications made to the
|
|
copy will affect the original one as well. See setDelayedReply()
|
|
for more information.
|
|
*/
|
|
QDBusMessage::QDBusMessage(const QDBusMessage &other)
|
|
{
|
|
d_ptr = other.d_ptr;
|
|
d_ptr->ref.ref();
|
|
}
|
|
|
|
/*!
|
|
Disposes of the object and frees any resources that were being held.
|
|
*/
|
|
QDBusMessage::~QDBusMessage()
|
|
{
|
|
if (!d_ptr->ref.deref())
|
|
delete d_ptr;
|
|
}
|
|
|
|
/*!
|
|
Copies the contents of the object given by \a other.
|
|
|
|
Note: QDBusMessage objects are shared. Modifications made to the
|
|
copy will affect the original one as well. See setDelayedReply()
|
|
for more information.
|
|
*/
|
|
QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
|
|
{
|
|
qAtomicAssign(d_ptr, other.d_ptr);
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
Returns the name of the service or the bus address of the remote method call.
|
|
*/
|
|
QString QDBusMessage::service() const
|
|
{
|
|
return d_ptr->service;
|
|
}
|
|
|
|
/*!
|
|
Returns the path of the object that this message is being sent to (in the case of a
|
|
method call) or being received from (for a signal).
|
|
*/
|
|
QString QDBusMessage::path() const
|
|
{
|
|
return d_ptr->path;
|
|
}
|
|
|
|
/*!
|
|
Returns the interface of the method being called (in the case of a method call) or of
|
|
the signal being received from.
|
|
*/
|
|
QString QDBusMessage::interface() const
|
|
{
|
|
return d_ptr->interface;
|
|
}
|
|
|
|
/*!
|
|
Returns the name of the signal that was emitted or the name of the method that was called.
|
|
*/
|
|
QString QDBusMessage::member() const
|
|
{
|
|
if (d_ptr->type != ErrorMessage)
|
|
return d_ptr->name;
|
|
return QString();
|
|
}
|
|
|
|
/*!
|
|
Returns the name of the error that was received.
|
|
*/
|
|
QString QDBusMessage::errorName() const
|
|
{
|
|
if (d_ptr->type == ErrorMessage)
|
|
return d_ptr->name;
|
|
return QString();
|
|
}
|
|
|
|
/*!
|
|
Returns the signature of the signal that was received or for the output arguments
|
|
of a method call.
|
|
*/
|
|
QString QDBusMessage::signature() const
|
|
{
|
|
return d_ptr->signature;
|
|
}
|
|
|
|
/*!
|
|
Returns the flag that indicates if this message should see a reply
|
|
or not. This is only meaningful for \l {MethodCallMessage}{method
|
|
call messages}: any other kind of message cannot have replies and
|
|
this function will always return false for them.
|
|
*/
|
|
bool QDBusMessage::isReplyRequired() const
|
|
{
|
|
// Only method calls can have replies
|
|
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);
|
|
}
|
|
|
|
/*!
|
|
Sets whether the message will be replied later (if \a enable is
|
|
true) or if an automatic reply should be generated by Qt D-Bus
|
|
(if \a enable is false).
|
|
|
|
In D-Bus, all method calls must generate a reply to the caller, unless the
|
|
caller explicitly indicates otherwise (see isReplyRequired()). QtDBus
|
|
automatically generates such replies for any slots being called, but it
|
|
also allows slots to indicate whether they will take responsibility
|
|
of sending the reply at a later time, after the function has finished
|
|
processing.
|
|
|
|
\sa {Delayed Replies}
|
|
*/
|
|
void QDBusMessage::setDelayedReply(bool enable) const
|
|
{
|
|
d_ptr->delayedReply = enable;
|
|
}
|
|
|
|
/*!
|
|
Returns the delayed reply flag, as set by setDelayedReply(). By default, this
|
|
flag is false, which means Qt D-Bus will generate automatic replies
|
|
when necessary.
|
|
*/
|
|
bool QDBusMessage::isDelayedReply() const
|
|
{
|
|
return d_ptr->delayedReply;
|
|
}
|
|
|
|
/*!
|
|
Sets the auto start flag to \a enable. This flag only makes sense
|
|
for method call messages, where it tells the D-Bus server to
|
|
either auto start the service responsible for the service name, or
|
|
not to auto start it.
|
|
|
|
By default this flag is true, i.e. a service is autostarted.
|
|
This means:
|
|
|
|
When the service that this method call is sent to is already
|
|
running, the method call is sent to it. If the service is not
|
|
running yet, the D-Bus daemon is requested to autostart the
|
|
service that is assigned to this service name. This is
|
|
handled by .service files that are placed in a directory known
|
|
to the D-Bus server. These files then each contain a service
|
|
name and the path to a program that should be executed when
|
|
this service name is requested.
|
|
|
|
\since 4.7
|
|
*/
|
|
void QDBusMessage::setAutoStartService(bool enable)
|
|
{
|
|
d_ptr->autoStartService = enable;
|
|
}
|
|
|
|
/*!
|
|
Returns the auto start flag, as set by setAutoStartService(). By default, this
|
|
flag is true, which means Qt D-Bus will auto start a service, if it is
|
|
not running already.
|
|
|
|
\sa setAutoStartService()
|
|
|
|
\since 4.7
|
|
*/
|
|
bool QDBusMessage::autoStartService() const
|
|
{
|
|
return d_ptr->autoStartService;
|
|
}
|
|
|
|
/*!
|
|
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.
|
|
|
|
By default this flag is false and the other end is expected to
|
|
make any authorization decisions non-interactively and promptly.
|
|
|
|
The \c org.freedesktop.DBus.Error.InteractiveAuthorizationRequired
|
|
error indicates that authorization failed, but could have succeeded
|
|
if this flag had been set.
|
|
|
|
\sa isInteractiveAuthorizationAllowed()
|
|
|
|
\since 5.12
|
|
*/
|
|
void QDBusMessage::setInteractiveAuthorizationAllowed(bool enable)
|
|
{
|
|
d_ptr->interactiveAuthorizationAllowed = 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.
|
|
|
|
\sa setInteractiveAuthorizationAllowed()
|
|
|
|
\since 5.12
|
|
*/
|
|
bool QDBusMessage::isInteractiveAuthorizationAllowed() const
|
|
{
|
|
return d_ptr->interactiveAuthorizationAllowed;
|
|
}
|
|
|
|
/*!
|
|
Sets the arguments that are going to be sent over D-Bus to \a arguments. Those
|
|
will be the arguments to a method call or the parameters in the signal.
|
|
|
|
\sa arguments()
|
|
*/
|
|
void QDBusMessage::setArguments(const QList<QVariant> &arguments)
|
|
{
|
|
// FIXME: should we detach?
|
|
d_ptr->arguments = arguments;
|
|
}
|
|
|
|
/*!
|
|
Returns the list of arguments that are going to be sent or were received from
|
|
D-Bus.
|
|
*/
|
|
QList<QVariant> QDBusMessage::arguments() const
|
|
{
|
|
return d_ptr->arguments;
|
|
}
|
|
|
|
/*!
|
|
Appends the argument \a arg to the list of arguments to be sent over D-Bus in
|
|
a method call or signal emission.
|
|
*/
|
|
|
|
QDBusMessage &QDBusMessage::operator<<(const QVariant &arg)
|
|
{
|
|
// FIXME: should we detach?
|
|
d_ptr->arguments.append(arg);
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
Returns the message type.
|
|
*/
|
|
QDBusMessage::MessageType QDBusMessage::type() const
|
|
{
|
|
switch (d_ptr->type) {
|
|
case DBUS_MESSAGE_TYPE_METHOD_CALL:
|
|
return MethodCallMessage;
|
|
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
|
|
return ReplyMessage;
|
|
case DBUS_MESSAGE_TYPE_ERROR:
|
|
return ErrorMessage;
|
|
case DBUS_MESSAGE_TYPE_SIGNAL:
|
|
return SignalMessage;
|
|
default:
|
|
break;
|
|
}
|
|
return InvalidMessage;
|
|
}
|
|
|
|
#ifndef QT_NO_DEBUG_STREAM
|
|
static QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
|
|
{
|
|
switch (t)
|
|
{
|
|
case QDBusMessage::MethodCallMessage:
|
|
return dbg << "MethodCall";
|
|
case QDBusMessage::ReplyMessage:
|
|
return dbg << "MethodReturn";
|
|
case QDBusMessage::SignalMessage:
|
|
return dbg << "Signal";
|
|
case QDBusMessage::ErrorMessage:
|
|
return dbg << "Error";
|
|
default:
|
|
return dbg << "Invalid";
|
|
}
|
|
}
|
|
|
|
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) {
|
|
if (!first)
|
|
dbg.nospace() << ", ";
|
|
dbg.nospace() << qPrintable(QDBusUtil::argumentToString(*it));
|
|
first = false;
|
|
}
|
|
}
|
|
|
|
QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
|
|
{
|
|
QDebugStateSaver saver(dbg);
|
|
dbg.nospace() << "QDBusMessage(type=" << msg.type()
|
|
<< ", service=" << msg.service();
|
|
if (msg.type() == QDBusMessage::MethodCallMessage ||
|
|
msg.type() == QDBusMessage::SignalMessage)
|
|
dbg.nospace() << ", path=" << msg.path()
|
|
<< ", interface=" << msg.interface()
|
|
<< ", member=" << msg.member();
|
|
if (msg.type() == QDBusMessage::ErrorMessage)
|
|
dbg.nospace() << ", error name=" << msg.errorName()
|
|
<< ", error message=" << msg.errorMessage();
|
|
dbg.nospace() << ", signature=" << msg.signature()
|
|
<< ", contents=(";
|
|
debugVariantList(dbg, msg.arguments());
|
|
dbg.nospace() << ") )";
|
|
return dbg;
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
\fn void QDBusMessage::swap(QDBusMessage &other)
|
|
|
|
Swaps this QDBusMessage instance with \a other.
|
|
*/
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
#endif // QT_NO_DBUS
|