00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "connection-manager.h"
00024 #include "debug.h"
00025 #include "libsignoncommon.h"
00026 #include "signond/signoncommon.h"
00027
00028 #include <QDBusConnectionInterface>
00029 #include <QDBusError>
00030 #include <QDBusPendingCallWatcher>
00031 #include <QPointer>
00032 #include <QProcessEnvironment>
00033 #include <QStandardPaths>
00034
00035 using namespace SignOn;
00036
00037 static QPointer<ConnectionManager> connectionInstance = 0;
00038
00039 ConnectionManager::ConnectionManager(QObject *parent):
00040 QObject(parent),
00041 m_connection(QLatin1String("libsignon-qt-invalid")),
00042 m_serviceStatus(ServiceStatusUnknown)
00043 {
00044 if (connectionInstance == 0) {
00045 init();
00046 connectionInstance = this;
00047 } else {
00048 BLAME() << "SignOn::ConnectionManager instantiated more than once!";
00049 }
00050 }
00051
00052 ConnectionManager::~ConnectionManager()
00053 {
00054 }
00055
00056 ConnectionManager *ConnectionManager::instance()
00057 {
00058 if (connectionInstance == 0) {
00059 connectionInstance = new ConnectionManager;
00060 }
00061 return connectionInstance;
00062 }
00063
00064 void ConnectionManager::connect()
00065 {
00066 if (m_connection.isConnected()) {
00067 Q_EMIT connected(m_connection);
00068 } else {
00069 init();
00070 }
00071 }
00072
00073 bool ConnectionManager::hasConnection() const
00074 {
00075 return m_connection.isConnected();
00076 }
00077
00078 ConnectionManager::SocketConnectionStatus
00079 ConnectionManager::setupSocketConnection()
00080 {
00081 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
00082 QLatin1String one("1");
00083 if (environment.value(QLatin1String("SSO_USE_PEER_BUS"), one) != one) {
00084 return SocketConnectionUnavailable;
00085 }
00086
00087 QString runtimeDir =
00088 QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
00089 if (runtimeDir.isEmpty()) return SocketConnectionUnavailable;
00090
00091 QString socketFileName =
00092 QString::fromLatin1("unix:path=%1/" SIGNOND_SOCKET_FILENAME).arg(runtimeDir);
00093 static int count = 0;
00094
00095 QDBusConnection connection =
00096 QDBusConnection::connectToPeer(socketFileName,
00097 QString(QLatin1String("libsignon-qt%1")).arg(count++));
00098 if (!connection.isConnected()) {
00099 QDBusError error = connection.lastError();
00100 QString name = error.name();
00101 TRACE() << "p2p error:" << error << error.type();
00102 if (name == QLatin1String("org.freedesktop.DBus.Error.FileNotFound") &&
00103 m_serviceStatus != ServiceActivated) {
00104 return SocketConnectionNoService;
00105 } else {
00106 return SocketConnectionUnavailable;
00107 }
00108 }
00109
00110 m_connection = connection;
00111 m_connection.connect(QString(),
00112 QLatin1String("/org/freedesktop/DBus/Local"),
00113 QLatin1String("org.freedesktop.DBus.Local"),
00114 QLatin1String("Disconnected"),
00115 this, SLOT(onDisconnected()));
00116
00117 return SocketConnectionOk;
00118 }
00119
00120 void ConnectionManager::init()
00121 {
00122 if (m_serviceStatus == ServiceActivating) return;
00123
00124 SocketConnectionStatus status = setupSocketConnection();
00125
00126 if (status == SocketConnectionNoService) {
00127 TRACE() << "Peer connection unavailable, activating service";
00128 QDBusConnectionInterface *interface =
00129 QDBusConnection::sessionBus().interface();
00130 QDBusPendingCall call =
00131 interface->asyncCall(QLatin1String("StartServiceByName"),
00132 SIGNOND_SERVICE, uint(0));
00133 m_serviceStatus = ServiceActivating;
00134 QDBusPendingCallWatcher *watcher =
00135 new QDBusPendingCallWatcher(call, this);
00136 QObject::connect(watcher,
00137 SIGNAL(finished(QDBusPendingCallWatcher*)),
00138 this,
00139 SLOT(onActivationDone(QDBusPendingCallWatcher*)));
00140 } else if (status == SocketConnectionUnavailable) {
00141 m_connection = SIGNOND_BUS;
00142 }
00143
00144 if (m_connection.isConnected()) {
00145 TRACE() << "Connected to" << m_connection.name();
00146 Q_EMIT connected(m_connection);
00147 }
00148 }
00149
00150 void ConnectionManager::onActivationDone(QDBusPendingCallWatcher *watcher)
00151 {
00152 QDBusPendingReply<> reply(*watcher);
00153 watcher->deleteLater();
00154
00155 if (!reply.isError()) {
00156 m_serviceStatus = ServiceActivated;
00157
00158 init();
00159 } else {
00160 BLAME() << reply.error();
00161 }
00162 }
00163
00164 void ConnectionManager::onDisconnected()
00165 {
00166 TRACE() << "Disconnected from daemon";
00167 m_serviceStatus = ServiceStatusUnknown;
00168 Q_EMIT disconnected();
00169 }