on xenial help sign in
Support fingerprint events; add tests
commit01498b758acb2bf724e1180aaeee340d02d70c82 authorMichael Terry <michael.terry@canonical.com> dateWed 30 Mar 2016, 14:50 (11 years ago) parentc4e7e98
8 files changed+143−2
qml/Greeter/CoverPage.qml+21−1 qml/Greeter/Greeter.qml+26−1 qml/Greeter/NarrowView.qml+4 qml/Greeter/WideView.qml+4 tests/qmltests/Greeter/TestView.qml+7 tests/qmltests/Greeter/tst_Greeter.qml+50 tests/qmltests/Greeter/tst_NarrowView.qml+16 tests/qmltests/tst_Shell.qml+15
qml/Greeter/CoverPage.qml+21−1
@@ -41,9 +41,16 @@ Showable {
4141 hide();
4242 }
4343
44+ function showErrorMessage(msg) {
45+ d.errorMessage = msg;
46+ showLabelAnimation.start();
47+ errorMessageAnimation.start();
48+ }
49+
4450 QtObject {
4551 id: d
4652 property bool forceRightOnNextHideAnimation: false
53+ property string errorMessage
4754 }
4855
4956 prepareToHide: function () {
@@ -110,17 +117,19 @@ Showable {
110117
111118 Label {
112119 id: swipeHint
120+ objectName: "swipeHint"
113121 property real baseOpacity: 0.5
114122 opacity: 0.0
115123 anchors.horizontalCenter: parent.horizontalCenter
116124 anchors.bottom: parent.bottom
117125 anchors.bottomMargin: units.gu(5)
118− text: "《 " + i18n.tr("Unlock") + " 》"
126+ text: "《 " + (d.errorMessage ? d.errorMessage : i18n.tr("Unlock")) + " 》"
119127 color: "white"
120128 font.weight: Font.Light
121129
122130 SequentialAnimation on opacity {
123131 id: showLabelAnimation
132+ objectName: "showLabelAnimation"
124133 running: false
125134 loops: 2
126135
@@ -135,9 +144,20 @@ Showable {
135144 to: 0.0
136145 duration: UbuntuAnimation.SleepyDuration
137146 }
147+
148+ onRunningChanged: {
149+ if (!running)
150+ d.errorMessage = "";
151+ }
138152 }
139153 }
140154
155+ WrongPasswordAnimation {
156+ id: errorMessageAnimation
157+ objectName: "errorMessageAnimation"
158+ target: swipeHint
159+ }
160+
141161 DragHandle {
142162 id: dragHandle
143163 objectName: "coverPageDragHandle"
qml/Greeter/Greeter.qml+26−1
@@ -18,6 +18,7 @@ import QtQuick 2.4
1818import AccountsService 0.1
1919import GSettings 1.0
2020import Ubuntu.Components 1.3
21+import Ubuntu.Fingerprints 0.1
2122import Ubuntu.SystemImage 0.1
2223import Unity.Launcher 0.1
2324import Unity.Session 0.1
@@ -60,8 +61,9 @@ Showable {
6061 signal emergencyCall()
6162
6263 function forceShow() {
64+ forcedUnlock = false;
6365 showNow();
64− loader.item.reset();
66+ d.selectUser(d.currentIndex, true);
6567 }
6668
6769 function notifyAppFocused(appId) {
@@ -114,6 +116,7 @@ Showable {
114116 readonly property bool multiUser: lightDM.users.count > 1
115117 property int currentIndex
116118 property bool waiting
119+ property int fingerprintFailureCount
117120
118121 // We want 'launcherOffset' to animate down to zero. But not to animate
119122 // while being dragged. So ideally we change this only when the user
@@ -129,8 +132,16 @@ Showable {
129132 UbuntuNumberAnimation {}
130133 }
131134
135+ onFingerprintFailureCountChanged: {
136+ if (d.fingerprintFailureCount >= 3) {
137+ d.startUnlock(false /* toTheRight */);
138+ d.fingerprintFailureCount = 0;
139+ }
140+ }
141+
132142 function selectUser(uid, reset) {
133143 d.waiting = true;
144+ d.fingerprintFailureCount = 0;
134145 if (reset) {
135146 loader.item.reset();
136147 }
@@ -469,4 +480,18 @@ Showable {
469480 target: i18n
470481 onLanguageChanged: lightDM.infographic.readyForDataChange()
471482 }
483+
484+ Connections {
485+ target: Fingerprints
486+ onIdentificationCompleted: {
487+ // FIXME validate uid
488+ if (root.active)
489+ root.forcedUnlock = true;
490+ }
491+ onIdentificationFailed: {
492+ d.fingerprintFailureCount++;
493+ if (loader.item)
494+ loader.item.showErrorMessage(i18n.tr("Try again"));
495+ }
496+ }
472497}
qml/Greeter/NarrowView.qml+4
@@ -73,6 +73,10 @@ FocusScope {
7373 lockscreen.clear(true);
7474 }
7575
76+ function showErrorMessage(msg) {
77+ coverPage.showErrorMessage(msg);
78+ }
79+
7680 function reset() {
7781 coverPage.show();
7882 }
qml/Greeter/WideView.qml+4
@@ -66,6 +66,10 @@ FocusScope {
6666 loginList.showError();
6767 }
6868
69+ function showErrorMessage(msg) {
70+ coverPage.showErrorMessage(msg);
71+ }
72+
6973 function reset() {
7074 loginList.reset();
7175 }
tests/qmltests/Greeter/TestView.qml+7
@@ -33,9 +33,11 @@ Item {
3333 property var infographicModel
3434 readonly property bool fullyShown: _fullyShown
3535 readonly property bool required: _required
36+ readonly property bool animating: _animating
3637
3738 property bool _fullyShown: true
3839 property bool _required: true
40+ property bool _animating: true
3941
4042 signal selected(int index)
4143 signal responded(string response)
@@ -48,6 +50,7 @@ Item {
4850 signal _hideCalled()
4951 signal _notifyAuthenticationSucceededCalled()
5052 signal _notifyAuthenticationFailedCalled()
53+ signal _showErrorMessageCalled(string msg)
5154 signal _resetCalled()
5255 signal _tryToUnlockCalled(bool toTheRight)
5356
@@ -77,6 +80,10 @@ Item {
7780 _notifyAuthenticationFailedCalled();
7881 }
7982
83+ function showErrorMessage(msg) {
84+ _showErrorMessageCalled(msg);
85+ }
86+
8087 function reset() {
8188 _resetCalled();
8289 }
tests/qmltests/Greeter/tst_Greeter.qml+50
@@ -19,6 +19,7 @@ import QtTest 1.0
1919import ".."
2020import "../../../qml/Greeter"
2121import Ubuntu.Components 1.3
22+import Ubuntu.Fingerprints 0.1
2223import AccountsService 0.1
2324import GSettings 1.0
2425import IntegratedLightDM 0.1 as LightDM
@@ -125,6 +126,12 @@ Item {
125126 signalName: "_notifyAuthenticationFailedCalled"
126127 }
127128
129+ SignalSpy {
130+ id: viewShowErrorMessageSpy
131+ target: testCase.view
132+ signalName: "_showErrorMessageCalled"
133+ }
134+
128135 SignalSpy {
129136 id: viewResetSpy
130137 target: testCase.view
@@ -149,6 +156,7 @@ Item {
149156 viewHideSpy.clear();
150157 viewAuthenticationSucceededSpy.clear();
151158 viewAuthenticationFailedSpy.clear();
159+ viewShowErrorMessageSpy.clear();
152160 viewResetSpy.clear();
153161 viewTryToUnlockSpy.clear();
154162 tryCompare(greeter, "waiting", false);
@@ -552,5 +560,47 @@ Item {
552560 LightDM.Greeter.showGreeter();
553561 compare(viewResetSpy.count, 1);
554562 }
563+
564+ function test_fingerprintSuccess() {
565+ selectUser("has-password");
566+ Fingerprints.mockIdentification(0, Fingerprints.None);
567+ verify(greeter.forcedUnlock);
568+ }
569+
570+ function test_fingerprintFailureMessage() {
571+ selectUser("has-password");
572+ Fingerprints.mockIdentification(0, Fingerprints.Error);
573+ compare(viewShowErrorMessageSpy.count, 1);
574+ compare(viewShowErrorMessageSpy.signalArguments[0][0], i18n.tr("Try again"));
575+ }
576+
577+ function test_fingerprintTooManyFailures() {
578+ selectUser("has-password");
579+ Fingerprints.mockIdentification(0, Fingerprints.Error);
580+ Fingerprints.mockIdentification(0, Fingerprints.Error);
581+ compare(viewTryToUnlockSpy.count, 0);
582+
583+ Fingerprints.mockIdentification(0, Fingerprints.Error);
584+ compare(viewTryToUnlockSpy.count, 1);
585+
586+ compare(viewShowErrorMessageSpy.count, 3);
587+ }
588+
589+ function test_fingerprintFailureCountReset() {
590+ selectUser("has-password");
591+ Fingerprints.mockIdentification(0, Fingerprints.Error);
592+ Fingerprints.mockIdentification(0, Fingerprints.Error);
593+ compare(viewTryToUnlockSpy.count, 0);
594+
595+ greeter.forceShow();
596+ Fingerprints.mockIdentification(0, Fingerprints.Error);
597+ Fingerprints.mockIdentification(0, Fingerprints.Error);
598+ compare(viewTryToUnlockSpy.count, 0);
599+
600+ Fingerprints.mockIdentification(0, Fingerprints.Error);
601+ compare(viewTryToUnlockSpy.count, 1);
602+
603+ compare(viewShowErrorMessageSpy.count, 5);
604+ }
555605 }
556606}
tests/qmltests/Greeter/tst_NarrowView.qml+16
@@ -527,5 +527,21 @@ Item {
527527 mouseClick(coverPage, coverPage.width/2, coverPage.height - units.gu(2));
528528 verify(!coverPage.shown);
529529 }
530+
531+ function test_showErrorMessage() {
532+ var coverPage = findChild(view, "coverPage");
533+ var swipeHint = findChild(coverPage, "swipeHint");
534+ var errorMessageAnimation = findInvisibleChild(coverPage, "errorMessageAnimation");
535+ var showLabelAnimation = findInvisibleChild(coverPage, "showLabelAnimation");
536+
537+ view.showErrorMessage("hello");
538+ compare(swipeHint.text, "《 hello 》");
539+ verify(errorMessageAnimation.running);
540+ verify(showLabelAnimation.running);
541+
542+ errorMessageAnimation.complete();
543+ showLabelAnimation.complete();
544+ compare(swipeHint.text, "《 " + i18n.tr("Unlock") + " 》");
545+ }
530546 }
531547}
tests/qmltests/tst_Shell.qml+15
@@ -21,6 +21,7 @@ import GSettings 1.0
2121import IntegratedLightDM 0.1 as LightDM
2222import Ubuntu.Components 1.3
2323import Ubuntu.Components.ListItems 1.3 as ListItem
24+import Ubuntu.Fingerprints 0.1
2425import Ubuntu.Telephony 0.1 as Telephony
2526import Unity.Application 0.1
2627import Unity.Connectivity 0.1
@@ -325,6 +326,20 @@ Rectangle {
325326 }
326327 }
327328
329+ Label {
330+ text: "Fingerprint"
331+ }
332+ Row {
333+ Button {
334+ text: "Success"
335+ onClicked: Fingerprints.mockIdentification(0, Fingerprints.None)
336+ }
337+
338+ Button {
339+ text: "Failure"
340+ onClicked: Fingerprints.mockIdentification(0, Fingerprints.Error)
341+ }
342+ }
328343 }
329344 }
330345 }