• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

DBusHelperProxy.cpp

Go to the documentation of this file.
00001 /*
00002 *   Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
00003 *   Copyright (C) 2009 Dario Freddi <drf@kde.org>
00004 *
00005 *   This program is free software; you can redistribute it and/or modify
00006 *   it under the terms of the GNU Lesser General Public License as published by
00007 *   the Free Software Foundation; either version 2.1 of the License, or
00008 *   (at your option) any later version.
00009 *
00010 *   This program is distributed in the hope that it will be useful,
00011 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 *   GNU General Public License for more details.
00014 *
00015 *   You should have received a copy of the GNU Lesser General Public License
00016 *   along with this program; if not, write to the
00017 *   Free Software Foundation, Inc.,
00018 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .
00019 */
00020 
00021 #include "DBusHelperProxy.h"
00022 
00023 #include <QObject>
00024 #include <QMap>
00025 #include <QtDBus/QDBusMessage>
00026 #include <QtDBus/QDBusConnection>
00027 #include <QDebug>
00028 #include <QTimer>
00029 
00030 #include <klocalizedstring.h>
00031 
00032 #include <syslog.h>
00033 
00034 #include "BackendsManager.h"
00035 #include "authadaptor.h"
00036 
00037 #ifndef KDE_USE_FINAL
00038 Q_DECLARE_METATYPE(QTimer*)
00039 #endif
00040 
00041 namespace KAuth
00042 {
00043 
00044 static void debugMessageReceived(int t, const QString &message);
00045 
00046 void DBusHelperProxy::stopAction(const QString &action, const QString &helperID)
00047 {
00048     QDBusMessage message;
00049     message = QDBusMessage::createMethodCall(helperID, "/", "org.kde.auth", "stopAction");
00050 
00051     QList<QVariant> args;
00052     args << action;
00053     message.setArguments(args);
00054 
00055     QDBusConnection::systemBus().asyncCall(message);
00056 }
00057 
00058 bool DBusHelperProxy::executeActions(const QList<QPair<QString, QVariantMap> > &list, const QString &helperID)
00059 {
00060     QByteArray blob;
00061     QDataStream stream(&blob, QIODevice::WriteOnly);
00062 
00063     stream << list;
00064 
00065     QDBusConnection::systemBus().interface()->startService(helperID);
00066 
00067     if (!QDBusConnection::systemBus().connect(helperID, "/", "org.kde.auth", "remoteSignal", this, SLOT(remoteSignalReceived(int, const QString &, QByteArray)))) {
00068         return false;
00069     }
00070 
00071     QDBusMessage message;
00072     message = QDBusMessage::createMethodCall(helperID, "/", "org.kde.auth", "performActions");
00073 
00074     QList<QVariant> args;
00075     args << blob << BackendsManager::authBackend()->callerID();
00076     message.setArguments(args);
00077 
00078     QDBusPendingCall reply = QDBusConnection::systemBus().asyncCall(message); // This is a NO_REPLY method
00079     if (reply.reply().type() == QDBusMessage::ErrorMessage) {
00080         return false;
00081     }
00082 
00083     return true;
00084 }
00085 
00086 ActionReply DBusHelperProxy::executeAction(const QString &action, const QString &helperID, const QVariantMap &arguments)
00087 {
00088     if (!m_actionsInProgress.isEmpty()) {
00089         return ActionReply::HelperBusyReply;
00090     }
00091 
00092     QByteArray blob;
00093     QDataStream stream(&blob, QIODevice::WriteOnly);
00094 
00095     stream << arguments;
00096     
00097     QDBusConnection::systemBus().interface()->startService(helperID);
00098 
00099     if (!QDBusConnection::systemBus().connect(helperID, "/", "org.kde.auth", "remoteSignal", this, SLOT(remoteSignalReceived(int, const QString &, QByteArray)))) {
00100         ActionReply errorReply = ActionReply::DBusErrorReply;
00101         errorReply.setErrorDescription(i18n("DBus Backend error: connection to helper failed. %1", 
00102                                             QDBusConnection::systemBus().lastError().message()));
00103         return errorReply;
00104     }
00105 
00106     QDBusMessage message;
00107     message = QDBusMessage::createMethodCall(helperID, "/", "org.kde.auth", "performAction");
00108 
00109     QList<QVariant> args;
00110     args << action << BackendsManager::authBackend()->callerID() << blob;
00111     message.setArguments(args);
00112 
00113     m_actionsInProgress.push_back(action);
00114 
00115     QEventLoop e;
00116     QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(message);
00117     QDBusPendingCallWatcher watcher(pendingCall, this);
00118     connect(&watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), &e, SLOT(quit()));
00119     e.exec();
00120     
00121     QDBusMessage reply = pendingCall.reply();
00122     
00123     if (reply.type() == QDBusMessage::ErrorMessage) {
00124         ActionReply r = ActionReply::DBusErrorReply;
00125         r.setErrorDescription(i18n("DBus Backend error: could not contact the helper. "
00126                                    "Connection error: %1. Message error: %2", QDBusConnection::systemBus().lastError().message(),
00127                                    reply.errorMessage()));
00128         qDebug() << reply.errorMessage();
00129 
00130         return r;
00131     }
00132 
00133     if (reply.arguments().size() != 1) {
00134         ActionReply errorReply = ActionReply::DBusErrorReply;
00135         errorReply.setErrorDescription(i18n("DBus Backend error: received corrupt data from helper %1 %2",
00136                                             reply.arguments().size(), QDBusConnection::systemBus().lastError().message()));
00137         return errorReply;
00138     }
00139 
00140     return ActionReply::deserialize(reply.arguments().first().toByteArray());
00141 }
00142 
00143 bool DBusHelperProxy::initHelper(const QString &name)
00144 {
00145     new AuthAdaptor(this);
00146 
00147     if (!QDBusConnection::systemBus().registerService(name)) {
00148         return false;
00149     }
00150 
00151     if (!QDBusConnection::systemBus().registerObject("/", this)) {
00152         return false;
00153     }
00154 
00155     m_name = name;
00156 
00157     return true;
00158 }
00159 
00160 void DBusHelperProxy::setHelperResponder(QObject *o)
00161 {
00162     responder = o;
00163 }
00164 
00165 void DBusHelperProxy::remoteSignalReceived(int t, const QString &action, QByteArray blob)
00166 {
00167     SignalType type = (SignalType)t;
00168     QDataStream stream(&blob, QIODevice::ReadOnly);
00169 
00170     if (type == ActionStarted) {
00171         emit actionStarted(action);
00172     } else if (type == ActionPerformed) {
00173         ActionReply reply;
00174         stream >> reply;
00175 
00176         m_actionsInProgress.removeOne(action);
00177         emit actionPerformed(action, reply);
00178     } else if (type == DebugMessage) {
00179         int level;
00180         QString message;
00181 
00182         stream >> level >> message;
00183 
00184         debugMessageReceived(level, message);
00185     } else if (type == ProgressStepIndicator) {
00186         int step;
00187         stream >> step;
00188 
00189         emit progressStep(action, step);
00190     } else if (type == ProgressStepData) {
00191         QVariantMap data;
00192         stream >> data;
00193 
00194         emit progressStep(action, data);
00195     }
00196 }
00197 
00198 void DBusHelperProxy::stopAction(const QString &action)
00199 {
00200 #ifndef Q_CC_MSVC
00201 #warning FIXME: The stop request should be action-specific rather than global
00202 #endif
00203     m_stopRequest = true;
00204 }
00205 
00206 bool DBusHelperProxy::hasToStopAction()
00207 {
00208     QEventLoop loop;
00209     loop.processEvents(QEventLoop::AllEvents);
00210 
00211     return m_stopRequest;
00212 }
00213 
00214 void DBusHelperProxy::performActions(QByteArray blob, const QByteArray &callerID)
00215 {
00216     QDataStream stream(&blob, QIODevice::ReadOnly);
00217     QList<QPair<QString, QVariantMap> > actions;
00218 
00219     stream >> actions;
00220 
00221     QList<QPair<QString, QVariantMap> >::const_iterator i = actions.constBegin();
00222     while (i != actions.constEnd()) {
00223         QByteArray blob;
00224         QDataStream stream(&blob, QIODevice::WriteOnly);
00225 
00226         stream << i->second;
00227 
00228         emit remoteSignal(ActionPerformed, i->first, performAction(i->first, callerID, blob));
00229 
00230         i++;
00231     }
00232 }
00233 
00234 QByteArray DBusHelperProxy::performAction(const QString &action, const QByteArray &callerID, QByteArray arguments)
00235 {
00236     if (!responder) {
00237         return ActionReply::NoResponderReply.serialized();
00238     }
00239 
00240     if (!m_currentAction.isEmpty()) {
00241         return ActionReply::HelperBusyReply.serialized();
00242     }
00243 
00244     QVariantMap args;
00245     QDataStream s(&arguments, QIODevice::ReadOnly);
00246     s >> args;
00247 
00248     if (BackendsManager::authBackend()->isCallerAuthorized(action, callerID)) {
00249         QTimer *timer = responder->property("__KAuth_Helper_Shutdown_Timer").value<QTimer*>();
00250         timer->stop();
00251 
00252         QString slotname = action;
00253         if (slotname.startsWith(m_name + '.')) {
00254             slotname = slotname.right(slotname.length() - m_name.length() - 1);
00255         }
00256 
00257         slotname.replace('.', '_');
00258 
00259         ActionReply retVal;
00260 
00261         m_currentAction = action;
00262         emit remoteSignal(ActionStarted, action, QByteArray());
00263         bool success = QMetaObject::invokeMethod(responder, slotname.toAscii(), Qt::DirectConnection, Q_RETURN_ARG(ActionReply, retVal), Q_ARG(QVariantMap, args));
00264         emit remoteSignal(ActionPerformed, action, retVal.serialized());
00265         m_currentAction = "";
00266 
00267         timer->start();
00268 
00269         if (success) {
00270             return retVal.serialized();
00271         } else {
00272             return ActionReply::NoSuchActionReply.serialized();
00273         }
00274 
00275     } else {
00276         return ActionReply::AuthorizationDeniedReply.serialized();
00277     }
00278 }
00279 
00280 void DBusHelperProxy::sendDebugMessage(int level, const char *msg)
00281 {
00282     QByteArray blob;
00283     QDataStream stream(&blob, QIODevice::WriteOnly);
00284 
00285     stream << level << QString(msg);
00286 
00287     emit remoteSignal(DebugMessage, m_currentAction, blob);
00288 }
00289 
00290 void DBusHelperProxy::sendProgressStep(int step)
00291 {
00292     QByteArray blob;
00293     QDataStream stream(&blob, QIODevice::WriteOnly);
00294 
00295     stream << step;
00296 
00297     emit remoteSignal(ProgressStepIndicator, m_currentAction, blob);
00298 }
00299 
00300 void DBusHelperProxy::sendProgressStep(const QVariantMap &data)
00301 {
00302     QByteArray blob;
00303     QDataStream stream(&blob, QIODevice::WriteOnly);
00304 
00305     stream << data;
00306 
00307     emit remoteSignal(ProgressStepIndicator, m_currentAction, blob);
00308 }
00309 
00310 void debugMessageReceived(int t, const QString &message)
00311 {
00312     QtMsgType type = (QtMsgType)t;
00313     switch (type) {
00314     case QtDebugMsg:
00315         qDebug("Debug message from helper: %s", message.toAscii().data());
00316         break;
00317     case QtWarningMsg:
00318         qWarning("Warning from helper: %s", message.toAscii().data());
00319         break;
00320     case QtCriticalMsg:
00321         qCritical("Critical warning from helper: %s", message.toAscii().data());
00322         break;
00323     case QtFatalMsg:
00324         qFatal("Fatal error from helper: %s", message.toAscii().data());
00325         break;
00326     }
00327 }
00328 
00329 } // namespace Auth
00330 
00331 #ifndef KDE_USE_FINAL
00332 Q_EXPORT_PLUGIN2(helper_proxy, KAuth::DBusHelperProxy)
00333 #endif

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  •     Sodep
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal