on xenial help sign in
Some initial async cleanup
commitd28fa914e01bb2787e374d5d5a4780fcd5b091bd authorMichael Terry <michael.terry@canonical.com> dateMon 26 Oct 2015, 10:05 (11 years ago) parentcab9943
19 files changed+237−314
plugins/AccountsService/AccountsService.cpp+3−3 plugins/AccountsService/AccountsServiceDBusAdaptor.cpp+1−22 plugins/AccountsService/AccountsServiceDBusAdaptor.h−12 plugins/Greeter/Unity/Launcher/launchermodelas.cpp+19−4 plugins/Greeter/Unity/Launcher/launchermodelas.h+2 plugins/Unity/Session/dbusunitysessionservice.cpp+64−36 tests/plugins/AccountsService/AccountsServer.cpp+11−5 tests/plugins/AccountsService/AccountsServer.h+1−6 tests/plugins/AccountsService/PropertiesServer.cpp+9 tests/plugins/AccountsService/client.cpp+6−8 tests/plugins/AccountsService/server.cpp+1−7 tests/plugins/Greeter/Unity/Launcher/AccountsServiceDBusAdaptor.cpp−48 tests/plugins/Greeter/Unity/Launcher/AccountsServiceDBusAdaptor.h−53 tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt+8−2 tests/plugins/Greeter/Unity/Launcher/launchermodelastest.cpp+81−16 tests/plugins/Unity/Launcher/AccountsServiceDBusAdaptor.cpp−42 tests/plugins/Unity/Launcher/AccountsServiceDBusAdaptor.h−47 tests/plugins/Unity/Launcher/CMakeLists.txt+8−2 tests/plugins/Unity/Launcher/launchermodeltest.cpp+23−1
plugins/AccountsService/AccountsService.cpp+3−3
@@ -74,7 +74,7 @@ void AccountsService::setDemoEdges(bool demoEdges)
7474{
7575 if (m_demoEdges != demoEdges) {
7676 m_demoEdges = demoEdges;
77− m_service->setUserProperty(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("demo-edges"), demoEdges);
77+ m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("demo-edges"), demoEdges);
7878
7979 Q_EMIT demoEdgesChanged();
8080 }
@@ -114,7 +114,7 @@ void AccountsService::setHereEnabled(bool enabled)
114114{
115115 if (m_hereEnabled != enabled) {
116116 m_hereEnabled = enabled;
117− m_service->setUserProperty(m_user, QStringLiteral("com.ubuntu.location.providers.here.AccountsService"), QStringLiteral("LicenseAccepted"), enabled);
117+ m_service->setUserPropertyAsync(m_user, QStringLiteral("com.ubuntu.location.providers.here.AccountsService"), QStringLiteral("LicenseAccepted"), enabled);
118118
119119 Q_EMIT hereEnabledChanged();
120120 }
@@ -403,7 +403,7 @@ void AccountsService::setFailedLogins(uint failedLogins)
403403{
404404 if (m_failedLogins != failedLogins) {
405405 m_failedLogins = failedLogins;
406− m_service->setUserProperty(m_user, QStringLiteral("com.canonical.unity.AccountsService.Private"), QStringLiteral("FailedLogins"), failedLogins);
406+ m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService.Private"), QStringLiteral("FailedLogins"), failedLogins);
407407
408408 Q_EMIT failedLoginsChanged();
409409 }
plugins/AccountsService/AccountsServiceDBusAdaptor.cpp+1−22
@@ -37,18 +37,6 @@ AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
3737 connection, this);
3838}
3939
40−QVariant AccountsServiceDBusAdaptor::getUserProperty(const QString &user, const QString &interface, const QString &property)
41−{
42− QDBusInterface *iface = getUserInterface(user);
43− if (iface != nullptr && iface->isValid()) {
44− QDBusReply<QVariant> answer = iface->call(QStringLiteral("Get"), interface, property);
45− if (answer.isValid()) {
46− return answer;
47− }
48− }
49− return QVariant();
50−}
51−
5240QDBusPendingReply<QVariant> AccountsServiceDBusAdaptor::getUserPropertyAsync(const QString &user, const QString &interface, const QString &property)
5341{
5442 QDBusInterface *iface = getUserInterface(user);
@@ -58,15 +46,6 @@ QDBusPendingReply<QVariant> AccountsServiceDBusAdaptor::getUserPropertyAsync(con
5846 return QDBusPendingReply<QVariant>(QDBusMessage::createError(QDBusError::Other, QStringLiteral("Invalid Interface")));
5947}
6048
61−void AccountsServiceDBusAdaptor::setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value)
62−{
63− QDBusInterface *iface = getUserInterface(user);
64− if (iface != nullptr && iface->isValid()) {
65− // The value needs to be carefully wrapped
66− iface->call(QStringLiteral("Set"), interface, property, QVariant::fromValue(QDBusVariant(value)));
67− }
68−}
69−
7049QDBusPendingCall AccountsServiceDBusAdaptor::setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value)
7150{
7251 QDBusInterface *iface = getUserInterface(user);
@@ -116,7 +95,7 @@ QDBusInterface *AccountsServiceDBusAdaptor::getUserInterface(const QString &user
11695{
11796 QDBusInterface *iface = m_users.value(user);
11897 if (iface == nullptr && m_accountsManager->isValid()) {
119− QDBusReply<QDBusObjectPath> answer = m_accountsManager->asyncCall(QStringLiteral("FindUserByName"), user);
98+ QDBusReply<QDBusObjectPath> answer = m_accountsManager->call(QStringLiteral("FindUserByName"), user);
12099 if (answer.isValid()) {
121100 const QString path = answer.value().path();
122101
plugins/AccountsService/AccountsServiceDBusAdaptor.h−12
@@ -35,19 +35,7 @@ public:
3535 explicit AccountsServiceDBusAdaptor(QObject *parent = 0);
3636 ~AccountsServiceDBusAdaptor() = default;
3737
38− Q_INVOKABLE QVariant getUserProperty(const QString &user, const QString &interface, const QString &property);
3938 Q_INVOKABLE QDBusPendingReply<QVariant> getUserPropertyAsync(const QString &user, const QString &interface, const QString &property);
40−
41− template <typename T>
42− inline T getUserProperty(const QString &user, const QString &interface, const QString &property) {
43− const QVariant variant = getUserProperty(user, interface, property);
44− if (variant.isValid() && variant.canConvert<QDBusArgument>()) {
45− return qdbus_cast<T>(variant.value<QDBusArgument>());
46− }
47− return T();
48− }
49−
50− Q_INVOKABLE void setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value);
5139 Q_INVOKABLE QDBusPendingCall setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value);
5240
5341Q_SIGNALS:
plugins/Greeter/Unity/Launcher/launchermodelas.cpp+19−4
@@ -194,15 +194,30 @@ int LauncherModel::findApplication(const QString &appId)
194194 return -1;
195195}
196196
197−typedef QList<QVariantMap> VariantMapList;
198197void LauncherModel::refresh()
199198{
200− QList<QVariantMap> items;
199+ if (!m_accounts || m_user.isEmpty()) {
200+ refreshWithItems(QList<QVariantMap>());
201+ } else {
202+ QDBusPendingCall pendingCall = m_accounts->getUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("LauncherItems"));
203+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
204+ connect(watcher, &QDBusPendingCallWatcher::finished,
205+ this, [this](QDBusPendingCallWatcher* watcher) {
206+
207+ QDBusPendingReply<QVariant> reply = *watcher;
208+ watcher->deleteLater();
209+ if (reply.isError()) {
210+ qWarning() << "Failed to refresh LauncherItems" << reply.error().message();
211+ return;
212+ }
201213
202− if (m_accounts && !m_user.isEmpty()) {
203− items = m_accounts->getUserProperty<VariantMapList>(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("LauncherItems"));
214+ refreshWithItems(qdbus_cast<QList<QVariantMap>>(reply.value().value<QDBusArgument>()));
215+ });
204216 }
217+}
205218
219+void LauncherModel::refreshWithItems(const QList<QVariantMap> &items)
220+{
206221 // First walk through all the existing items and see if we need to remove something
207222 QList<LauncherItem*> toBeRemoved;
208223
plugins/Greeter/Unity/Launcher/launchermodelas.h+2
@@ -65,6 +65,8 @@ private Q_SLOTS:
6565 void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
6666
6767private:
68+ void refreshWithItems(const QList<QVariantMap> &items);
69+
6870 QString m_user;
6971 QList<LauncherItem*> m_list;
7072 AccountsServiceDBusAdaptor *m_accounts;
plugins/Unity/Session/dbusunitysessionservice.cpp+64−36
@@ -61,7 +61,7 @@ public:
6161 QStringLiteral("GetSessionByPID"));
6262 msg << (quint32) getpid();
6363
64− QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().asyncCall(msg);
64+ QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().call(msg);
6565 if (reply.isValid()) {
6666 logindSessionPath = reply.value().path();
6767
@@ -92,20 +92,28 @@ public:
9292 msg << "Unity"; // who
9393 msg << "Unity8 handles power events"; // why
9494 msg << "block"; // mode
95− QDBusReply<QDBusUnixFileDescriptor> desc = QDBusConnection::systemBus().asyncCall(msg);
9695
97− if (desc.isValid()) {
98− m_systemdInhibitFd = desc.value();
99− } else {
100− qWarning() << "failed to inhibit systemd powersave handling";
101− }
96+ QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
97+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
98+ connect(watcher, &QDBusPendingCallWatcher::finished,
99+ this, [this](QDBusPendingCallWatcher* watcher) {
100+
101+ QDBusPendingReply<QDBusUnixFileDescriptor> reply = *watcher;
102+ watcher->deleteLater();
103+ if (reply.isError()) {
104+ qWarning() << "Failed to inhibit systemd powersave handling" << reply.error().message();
105+ return;
106+ }
107+
108+ m_systemdInhibitFd = reply.value();
109+ });
102110 }
103111
104112
105113 bool checkLogin1Call(const QString &method) const
106114 {
107115 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
108− QDBusReply<QString> reply = QDBusConnection::systemBus().asyncCall(msg);
116+ QDBusReply<QString> reply = QDBusConnection::systemBus().call(msg);
109117 return reply.isValid() && (reply == QStringLiteral("yes") || reply == QStringLiteral("challenge"));
110118 }
111119
@@ -119,6 +127,21 @@ public:
119127 QDBusConnection::systemBus().asyncCall(msg);
120128 }
121129
130+ void setActive(bool active)
131+ {
132+ isSessionActive = active;
133+
134+ Q_EMIT screensaverActiveChanged(!isSessionActive);
135+
136+ if (isSessionActive) {
137+ screensaverActiveTimer.invalidate();
138+ setIdleHint(false);
139+ } else {
140+ screensaverActiveTimer.start();
141+ setIdleHint(true);
142+ }
143+ }
144+
122145 void checkActive()
123146 {
124147 if (logindSessionPath.isEmpty()) {
@@ -133,12 +156,20 @@ public:
133156 msg << LOGIN1_SESSION_IFACE;
134157 msg << ACTIVE_KEY;
135158
136− QDBusReply<QVariant> reply = QDBusConnection::systemBus().asyncCall(msg);
137− if (reply.isValid()) {
138− isSessionActive = reply.value().toBool();
139− } else {
140− qWarning() << "Failed to get Active property" << reply.error().message();
141− }
159+ QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
160+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
161+ connect(watcher, &QDBusPendingCallWatcher::finished,
162+ this, [this](QDBusPendingCallWatcher* watcher) {
163+
164+ QDBusPendingReply<QVariant> reply = *watcher;
165+ watcher->deleteLater();
166+ if (reply.isError()) {
167+ qWarning() << "Failed to get Active property" << reply.error().message();
168+ return;
169+ }
170+
171+ setActive(reply.value().toBool());
172+ });
142173 }
143174
144175 quint32 screensaverActiveTime() const
@@ -159,7 +190,7 @@ public:
159190 msg << LOGIN1_SESSION_IFACE;
160191 msg << IDLE_SINCE_KEY;
161192
162− QDBusReply<QVariant> reply = QDBusConnection::systemBus().asyncCall(msg);
193+ QDBusReply<QVariant> reply = QDBusConnection::systemBus().call(msg);
163194 if (reply.isValid()) {
164195 return reply.value().value<quint64>();
165196 } else {
@@ -184,22 +215,10 @@ private Q_SLOTS:
184215 {
185216 Q_UNUSED(iface)
186217
187− if (changedProps.contains(ACTIVE_KEY) || invalidatedProps.contains(ACTIVE_KEY)) {
188− if (changedProps.value(ACTIVE_KEY).isValid()) {
189− isSessionActive = changedProps.value(ACTIVE_KEY).toBool();
190− } else {
191− checkActive();
192− }
193−
194− Q_EMIT screensaverActiveChanged(!isSessionActive);
195−
196− if (isSessionActive) {
197− screensaverActiveTimer.invalidate();
198− setIdleHint(false);
199− } else {
200− screensaverActiveTimer.start();
201− setIdleHint(true);
202− }
218+ if (changedProps.contains(ACTIVE_KEY)) {
219+ setActive(changedProps.value(ACTIVE_KEY).toBool());
220+ } else if (invalidatedProps.contains(ACTIVE_KEY)) {
221+ checkActive();
203222 }
204223 }
205224
@@ -324,13 +343,22 @@ void DBusUnitySessionService::Lock()
324343 sessionPath,
325344 QStringLiteral("org.freedesktop.DisplayManager.Session"),
326345 QStringLiteral("Lock"));
327− QDBusReply<void> reply = QDBusConnection::systemBus().asyncCall(msg);
328− if (!reply.isValid()) {
329− qWarning() << "Lock call failed" << reply.error().message();
330− } else {
346+
347+ QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
348+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
349+ connect(watcher, &QDBusPendingCallWatcher::finished,
350+ this, [this](QDBusPendingCallWatcher* watcher) {
351+
352+ QDBusPendingReply<QVariant> reply = *watcher;
353+ watcher->deleteLater();
354+ if (reply.isError()) {
355+ qWarning() << "Lock call failed" << reply.error().message();
356+ return;
357+ }
358+
331359 // emit Locked when the call succeeds
332360 Q_EMIT Locked();
333− }
361+ });
334362}
335363
336364bool DBusUnitySessionService::IsLocked() const
tests/plugins/AccountsService/AccountsServer.cpp+11−5
@@ -18,13 +18,14 @@
1818 */
1919
2020#include "AccountsServer.h"
21+#include "AccountsUserAdaptor.h"
22+#include "PropertiesAdaptor.h"
2123#include "PropertiesServer.h"
2224#include <QDBusConnection>
2325#include <QDebug>
2426
25−AccountsServer::AccountsServer(PropertiesServer* propServer, QObject *parent)
27+AccountsServer::AccountsServer(QObject *parent)
2628 : QObject(parent)
27− , m_propServer(propServer)
2829{
2930}
3031
@@ -36,16 +37,21 @@ QDBusObjectPath AccountsServer::FindUserByName(const QString &user)
3637bool AccountsServer::AddUser(const QString &user)
3738{
3839 QString path(QString("/%1").arg(user));
39− if (QDBusConnection::sessionBus().objectRegisteredAt(path) == m_propServer)
40+ if (QDBusConnection::sessionBus().objectRegisteredAt(path) != nullptr)
4041 return true;
41− return QDBusConnection::sessionBus().registerObject(path, m_propServer);
42+
43+ auto props = new PropertiesServer(this);
44+ new PropertiesAdaptor(props);
45+ new AccountsUserAdaptor(props);
46+ return QDBusConnection::sessionBus().registerObject(path, props);
4247}
4348
4449bool AccountsServer::RemoveUser(const QString &user)
4550{
4651 QString path(QString("/%1").arg(user));
47− if (QDBusConnection::sessionBus().objectRegisteredAt(path) != m_propServer)
52+ if (QDBusConnection::sessionBus().objectRegisteredAt(path) == nullptr)
4853 return false;
54+
4955 QDBusConnection::sessionBus().unregisterObject(path);
5056 return true;
5157}
tests/plugins/AccountsService/AccountsServer.h+1−6
@@ -25,14 +25,12 @@
2525#include <QObject>
2626#include <QString>
2727
28−class PropertiesServer;
29−
3028class AccountsServer: public QObject, protected QDBusContext
3129{
3230 Q_OBJECT
3331
3432public:
35− explicit AccountsServer(PropertiesServer *propServer, QObject *parent = 0);
33+ explicit AccountsServer(QObject *parent = 0);
3634
3735public Q_SLOTS:
3836
@@ -41,9 +39,6 @@ public Q_SLOTS:
4139 // mock only.
4240 bool AddUser(const QString &user);
4341 bool RemoveUser(const QString &user);
44−
45−private:
46− PropertiesServer* m_propServer;
4742};
4843
4944#endif
tests/plugins/AccountsService/PropertiesServer.cpp+9
@@ -23,10 +23,12 @@
2323// Qt
2424#include <QDebug>
2525#include <QDBusMessage>
26+#include <QDBusMetaType>
2627
2728PropertiesServer::PropertiesServer(QObject *parent)
2829 : QObject(parent)
2930{
31+ qDBusRegisterMetaType<QList<QVariantMap>>();
3032 Reset();
3133}
3234
@@ -47,6 +49,12 @@ void PropertiesServer::Set(const QString &interface, const QString &property, co
4749 if (m_properties[interface].contains(property)) {
4850 QVariant& oldValue = m_properties[interface][property];
4951 if (oldValue != newValue) {
52+ // complex types have an extra layer of wrapping via QDBusArgument
53+ if (interface == QStringLiteral("com.canonical.unity.AccountsService") &&
54+ property == QStringLiteral("LauncherItems")) {
55+ newValue = QVariant::fromValue(qdbus_cast<QList<QVariantMap>>(newValue.value<QDBusArgument>()));
56+ }
57+
5058 oldValue = newValue;
5159
5260 // Special case for Background file.
@@ -71,6 +79,7 @@ void PropertiesServer::Set(const QString &interface, const QString &property, co
7179void PropertiesServer::Reset()
7280{
7381 m_properties["com.canonical.unity.AccountsService"]["demo-edges"] = false;
82+ m_properties["com.canonical.unity.AccountsService"]["LauncherItems"] = QVariant::fromValue(QList<QVariantMap>());
7483 m_properties["com.canonical.unity.AccountsService.Private"]["FailedLogins"] = 0;
7584 m_properties["com.ubuntu.touch.AccountsService.SecurityPrivacy"]["StatsWelcomeScreen"] = true;
7685 m_properties["com.ubuntu.AccountsService.SecurityPrivacy"]["EnableLauncherWhileLocked"] = true;
tests/plugins/AccountsService/client.cpp+6−8
@@ -57,8 +57,6 @@ private Q_SLOTS:
5757 m_userInterface = new QDBusInterface("org.freedesktop.Accounts",
5858 QString("/%1").arg(QTest::currentTestFunction()),
5959 "org.freedesktop.DBus.Properties", QDBusConnection::sessionBus(), this);
60− QDBusReply<void> resetReply = m_userInterface->call("Reset");
61− QVERIFY(resetReply.isValid());
6260
6361 QVERIFY(QObject::connect(m_userInterface, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)),
6462 this, SIGNAL(propertiesChanged(QString, QVariantMap, QStringList))));
@@ -79,17 +77,17 @@ private Q_SLOTS:
7977 {
8078 // Test various invalid calls
8179 AccountsServiceDBusAdaptor session;
82− QCOMPARE(session.getUserProperty("NOPE", "com.canonical.unity.AccountsService", "demo-edges"), QVariant());
83− QCOMPARE(session.getUserProperty(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "NOPE"), QVariant());
80+ QCOMPARE(session.getUserPropertyAsync("NOPE", "com.canonical.unity.AccountsService", "demo-edges").value(), QVariant());
81+ QCOMPARE(session.getUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "NOPE").value(), QVariant());
8482 }
8583
8684 void testGetSetServiceDBusAdaptor()
8785 {
8886 AccountsServiceDBusAdaptor session;
89− session.setUserProperty(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges", QVariant(true));
90− QCOMPARE(session.getUserProperty(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges"), QVariant(true));
91− session.setUserProperty(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges", QVariant(false));
92− QCOMPARE(session.getUserProperty(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges"), QVariant(false));
87+ session.setUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges", QVariant(true)).waitForFinished();
88+ QCOMPARE(session.getUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges").value(), QVariant(true));
89+ session.setUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges", QVariant(false)).waitForFinished();
90+ QCOMPARE(session.getUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges").value(), QVariant(false));
9391 }
9492
9593 void testGetSetService()
tests/plugins/AccountsService/server.cpp+1−7
@@ -19,11 +19,9 @@
1919
2020#include "AccountsAdaptor.h"
2121#include "AccountsServer.h"
22−#include "PropertiesAdaptor.h"
2322#include "PropertiesServer.h"
2423#include "SecurityPrivacyAdaptor.h"
2524#include "LocationAdaptor.h"
26−#include "AccountsUserAdaptor.h"
2725#include "AccountsPrivateAdaptor.h"
2826#include <QCoreApplication>
2927
@@ -31,11 +29,7 @@ int main(int argc, char *argv[])
3129{
3230 QCoreApplication a(argc, argv);
3331
34− auto props = new PropertiesServer(&a);
35− new PropertiesAdaptor(props);
36− new AccountsUserAdaptor(props);
37−
38− auto accounts = new AccountsServer(props, &a);
32+ auto accounts = new AccountsServer(&a);
3933 new AccountsAdaptor(accounts);
4034 new SecurityPrivacyAdaptor(accounts);
4135 new LocationAdaptor(accounts);
tests/plugins/Greeter/Unity/Launcher/AccountsServiceDBusAdaptor.cppdeleted−48
@@ -1,48 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "AccountsServiceDBusAdaptor.h"
18−#include <QDebug>
19−#include <QDBusArgument>
20−#include <QDBusMessage>
21−#include <QDBusMetaType>
22−
23−AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
24− : QObject(parent)
25−{
26− qDBusRegisterMetaType<QList<QVariantMap>>();
27−}
28−
29−QVariant AccountsServiceDBusAdaptor::getUserProperty(const QString &user, const QString &interface, const QString &property)
30−{
31− Q_UNUSED(interface)
32− Q_UNUSED(property) // We only fake one property here (LauncherItems)
33−
34− QDBusMessage msg;
35− QVariant v = QVariant::fromValue(mockProperties.value(user));
36− QDBusVariant dv(v);
37− QVariant packed = QVariant::fromValue(dv);
38− msg << packed;
39−
40− return packed.value<QDBusArgument>().asVariant();
41−}
42−
43−void AccountsServiceDBusAdaptor::simulatePropertyChange(const QString &user, const QString &property, const QVariant &value)
44−{
45− Q_ASSERT(property == "LauncherItems");
46− mockProperties[user] = value.value<QList<QVariantMap>>();
47− Q_EMIT propertiesChanged(user, "com.canonical.unity.AccountsService", QStringList() << property);
48−}
tests/plugins/Greeter/Unity/Launcher/AccountsServiceDBusAdaptor.hdeleted−53
@@ -1,53 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
18−#define UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
19−
20−#include <QMap>
21−#include <QObject>
22−#include <QString>
23−#include <QHash>
24−#include <QDBusArgument>
25−
26−extern QHash<QString, QList<QVariantMap>> mockProperties;
27−
28−class AccountsServiceDBusAdaptor: public QObject
29−{
30− Q_OBJECT
31−
32−public:
33− explicit AccountsServiceDBusAdaptor(QObject *parent = 0);
34−
35− Q_INVOKABLE QVariant getUserProperty(const QString &user, const QString &interface, const QString &property);
36− template <typename T>
37− inline T getUserProperty(const QString &user, const QString &interface, const QString &property) {
38− Q_UNUSED(interface)
39− Q_ASSERT(property == "LauncherItems");
40− T ret = mockProperties[user];
41− return ret;
42− }
43−
44−Q_SIGNALS:
45− void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
46−
47−private:
48− void simulatePropertyChange(const QString &user, const QString &property, const QVariant &value);
49−
50− friend class LauncherModelASTest;
51−};
52−
53−#endif
tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt+8−2
@@ -3,6 +3,7 @@ pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
33include_directories(
44 ${CMAKE_CURRENT_SOURCE_DIR}
55 ${CMAKE_CURRENT_BINARY_DIR}
6+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
67 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher
78 ${libunity8-private_SOURCE_DIR}
89 )
@@ -14,7 +15,7 @@ add_definitions(-DLAUNCHER_TESTING)
1415### LauncherModelASTest
1516add_executable(launchermodelastestExec
1617 launchermodelastest.cpp
17− AccountsServiceDBusAdaptor.cpp
18+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
1819 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher/launchermodelas.cpp
1920 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher/launcheritem.cpp
2021 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher/quicklistmodel.cpp
@@ -29,10 +30,15 @@ target_link_libraries(launchermodelastestExec
2930 unity8-private
3031 ${GSETTINGS_QT_LDFLAGS}
3132 )
33+add_dependencies(launchermodelastestExec mock-server)
3234qt5_use_modules(launchermodelastestExec Test Core DBus Gui)
3335add_unity8_unittest(LauncherModelAS dbus-test-runner
3436 ARG_PREFIX "--parameter"
35− ARGS --task $<TARGET_FILE:launchermodelastestExec>
37+ ARGS
38+ --task $<TARGET_FILE:mock-server>
39+ --ignore-return
40+ --task $<TARGET_FILE:launchermodelastestExec>
41+ --wait-for org.freedesktop.Accounts
3642)
3743
3844# copy .desktop files into build directory for shadow builds
tests/plugins/Greeter/Unity/Launcher/launchermodelastest.cpp+81−16
@@ -22,9 +22,12 @@
2222#include "launchermodelas.h"
2323#include "AccountsServiceDBusAdaptor.h"
2424
25+#include <QDBusInterface>
26+#include <QDBusMetaType>
27+#include <QDBusReply>
28+#include <QSignalSpy>
2529#include <QtTest>
2630
27−QHash<QString, QList<QVariantMap>> mockProperties;
2831
2932class LauncherModelASTest : public QObject
3033{
@@ -32,9 +35,15 @@ class LauncherModelASTest : public QObject
3235
3336private:
3437 LauncherModel *launcherModel;
38+ QStringList users;
39+ QHash<QString, QList<QVariantMap>> mockProperties;
3540
3641private Q_SLOTS:
3742
43+ void initTestCase() {
44+ qDBusRegisterMetaType<QList<QVariantMap>>();
45+ }
46+
3847 void init() {
3948 // Prepare some fake list
4049 QList<QVariantMap> list;
@@ -50,7 +59,63 @@ private Q_SLOTS:
5059 item["id"] = "appId2";
5160 item["name"] = "Item 2";
5261 list.append(item);
53− mockProperties["user1"] = list;
62+ setASLauncherItems("user1", list);
63+ }
64+
65+ void cleanup() {
66+ Q_FOREACH(QString user, users) {
67+ QDBusInterface accountsInterface(QStringLiteral("org.freedesktop.Accounts"),
68+ QStringLiteral("/org/freedesktop/Accounts"),
69+ QStringLiteral("org.freedesktop.Accounts"));
70+ QDBusReply<bool> removeReply = accountsInterface.call(QStringLiteral("RemoveUser"),
71+ user);
72+ QVERIFY(removeReply.isValid());
73+ QCOMPARE(removeReply.value(), true);
74+ }
75+
76+ users.clear();
77+ mockProperties.clear();
78+ }
79+
80+ void addASUser(const QString &user)
81+ {
82+ QDBusInterface accountsInterface(QStringLiteral("org.freedesktop.Accounts"),
83+ QStringLiteral("/org/freedesktop/Accounts"),
84+ QStringLiteral("org.freedesktop.Accounts"));
85+ QDBusReply<bool> addReply = accountsInterface.call(QStringLiteral("AddUser"),
86+ user);
87+ QVERIFY(addReply.isValid());
88+ QCOMPARE(addReply.value(), true);
89+
90+ users << user;
91+ mockProperties[user] = QList<QVariantMap>();
92+ }
93+
94+ void setASLauncherItems(const QString &user, const QList<QVariantMap> &items)
95+ {
96+ if (!users.contains(user)) {
97+ addASUser(user);
98+ }
99+
100+ QDBusInterface userInterface(QStringLiteral("org.freedesktop.Accounts"),
101+ QString("/%1").arg(user),
102+ QStringLiteral("org.freedesktop.DBus.Properties"));
103+
104+ QVariant wrapped = QVariant::fromValue(QDBusVariant(QVariant::fromValue(items)));
105+ QDBusReply<void> setReply = userInterface.call(QStringLiteral("Set"),
106+ QStringLiteral("com.canonical.unity.AccountsService"),
107+ QStringLiteral("LauncherItems"),
108+ wrapped);
109+ QVERIFY(setReply.isValid());
110+
111+ // Record what we set for comparison's sake
112+ mockProperties[user] = items;
113+ }
114+
115+ void setUser(LauncherModel *model, const QString &user) {
116+ QSignalSpy spy(model, &QAbstractItemModel::rowsInserted);
117+ model->setUser(user);
118+ QTRY_COMPARE(spy.count(), mockProperties[user].count());
54119 }
55120
56121 bool isInSync(LauncherModel *model, const QList<QVariantMap> &properties) {
@@ -81,7 +146,7 @@ private Q_SLOTS:
81146 // We didn't set a user yet. model should be empty
82147 QCOMPARE(model->rowCount(), 0);
83148
84− model->setUser("user1");
149+ setUser(model, "user1");
85150
86151 QCOMPARE(isInSync(model, mockProperties["user1"]), true);
87152 model->deleteLater();
@@ -102,7 +167,7 @@ private Q_SLOTS:
102167 QFETCH(bool, inSync);
103168
104169 LauncherModel* model = new LauncherModel(this);
105− model->setUser(modelUser);
170+ setUser(model, modelUser);
106171
107172 int oldCount = mockProperties[modelUser].count();
108173 QCOMPARE(model->rowCount(), oldCount);
@@ -117,17 +182,17 @@ private Q_SLOTS:
117182 newEntry.insert("countVisible", false);
118183 newEntry.insert("pinned", true);
119184 newList.append(newEntry);
120− model->m_accounts->simulatePropertyChange(changedUser, "LauncherItems", QVariant::fromValue(newList));
185+ setASLauncherItems(changedUser, newList);
121186
122− QCOMPARE(isInSync(model, mockProperties[modelUser]), true);
123− QCOMPARE(isInSync(model, mockProperties[changedUser]), inSync);
187+ QTRY_COMPARE(isInSync(model, mockProperties[modelUser]), true);
188+ QTRY_COMPARE(isInSync(model, mockProperties[changedUser]), inSync);
124189
125190 model->deleteLater();
126191 }
127192
128193 void testUpdateCount() {
129194 LauncherModel* model = new LauncherModel(this);
130− model->setUser("user1");
195+ setUser(model, "user1");
131196
132197 QCOMPARE(model->get(0)->countVisible(), false);
133198 QCOMPARE(model->get(0)->count(), 0);
@@ -137,34 +202,34 @@ private Q_SLOTS:
137202 entry["countVisible"] = true;
138203 entry["count"] = 55;
139204 newList[0] = entry;
140− model->m_accounts->simulatePropertyChange("user1", "LauncherItems", QVariant::fromValue(newList));
205+ setASLauncherItems("user1", newList);
141206
142− QCOMPARE(isInSync(model, mockProperties["user1"]), true);
207+ QTRY_COMPARE(isInSync(model, mockProperties["user1"]), true);
143208
144209 model->deleteLater();
145210 }
146211
147212 void testOnlyPinned() {
148213 LauncherModel *model = new LauncherModel(this);
149− model->setUser("user1");
214+ setUser(model, "user1");
150215 model->setOnlyPinned(true);
151216
152− QCOMPARE(isInSync(model, mockProperties["user1"]), true);
217+ QTRY_COMPARE(isInSync(model, mockProperties["user1"]), true);
153218
154219 // Let's unpin one item
155220 QList<QVariantMap> newList = mockProperties["user1"];
156221 QVariantMap entry = newList.at(0);
157222 entry["pinned"] = false;
158223 newList[0] = entry;
159− model->m_accounts->simulatePropertyChange("user1", "LauncherItems", QVariant::fromValue(newList));
160− QCOMPARE(isInSync(model, mockProperties["user1"]), true);
224+ setASLauncherItems("user1", newList);
225+ QTRY_COMPARE(isInSync(model, mockProperties["user1"]), true);
161226
162227 // Now toggle onlyPinned and make sure the model keeps up
163228 model->setOnlyPinned(false);
164− QCOMPARE(isInSync(model, mockProperties["user1"]), true);
229+ QTRY_COMPARE(isInSync(model, mockProperties["user1"]), true);
165230
166231 model->setOnlyPinned(true);
167− QCOMPARE(isInSync(model, mockProperties["user1"]), true);
232+ QTRY_COMPARE(isInSync(model, mockProperties["user1"]), true);
168233 }
169234};
170235
tests/plugins/Unity/Launcher/AccountsServiceDBusAdaptor.cppdeleted−42
@@ -1,42 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "AccountsServiceDBusAdaptor.h"
18−#include <QDebug>
19−
20−AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
21− : QObject(parent)
22−{
23−}
24−
25−QVariant AccountsServiceDBusAdaptor::getUserProperty(const QString &user, const QString &interface, const QString &property)
26−{
27− Q_UNUSED(user)
28− Q_UNUSED(interface)
29− return m_properties.value(property);
30−}
31−
32−void AccountsServiceDBusAdaptor::setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value)
33−{
34− Q_UNUSED(user)
35− Q_UNUSED(interface)
36− m_properties[property] = value;
37−}
38−
39−void AccountsServiceDBusAdaptor::setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value)
40−{
41− setUserProperty(user, interface, property, value);
42−}
tests/plugins/Unity/Launcher/AccountsServiceDBusAdaptor.hdeleted−47
@@ -1,47 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
18−#define UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
19−
20−#include <QMap>
21−#include <QObject>
22−#include <QString>
23−#include <QHash>
24−
25−class AccountsServiceDBusAdaptor: public QObject
26−{
27− Q_OBJECT
28−
29−public:
30− explicit AccountsServiceDBusAdaptor(QObject *parent = 0);
31−
32− Q_INVOKABLE QVariant getUserProperty(const QString &user, const QString &interface, const QString &property);
33− Q_INVOKABLE void setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value);
34− Q_INVOKABLE void setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value);
35−
36−Q_SIGNALS:
37− void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
38− void maybeChanged(const QString &user); // Standard properties might have changed
39−
40−private:
41− void simulatePropertyChange(const QString &property, const QVariant &value);
42−
43−private:
44− QHash<QString, QVariant> m_properties;
45−};
46−
47−#endif
tests/plugins/Unity/Launcher/CMakeLists.txt+8−2
@@ -4,6 +4,7 @@ pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
44include_directories(
55 ${CMAKE_CURRENT_SOURCE_DIR}
66 ${CMAKE_CURRENT_BINARY_DIR}
7+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
78 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher
89 ${GSETTINGS_QT_INCLUDE_DIRS}
910 ${libunity8-private_SOURCE_DIR}
@@ -17,7 +18,7 @@ add_definitions(-DLAUNCHER_TESTING)
1718add_executable(launchermodeltestExec
1819 launchermodeltest.cpp
1920 gsettings.cpp
20− AccountsServiceDBusAdaptor.cpp
21+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
2122 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launchermodel.cpp
2223 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/asadapter.cpp
2324 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launcheritem.cpp
@@ -35,11 +36,16 @@ target_link_libraries(launchermodeltestExec
3536 unity8-private
3637 ${GSETTINGS_QT_LDFLAGS}
3738 )
39+add_dependencies(launchermodeltestExec mock-server)
3840qt5_use_modules(launchermodeltestExec Test Core DBus Xml Gui)
3941
4042add_unity8_unittest(LauncherModel dbus-test-runner
4143 ARG_PREFIX "--parameter"
42− ARGS --task $<TARGET_FILE:launchermodeltestExec>
44+ ARGS
45+ --task $<TARGET_FILE:mock-server>
46+ --ignore-return
47+ --task $<TARGET_FILE:launchermodeltestExec>
48+ --wait-for org.freedesktop.Accounts
4349)
4450
4551# copy .desktop files into build directory for shadow builds
tests/plugins/Unity/Launcher/launchermodeltest.cpp+23−1
@@ -31,6 +31,7 @@
3131#include <QtTest>
3232#include <QDBusInterface>
3333#include <QDBusReply>
34+#include <QDBusMetaType>
3435#include <QDomDocument>
3536
3637// This is a mock, specifically to test the LauncherModel
@@ -135,12 +136,17 @@ private:
135136
136137 QList<QVariantMap> getASConfig() {
137138 AccountsServiceDBusAdaptor *as = launcherModel->m_asAdapter->m_accounts;
138− return as->getUserProperty("", "", "LauncherItems").value<QList<QVariantMap>>();
139+ QDBusReply<QVariant> reply = as->getUserPropertyAsync(QString(qgetenv("USER")),
140+ "com.canonical.unity.AccountsService",
141+ "LauncherItems");
142+ return qdbus_cast<QList<QVariantMap>>(reply.value().value<QDBusArgument>());
139143 }
140144
141145private Q_SLOTS:
142146
143147 void initTestCase() {
148+ qDBusRegisterMetaType<QList<QVariantMap>>();
149+
144150 launcherModel = new LauncherModel(this);
145151 QCoreApplication::processEvents(); // to let the model register on DBus
146152 QCOMPARE(launcherModel->rowCount(QModelIndex()), 0);
@@ -151,6 +157,14 @@ private Q_SLOTS:
151157
152158 // Adding 2 apps to the mock appmanager. Both should appear in the launcher.
153159 void init() {
160+ QDBusInterface accountsInterface(QStringLiteral("org.freedesktop.Accounts"),
161+ QStringLiteral("/org/freedesktop/Accounts"),
162+ QStringLiteral("org.freedesktop.Accounts"));
163+ QDBusReply<bool> addReply = accountsInterface.call(QStringLiteral("AddUser"),
164+ QString(qgetenv("USER")));
165+ QVERIFY(addReply.isValid());
166+ QCOMPARE(addReply.value(), true);
167+
154168 appManager->addApplication(new MockApp("abs-icon"));
155169 QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
156170
@@ -168,6 +182,14 @@ private Q_SLOTS:
168182 while (launcherModel->rowCount(QModelIndex()) > 0) {
169183 launcherModel->requestRemove(launcherModel->get(0)->appId());
170184 }
185+
186+ QDBusInterface accountsInterface(QStringLiteral("org.freedesktop.Accounts"),
187+ QStringLiteral("/org/freedesktop/Accounts"),
188+ QStringLiteral("org.freedesktop.Accounts"));
189+ QDBusReply<bool> removeReply = accountsInterface.call(QStringLiteral("RemoveUser"),
190+ QString(qgetenv("USER")));
191+ QVERIFY(removeReply.isValid());
192+ QCOMPARE(removeReply.value(), true);
171193 }
172194
173195 void testMove() {