on xenial help sign in
Merge greeter-guest
commit27fa2c9541836407f243d26bfd831f9697b019c6 authorMichael Terry <mike@mterry.name> dateThu 19 Jan 2017, 10:25 (10 years ago) parente3f492ed31f301
11 files changed+150−46
plugins/LightDM/Greeter.cpp+5 plugins/LightDM/IntegratedLightDM/liblightdm/Greeter.cpp+7−4 plugins/LightDM/IntegratedLightDM/liblightdm/GreeterPrivate.cpp+27−22 plugins/LightDM/IntegratedLightDM/liblightdm/GreeterPrivate.h+1 qml/Greeter/LoginList.qml−2 qml/Greeter/WideView.qml+1−4 tests/mocks/liblightdm/MockController.cpp+24 tests/mocks/liblightdm/MockController.h+15 tests/mocks/liblightdm/MockUsersModel.cpp+37−14 tests/mocks/liblightdm/MockUsersModel.h+2 tests/qmltests/Greeter/tst_WideView.qml+31
plugins/LightDM/Greeter.cpp+5
@@ -17,6 +17,7 @@
1717
1818#include "Greeter.h"
1919#include "GreeterPrivate.h"
20+#include <QCoreApplication>
2021#include <libintl.h>
2122
2223static Greeter *singleton = nullptr;
@@ -43,6 +44,10 @@ Greeter::Greeter(QObject* parent)
4344 connect(d->m_greeter, &QLightDM::Greeter::authenticationComplete,
4445 this, &Greeter::authenticationCompleteFilter);
4546
47+ // Don't get stuck waiting for PAM as we shut down.
48+ connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
49+ d->m_greeter, &QLightDM::Greeter::cancelAuthentication);
50+
4651 d->m_greeter->connectSync();
4752}
4853
plugins/LightDM/IntegratedLightDM/liblightdm/Greeter.cpp+7−4
@@ -49,7 +49,7 @@ QString Greeter::authenticationUser() const
4949
5050bool Greeter::hasGuestAccountHint() const
5151{
52− return true;
52+ return false;
5353}
5454
5555QString Greeter::getHint(const QString &name) const
@@ -70,12 +70,12 @@ bool Greeter::hideUsersHint() const
7070
7171bool Greeter::showManualLoginHint() const
7272{
73− return true;
73+ return false;
7474}
7575
7676bool Greeter::showRemoteLoginHint() const
7777{
78− return true;
78+ return false;
7979}
8080
8181QString Greeter::selectUserHint() const
@@ -146,7 +146,10 @@ void Greeter::authenticateRemote(const QString &session, const QString &username
146146}
147147
148148void Greeter::cancelAuthentication()
149−{}
149+{
150+ Q_D(Greeter);
151+ d->cancelAuthentication();
152+}
150153
151154void Greeter::setLanguage (const QString &language)
152155{
plugins/LightDM/IntegratedLightDM/liblightdm/GreeterPrivate.cpp+27−22
@@ -206,6 +206,28 @@ public Q_SLOTS:
206206 }
207207 }
208208
209+ void cancelPam()
210+ {
211+ if (pamHandle != nullptr) {
212+ QFuture<int> pamFuture = futureWatcher.future();
213+ pam_handle *handle = pamHandle;
214+ pamHandle = nullptr; // to disable normal finishPam() handling
215+ pamFuture.cancel();
216+
217+ // Note the empty loop, we just want to clear the futures queue.
218+ // Any further prompts from the pam thread will be immediately
219+ // responded to/dismissed in handlePrompt().
220+ while (respond(QString()));
221+
222+ // Now let signal/slot handling happen so the thread can finish
223+ while (!pamFuture.isFinished()) {
224+ QCoreApplication::processEvents();
225+ }
226+
227+ pam_end(handle, PAM_CONV_ERR);
228+ }
229+ }
230+
209231Q_SIGNALS:
210232 void showMessage(pam_handle *handle, QString text, QLightDM::Greeter::MessageType type);
211233 void showPrompt(pam_handle *handle, QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture response);
@@ -247,28 +269,6 @@ private Q_SLOTS:
247269 }
248270
249271private:
250− void cancelPam()
251− {
252− if (pamHandle != nullptr) {
253− QFuture<int> pamFuture = futureWatcher.future();
254− pam_handle *handle = pamHandle;
255− pamHandle = nullptr; // to disable normal finishPam() handling
256− pamFuture.cancel();
257−
258− // Note the empty loop, we just want to clear the futures queue.
259− // Any further prompts from the pam thread will be immediately
260− // responded to/dismissed in handlePrompt().
261− while (respond(QString()));
262−
263− // Now let signal/slot handling happen so the thread can finish
264− while (!pamFuture.isFinished()) {
265− QCoreApplication::processEvents();
266− }
267−
268− pam_end(handle, PAM_CONV_ERR);
269− }
270− }
271−
272272 Greeter *greeter;
273273 GreeterPrivate *greeterPrivate;
274274 pam_handle* pamHandle;
@@ -299,6 +299,11 @@ void GreeterPrivate::handleRespond(const QString &response)
299299 m_impl->respond(response);
300300}
301301
302+void GreeterPrivate::cancelAuthentication()
303+{
304+ m_impl->cancelPam();
305+}
306+
302307}
303308
304309#include "GreeterPrivate.moc"
plugins/LightDM/IntegratedLightDM/liblightdm/GreeterPrivate.h+1
@@ -38,6 +38,7 @@ public:
3838
3939 void handleAuthenticate();
4040 void handleRespond(const QString &response);
41+ void cancelAuthentication();
4142
4243protected:
4344 GreeterImpl *m_impl; // if the backend needs more private data
qml/Greeter/LoginList.qml−2
@@ -36,12 +36,10 @@ StyledItem {
3636 readonly property int cellHeight: units.gu(5)
3737 readonly property int highlightedHeight: units.gu(15)
3838 readonly property int moveDuration: UbuntuAnimation.FastDuration
39− property string selectedSession
4039 property string currentSession
4140 readonly property string currentUser: userList.currentItem.username
4241 property bool wasPrompted: false
4342
44− signal loginListSessionChanged(string session)
4543 signal responded(string response)
4644 signal selected(int index)
4745 signal sessionChooserButtonClicked()
qml/Greeter/WideView.qml+1−4
@@ -125,8 +125,6 @@ FocusScope {
125125 id: loginList
126126 objectName: "loginList"
127127
128− property int selectedUserIndex: 0
129−
130128 width: units.gu(40)
131129 anchors {
132130 left: parent.left
@@ -141,11 +139,10 @@ FocusScope {
141139 Behavior on boxVerticalOffset { UbuntuNumberAnimation {} }
142140
143141 model: root.userModel
144− currentSession: LightDMService.users.data(selectedUserIndex, LightDMService.userRoles.SessionRole);
145142 onResponded: root.responded(response)
146143 onSelected: {
147144 root.selected(index)
148− loginList.selectedUserIndex = index;
145+ currentSession = LightDMService.users.data(index, LightDMService.userRoles.SessionRole);
149146 }
150147 onSessionChooserButtonClicked: parent.state = "SessionsList"
151148
tests/mocks/liblightdm/MockController.cpp+24
@@ -152,6 +152,30 @@ void MockController::setUserMode(const QString &userMode)
152152 }
153153}
154154
155+QString MockController::sessionName() const
156+{
157+ return QString("INVALID - Please read directly from the UserModel");
158+}
159+
160+void MockController::setSessionName(const QString &sessionName)
161+{
162+ // Let the user model deal with this
163+ Q_EMIT sessionNameChanged(sessionName, m_currentUsername);
164+}
165+
166+QString MockController::currentUsername() const
167+{
168+ return m_currentUsername;
169+}
170+
171+void MockController::setCurrentUsername(const QString &username)
172+{
173+ if (m_currentUsername != username) {
174+ m_currentUsername = username;
175+ Q_EMIT currentUsernameChanged();
176+ }
177+}
178+
155179QString MockController::sessionMode() const
156180{
157181 return m_sessionMode;
tests/mocks/liblightdm/MockController.h+15
@@ -38,6 +38,11 @@ class Q_DECL_EXPORT MockController : public QObject
3838 // single, none, full
3939 Q_PROPERTY(QString sessionMode READ sessionMode WRITE setSessionMode NOTIFY sessionModeChanged)
4040
41+ // This would be best as a Q_INVOKABLE, but using a property allows for
42+ // keeping the mock cleaner
43+ Q_PROPERTY(QString sessionName READ sessionName WRITE setSessionName NOTIFY sessionNameChanged)
44+ Q_PROPERTY(QString currentUsername READ currentUsername WRITE setCurrentUsername NOTIFY currentUsernameChanged)
45+
4146 Q_PROPERTY(int numAvailableSessions READ numFullSessions CONSTANT)
4247 Q_PROPERTY(int numSessions READ numSessions WRITE setNumSessions NOTIFY numSessionsChanged)
4348
@@ -68,6 +73,12 @@ public:
6873 QString sessionMode() const;
6974 void setSessionMode(const QString &sessionMode);
7075
76+ QString sessionName() const;
77+ void setSessionName(const QString &userIndex);
78+
79+ QString currentUsername() const;
80+ void setCurrentUsername(const QString &username);
81+
7182 class SessionItem
7283 {
7384 public:
@@ -81,6 +92,7 @@ public:
8192 void setNumSessions(int numSessions);
8293
8394Q_SIGNALS:
95+ void currentUsernameChanged();
8496 void selectUserHintChanged();
8597 void selectGuestHintChanged();
8698 void hasGuestAccountHintChanged();
@@ -89,10 +101,13 @@ Q_SIGNALS:
89101 void userModeChanged();
90102 void sessionModeChanged();
91103 void numSessionsChanged();
104+ void sessionNameChanged(const QString &sessionName, const QString &username);
92105
93106private:
94107 explicit MockController(QObject* parent=0);
95108
109+ QString m_currentUsername;
110+ QString m_sessionName;
96111 QString m_selectUserHint;
97112 bool m_selectGuestHint;
98113 bool m_hasGuestAccountHint;
tests/mocks/liblightdm/MockUsersModel.cpp+37−14
@@ -73,6 +73,8 @@ UsersModel::UsersModel(QObject *parent)
7373 this, &UsersModel::resetEntries);
7474 connect(MockController::instance(), &MockController::userModeChanged,
7575 this, &UsersModel::resetEntries);
76+ connect(MockController::instance(), &MockController::sessionNameChanged,
77+ this, &UsersModel::setCurrentSessionName);
7678 resetEntries();
7779}
7880
@@ -81,6 +83,22 @@ UsersModel::~UsersModel()
8183 delete d_ptr;
8284}
8385
86+void UsersModel::setCurrentSessionName(const QString &sessionName, const QString &username)
87+{
88+ Q_D(UsersModel);
89+
90+ int usersIndex = 0;
91+ for (auto &entry : d->entries) {
92+ if (username == entry.username) {
93+ entry.session = sessionName;
94+ break;
95+ }
96+ usersIndex++;
97+ }
98+
99+ dataChanged(index(usersIndex, 0), index(usersIndex, 0), QVector<int>(SessionRole));
100+}
101+
84102int UsersModel::rowCount(const QModelIndex &parent) const
85103{
86104 Q_D(const UsersModel);
@@ -144,28 +162,33 @@ void UsersModel::resetEntries()
144162 } else if (userMode == "single-pin") {
145163 d->entries = {{"has-pin", "Has PIN", "", 0, false, false, "ubuntu", 0}};
146164 } else if (userMode == "full") {
165+ /*
166+ * Since the real model sorts these entries alphabetically, the model indices
167+ * don't line up correctly. The easiest way to fix this is to ensure that this
168+ * list of entries REMAINS IN ALPHABETICAL ORDER at all times.
169+ */
147170 d->entries = {
171+ { "active", "Active Account", 0, 0, true, false, "ubuntu", 0 },
172+ { "auth-error", "Auth Error", 0, 0, false, false, "ubuntu", 0 },
173+ { "black-background", "Black Background", "#000000", 0, false, false, "ubuntu", 0 },
174+ { "color-background", "Color Background", "#E95420", 0, false, false, "ubuntu", 0 },
175+ { "different-prompt", "Different Prompt", 0, 0, false, false, "ubuntu", 0 },
176+ { "empty-name", "", 0, 0, false, false, "ubuntu", 0 },
148177 { "has-password", "Has Password", 0, 0, false, false, "ubuntu", 0 },
149178 { "has-pin", "Has PIN", 0, 0, false, false, "ubuntu", 0 },
150− { "different-prompt", "Different Prompt", 0, 0, false, false, "ubuntu", 0 },
151− { "no-password", "No Password", 0, 0, false, false, "ubuntu", 0 },
152− { "auth-error", "Auth Error", 0, 0, false, false, "ubuntu", 0 },
153− { "two-factor", "Two Factor", 0, 0, false, false, "ubuntu", 0 },
154− { "info-prompt", "Info Prompt", 0, 0, false, false, "ubuntu", 0 },
155179 { "html-info-prompt", "HTML Info Prompt", 0, 0, false, false, "ubuntu", 0 },
180+ { "info-prompt", "Info Prompt", 0, 0, false, false, "ubuntu", 0 },
156181 { "long-info-prompt", "Long Info Prompt", 0, 0, false, false, "ubuntu", 0 },
157− { "wide-info-prompt", "Wide Info Prompt", 0, 0, false, false, "ubuntu", 0 },
158− { "multi-info-prompt", "Multi Info Prompt", 0, 0, false, false, "ubuntu", 0 },
159182 { "long-name", "Long name (far far too long to fit, seriously this would never fit on the screen, you will never see this part of the name)", 0, 0, false, false, "ubuntu", 0 },
160− { "color-background", "Color Background", "#E95420", 0, false, false, "ubuntu", 0 },
161− // white and black are a bit redundant, but useful for manually testing if UI is still readable
162− { "white-background", "White Background", "#ffffff", 0, false, false, "ubuntu", 0 },
163− { "black-background", "Black Background", "#000000", 0, false, false, "ubuntu", 0 },
183+ { "multi-info-prompt", "Multi Info Prompt", 0, 0, false, false, "ubuntu", 0 },
164184 { "no-background", "No Background", "", 0, false, false, "ubuntu", 0 },
165− { "unicode", "가나다라마", 0, 0, false, false, "ubuntu", 0 },
185+ { "no-password", "No Password", 0, 0, false, false, "ubuntu", 0 },
166186 { "no-response", "No Response", 0, 0, false, false, "ubuntu", 0 },
167− { "empty-name", "", 0, 0, false, false, "ubuntu", 0 },
168− { "active", "Active Account", 0, 0, true, false, "ubuntu", 0 },
187+ { "two-factor", "Two Factor", 0, 0, false, false, "ubuntu", 0 },
188+ { "unicode", "가나다라마", 0, 0, false, false, "ubuntu", 0 },
189+ // white and black are a bit redundant, but useful for manually testing if UI is still readable
190+ { "white-background", "White Background", "#ffffff", 0, false, false, "ubuntu", 0 },
191+ { "wide-info-prompt", "Wide Info Prompt", 0, 0, false, false, "ubuntu", 0 }
169192 };
170193 }
171194
tests/mocks/liblightdm/MockUsersModel.h+2
@@ -48,6 +48,8 @@ public:
4848 int rowCount(const QModelIndex &parent) const override;
4949 QVariant data(const QModelIndex &index, int role) const override;
5050
51+ void setCurrentSessionName(const QString &sessionName, const QString &username);
52+
5153private Q_SLOTS:
5254 void resetEntries();
5355
tests/qmltests/Greeter/tst_WideView.qml+31
@@ -411,6 +411,37 @@ StyledItem {
411411 waitForRendering(view);
412412 }
413413
414+ function test_changingSessionSticksToUser() {
415+ LightDMController.sessionMode = "full";
416+
417+ var loginList = findChild(view, "loginList");
418+ var fakeSession1 = "ASessionWillNeverBeCalledThis";
419+ var fakeSession2 = "ASessionWillAlsoNeverBeCalledThis";
420+
421+ // For this test to work, a user has to be selected and the
422+ // mock must be made aware of that user
423+ selectUser("has-password")
424+ LightDMController.currentUsername = "has-password"
425+ compare(LightDM.Sessions.count > 1, true);
426+ compare(loginList.currentSession != fakeSession1, true);
427+ LightDMController.sessionName = fakeSession1;
428+
429+ selectUser("has-pin")
430+ LightDMController.currentUsername = "has-pin"
431+ compare(loginList.currentSession != fakeSession2, true);
432+ LightDMController.sessionName = fakeSession2;
433+
434+ selectUser("has-password")
435+ tryCompare(loginList, "currentSession", fakeSession1);
436+
437+ selectUser("has-pin")
438+ tryCompare(loginList, "currentSession", fakeSession2);
439+
440+ // Force a model reset
441+ LightDMController.userMode = "single";
442+ LightDMController.userMode = "full";
443+ }
444+
414445 function test_tease_data() {
415446 return [
416447 {tag: "locked", x: 0, offset: 0, count: 0, locked: true},