on fe71e21 help sign in
unity8/tests/mocks/liblightdm/MockGreeter.cpp
316 lines 8.9 kB history raw
1/*
2 * Copyright (C) 2014-2017 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 */
17#include "MockController.h"
18#include "MockGreeter.h"
19#include <QDBusInterface>
20#include <QDBusPendingCall>
21#include <QTimer>
23namespace QLightDM
26class GreeterPrivate
28public:
29 bool authenticated = false;
30 QString authenticationUser;
31 bool twoFactorDone = false;
32 QTimer authCallbackTimer;
33};
35Greeter::Greeter(QObject *parent)
36 : QObject(parent)
37 , d_ptr(new GreeterPrivate)
39 Q_D(Greeter);
41 d->authCallbackTimer.setSingleShot(true);
42 connect(&d->authCallbackTimer, &QTimer::timeout,
43 this, &QLightDM::Greeter::handleAuthenticate);
46Greeter::~Greeter()
48 delete d_ptr;
51QString Greeter::authenticationUser() const
53 Q_D(const Greeter);
55 return d->authenticationUser;
58bool Greeter::hasGuestAccountHint() const
60 return MockController::instance()->hasGuestAccountHint();
63QString Greeter::getHint(const QString &name) const
65 Q_UNUSED(name)
66 return "";
69QString Greeter::defaultSessionHint() const
71 return QStringLiteral("ubuntu");
74bool Greeter::hideUsersHint() const
76 return MockController::instance()->hideUsersHint();
79bool Greeter::showManualLoginHint() const
81 return MockController::instance()->showManualLoginHint();
84bool Greeter::showRemoteLoginHint() const
86 return false;
89QString Greeter::selectUserHint() const
91 return MockController::instance()->selectUserHint();
94bool Greeter::selectGuestHint() const
96 return MockController::instance()->selectGuestHint();
99QString Greeter::autologinUserHint() const
101 return "";
104bool Greeter::autologinGuestHint() const
106 return false;
109int Greeter::autologinTimeoutHint() const
111 return 0;
114bool Greeter::inAuthentication() const
116 return false;
119QString Greeter::hostname() const
121 return "hostname1";
124bool Greeter::isAuthenticated() const
126 Q_D(const Greeter);
128 return d->authenticated;
131bool Greeter::connectSync()
133 return true;
136void Greeter::authenticate(const QString &username)
138 Q_D(Greeter);
140 d->authenticated = false;
141 d->authenticationUser = username;
142 d->twoFactorDone = false;
143 d->authCallbackTimer.start();
146void Greeter::handleAuthenticate()
148 Q_D(Greeter);
150 if (d->authenticated) {
151 // This can happen from the guest authentication flow
152 Q_EMIT authenticationComplete();
153 return;
154 }
156 if (d->authenticationUser.isEmpty()) {
157 Q_EMIT showPrompt("Username: ", Greeter::PromptTypeQuestion);
158 return;
159 }
161 // Send out any messages we need to
162 if (d->authenticationUser == "info-prompt")
163 Q_EMIT showMessage("Welcome to Unity Greeter", Greeter::MessageTypeInfo);
164 else if (d->authenticationUser == "wide-info-prompt")
165 Q_EMIT showMessage("Welcome to Unity Greeter, the greeteriest greeter that ever did appear in these fine lands", Greeter::MessageTypeInfo);
166 else if (d->authenticationUser == "html-info-prompt")
167 Q_EMIT showMessage("<b>&</b>", Greeter::MessageTypeInfo);
168 else if (d->authenticationUser == "long-info-prompt")
169 Q_EMIT showMessage("Welcome to Unity Greeter\n\nWe like to annoy you with super ridiculously long messages.\nLike this one\n\nThis is the last line of a multiple line message.", Greeter::MessageTypeInfo);
170 else if (d->authenticationUser == "multi-info-prompt") {
171 Q_EMIT showMessage("Welcome to Unity Greeter", Greeter::MessageTypeInfo);
172 Q_EMIT showMessage("This is an error", Greeter::MessageTypeError);
173 Q_EMIT showMessage("You should have seen three messages", Greeter::MessageTypeInfo);
174 }
176 // OK, now actually do the prompt
177 if (d->authenticationUser == "no-password") {
178 d->authenticated = true;
179 Q_EMIT authenticationComplete();
180 } else if (d->authenticationUser == "has-pin") {
181 Q_EMIT showPrompt("Password: ", Greeter::PromptTypeSecret);
182 } else if (d->authenticationUser == "auth-error") {
183 d->authenticated = false;
184 Q_EMIT authenticationComplete();
185 } else if (d->authenticationUser == "different-prompt") {
186 Q_EMIT showPrompt("Secret word: ", Greeter::PromptTypeSecret);
187 } else if (d->authenticationUser == "question-prompt") {
188 Q_EMIT showPrompt("Favorite Color (blue): ", Greeter::PromptTypeQuestion);
189 } else if (d->authenticationUser == "two-prompts") {
190 Q_EMIT showPrompt("Favorite Color (blue):", Greeter::PromptTypeQuestion);
191 Q_EMIT showPrompt("Password: ", Greeter::PromptTypeSecret);
192 } else if (d->authenticationUser == "wacky-prompts") {
193 Q_EMIT showMessage("First message", Greeter::MessageTypeInfo);
194 Q_EMIT showPrompt("Favorite Color (blue)", Greeter::PromptTypeQuestion);
195 Q_EMIT showMessage("Second message", Greeter::MessageTypeError);
196 Q_EMIT showPrompt("Password: ", Greeter::PromptTypeSecret);
197 Q_EMIT showMessage("Last message", Greeter::MessageTypeInfo);
198 } else {
199 Q_EMIT showPrompt("Password: ", Greeter::PromptTypeSecret);
200 }
203void Greeter::authenticateAsGuest()
205 Q_D(Greeter);
207 d->authenticated = true;
208 d->authenticationUser = QString(); // this is what the real liblightdm does
209 d->twoFactorDone = false;
210 d->authCallbackTimer.start();
213void Greeter::authenticateAutologin()
214{}
216void Greeter::authenticateRemote(const QString &session, const QString &username)
218 Q_UNUSED(session)
219 Q_UNUSED(username)
222void Greeter::cancelAuthentication()
224 Q_D(Greeter);
225 d->authCallbackTimer.stop();
228void Greeter::setLanguage (const QString &language)
230 Q_UNUSED(language)
233bool Greeter::startSessionSync(const QString &session)
235 Q_UNUSED(session)
237 // Send a request to hide the greeter. This is normally done by logind,
238 // but when testing, we don't want the bother of mocking that out. Instead,
239 // just send the request directly ourselves.
240 QDBusInterface iface("com.canonical.UnityGreeter",
241 "/",
242 "com.canonical.UnityGreeter",
243 QDBusConnection::sessionBus());
244 iface.asyncCall("HideGreeter");
246 return true;
249void Greeter::respond(const QString &response)
251 Q_D(Greeter);
253 if (d->authenticationUser.isEmpty()) {
254 // A manual login, our first question was which username
255 d->authenticationUser = response;
256 handleAuthenticate();
257 return;
258 }
260 if (d->authenticationUser == "no-response") {
261 return;
262 } else if (d->authenticationUser == "locked") {
263 Q_EMIT showMessage("Account is locked", Greeter::MessageTypeError);
264 sendAuthenticationComplete();
265 return;
266 } else if (d->authenticationUser == "two-factor") {
267 if (!d->twoFactorDone) {
268 if (response == "password") {
269 d->twoFactorDone = true;
270 Q_EMIT showPrompt("otp", Greeter::PromptTypeQuestion);
271 } else {
272 d->authenticated = false;
273 sendAuthenticationComplete();
274 }
275 } else {
276 d->authenticated = (response == "otp");
277 sendAuthenticationComplete();
278 }
279 return;
280 } else if (d->authenticationUser == "two-prompts" || d->authenticationUser == "wacky-prompts") {
281 if (!d->twoFactorDone) {
282 d->authenticated = (response == "blue");
283 d->twoFactorDone = true;
284 } else {
285 d->authenticated = d->authenticated && (response == "password");
286 sendAuthenticationComplete();
287 }
288 return;
289 }
291 if (d->authenticationUser == "has-pin") {
292 d->authenticated = (response == "1234");
293 } else if (d->authenticationUser == "question-prompt") {
294 d->authenticated = (response == "blue");
295 } else {
296 d->authenticated = (response == "password");
297 }
299 if (d->authenticationUser == "info-after-login" && d->authenticated) {
300 Q_EMIT showMessage("Congratulations on logging in!", Greeter::MessageTypeInfo);
301 }
303 sendAuthenticationComplete();
306void Greeter::sendAuthenticationComplete()
308 if (qEnvironmentVariableIsEmpty("UNITY_TESTING")) {
309 // simulate PAM's delay
310 QTimer::singleShot(1000, this, &Greeter::authenticationComplete);
311 } else {
312 Q_EMIT authenticationComplete();
313 }