24 #include "async-dbus-proxy.h"
26 #include <QDBusConnection>
27 #include <QDBusObjectPath>
28 #include <QDBusPendingCallWatcher>
30 #include <QMetaMethod>
33 #include "connection-manager.h"
34 #include "dbusinterface.h"
36 #include "libsignoncommon.h"
37 #include "signond/signoncommon.h"
46 Connection(
const char *name, QObject *receiver,
const char *slot):
61 PendingCall::PendingCall(
const QString &method,
62 const QList<QVariant> &args,
68 m_interfaceWasDestroyed(false)
72 PendingCall::~PendingCall()
76 bool PendingCall::cancel()
86 void PendingCall::doCall(QDBusAbstractInterface *interface)
88 QDBusPendingCall call =
89 interface->asyncCallWithArgumentList(m_method, m_args);
90 m_watcher =
new QDBusPendingCallWatcher(call,
this);
91 QObject::connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
92 this, SLOT(onFinished(QDBusPendingCallWatcher*)));
94 m_interfaceWasDestroyed =
false;
95 QObject::connect(interface, SIGNAL(destroyed()),
96 this, SLOT(onInterfaceDestroyed()));
99 void PendingCall::fail(
const QDBusError &err)
105 void PendingCall::onFinished(QDBusPendingCallWatcher *watcher)
110 if (m_interfaceWasDestroyed && watcher->isError()) {
111 QDBusError::ErrorType type = watcher->error().type();
112 if (type == QDBusError::Disconnected ||
113 type == QDBusError::UnknownObject) {
114 TRACE() <<
"emitting retry signal";
115 Q_EMIT requeueRequested();
120 if (watcher->isError()) {
121 Q_EMIT error(watcher->error());
123 Q_EMIT success(watcher);
125 Q_EMIT finished(watcher);
128 void PendingCall::onInterfaceDestroyed()
136 m_interfaceWasDestroyed =
true;
139 AsyncDBusProxy::AsyncDBusProxy(
const QString &service,
140 const char *interface,
141 QObject *clientObject):
142 m_serviceName(service),
143 m_interfaceName(interface),
145 m_clientObject(clientObject),
151 AsyncDBusProxy::~AsyncDBusProxy()
153 qDeleteAll(m_connectionsQueue);
154 m_connectionsQueue.clear();
159 void AsyncDBusProxy::setStatus(Status status)
163 if (status == Ready) {
165 Q_FOREACH(Connection *connection, m_connectionsQueue) {
166 m_interface->connect(connection->m_name,
167 connection->m_receiver,
171 Q_FOREACH(PendingCall *call, m_operationsQueue) {
172 call->doCall(m_interface);
174 m_operationsQueue.clear();
175 }
else if (status == Invalid) {
177 Q_FOREACH(PendingCall *call, m_operationsQueue) {
178 call->fail(m_lastError);
180 m_operationsQueue.clear();
184 void AsyncDBusProxy::update()
186 if (m_interface != NULL) {
191 if (m_connection == NULL || m_path.isEmpty()) {
192 setStatus(Incomplete);
196 if (!m_connection->isConnected()) {
197 setError(m_connection->lastError());
209 void AsyncDBusProxy::setConnection(
const QDBusConnection &connection)
212 m_connection =
new QDBusConnection(connection);
216 void AsyncDBusProxy::setDisconnected()
226 void AsyncDBusProxy::setObjectPath(
const QDBusObjectPath &objectPath)
228 Q_ASSERT(m_path.isEmpty() || objectPath.path().isEmpty());
229 m_path = objectPath.path();
233 void AsyncDBusProxy::setError(
const QDBusError &error)
240 PendingCall *AsyncDBusProxy::queueCall(
const QString &method,
241 const QList<QVariant> &args,
242 const char *replySlot,
243 const char *errorSlot)
245 return queueCall(method, args, m_clientObject, replySlot, errorSlot);
248 PendingCall *AsyncDBusProxy::queueCall(
const QString &method,
249 const QList<QVariant> &args,
251 const char *replySlot,
252 const char *errorSlot)
254 PendingCall *call =
new PendingCall(method, args,
this);
255 QObject::connect(call, SIGNAL(finished(QDBusPendingCallWatcher*)),
256 this, SLOT(onCallFinished(QDBusPendingCallWatcher*)));
257 QObject::connect(call, SIGNAL(requeueRequested()),
258 this, SLOT(onRequeueRequested()));
261 QObject::connect(call, SIGNAL(error(
const QDBusError&)),
262 receiver, errorSlot);
264 QObject::connect(call, SIGNAL(success(QDBusPendingCallWatcher*)),
265 receiver, replySlot);
267 }
else if (replySlot) {
268 QObject::connect(call, SIGNAL(finished(QDBusPendingCallWatcher*)),
269 receiver, replySlot);
272 if (m_status == Ready) {
273 call->doCall(m_interface);
274 }
else if (m_status == Incomplete) {
277 QMetaObject::invokeMethod(call,
"fail",
278 Qt::QueuedConnection,
279 Q_ARG(QDBusError, m_lastError));
284 bool AsyncDBusProxy::connect(
const char *name,
290 Connection *connection =
new Connection(name, receiver, slot);
291 m_connectionsQueue.enqueue(connection);
293 if (m_status == Ready) {
294 return m_interface->connect(name, receiver, slot);
299 void AsyncDBusProxy::enqueue(PendingCall *call)
301 m_operationsQueue.enqueue(call);
303 Q_EMIT connectionNeeded();
305 if (m_path.isEmpty()) {
306 Q_EMIT objectPathNeeded();
310 void AsyncDBusProxy::onCallFinished(QDBusPendingCallWatcher *watcher)
313 PendingCall *call = qobject_cast<PendingCall*>(sender());
314 m_operationsQueue.removeOne(call);
318 void AsyncDBusProxy::onRequeueRequested()
320 PendingCall *call = qobject_cast<PendingCall*>(sender());
324 SignondAsyncDBusProxy::SignondAsyncDBusProxy(
const char *interface,
325 QObject *clientObject):
326 AsyncDBusProxy(SIGNOND_SERVICE, interface, clientObject)
331 SignondAsyncDBusProxy::~SignondAsyncDBusProxy()
335 void SignondAsyncDBusProxy::setupConnection()
338 QObject::connect(connManager, SIGNAL(connected(
const QDBusConnection&)),
339 this, SLOT(setConnection(
const QDBusConnection&)));
340 QObject::connect(connManager, SIGNAL(disconnected()),
341 this, SLOT(setDisconnected()));
342 QObject::connect(
this, SIGNAL(connectionNeeded()),
343 connManager, SLOT(connect()));
344 if (connManager->hasConnection()) {
345 setConnection(connManager->connection());