on xenial help sign in
And handle proper DBus signals for our properties too
5e8e0f5Michael Terry
plugins/LightDM/DBusGreeterList.cpp+40−4
@@ -17,12 +17,17 @@
17#include "DBusGreeterList.h"
17#include "DBusGreeterList.h"
18#include "Greeter.h"
18#include "Greeter.h"
19
19
20+#include <QDBusMessage>
21+#include <QStringList>
22+
20−DBusGreeterList::DBusGreeterList(Greeter *greeter)
23+DBusGreeterList::DBusGreeterList(Greeter *greeter, const QDBusConnection &connection, const QString &path)
21 : QObject(greeter),
24 : QObject(greeter),
22− m_greeter(greeter)
25+ m_greeter(greeter),
26+ m_connection(connection),
27+ m_path(path)
23{
28{
24− connect(m_greeter, SIGNAL(authenticationUserChanged(const QString &)), this, SIGNAL(EntrySelected(const QString &)));
29+ connect(m_greeter, SIGNAL(authenticationUserChanged(const QString &)), this, SLOT(authenticationUserChangedHandler(const QString &)));
25− connect(m_greeter, SIGNAL(promptlessChanged()), this, SIGNAL(entryIsLockedChanged()));
30+ connect(m_greeter, SIGNAL(promptlessChanged()), this, SLOT(promptlessChangedHandler()));
26}
31}
27
32
28QString DBusGreeterList::GetActiveEntry() const
33QString DBusGreeterList::GetActiveEntry() const
@@ -39,3 +44,34 @@ bool DBusGreeterList::entryIsLocked() const
39{
44{
40 return !m_greeter->promptless();
45 return !m_greeter->promptless();
41}
46}
47+
48+void DBusGreeterList::authenticationUserChangedHandler(const QString &user)
49+{
50+ notifyPropertyChanged("ActiveEntry", user);
51+ Q_EMIT EntrySelected(user);
52+}
53+
54+void DBusGreeterList::promptlessChangedHandler()
55+{
56+ notifyPropertyChanged("EntryIsLocked", entryIsLocked());
57+ Q_EMIT entryIsLockedChanged();
58+}
59+
60+// Manually emit a PropertiesChanged signal over DBus, because QtDBus
61+// doesn't do it for us on Q_PROPERTIES, oddly enough.
62+void DBusGreeterList::notifyPropertyChanged(const QString& propertyName, const QVariant &value)
63+{
64+ QDBusMessage message;
65+ QVariantMap changedProps;
66+
67+ changedProps.insert(propertyName, value);
68+
69+ message = QDBusMessage::createSignal(m_path,
70+ "org.freedesktop.DBus.Properties",
71+ "PropertiesChanged");
72+ message << "com.canonical.UnityGreeter.List";
73+ message << changedProps;
74+ message << QStringList();
75+
76+ m_connection.send(message);
77+}
plugins/LightDM/DBusGreeterList.h+9−1
@@ -17,6 +17,7 @@
17#ifndef UNITY_DBUSGREETERLIST_H
17#ifndef UNITY_DBUSGREETERLIST_H
18#define UNITY_DBUSGREETERLIST_H
18#define UNITY_DBUSGREETERLIST_H
19
19
20+#include <QDBusConnection>
20#include <QObject>
21#include <QObject>
21
22
22class Greeter;
23class Greeter;
@@ -34,7 +35,7 @@ class DBusGreeterList : public QObject
34 Q_PROPERTY(bool EntryIsLocked READ entryIsLocked NOTIFY entryIsLockedChanged) // since 14.04
35 Q_PROPERTY(bool EntryIsLocked READ entryIsLocked NOTIFY entryIsLockedChanged) // since 14.04
35
36
36public:
37public:
37− explicit DBusGreeterList(Greeter *greeter);
38+ explicit DBusGreeterList(Greeter *greeter, const QDBusConnection &connection, const QString &path);
38
39
39 Q_SCRIPTABLE void SetActiveEntry(const QString &entry); // since 13.04
40 Q_SCRIPTABLE void SetActiveEntry(const QString &entry); // since 13.04
40 Q_SCRIPTABLE QString GetActiveEntry() const; // since 13.10
41 Q_SCRIPTABLE QString GetActiveEntry() const; // since 13.10
@@ -46,8 +47,15 @@ Q_SIGNALS:
46
47
47 void entryIsLockedChanged();
48 void entryIsLockedChanged();
48
49
50+private Q_SLOTS:
51+ void authenticationUserChangedHandler(const QString &user);
52+ void promptlessChangedHandler();
53+ void notifyPropertyChanged(const QString &propertyName, const QVariant &value);
54+
49private:
55private:
50 Greeter *m_greeter;
56 Greeter *m_greeter;
57+ QDBusConnection m_connection;
58+ QString m_path;
51};
59};
52
60
53#endif
61#endif
plugins/LightDM/plugin.cpp+4−3
@@ -38,9 +38,10 @@ static QObject *greeter_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
38 Q_UNUSED(scriptEngine)
38 Q_UNUSED(scriptEngine)
39
39
40 Greeter *greeter = new Greeter();
40 Greeter *greeter = new Greeter();
41+ QDBusConnection connection = QDBusConnection::sessionBus();
41− DBusGreeterList *list = new DBusGreeterList(greeter);
42+ DBusGreeterList *list = new DBusGreeterList(greeter, connection, GREETER_LIST_DBUS_PATH);
42− QDBusConnection::sessionBus().registerObject(GREETER_LIST_DBUS_PATH, list, QDBusConnection::ExportScriptableContents);
43+ connection.registerObject(GREETER_LIST_DBUS_PATH, list, QDBusConnection::ExportScriptableContents);
43− QDBusConnection::sessionBus().registerService(GREETER_DBUS_SERVICE);
44+ connection.registerService(GREETER_DBUS_SERVICE);
44
45
45 return greeter;
46 return greeter;
46}
47}
tests/plugins/LightDM/CMakeLists.txt+1
@@ -19,5 +19,6 @@ target_link_libraries(test-lightdm-dbus
19add_definitions(-DCURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
19add_definitions(-DCURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
20
20
21add_custom_target(testLightDMDBus dbus-launch env QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full ${CMAKE_CURRENT_BINARY_DIR}/test-lightdm-dbus)
21add_custom_target(testLightDMDBus dbus-launch env QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full ${CMAKE_CURRENT_BINARY_DIR}/test-lightdm-dbus)
22+add_dependencies(testLightDMDBus test-lightdm-dbus)
22
23
23add_dependencies(qmluitests testLightDMDBus)
24add_dependencies(qmluitests testLightDMDBus)
tests/plugins/LightDM/dbus.cpp+47−1
@@ -27,8 +27,26 @@ class GreeterDBusTest : public QObject
27{
27{
28 Q_OBJECT
28 Q_OBJECT
29
29
30+Q_SIGNALS:
31+ void PropertiesChangedRelay(const QString &interface, const QVariantMap &changed, const QStringList &invalidated);
32+
30private Q_SLOTS:
33private Q_SLOTS:
31
34
35+ void initTestCase()
36+ {
37+ // Qt doesn't like us connecting to PropertiesChanged using normal
38+ // SIGNAL method, because QtDBus doesn't know about PropertiesChanged.
39+ // So we connect the hard way for the benefit of any tests that want
40+ // to watch.
41+ QDBusConnection::sessionBus().connect(
42+ "com.canonical.UnityGreeter",
43+ "/list",
44+ "org.freedesktop.DBus.Properties",
45+ "PropertiesChanged",
46+ this,
47+ SIGNAL(PropertiesChangedRelay(const QString&, const QVariantMap&, const QStringList&)));
48+ }
49+
32 void init()
50 void init()
33 {
51 {
34 view = new QQuickView();
52 view = new QQuickView();
@@ -100,13 +118,41 @@ private Q_SLOTS:
100 QVERIFY(arguments.at(0).toString() == "has-password");
118 QVERIFY(arguments.at(0).toString() == "has-password");
101 }
119 }
102
120
103− void testEntryIsLockedGet()
121+ void testActiveEntryChanged()
104 {
122 {
123+ QSignalSpy spy(this, SIGNAL(PropertiesChangedRelay(QString, QVariantMap, QStringList)));
105 greeter->authenticate("has-password");
124 greeter->authenticate("has-password");
125+ spy.wait();
126+
127+ QCOMPARE(spy.count(), 1);
128+ QList<QVariant> arguments = spy.takeFirst();
129+ QVERIFY(arguments.at(0).toString() == "com.canonical.UnityGreeter.List");
130+ QVERIFY(arguments.at(1).toMap().contains("ActiveEntry"));
131+ QVERIFY(arguments.at(1).toMap()["ActiveEntry"] == "has-password");
132+ }
133+
134+ void testEntryIsLockedGet()
135+ {
106 QVERIFY(dbusList->property("EntryIsLocked").toBool());
136 QVERIFY(dbusList->property("EntryIsLocked").toBool());
107
137
108 greeter->authenticate("no-password");
138 greeter->authenticate("no-password");
109 QVERIFY(!dbusList->property("EntryIsLocked").toBool());
139 QVERIFY(!dbusList->property("EntryIsLocked").toBool());
140+
141+ greeter->authenticate("has-password");
142+ QVERIFY(dbusList->property("EntryIsLocked").toBool());
143+ }
144+
145+ void testEntryIsLockedChanged()
146+ {
147+ QSignalSpy spy(this, SIGNAL(PropertiesChangedRelay(QString, QVariantMap, QStringList)));
148+ greeter->authenticate("no-password");
149+ spy.wait();
150+
151+ QCOMPARE(spy.count(), 2); // once for locked, once for user; first will be locked mode
152+ QList<QVariant> arguments = spy.takeFirst();
153+ QVERIFY(arguments.at(0).toString() == "com.canonical.UnityGreeter.List");
154+ QVERIFY(arguments.at(1).toMap().contains("EntryIsLocked"));
155+ QVERIFY(arguments.at(1).toMap()["EntryIsLocked"] == false);
110 }
156 }
111
157
112private:
158private: