on xenial help sign in
add login1 session props, user/real/hostname, prompt/lock
commitbbaa2debb27243238a36f6d58004017843834852 authorLukáš Tinkl <lukas.tinkl@canonical.com> dateTue 16 Jun 2015, 00:31 (11 years ago) parentf5365cc
5 files changed+246−42
plugins/AccountsService/AccountsService.cpp+1−2 plugins/Unity/Session/dbusunitysessionservice.cpp+134−16 plugins/Unity/Session/dbusunitysessionservice.h+53−15 plugins/Utils/relativetimeformatter.cpp+1−1 tests/plugins/Unity/Session/sessionbackendtest.cpp+57−8
plugins/AccountsService/AccountsService.cpp+1−2
@@ -141,9 +141,9 @@ void AccountsService::updateDemoEdges(bool async)
141141 this, [this](QDBusPendingCallWatcher* watcher) {
142142
143143 QDBusPendingReply<QDBusVariant> reply = *watcher;
144+ watcher->deleteLater();
144145 if (reply.isError()) {
145146 qWarning() << "Failed to get 'demo-edges' property - " << reply.error().message();
146− watcher->deleteLater();
147147 return;
148148 }
149149
@@ -152,7 +152,6 @@ void AccountsService::updateDemoEdges(bool async)
152152 m_demoEdges = demoEdges;
153153 Q_EMIT demoEdgesChanged();
154154 }
155− watcher->deleteLater();
156155 });
157156 if (!async) {
158157 watcher->waitForFinished();
plugins/Unity/Session/dbusunitysessionservice.cpp+134−16
@@ -17,8 +17,38 @@
1717// local
1818#include "dbusunitysessionservice.h"
1919
20+// system
21+#include <sys/types.h>
22+#include <unistd.h>
23+#include <pwd.h>
24+
2025// Qt
26+#include <QDebug>
2127#include <QDBusPendingCall>
28+#include <QDBusReply>
29+
30+#define LOGIN1_SERVICE QStringLiteral("org.freedesktop.login1")
31+#define LOGIN1_PATH QStringLiteral("/org/freedesktop/login1")
32+#define LOGIN1_IFACE QStringLiteral("org.freedesktop.login1.Manager")
33+#define LOGIN1_SESSION_IFACE QStringLiteral("org.freedesktop.login1.Session")
34+
35+bool checkLogin1Call(const QString &method)
36+{
37+ QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
38+ QDBusReply<QString> reply = QDBusConnection::systemBus().asyncCall(msg);
39+ const QString retval = reply.value();
40+ return (retval == QStringLiteral("yes") || retval == QStringLiteral("challenge"));
41+}
42+
43+void makeLogin1Call(const QString &method, const QVariantList &args)
44+{
45+ QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
46+ LOGIN1_PATH,
47+ LOGIN1_IFACE,
48+ method);
49+ msg.setArguments(args);
50+ QDBusConnection::systemBus().asyncCall(msg);
51+}
2252
2353DBusUnitySessionService::DBusUnitySessionService()
2454 : UnityDBusObject("/com/canonical/Unity/Session", "com.canonical.Unity")
@@ -28,7 +58,7 @@ DBusUnitySessionService::DBusUnitySessionService()
2858void DBusUnitySessionService::Logout()
2959{
3060 // TODO ask the apps to quit and then emit the signal
31− Q_EMIT logoutReady();
61+ Q_EMIT LogoutReady();
3262}
3363
3464void DBusUnitySessionService::EndSession()
@@ -40,39 +70,127 @@ void DBusUnitySessionService::EndSession()
4070 QDBusConnection::sessionBus().asyncCall(msg);
4171}
4272
73+bool DBusUnitySessionService::CanHibernate() const
74+{
75+ return checkLogin1Call("CanHibernate");
76+}
77+
78+bool DBusUnitySessionService::CanSuspend() const
79+{
80+ return checkLogin1Call("CanSuspend");
81+}
82+
83+bool DBusUnitySessionService::CanHybridSleep() const
84+{
85+ return checkLogin1Call("CanHybridSleep");
86+}
87+
88+bool DBusUnitySessionService::CanReboot() const
89+{
90+ return checkLogin1Call("CanReboot");
91+}
92+
93+bool DBusUnitySessionService::CanShutdown() const
94+{
95+ return checkLogin1Call("CanPowerOff");
96+}
97+
98+bool DBusUnitySessionService::CanLock() const
99+{
100+ return true; // FIXME
101+}
102+
103+QString DBusUnitySessionService::UserName() const
104+{
105+ struct passwd *p = getpwuid(getuid());
106+ if (p) {
107+ return QString::fromUtf8(p->pw_name);
108+ }
109+
110+ return QString();
111+}
112+
113+QString DBusUnitySessionService::RealName() const
114+{
115+ struct passwd *p = getpwuid(getuid());
116+ if (p) {
117+ const QString gecos = QString::fromLocal8Bit(p->pw_gecos);
118+ if (!gecos.isEmpty()) {
119+ return gecos.split(QLatin1Char(',')).first();
120+ }
121+ }
122+
123+ return QString();
124+}
125+
126+QString DBusUnitySessionService::HostName() const
127+{
128+ char hostName[512];
129+ if (gethostname(hostName, sizeof(hostName)) == -1) {
130+ qWarning() << "Could not determine local hostname";
131+ return QString();
132+ }
133+ hostName[sizeof(hostName) - 1] = '\0';
134+ return QString::fromLocal8Bit(hostName);
135+}
136+
137+void DBusUnitySessionService::PromptLock()
138+{
139+ Q_EMIT LockRequested();
140+}
141+
142+void DBusUnitySessionService::Lock()
143+{
144+ const QString sessionId = QString::fromLocal8Bit(qgetenv("XDG_SESSION_PATH"));
145+ QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.DisplayManager",
146+ sessionId,
147+ "org.freedesktop.DisplayManager.Session",
148+ "Lock");
149+ qDebug() << "Locking session" << msg.path();
150+ QDBusReply<void> reply = QDBusConnection::systemBus().asyncCall(msg);
151+ if (!reply.isValid()) {
152+ qWarning() << "Lock call failed" << reply.error().message();
153+ }
154+}
155+
43156void DBusUnitySessionService::RequestLogout()
44157{
45− Q_EMIT logoutRequested(false);
158+ Q_EMIT LogoutRequested(false);
46159}
47160
48161void DBusUnitySessionService::Reboot()
49162{
50− QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.login1",
51− "/org/freedesktop/login1",
52− "org.freedesktop.login1.Manager",
53− "Reboot");
54− msg << false;
55− QDBusConnection::systemBus().asyncCall(msg);
163+ makeLogin1Call("Reboot", {false});
56164}
57165
58166void DBusUnitySessionService::RequestReboot()
59167{
60− Q_EMIT rebootRequested(false);
168+ Q_EMIT RebootRequested(false);
61169}
62170
63171void DBusUnitySessionService::Shutdown()
64172{
65− QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.login1",
66− "/org/freedesktop/login1",
67− "org.freedesktop.login1.Manager",
68− "PowerOff");
69− msg << false;
70− QDBusConnection::systemBus().asyncCall(msg);
173+ makeLogin1Call("PowerOff", {false});
174+}
175+
176+void DBusUnitySessionService::Suspend()
177+{
178+ makeLogin1Call("Suspend", {false});
179+}
180+
181+void DBusUnitySessionService::Hibernate()
182+{
183+ makeLogin1Call("Hibernate", {false});
184+}
185+
186+void DBusUnitySessionService::HybridSleep()
187+{
188+ makeLogin1Call("HybridSleep", {false});
71189}
72190
73191void DBusUnitySessionService::RequestShutdown()
74192{
75− Q_EMIT shutdownRequested(false);
193+ Q_EMIT ShutdownRequested(false);
76194}
77195
78196enum class Action : unsigned
plugins/Unity/Session/dbusunitysessionservice.h+53−15
@@ -1,4 +1,4 @@
1−/*
1+/*
22 * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it under
@@ -48,43 +48,44 @@ public:
4848
4949Q_SIGNALS:
5050 /**
51− * logoutRequested signal
51+ * LogoutRequested signal
5252 *
5353 * This signal is emitted when some applications request the system to
5454 * logout.
5555 * @param have_inhibitors if there are any special running applications
5656 * which inhibit the logout.
5757 */
58− Q_SCRIPTABLE void logoutRequested(bool have_inhibitors);
58+ Q_SCRIPTABLE void LogoutRequested(bool have_inhibitors);
5959
6060 /**
61− * rebootRequested signal
61+ * RebootRequested signal
6262 *
6363 * This signal is emitted when some applications request the system to
6464 * reboot.
6565 * @param have_inhibitors if there are any special running applications
6666 * which inhibit the reboot.
6767 */
68− Q_SCRIPTABLE void rebootRequested(bool have_inhibitors);
68+ Q_SCRIPTABLE void RebootRequested(bool have_inhibitors);
6969
7070 /**
71− * shutdownRequested signal
71+ * ShutdownRequested signal
7272 *
7373 * This signal is emitted when some applications request the system to
7474 * shutdown.
7575 * @param have_inhibitors if there are any special running applications
7676 * which inhibit the shutdown.
7777 */
78− Q_SCRIPTABLE void shutdownRequested(bool have_inhibitors);
79−
78+ Q_SCRIPTABLE void ShutdownRequested(bool have_inhibitors);
8079
8180 /**
82− * logoutReady signal
81+ * LogoutReady signal
8382 *
8483 * This signal is emitted when all the apps are closed. And the system
8584 * is safe to logout.
8685 */
87− void logoutReady();
86+ Q_SCRIPTABLE void LogoutReady();
87+
88+ Q_SCRIPTABLE void LockRequested();
8889
8990public Q_SLOTS:
9091 /**
@@ -114,10 +115,19 @@ public Q_SLOTS:
114115 */
115116 Q_SCRIPTABLE void Shutdown();
116117
118+ Q_SCRIPTABLE void Suspend();
119+
120+ Q_SCRIPTABLE void Hibernate();
121+
122+ /**
123+ * @since unity8
124+ */
125+ Q_SCRIPTABLE void HybridSleep();
126+
117127 /**
118128 * Issue a logout request.
119129 *
120− * This method emits the logoutRequested signal to the shell with a boolean
130+ * This method emits the LogoutRequested signal to the shell with a boolean
121131 * which indicates if there's any inhibitors. The shell should receive
122132 * this signal and display a dialog to ask the user to confirm the logout
123133 * action. If confirmed, shell can call Logout() method to logout.
@@ -127,21 +137,21 @@ public Q_SLOTS:
127137 /**
128138 * Issue a reboot request.
129139 *
130− * This method emist the rebootRequested signal to the shell with a boolean
140+ * This method emits the RebootRequested signal to the shell with a boolean
131141 * which indicates if there's any inhibitors. The shell should receive
132142 * this signal and display a dialog to ask the user to confirm the reboot
133− * action. If confirmed, shell can call Reboot() method to reboot
143+ * action. If confirmed, shell can call Reboot() method to reboot.
134144 */
135145 Q_SCRIPTABLE void RequestReboot();
136146
137147 /**
138148 * Issue a shutdown request.
139149 *
140− * This method emits the shutdownRequested signal to the shell with a
150+ * This method emits the ShutdownRequested signal to the shell with a
141151 * boolean which indicates if there's any inhibitors.
142152 * The shell should receive
143153 * this signal and display a dialog to ask the user to confirm the reboot
144− * action. If confirmed, shell can call Shutdown() method to reboot
154+ * action. If confirmed, shell can call Shutdown() method to shutdown.
145155 */
146156 Q_SCRIPTABLE void RequestShutdown();
147157
@@ -152,6 +162,34 @@ public Q_SLOTS:
152162 * current DBus session bus.
153163 */
154164 Q_SCRIPTABLE void EndSession();
165+
166+ Q_SCRIPTABLE bool CanHibernate() const;
167+
168+ Q_SCRIPTABLE bool CanSuspend() const;
169+
170+ /**
171+ * @since unity8
172+ */
173+ Q_SCRIPTABLE bool CanHybridSleep() const;
174+
175+ /**
176+ * @since unity8
177+ */
178+ Q_SCRIPTABLE bool CanReboot() const;
179+
180+ Q_SCRIPTABLE bool CanShutdown() const;
181+
182+ Q_SCRIPTABLE bool CanLock() const;
183+
184+ Q_SCRIPTABLE QString UserName() const;
185+
186+ Q_SCRIPTABLE QString RealName() const;
187+
188+ Q_SCRIPTABLE QString HostName() const;
189+
190+ Q_SCRIPTABLE void PromptLock();
191+
192+ Q_SCRIPTABLE void Lock();
155193};
156194
157195class DBusGnomeSessionManagerWrapper : public UnityDBusObject
plugins/Utils/relativetimeformatter.cpp+1−1
@@ -121,7 +121,7 @@ getDateProximity(GDateTime* now, GDateTime* time)
121121const char*
122122dgettext_datetime(const char *text)
123123{
124− return dgettext("indicator-datetime", text);
124+ return dgettext("unity8", text);
125125}
126126
127127/**
tests/plugins/Unity/Session/sessionbackendtest.cpp+57−8
@@ -24,8 +24,14 @@
2424#include <QDBusInterface>
2525#include <QDBusReply>
2626#include <QDBusVariant>
27+#include <QDebug>
28+#include <QDBusObjectPath>
29+
30+#include <unistd.h>
31+#include <sys/types.h>
2732
2833#include "dbusunitysessionservice.h"
34+#include "../../AccountsService/AccountsServiceDBusAdaptor.h"
2935
3036enum class Action : unsigned
3137{
@@ -52,9 +58,10 @@ private Q_SLOTS:
5258 QTest::addColumn<QString>("method");
5359 QTest::addColumn<QString>("signal");
5460
55− QTest::newRow("Logout") << "RequestLogout" << "logoutRequested(bool)";
56− QTest::newRow("Reboot") << "RequestReboot" << "rebootRequested(bool)";
57− QTest::newRow("Shutdown") << "RequestShutdown" << "shutdownRequested(bool)";
61+ QTest::newRow("Logout") << "RequestLogout" << "LogoutRequested(bool)";
62+ QTest::newRow("Reboot") << "RequestReboot" << "RebootRequested(bool)";
63+ QTest::newRow("Shutdown") << "RequestShutdown" << "ShutdownRequested(bool)";
64+ QTest::newRow("PromptLock") << "PromptLock" << "LockRequested()";
5865 }
5966
6067 void testUnitySessionLogoutRequested() {
@@ -65,7 +72,7 @@ private Q_SLOTS:
6572 QCoreApplication::processEvents(); // to let the service register on DBus
6673
6774 // .. because QSignalSpy checks the signal signature like this: "if (((aSignal[0] - '0') & 0x03) != QSIGNAL_CODE)"
68− QSignalSpy spy(&dbusUnitySessionService, signal.prepend(QSIGNAL_CODE).toLocal8Bit().constData());
75+ QSignalSpy spy(&dbusUnitySessionService, qPrintable(signal.prepend(QSIGNAL_CODE)));
6976
7077 QDBusReply<void> reply = dbusUnitySession->call(method);
7178 QCOMPARE(reply.isValid(), true);
@@ -77,9 +84,9 @@ private Q_SLOTS:
7784 QTest::addColumn<uint>("method");
7885 QTest::addColumn<QString>("signal");
7986
80− QTest::newRow("Logout") << (uint)Action::LOGOUT << "logoutRequested(bool)";
81− QTest::newRow("Shutdown") << (unsigned)Action::SHUTDOWN << "shutdownRequested(bool)";
82− QTest::newRow("Reboot") << (unsigned)Action::REBOOT << "rebootRequested(bool)";
87+ QTest::newRow("Logout") << (uint)Action::LOGOUT << "LogoutRequested(bool)";
88+ QTest::newRow("Shutdown") << (unsigned)Action::SHUTDOWN << "ShutdownRequested(bool)";
89+ QTest::newRow("Reboot") << (unsigned)Action::REBOOT << "RebootRequested(bool)";
8390 }
8491
8592 void testGnomeSessionWrapper() {
@@ -92,7 +99,7 @@ private Q_SLOTS:
9299 // Spy on the given signal on the /com/canonical/Unity/Session object
93100 // as proof we are actually calling the actual method.
94101 // .. because QSignalSpy checks the signal signature like this: "if (((aSignal[0] - '0') & 0x03) != QSIGNAL_CODE)"
95− QSignalSpy spy(&dbusUnitySessionService, signal.prepend(QSIGNAL_CODE).toLocal8Bit().constData());
102+ QSignalSpy spy(&dbusUnitySessionService, qPrintable(signal.prepend(QSIGNAL_CODE)));
96103
97104 DBusGnomeSessionManagerWrapper dbusGnomeSessionManagerWrapper;
98105 QCoreApplication::processEvents(); // to let the service register on DBus
@@ -116,6 +123,48 @@ private Q_SLOTS:
116123 QCOMPARE(spy.count(), 1);
117124 }
118125
126+ void testUserName() {
127+ DBusUnitySessionService dbusUnitySessionService;
128+ QCoreApplication::processEvents(); // to let the service register on DBus
129+
130+ QCOMPARE(dbusUnitySessionService.UserName(), QString::fromUtf8(qgetenv("USER")));
131+ }
132+
133+ void testRealName() {
134+ DBusUnitySessionService dbusUnitySessionService;
135+ QCoreApplication::processEvents(); // to let the service register on DBus
136+
137+ QDBusInterface accIface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", QDBusConnection::systemBus());
138+ QVERIFY(accIface.isValid());
139+ QDBusReply<QDBusObjectPath> userPath = accIface.asyncCall("FindUserById", static_cast<qint64>(geteuid()));
140+ if (!userPath.isValid()) {
141+ QFAIL("Could not get user path in Account Service");
142+ }
143+
144+ QDBusInterface userAccIface("org.freedesktop.Accounts", userPath.value().path(), "org.freedesktop.Accounts.User", QDBusConnection::systemBus());
145+ QCOMPARE(dbusUnitySessionService.RealName(), userAccIface.property("RealName").toString());
146+ }
147+
148+ void testLogin1Capabilities() {
149+ DBusUnitySessionService dbusUnitySessionService;
150+ QDBusInterface login1face("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus());
151+ QCoreApplication::processEvents(); // to let the services register on DBus
152+
153+ QCOMPARE(dbusUnitySessionService.CanHibernate(), (login1face.call("CanHibernate").arguments().first().toString() != "no"));
154+ QCOMPARE(dbusUnitySessionService.CanSuspend(), (login1face.call("CanSuspend").arguments().first().toString() != "no"));
155+ QCOMPARE(dbusUnitySessionService.CanReboot(), (login1face.call("CanReboot").arguments().first().toString() != "no"));
156+ QCOMPARE(dbusUnitySessionService.CanShutdown(), (login1face.call("CanPowerOff").arguments().first().toString() != "no"));
157+ QCOMPARE(dbusUnitySessionService.CanHybridSleep(), (login1face.call("CanHybridSleep").arguments().first().toString() != "no"));
158+ }
159+
160+ void testLock() {
161+ DBusUnitySessionService dbusUnitySessionService;
162+ QCoreApplication::processEvents(); // to let the service register on DBus
163+
164+ qDebug() << "Locking up...";
165+ dbusUnitySessionService.Lock();
166+ }
167+
119168private:
120169 QDBusInterface *dbusUnitySession;
121170};