- Main Page
- Related Pages
- Classes
- Files

- File List

connection-manager.cpp
1 /*
2 * This file is part of signon
3 *
4 * Copyright (C) 2013 Canonical Ltd.
5 *
6 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * version 2.1 as published by the Free Software Foundation.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23 #include "connection-manager.h"
24 #include "libsignoncommon.h"
25 #include "signond/signoncommon.h"
26
27 #include <QDBusConnectionInterface>
28 #include <QDBusError>
29 #include <QDBusPendingCallWatcher>
30 #include <QPointer>
31 #include <QProcessEnvironment>
32 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
33 #include <QStandardPaths>
34 #endif
35
36 using namespace SignOn;
37
38 static QPointer<ConnectionManager> connectionInstance = 0;
39
40 ConnectionManager::ConnectionManager(QObject *parent):
41 QObject(parent),
42 m_connection(QLatin1String("libsignon-qt-invalid")),
43 m_serviceStatus(ServiceStatusUnknown)
44 {
45 if (connectionInstance == 0) {
46 init();
47 connectionInstance = this;
48 } else {
49 BLAME() << "SignOn::ConnectionManager instantiated more than once!";
50 }
51 }
52
53 ConnectionManager::~ConnectionManager()
54 {
55 }
56
57 ConnectionManager *ConnectionManager::instance()
58 {
59 if (connectionInstance == 0) {
60 connectionInstance = new ConnectionManager;
61 }
62 return connectionInstance;
63 }
64
65 void ConnectionManager::connect()
66 {
67 if (m_connection.isConnected()) {
68 Q_EMIT connected(m_connection);
69 } else {
70 init();
71 }
72 }
73
74 bool ConnectionManager::hasConnection() const
75 {
76 return m_connection.isConnected();
77 }
78
79 ConnectionManager::SocketConnectionStatus
80 ConnectionManager::setupSocketConnection()
81 {
82 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
83 QLatin1String one("1");
84 if (environment.value(QLatin1String("SSO_USE_PEER_BUS"), one) != one) {
85 return SocketConnectionUnavailable;
86 }
87
88 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
89 QString runtimeDir =
90 QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
91 #else
92 QString runtimeDir = environment.value(QLatin1String("XDG_RUNTIME_DIR"));
93 #endif
94 if (runtimeDir.isEmpty()) return SocketConnectionUnavailable;
95
96 QString socketFileName =
97 QString::fromLatin1("unix:path=%1/" SIGNOND_SOCKET_FILENAME).arg(runtimeDir);
98 static int count = 0;
99
100 QDBusConnection connection =
101 QDBusConnection::connectToPeer(socketFileName,
102 QString(QLatin1String("libsignon-qt%1")).arg(count++));
103 if (!connection.isConnected()) {
104 QDBusError error = connection.lastError();
105 QString name = error.name();
106 BLAME() << "p2p error:" << error << error.type();
107 if (name == QLatin1String("org.freedesktop.DBus.Error.FileNotFound") &&
108 m_serviceStatus != ServiceActivated) {
109 return SocketConnectionNoService;
110 } else {
111 return SocketConnectionUnavailable;
112 }
113 }
114
115 m_connection = connection;
116 m_connection.connect(QString(),
117 QLatin1String("/org/freedesktop/DBus/Local"),
118 QLatin1String("org.freedesktop.DBus.Local"),
119 QLatin1String("Disconnected"),
120 this, SLOT(onDisconnected()));
121
122 return SocketConnectionOk;
123 }
124
125 void ConnectionManager::init()
126 {
127 if (m_serviceStatus == ServiceActivating) return;
128
129 SocketConnectionStatus status = setupSocketConnection();
130
131 if (status == SocketConnectionNoService) {
132 TRACE() << "Peer connection unavailable, activating service";
133 QDBusConnectionInterface *interface =
134 QDBusConnection::sessionBus().interface();
135 QDBusPendingCall call =
136 interface->asyncCall(QLatin1String("StartServiceByName"),
137 SIGNOND_SERVICE, uint(0));
138 m_serviceStatus = ServiceActivating;
139 QDBusPendingCallWatcher *watcher =
140 new QDBusPendingCallWatcher(call, this);
141 QObject::connect(watcher,
142 SIGNAL(finished(QDBusPendingCallWatcher*)),
143 this,
144 SLOT(onActivationDone(QDBusPendingCallWatcher*)));
145 } else if (status == SocketConnectionUnavailable) {
146 m_connection = SIGNOND_BUS;
147 }
148
149 if (m_connection.isConnected()) {
150 TRACE() << "Connected to" << m_connection.name();
151 Q_EMIT connected(m_connection);
152 }
153 }
154
155 void ConnectionManager::onActivationDone(QDBusPendingCallWatcher *watcher)
156 {
157 QDBusPendingReply<> reply(*watcher);
158 watcher->deleteLater();
159
160 if (!reply.isError()) {
161 m_serviceStatus = ServiceActivated;
162 /* Attempt to connect again */
163 init();
164 } else {
165 BLAME() << reply.error();
166 }
167 }
168
169 void ConnectionManager::onDisconnected()
170 {
171 TRACE() << "Disconnected from daemon";
172 m_serviceStatus = ServiceStatusUnknown;
173 Q_EMIT disconnected();
174 }
SignOn::ConnectionManager
Definition: connection-manager.h:33