Merge lp:~mterry/unity8/locking-hash into lp:unity8
- locking-hash
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Michał Sawicz |
Approved revision: | 999 |
Merged at revision: | 1090 |
Proposed branch: | lp:~mterry/unity8/locking-hash |
Merge into: | lp:unity8 |
Prerequisite: | lp:~mterry/unity8/dialer-above |
Diff against target: |
845 lines (+338/-75) 20 files modified
debian/control (+1/-0) plugins/AccountsService/AccountsService.cpp (+21/-1) plugins/AccountsService/AccountsService.h (+13/-0) plugins/AccountsService/plugin.cpp (+1/-0) plugins/LightDM/plugin.cpp (+2/-0) qml/Components/PassphraseLockscreen.qml (+3/-0) qml/Shell.qml (+27/-21) run.sh (+15/-6) tests/mocks/AccountsService/AccountsService.cpp (+12/-2) tests/mocks/AccountsService/AccountsService.h (+12/-0) tests/mocks/AccountsService/CMakeLists.txt (+4/-1) tests/mocks/AccountsService/plugin.cpp (+1/-0) tests/mocks/LightDM/GreeterPrivate.h (+2/-0) tests/mocks/LightDM/demo/CMakeLists.txt (+4/-2) tests/mocks/LightDM/demo/GreeterPrivate.cpp (+205/-33) tests/mocks/LightDM/demo/UsersModelPrivate.cpp (+1/-1) tests/mocks/LightDM/full/GreeterPrivate.cpp (+1/-1) tests/mocks/LightDM/single-pin/GreeterPrivate.cpp (+1/-1) tests/mocks/LightDM/single-pin/UsersModelPrivate.cpp (+1/-1) tests/qmltests/Greeter/tst_Lockscreen.qml (+11/-5) |
To merge this branch: | bzr merge lp:~mterry/unity8/locking-hash |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Albert Astals Cid (community) | Abstain | ||
Michał Sawicz | Approve | ||
Seth Arnold (community) | Approve | ||
Marc Deslauriers | Pending | ||
Review via email: mp+225538@code.launchpad.net |
Commit message
Check user's pin/password using PAM, instead of a plaintext keyfile.
New build dependency: libpam0g-dev for phone unlock with PAM
Description of the change
Check user's pin/password using PAM, instead of a plaintext keyfile.
== Checklist ==
* Are there any related MPs required for this MP to build/function as expected? Please list.
- lp:~mterry/gsettings-ubuntu-touch-schemas/password-hint
- https:/
- https:/
* Did you perform an exploratory manual test run of your code change and any related functionality?
- Yes
* Did you make sure that your branch does not contain spurious tags?
- Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
- I am in that team
* If you changed the UI, has there been a design review?
- NA
Michael Terry (mterry) wrote : | # |
Stéphane Graber (stgraber) wrote : | # |
Why the added build-dep and dep on whois? I fail to see how querying an RFC 3912 online database is even remotely related to unity8 :)
Michael Terry (mterry) wrote : | # |
> Why the added build-dep and dep on whois?
> I fail to see how querying an RFC 3912 online
> database is even remotely related to unity8 :)
Oh whoops, I forgot to push to the branch again. That's gone now. It was there from the previous incarnation of this branch, which put shadow-style entries into a keyfile in the user's HOME.
Oddly enough, whois contains the mkpasswd executable.
Seth Arnold (seth-arnold) wrote : | # |
This looks great. I think I found one minor bug, have some large questions about the goals and implementation, and then some further clarifying questions.
First, the minor bug:
- pamStatus isn't updated after pam_setcreds()
Next, I noticed that there's no use of PAM sessions, initgroups(), or set*id() functions; this might be consistent with single-user phones, but it would probably need extending to support multiple users. Are we aiming for multiple user support?
What are we missing by not supporting pam_open_session()? (ecryptfs and auditing at least; what else?)
Would we need to fork() a new process for the session, groups, and user change, so that the parent could still have sufficient privileges to call pam_close_session() at the end?
The PAM application developer guide mentions the PAM_USER, PAM_RUSER, and PAM_RHOST variables; I don't know how important these are for our uses but we might want to set them all the same so we provide the widest amount of compatibility with existing PAM modules.
I think we can merge this after the minor pamStatus = pam_setcreds() fixup regardless of the answers to my questions -- they'll either be bug fixes or new features that we can handle in good time.
Thanks
Michael Terry (mterry) wrote : | # |
The pam flow, including not changing pamStatus after pam_setcred and not using session is all stolen from ./lockscreen/
Specifically about pam_setcred, even sudo ignores the return (from ./plugins/
* We don't worry about a failure from pam_setcred() since with
* stacked PAM auth modules a failure from one module may override
* PAM_SUCCESS from another. For example, given a non-local user,
* pam_unix will fail but pam_ldap or pam_sss may succeed, but if
* pam_unix is first in the stack, pam_setcred() will fail.
> Are we aiming for multiple user support?
Not on this screen, no. This is the equivalent of the unity7 lock screen. (When the user sees this, we've already logged them in and presented the "greeter" as a lock screen.) So no worries about ecryptfs etc either. That isn't in scope unless we have a proper split greeter, for which this branch is an interim alternative.
Seth Arnold (seth-arnold) wrote : | # |
Michael, thanks for the detailed answers. Very nice.
Thanks!
Michał Sawicz (saviq) wrote : | # |
In general I'm in favour of bracketing single-line if/else()s, but I won't hold it against you.
Is there any chance of stuff getting out of sync (like response coming to a different future than expected)? Should we pass around an id of the message and expect it back from the prompt?
Is there any chance of futureWatcher.
I tried to run it with ./run.sh, got the password prompt, but couldn't authenticated, that expected?
Also see inline.
Really like the approach!
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:990
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michael Terry (mterry) wrote : | # |
> In general I'm in favour of bracketing single-line if/else()s, but I won't hold it against you.
I added a few more brackets.
> Is there any chance of stuff getting out of sync (like response coming to a different future than expected)? Should we pass around an id of the message and expect it back from the prompt?
Shouldn't be. That's up the to the UI side of things to make sure to give back a response for each prompt in order. Order is important with PAM prompts, so we don't expect a UI component to present them out of order.
> Is there any chance of futureWatcher.
No, futureWatcher.
> I tried to run it with ./run.sh, got the password prompt, but couldn't authenticated, that expected?
Fixed. I'm so used to testing on the device, that I didn't notice we still hardcode the phablet user in one place.
> Also see inline.
Replies inline. Except all of a sudden LP wouldn't let me edit or make new comments. So here's a little bit extra:
Regarding whether to call it a mock, I will say that it *is* a mock for liblightdm-qt5. It's just a functional one.
And as for qRegisterMetaType, it only seems to work with that method. Note this section of the documenation for Q_DECLARE_METATYPE:
"Note that if you intend to use the type in queued signal and slot connections or in QObject's property system, you also have to call qRegisterMetaType() since the names are resolved at runtime."
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:992
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:994
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:995
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michał Sawicz (saviq) wrote : | # |
> Replies inline. Except all of a sudden LP wouldn't let me edit or make new
> comments. So here's a little bit extra:
Sounds like you didn't press "save" on one of them, it will then prevent you from doing changes to any other.
> And as for qRegisterMetaType, it only seems to work with that method. Note
> this section of the documenation for Q_DECLARE_METATYPE:
>
> "Note that if you intend to use the type in queued signal and slot connections
> or in QObject's property system, you also have to call qRegisterMetaType()
> since the names are resolved at runtime."
Yeah, the thing is they should get registered as you register the singletons, off which you then take the enum values... Basically what I'm saying we barely have this anywhere else, and using singletons and enums everywhere.
Hmm ah-ha! plugins/
=====
Can we do anything about the fact that now while developing this will generally require a password?
Should we in ./run.sh and ./run_on_device preload a passwordless LightDM mock?
=====
See inline.
Michael Terry (mterry) wrote : | # |
> Should we in ./run.sh and ./run_on_device preload a passwordless LightDM mock?
Isn't that what -f is for?
What might be nice is once I have re-split the greeter again, by default ./run.sh can give you just the dash. But passing -G or some such will give you greeter too.
> Basically what I'm saying we barely have this anywhere else, and using singletons and enums everywhere.
OK, will give this another look.
Michael Terry (mterry) wrote : | # |
> Hmm ah-ha! plugins/
The Q_ENUMS definition for those is in tests/mocks/
"QObject::connect: Cannot queue arguments of type 'QLightDM:
(Make sure 'QLightDM:
Which seems to coincide with the documentation comments about queued connection arguments.
Probably the reason it is necessary here is that we never actually call qmlRegisterSing
Michael Terry (mterry) wrote : | # |
OK, made it so that even just plain ./run.sh will skip requiring a password.
Seth Arnold (seth-arnold) wrote : | # |
Sorry, I forgot to mark this "Approve" after an earlier review and feedback from Michael.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:996
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michał Sawicz (saviq) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes.
* Did CI run pass? If not, please explain why.
Jenkins is unhappy today.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:996
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Albert Astals Cid (aacid) wrote : | # |
Text conflict in debian/control
1 conflicts encountered.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:997
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 998. By Michael Terry
-
Merge from trunk
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:998
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 999. By Michael Terry
-
Merge from trunk
Albert Astals Cid (aacid) wrote : | # |
Merges cleanly now
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:999
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:999
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2014-07-24 20:40:44 +0000 |
3 | +++ debian/control 2014-07-25 13:39:35 +0000 |
4 | @@ -19,6 +19,7 @@ |
5 | libgsettings-qt-dev, |
6 | libhardware-dev, |
7 | libhud-client2-dev, |
8 | + libpam0g-dev, |
9 | libpay2-dev, |
10 | libpulse-dev, |
11 | libqmenumodel-dev (>= 0.2.8), |
12 | |
13 | === modified file 'plugins/AccountsService/AccountsService.cpp' |
14 | --- plugins/AccountsService/AccountsService.cpp 2014-06-11 15:36:51 +0000 |
15 | +++ plugins/AccountsService/AccountsService.cpp 2014-07-25 13:39:35 +0000 |
16 | @@ -26,7 +26,8 @@ |
17 | m_service(new AccountsServiceDBusAdaptor(this)), |
18 | m_user(qgetenv("USER")), |
19 | m_demoEdges(false), |
20 | - m_statsWelcomeScreen(false) |
21 | + m_statsWelcomeScreen(false), |
22 | + m_passwordDisplayHint(Keyboard) |
23 | { |
24 | connect(m_service, SIGNAL(propertiesChanged(const QString &, const QString &, const QStringList &)), |
25 | this, SLOT(propertiesChanged(const QString &, const QString &, const QStringList &))); |
26 | @@ -47,6 +48,7 @@ |
27 | updateDemoEdges(); |
28 | updateBackgroundFile(); |
29 | updateStatsWelcomeScreen(); |
30 | + updatePasswordDisplayHint(); |
31 | } |
32 | |
33 | bool AccountsService::demoEdges() const |
34 | @@ -70,6 +72,11 @@ |
35 | return m_statsWelcomeScreen; |
36 | } |
37 | |
38 | +AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const |
39 | +{ |
40 | + return m_passwordDisplayHint; |
41 | +} |
42 | + |
43 | void AccountsService::updateDemoEdges() |
44 | { |
45 | auto demoEdges = m_service->getUserProperty(m_user, "com.canonical.unity.AccountsService", "demo-edges").toBool(); |
46 | @@ -97,6 +104,15 @@ |
47 | } |
48 | } |
49 | |
50 | +void AccountsService::updatePasswordDisplayHint() |
51 | +{ |
52 | + PasswordDisplayHint passwordDisplayHint = (PasswordDisplayHint)m_service->getUserProperty(m_user, "com.ubuntu.AccountsService.SecurityPrivacy", "PasswordDisplayHint").toInt(); |
53 | + if (m_passwordDisplayHint != passwordDisplayHint) { |
54 | + m_passwordDisplayHint = passwordDisplayHint; |
55 | + Q_EMIT passwordDisplayHintChanged(); |
56 | + } |
57 | +} |
58 | + |
59 | void AccountsService::propertiesChanged(const QString &user, const QString &interface, const QStringList &changed) |
60 | { |
61 | if (m_user != user) { |
62 | @@ -111,6 +127,10 @@ |
63 | if (changed.contains("StatsWelcomeScreen")) { |
64 | updateStatsWelcomeScreen(); |
65 | } |
66 | + } else if (interface == "com.ubuntu.AccountsService.SecurityPrivacy") { |
67 | + if (changed.contains("PasswordDisplayHint")) { |
68 | + updatePasswordDisplayHint(); |
69 | + } |
70 | } |
71 | } |
72 | |
73 | |
74 | === modified file 'plugins/AccountsService/AccountsService.h' |
75 | --- plugins/AccountsService/AccountsService.h 2014-06-11 15:36:51 +0000 |
76 | +++ plugins/AccountsService/AccountsService.h 2014-07-25 13:39:35 +0000 |
77 | @@ -27,6 +27,7 @@ |
78 | class AccountsService: public QObject |
79 | { |
80 | Q_OBJECT |
81 | + Q_ENUMS(PasswordDisplayHint) |
82 | Q_PROPERTY (QString user |
83 | READ user |
84 | WRITE setUser |
85 | @@ -41,8 +42,16 @@ |
86 | Q_PROPERTY (bool statsWelcomeScreen |
87 | READ statsWelcomeScreen |
88 | NOTIFY statsWelcomeScreenChanged) |
89 | + Q_PROPERTY (PasswordDisplayHint passwordDisplayHint |
90 | + READ passwordDisplayHint |
91 | + NOTIFY passwordDisplayHintChanged) |
92 | |
93 | public: |
94 | + enum PasswordDisplayHint { |
95 | + Keyboard, |
96 | + Numeric, |
97 | + }; |
98 | + |
99 | explicit AccountsService(QObject *parent = 0); |
100 | |
101 | QString user() const; |
102 | @@ -51,12 +60,14 @@ |
103 | void setDemoEdges(bool demoEdges); |
104 | QString backgroundFile() const; |
105 | bool statsWelcomeScreen() const; |
106 | + PasswordDisplayHint passwordDisplayHint() const; |
107 | |
108 | Q_SIGNALS: |
109 | void userChanged(); |
110 | void demoEdgesChanged(); |
111 | void backgroundFileChanged(); |
112 | void statsWelcomeScreenChanged(); |
113 | + void passwordDisplayHintChanged(); |
114 | |
115 | private Q_SLOTS: |
116 | void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed); |
117 | @@ -66,12 +77,14 @@ |
118 | void updateDemoEdges(); |
119 | void updateBackgroundFile(); |
120 | void updateStatsWelcomeScreen(); |
121 | + void updatePasswordDisplayHint(); |
122 | |
123 | AccountsServiceDBusAdaptor *m_service; |
124 | QString m_user; |
125 | bool m_demoEdges; |
126 | QString m_backgroundFile; |
127 | bool m_statsWelcomeScreen; |
128 | + PasswordDisplayHint m_passwordDisplayHint; |
129 | }; |
130 | |
131 | #endif |
132 | |
133 | === modified file 'plugins/AccountsService/plugin.cpp' |
134 | --- plugins/AccountsService/plugin.cpp 2013-11-19 17:01:25 +0000 |
135 | +++ plugins/AccountsService/plugin.cpp 2014-07-25 13:39:35 +0000 |
136 | @@ -33,5 +33,6 @@ |
137 | { |
138 | Q_ASSERT(uri == QLatin1String("AccountsService")); |
139 | qDBusRegisterMetaType<QList<QVariantMap>>(); |
140 | + qRegisterMetaType<AccountsService::PasswordDisplayHint>("AccountsService::PasswordDisplayHint"); |
141 | qmlRegisterSingletonType<AccountsService>(uri, 0, 1, "AccountsService", service_provider); |
142 | } |
143 | |
144 | === modified file 'plugins/LightDM/plugin.cpp' |
145 | --- plugins/LightDM/plugin.cpp 2014-06-18 17:26:30 +0000 |
146 | +++ plugins/LightDM/plugin.cpp 2014-07-25 13:39:35 +0000 |
147 | @@ -69,6 +69,8 @@ |
148 | qmlRegisterType<UserMetricsOutput::ColorTheme>(); |
149 | |
150 | Q_ASSERT(uri == QLatin1String("LightDM")); |
151 | + qRegisterMetaType<QLightDM::Greeter::MessageType>("QLightDM::Greeter::MessageType"); |
152 | + qRegisterMetaType<QLightDM::Greeter::PromptType>("QLightDM::Greeter::PromptType"); |
153 | qmlRegisterSingletonType<Greeter>(uri, 0, 1, "Greeter", greeter_provider); |
154 | qmlRegisterSingletonType<UsersModel>(uri, 0, 1, "Users", users_provider); |
155 | qmlRegisterUncreatableType<QLightDM::UsersModel>(uri, 0, 1, "UserRoles", "Type is not instantiable"); |
156 | |
157 | === modified file 'qml/Components/PassphraseLockscreen.qml' |
158 | --- qml/Components/PassphraseLockscreen.qml 2014-05-28 07:17:08 +0000 |
159 | +++ qml/Components/PassphraseLockscreen.qml 2014-07-25 13:39:35 +0000 |
160 | @@ -31,8 +31,10 @@ |
161 | |
162 | function clear(playAnimation) { |
163 | pinentryField.text = ""; |
164 | + pinentryField.enabled = true |
165 | if (playAnimation) { |
166 | wrongPasswordAnimation.start(); |
167 | + pinentryField.forceActiveFocus(); |
168 | } else { |
169 | pinentryField.focus = false |
170 | } |
171 | @@ -78,6 +80,7 @@ |
172 | |
173 | onAccepted: { |
174 | if (pinentryField.text) { |
175 | + pinentryField.enabled = false; |
176 | root.entered(pinentryField.text); |
177 | } |
178 | } |
179 | |
180 | === modified file 'qml/Shell.qml' |
181 | --- qml/Shell.qml 2014-07-18 15:13:35 +0000 |
182 | +++ qml/Shell.qml 2014-07-25 13:39:35 +0000 |
183 | @@ -490,6 +490,7 @@ |
184 | width: parent.width |
185 | height: parent.height - panel.panelHeight |
186 | background: shell.background |
187 | + alphaNumeric: AccountsService.passwordDisplayHint === AccountsService.Keyboard |
188 | minPinLength: 4 |
189 | maxPinLength: 4 |
190 | |
191 | @@ -504,7 +505,7 @@ |
192 | onShownChanged: if (shown) greeter.fakeActiveForApp = "" |
193 | |
194 | Component.onCompleted: { |
195 | - if (LightDM.Users.count == 1) { |
196 | + if (greeter.narrowMode) { |
197 | LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole)) |
198 | } |
199 | } |
200 | @@ -516,14 +517,17 @@ |
201 | onShowGreeter: greeter.show() |
202 | |
203 | onShowPrompt: { |
204 | - if (LightDM.Users.count == 1) { |
205 | - // TODO: There's no better way for now to determine if its a PIN or a passphrase. |
206 | - if (text == "PIN") { |
207 | - lockscreen.alphaNumeric = false |
208 | - } else { |
209 | - lockscreen.alphaNumeric = true |
210 | - } |
211 | - lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text); |
212 | + if (greeter.narrowMode) { |
213 | + lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text.toLowerCase()); |
214 | + lockscreen.show(); |
215 | + } |
216 | + } |
217 | + |
218 | + onPromptlessChanged: { |
219 | + if (LightDM.Greeter.promptless) { |
220 | + lockscreen.hide() |
221 | + } else { |
222 | + lockscreen.reset(); |
223 | lockscreen.show(); |
224 | } |
225 | } |
226 | @@ -537,6 +541,9 @@ |
227 | greeter.login(); |
228 | } else { |
229 | lockscreen.clear(true); |
230 | + if (greeter.narrowMode) { |
231 | + LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole)) |
232 | + } |
233 | } |
234 | } |
235 | } |
236 | @@ -590,24 +597,23 @@ |
237 | |
238 | function login() { |
239 | enabled = false; |
240 | - LightDM.Greeter.startSessionSync(); |
241 | - sessionStarted(); |
242 | - greeter.hide(); |
243 | - lockscreen.hide(); |
244 | - launcher.hide(); |
245 | + if (LightDM.Greeter.startSessionSync()) { |
246 | + sessionStarted(); |
247 | + greeter.hide(); |
248 | + lockscreen.hide(); |
249 | + launcher.hide(); |
250 | + } |
251 | enabled = true; |
252 | } |
253 | |
254 | onShownChanged: { |
255 | if (shown) { |
256 | - lockscreen.reset(); |
257 | + if (greeter.narrowMode) { |
258 | + LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole)); |
259 | + } |
260 | if (!LightDM.Greeter.promptless) { |
261 | - lockscreen.show(); |
262 | - } |
263 | - // If there is only one user, we start authenticating with that one here. |
264 | - // If there are more users, the Greeter will handle that |
265 | - if (LightDM.Users.count == 1) { |
266 | - LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole)); |
267 | + lockscreen.reset(); |
268 | + lockscreen.show(); |
269 | } |
270 | greeter.fakeActiveForApp = ""; |
271 | greeter.forceActiveFocus(); |
272 | |
273 | === modified file 'run.sh' |
274 | --- run.sh 2014-06-24 17:04:11 +0000 |
275 | +++ run.sh 2014-07-25 13:39:35 +0000 |
276 | @@ -8,6 +8,7 @@ |
277 | FAKE=false |
278 | PINLOCK=false |
279 | KEYLOCK=false |
280 | +USE_MOCKS=false |
281 | MOUSE_TOUCH=true |
282 | |
283 | usage() { |
284 | @@ -31,9 +32,9 @@ |
285 | while [ $# -gt 0 ] |
286 | do |
287 | case "$1" in |
288 | - -f|--fake) FAKE=true;; |
289 | - -p|--pinlock) PINLOCK=true;; |
290 | - -k|--keylock) KEYLOCK=true;; |
291 | + -f|--fake) FAKE=true; USE_MOCKS=true;; |
292 | + -p|--pinlock) PINLOCK=true; USE_MOCKS=true;; |
293 | + -k|--keylock) KEYLOCK=true; USE_MOCKS=true;; |
294 | -g|--gdb) GDB=true;; |
295 | -h|--help) usage;; |
296 | -m|--nomousetouch) MOUSE_TOUCH=false;; |
297 | @@ -43,20 +44,28 @@ |
298 | done |
299 | |
300 | if $FAKE; then |
301 | - export QML2_IMPORT_PATH=$QML2_IMPORT_PATH:$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules |
302 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single |
303 | fi |
304 | |
305 | if $PINLOCK; then |
306 | - export QML2_IMPORT_PATH=$QML2_IMPORT_PATH:$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules |
307 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single-pin |
308 | fi |
309 | |
310 | if $KEYLOCK; then |
311 | - export QML2_IMPORT_PATH=$QML2_IMPORT_PATH:$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules |
312 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single-passphrase |
313 | fi |
314 | |
315 | +if $USE_MOCKS; then |
316 | + rm -f $PWD/builddir/nonmirplugins/LightDM # undo symlink (from below) for cleanliness |
317 | + export QML2_IMPORT_PATH=$QML2_IMPORT_PATH:$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules |
318 | +else |
319 | + # Still fake no-login user for convenience (it's annoying to be prompted for your password when testing) |
320 | + # And in particular, just link our LightDM mock into the nonmirplugins folder. We don't want the rest of |
321 | + # our plugins to be used. |
322 | + ln -s $PWD/builddir/tests/mocks/LightDM $PWD/builddir/nonmirplugins/ |
323 | + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/LightDM/single |
324 | +fi |
325 | + |
326 | QML_PHONE_SHELL_ARGS="" |
327 | if $MOUSE_TOUCH; then |
328 | QML_PHONE_SHELL_ARGS="$QML_PHONE_SHELL_ARGS -mousetouch" |
329 | |
330 | === modified file 'tests/mocks/AccountsService/AccountsService.cpp' |
331 | --- tests/mocks/AccountsService/AccountsService.cpp 2014-06-17 18:23:44 +0000 |
332 | +++ tests/mocks/AccountsService/AccountsService.cpp 2014-07-25 13:39:35 +0000 |
333 | @@ -29,12 +29,14 @@ |
334 | |
335 | QString AccountsService::user() const |
336 | { |
337 | - return "testuser"; |
338 | + return m_user; |
339 | } |
340 | |
341 | void AccountsService::setUser(const QString &user) |
342 | { |
343 | - Q_UNUSED(user) |
344 | + m_user = user; |
345 | + Q_EMIT userChanged(); |
346 | + Q_EMIT passwordDisplayHintChanged(); |
347 | } |
348 | |
349 | bool AccountsService::demoEdges() const |
350 | @@ -68,3 +70,11 @@ |
351 | m_statsWelcomeScreen = statsWelcomeScreen; |
352 | statsWelcomeScreenChanged(); |
353 | } |
354 | + |
355 | +AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const |
356 | +{ |
357 | + if (m_user == "has-pin") |
358 | + return PasswordDisplayHint::Numeric; |
359 | + else |
360 | + return PasswordDisplayHint::Keyboard; |
361 | +} |
362 | |
363 | === modified file 'tests/mocks/AccountsService/AccountsService.h' |
364 | --- tests/mocks/AccountsService/AccountsService.h 2014-06-11 15:36:51 +0000 |
365 | +++ tests/mocks/AccountsService/AccountsService.h 2014-07-25 13:39:35 +0000 |
366 | @@ -27,6 +27,7 @@ |
367 | class AccountsService: public QObject |
368 | { |
369 | Q_OBJECT |
370 | + Q_ENUMS(PasswordDisplayHint) |
371 | Q_PROPERTY (QString user |
372 | READ user |
373 | WRITE setUser |
374 | @@ -43,8 +44,16 @@ |
375 | READ statsWelcomeScreen |
376 | WRITE setStatsWelcomeScreen // only available in mock |
377 | NOTIFY statsWelcomeScreenChanged) |
378 | + Q_PROPERTY (PasswordDisplayHint passwordDisplayHint |
379 | + READ passwordDisplayHint |
380 | + NOTIFY passwordDisplayHintChanged) |
381 | |
382 | public: |
383 | + enum PasswordDisplayHint { |
384 | + Keyboard, |
385 | + Numeric, |
386 | + }; |
387 | + |
388 | explicit AccountsService(QObject *parent = 0); |
389 | |
390 | QString user() const; |
391 | @@ -55,15 +64,18 @@ |
392 | void setBackgroundFile(const QString &backgroundFile); |
393 | bool statsWelcomeScreen() const; |
394 | void setStatsWelcomeScreen(bool statsWelcomeScreen); |
395 | + PasswordDisplayHint passwordDisplayHint() const; |
396 | |
397 | Q_SIGNALS: |
398 | void userChanged(); |
399 | void demoEdgesChanged(); |
400 | void backgroundFileChanged(); |
401 | void statsWelcomeScreenChanged(); |
402 | + void passwordDisplayHintChanged(); |
403 | |
404 | private: |
405 | QString m_backgroundFile; |
406 | + QString m_user; |
407 | bool m_statsWelcomeScreen; |
408 | }; |
409 | |
410 | |
411 | === modified file 'tests/mocks/AccountsService/CMakeLists.txt' |
412 | --- tests/mocks/AccountsService/CMakeLists.txt 2014-06-17 18:23:44 +0000 |
413 | +++ tests/mocks/AccountsService/CMakeLists.txt 2014-07-25 13:39:35 +0000 |
414 | @@ -5,4 +5,7 @@ |
415 | |
416 | qt5_use_modules(MockAccountsService-qml DBus Qml) |
417 | |
418 | -add_unity8_mock(AccountsService 0.1 AccountsService TARGETS MockAccountsService-qml) |
419 | +add_unity8_mock(AccountsService 0.1 AccountsService |
420 | + PREFIX mocks |
421 | + TARGETS MockAccountsService-qml |
422 | + ) |
423 | |
424 | === modified file 'tests/mocks/AccountsService/plugin.cpp' |
425 | --- tests/mocks/AccountsService/plugin.cpp 2013-11-19 17:01:25 +0000 |
426 | +++ tests/mocks/AccountsService/plugin.cpp 2014-07-25 13:39:35 +0000 |
427 | @@ -32,5 +32,6 @@ |
428 | void AccountsServicePlugin::registerTypes(const char *uri) |
429 | { |
430 | Q_ASSERT(uri == QLatin1String("AccountsService")); |
431 | + qRegisterMetaType<AccountsService::PasswordDisplayHint>("AccountsService::PasswordDisplayHint"); |
432 | qmlRegisterSingletonType<AccountsService>(uri, 0, 1, "AccountsService", service_provider); |
433 | } |
434 | |
435 | === modified file 'tests/mocks/LightDM/GreeterPrivate.h' |
436 | --- tests/mocks/LightDM/GreeterPrivate.h 2013-06-05 22:03:08 +0000 |
437 | +++ tests/mocks/LightDM/GreeterPrivate.h 2014-07-25 13:39:35 +0000 |
438 | @@ -24,6 +24,7 @@ |
439 | namespace QLightDM |
440 | { |
441 | class Greeter; |
442 | +class GreeterImpl; |
443 | |
444 | class GreeterPrivate |
445 | { |
446 | @@ -40,6 +41,7 @@ |
447 | void handleRespond(const QString &response); |
448 | |
449 | protected: |
450 | + GreeterImpl *m_impl; // if the backend needs more private data |
451 | Greeter * const q_ptr; |
452 | |
453 | private: |
454 | |
455 | === modified file 'tests/mocks/LightDM/demo/CMakeLists.txt' |
456 | --- tests/mocks/LightDM/demo/CMakeLists.txt 2014-06-11 15:36:51 +0000 |
457 | +++ tests/mocks/LightDM/demo/CMakeLists.txt 2014-07-25 13:39:35 +0000 |
458 | @@ -11,11 +11,13 @@ |
459 | add_library(MockLightDM-demo STATIC ${LibLightDM_SOURCES}) |
460 | |
461 | include_directories( |
462 | + ${CMAKE_CURRENT_BINARY_DIR} |
463 | ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS} |
464 | ) |
465 | |
466 | target_link_libraries(MockLightDM-demo |
467 | ${LIBUSERMETRICSOUTPUT_LDFLAGS} |
468 | - ) |
469 | + -lpam |
470 | +) |
471 | |
472 | -qt5_use_modules(MockLightDM-demo Gui) |
473 | +qt5_use_modules(MockLightDM-demo Concurrent Gui) |
474 | |
475 | === modified file 'tests/mocks/LightDM/demo/GreeterPrivate.cpp' |
476 | --- tests/mocks/LightDM/demo/GreeterPrivate.cpp 2014-06-11 15:36:51 +0000 |
477 | +++ tests/mocks/LightDM/demo/GreeterPrivate.cpp 2014-07-25 13:39:35 +0000 |
478 | @@ -18,53 +18,225 @@ |
479 | |
480 | #include "../Greeter.h" |
481 | #include "../GreeterPrivate.h" |
482 | -#include <QtCore/QDir> |
483 | -#include <QtCore/QSettings> |
484 | +#include <QFuture> |
485 | +#include <QFutureInterface> |
486 | +#include <QFutureWatcher> |
487 | +#include <QQueue> |
488 | +#include <QtConcurrent> |
489 | +#include <QVector> |
490 | +#include <security/pam_appl.h> |
491 | |
492 | namespace QLightDM |
493 | { |
494 | |
495 | +class GreeterImpl : public QObject |
496 | +{ |
497 | + Q_OBJECT |
498 | + |
499 | + typedef QFutureInterface<QString> ResponseFuture; |
500 | + |
501 | +public: |
502 | + explicit GreeterImpl(Greeter *parent, GreeterPrivate *greeterPrivate) |
503 | + : QObject(parent), |
504 | + greeter(parent), |
505 | + greeterPrivate(greeterPrivate), |
506 | + pamHandle(NULL) |
507 | + { |
508 | + qRegisterMetaType<QLightDM::GreeterImpl::ResponseFuture>("QLightDM::GreeterImpl::ResponseFuture"); |
509 | + |
510 | + connect(&futureWatcher, SIGNAL(finished()), |
511 | + this, SLOT(finishPam())); |
512 | + connect(this, SIGNAL(showMessage(QString, QLightDM::Greeter::MessageType)), |
513 | + greeter, SIGNAL(showMessage(QString, QLightDM::Greeter::MessageType))); |
514 | + // This next connect is how we pass ResponseFutures between threads |
515 | + connect(this, SIGNAL(showPrompt(QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)), |
516 | + this, SLOT(handlePrompt(QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture))); |
517 | + } |
518 | + |
519 | + void start(QString username) |
520 | + { |
521 | + // Clear out any existing PAM interactions first (we can't simply |
522 | + // cancel our QFuture because QtConcurrent::run doesn't support cancel) |
523 | + if (pamHandle != NULL) { |
524 | + pam_handle *handle = pamHandle; |
525 | + pamHandle = NULL; // to disable normal finishPam() handling |
526 | + while (respond(QString())); // clear our local queue of QFutures |
527 | + pam_end(handle, PAM_CONV_ERR); |
528 | + } |
529 | + |
530 | + // Now actually start a new conversation with PAM |
531 | + pam_conv conversation; |
532 | + conversation.conv = converseWithPam; |
533 | + conversation.appdata_ptr = static_cast<void*>(this); |
534 | + |
535 | + if (pam_start("lightdm", username.toUtf8(), &conversation, &pamHandle) == PAM_SUCCESS) { |
536 | + futureWatcher.setFuture(QtConcurrent::run(authenticateWithPam, pamHandle)); |
537 | + } else { |
538 | + greeterPrivate->authenticated = false; |
539 | + Q_EMIT greeter->showMessage("Internal error: could not start PAM authentication", QLightDM::Greeter::MessageTypeError); |
540 | + Q_EMIT greeter->authenticationComplete(); |
541 | + } |
542 | + } |
543 | + |
544 | + static int authenticateWithPam(pam_handle* pamHandle) |
545 | + { |
546 | + int pamStatus = pam_authenticate(pamHandle, 0); |
547 | + if (pamStatus == PAM_SUCCESS) { |
548 | + pamStatus = pam_acct_mgmt(pamHandle, 0); |
549 | + } |
550 | + if (pamStatus == PAM_NEW_AUTHTOK_REQD) { |
551 | + pamStatus = pam_chauthtok(pamHandle, PAM_CHANGE_EXPIRED_AUTHTOK); |
552 | + } |
553 | + if (pamStatus == PAM_SUCCESS) { |
554 | + pam_setcred(pamHandle, PAM_REINITIALIZE_CRED); |
555 | + } |
556 | + return pamStatus; |
557 | + } |
558 | + |
559 | + static int converseWithPam(int num_msg, const pam_message** msg, |
560 | + pam_response** resp, void* appdata_ptr) |
561 | + { |
562 | + if (num_msg <= 0) |
563 | + return PAM_CONV_ERR; |
564 | + |
565 | + auto* tmp_response = static_cast<pam_response*>(calloc(num_msg, sizeof(pam_response))); |
566 | + if (!tmp_response) |
567 | + return PAM_CONV_ERR; |
568 | + |
569 | + GreeterImpl* impl = static_cast<GreeterImpl*>(appdata_ptr); |
570 | + |
571 | + int count; |
572 | + QVector<ResponseFuture> responses; |
573 | + |
574 | + for (count = 0; count < num_msg; ++count) |
575 | + { |
576 | + switch (msg[count]->msg_style) |
577 | + { |
578 | + case PAM_PROMPT_ECHO_ON: |
579 | + { |
580 | + QString message(msg[count]->msg); |
581 | + responses.append(ResponseFuture()); |
582 | + responses.last().reportStarted(); |
583 | + Q_EMIT impl->showPrompt(message, Greeter::PromptTypeQuestion, responses.last()); |
584 | + break; |
585 | + } |
586 | + case PAM_PROMPT_ECHO_OFF: |
587 | + { |
588 | + QString message(msg[count]->msg); |
589 | + responses.append(ResponseFuture()); |
590 | + responses.last().reportStarted(); |
591 | + Q_EMIT impl->showPrompt(message, Greeter::PromptTypeSecret, responses.last()); |
592 | + break; |
593 | + } |
594 | + case PAM_TEXT_INFO: |
595 | + { |
596 | + QString message(msg[count]->msg); |
597 | + Q_EMIT impl->showMessage(message, Greeter::MessageTypeInfo); |
598 | + break; |
599 | + } |
600 | + default: |
601 | + { |
602 | + QString message(msg[count]->msg); |
603 | + Q_EMIT impl->showMessage(message, Greeter::MessageTypeError); |
604 | + break; |
605 | + } |
606 | + } |
607 | + } |
608 | + |
609 | + int i = 0; |
610 | + bool raise_error = false; |
611 | + |
612 | + for (auto &response : responses) |
613 | + { |
614 | + pam_response* resp_item = &tmp_response[i++]; |
615 | + resp_item->resp_retcode = 0; |
616 | + resp_item->resp = strdup(response.future().result().toUtf8()); |
617 | + |
618 | + if (!resp_item->resp) |
619 | + { |
620 | + raise_error = true; |
621 | + break; |
622 | + } |
623 | + } |
624 | + |
625 | + if (raise_error) |
626 | + { |
627 | + for (int i = 0; i < count; ++i) |
628 | + free(tmp_response[i].resp); |
629 | + |
630 | + free(tmp_response); |
631 | + return PAM_CONV_ERR; |
632 | + } |
633 | + else |
634 | + { |
635 | + *resp = tmp_response; |
636 | + return PAM_SUCCESS; |
637 | + } |
638 | + } |
639 | + |
640 | +public Q_SLOTS: |
641 | + bool respond(QString response) |
642 | + { |
643 | + if (!futures.isEmpty()) { |
644 | + futures.dequeue().reportFinished(&response); |
645 | + return true; |
646 | + } else { |
647 | + return false; |
648 | + } |
649 | + } |
650 | + |
651 | +Q_SIGNALS: |
652 | + void showMessage(QString text, QLightDM::Greeter::MessageType type); |
653 | + void showPrompt(QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture response); |
654 | + |
655 | +private Q_SLOTS: |
656 | + void finishPam() |
657 | + { |
658 | + if (pamHandle == NULL) { |
659 | + return; |
660 | + } |
661 | + |
662 | + int pamStatus = futureWatcher.result(); |
663 | + |
664 | + pam_end(pamHandle, pamStatus); |
665 | + pamHandle = NULL; |
666 | + |
667 | + greeterPrivate->authenticated = (pamStatus == PAM_SUCCESS); |
668 | + Q_EMIT greeter->authenticationComplete(); |
669 | + } |
670 | + |
671 | + void handlePrompt(QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture future) |
672 | + { |
673 | + futures.enqueue(future); |
674 | + Q_EMIT greeter->showPrompt(text, type); |
675 | + } |
676 | + |
677 | +private: |
678 | + Greeter *greeter; |
679 | + GreeterPrivate *greeterPrivate; |
680 | + pam_handle* pamHandle; |
681 | + QFutureWatcher<int> futureWatcher; |
682 | + QQueue<ResponseFuture> futures; |
683 | +}; |
684 | + |
685 | GreeterPrivate::GreeterPrivate(Greeter* parent) |
686 | : authenticated(false), |
687 | authenticationUser(), |
688 | + m_impl(new GreeterImpl(parent, this)), |
689 | q_ptr(parent) |
690 | { |
691 | } |
692 | |
693 | void GreeterPrivate::handleAuthenticate() |
694 | { |
695 | - Q_Q(Greeter); |
696 | - |
697 | - QSettings settings(QDir::homePath() + "/.unity8-greeter-demo", QSettings::NativeFormat); |
698 | - settings.beginGroup(authenticationUser); |
699 | - QVariant password = settings.value("password", "none"); |
700 | - |
701 | - if (password == "pin") { |
702 | - Q_EMIT q->showPrompt("PIN", Greeter::PromptTypeSecret); |
703 | - } else if (password == "keyboard") { |
704 | - Q_EMIT q->showPrompt("Password", Greeter::PromptTypeSecret); |
705 | - } else { |
706 | - authenticated = true; |
707 | - Q_EMIT q->authenticationComplete(); |
708 | - } |
709 | + m_impl->start(authenticationUser); |
710 | } |
711 | |
712 | void GreeterPrivate::handleRespond(const QString &response) |
713 | { |
714 | - Q_Q(Greeter); |
715 | - |
716 | - QSettings settings(QDir::homePath() + "/.unity8-greeter-demo", QSettings::NativeFormat); |
717 | - settings.beginGroup(authenticationUser); |
718 | - QVariant password = settings.value("password", "none"); |
719 | - |
720 | - QString passwordValue; |
721 | - if (password == "pin") { |
722 | - passwordValue = settings.value("passwordValue", "1234").toString(); |
723 | - } else { |
724 | - passwordValue = settings.value("passwordValue", "password").toString(); |
725 | - } |
726 | - authenticated = (response == passwordValue); |
727 | - Q_EMIT q->authenticationComplete(); |
728 | -} |
729 | - |
730 | -} |
731 | + m_impl->respond(response); |
732 | +} |
733 | + |
734 | +} |
735 | + |
736 | +#include "GreeterPrivate.moc" |
737 | |
738 | === modified file 'tests/mocks/LightDM/demo/UsersModelPrivate.cpp' |
739 | --- tests/mocks/LightDM/demo/UsersModelPrivate.cpp 2014-06-11 15:36:51 +0000 |
740 | +++ tests/mocks/LightDM/demo/UsersModelPrivate.cpp 2014-07-25 13:39:35 +0000 |
741 | @@ -29,7 +29,7 @@ |
742 | : q_ptr(parent) |
743 | { |
744 | QSettings settings(QDir::homePath() + "/.unity8-greeter-demo", QSettings::NativeFormat); |
745 | - QStringList users = settings.value("users", QStringList() << "phablet").toStringList(); |
746 | + QStringList users = settings.value("users", QStringList() << qgetenv("USER")).toStringList(); |
747 | |
748 | Q_FOREACH(const QString &user, users) |
749 | { |
750 | |
751 | === modified file 'tests/mocks/LightDM/full/GreeterPrivate.cpp' |
752 | --- tests/mocks/LightDM/full/GreeterPrivate.cpp 2013-06-11 10:30:07 +0000 |
753 | +++ tests/mocks/LightDM/full/GreeterPrivate.cpp 2014-07-25 13:39:35 +0000 |
754 | @@ -54,7 +54,7 @@ |
755 | authenticated = true; |
756 | Q_EMIT q->authenticationComplete(); |
757 | } else if (authenticationUser == "has-pin"){ |
758 | - Q_EMIT q->showPrompt("PIN", Greeter::PromptTypeSecret); |
759 | + Q_EMIT q->showPrompt("Password:", Greeter::PromptTypeSecret); |
760 | } else if (authenticationUser == "auth-error") { |
761 | authenticated = false; |
762 | Q_EMIT q->authenticationComplete(); |
763 | |
764 | === modified file 'tests/mocks/LightDM/single-pin/GreeterPrivate.cpp' |
765 | --- tests/mocks/LightDM/single-pin/GreeterPrivate.cpp 2014-06-24 23:52:12 +0000 |
766 | +++ tests/mocks/LightDM/single-pin/GreeterPrivate.cpp 2014-07-25 13:39:35 +0000 |
767 | @@ -32,7 +32,7 @@ |
768 | void GreeterPrivate::handleAuthenticate() |
769 | { |
770 | Q_Q(Greeter); |
771 | - Q_EMIT q->showPrompt("PIN", Greeter::PromptTypeSecret); |
772 | + Q_EMIT q->showPrompt("Password:", Greeter::PromptTypeSecret); |
773 | } |
774 | |
775 | void GreeterPrivate::handleRespond(const QString &response) |
776 | |
777 | === modified file 'tests/mocks/LightDM/single-pin/UsersModelPrivate.cpp' |
778 | --- tests/mocks/LightDM/single-pin/UsersModelPrivate.cpp 2013-06-14 19:35:25 +0000 |
779 | +++ tests/mocks/LightDM/single-pin/UsersModelPrivate.cpp 2014-07-25 13:39:35 +0000 |
780 | @@ -26,7 +26,7 @@ |
781 | { |
782 | entries = |
783 | { |
784 | - { "single", "Has PIN", 0, 0, false, false, 0, 0 }, |
785 | + { "has-pin", "Has PIN", 0, 0, false, false, 0, 0 }, |
786 | }; |
787 | } |
788 | |
789 | |
790 | === modified file 'tests/qmltests/Greeter/tst_Lockscreen.qml' |
791 | --- tests/qmltests/Greeter/tst_Lockscreen.qml 2014-06-30 22:26:41 +0000 |
792 | +++ tests/qmltests/Greeter/tst_Lockscreen.qml 2014-07-25 13:39:35 +0000 |
793 | @@ -18,8 +18,9 @@ |
794 | import QtTest 1.0 |
795 | import ".." |
796 | import "../../../qml/Components" |
797 | +import AccountsService 0.1 |
798 | +import LightDM 0.1 as LightDM |
799 | import Ubuntu.Components 0.1 |
800 | -import LightDM 0.1 as LightDM |
801 | import Unity.Test 0.1 as UT |
802 | |
803 | Rectangle { |
804 | @@ -53,11 +54,16 @@ |
805 | } |
806 | } |
807 | |
808 | + function setUser(username) { |
809 | + AccountsService.user = username |
810 | + LightDM.Greeter.authenticate(username) |
811 | + } |
812 | + |
813 | Connections { |
814 | target: LightDM.Greeter |
815 | |
816 | onShowPrompt: { |
817 | - if (text === "PIN") { |
818 | + if (AccountsService.passwordDisplayHint === AccountsService.Numeric) { |
819 | pinPadCheckBox.checked = false |
820 | } else { |
821 | pinPadCheckBox.checked = true |
822 | @@ -139,12 +145,12 @@ |
823 | Button { |
824 | text: "start auth (1234)" |
825 | width: parent.width |
826 | - onClicked: LightDM.Greeter.authenticate("has-pin") |
827 | + onClicked: setUser("has-pin") |
828 | } |
829 | Button { |
830 | text: "start auth (password)" |
831 | width: parent.width |
832 | - onClicked: LightDM.Greeter.authenticate("has-password") |
833 | + onClicked: setUser("has-password") |
834 | } |
835 | |
836 | TextField { |
837 | @@ -255,7 +261,7 @@ |
838 | enteredLabel.text = "" |
839 | minPinLengthTextField.text = data.minPinLength |
840 | maxPinLengthTextField.text = data.maxPinLength |
841 | - LightDM.Greeter.authenticate(data.username) |
842 | + setUser(data.username) |
843 | waitForLockscreenReady(); |
844 | |
845 | var inputField = findChild(lockscreen, "pinentryField") |
Marc, this branch implements PAM password-checking. Most of the interesting-to-you changes are probably in tests/mocks/ LightDM/ demo/GreeterPri vate.cpp.