Merge lp:~unity-team/unity8/fingerprint into lp:unity8

Proposed by Michael Terry on 2016-05-03
Status: Merged
Approved by: Michael Zanetti on 2016-06-22
Approved revision: 2344
Merged at revision: 2491
Proposed branch: lp:~unity-team/unity8/fingerprint
Merge into: lp:unity8
Diff against target: 1908 lines (+1022/-49)
44 files modified
debian/control (+2/-1)
plugins/AccountsService/AccountsService.cpp (+21/-1)
plugins/AccountsService/AccountsService.h (+13/-1)
plugins/AccountsService/com.canonical.unity.AccountsService.xml (+4/-0)
plugins/IntegratedLightDM/liblightdm/UsersModel.cpp (+4/-1)
plugins/IntegratedLightDM/liblightdm/UsersModel.h (+2/-1)
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp (+5/-3)
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h (+2/-1)
qml/Components/DelayedLockscreen.qml (+1/-0)
qml/Components/Lockscreen.qml (+8/-0)
qml/Components/PassphraseLockscreen.qml (+4/-0)
qml/Components/PinLockscreen.qml (+4/-0)
qml/Greeter/CoverPage.qml (+22/-1)
qml/Greeter/Greeter.qml (+97/-4)
qml/Greeter/NarrowView.qml (+18/-2)
qml/Greeter/WideView.qml (+5/-1)
qml/Shell.qml (+3/-0)
tests/mocks/AccountsService/AccountsService.cpp (+24/-0)
tests/mocks/AccountsService/AccountsService.h (+16/-0)
tests/mocks/Biometryd/CMakeLists.txt (+14/-0)
tests/mocks/Biometryd/MockBiometryd.cpp (+43/-0)
tests/mocks/Biometryd/MockBiometryd.h (+50/-0)
tests/mocks/Biometryd/MockDevice.cpp (+29/-0)
tests/mocks/Biometryd/MockDevice.h (+40/-0)
tests/mocks/Biometryd/MockIdentifier.cpp (+28/-0)
tests/mocks/Biometryd/MockIdentifier.h (+36/-0)
tests/mocks/Biometryd/MockObserver.cpp (+22/-0)
tests/mocks/Biometryd/MockObserver.h (+37/-0)
tests/mocks/Biometryd/MockOperation.cpp (+56/-0)
tests/mocks/Biometryd/MockOperation.h (+48/-0)
tests/mocks/Biometryd/plugin.cpp (+41/-0)
tests/mocks/Biometryd/plugin.h (+31/-0)
tests/mocks/Biometryd/qmldir (+3/-0)
tests/mocks/CMakeLists.txt (+1/-0)
tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp (+4/-1)
tests/mocks/IntegratedLightDM/liblightdm/UsersModel.h (+2/-1)
tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp (+29/-23)
tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.h (+2/-1)
tests/qmltests/Components/tst_Lockscreen.qml (+20/-1)
tests/qmltests/Greeter/TestView.qml (+10/-3)
tests/qmltests/Greeter/tst_Greeter.qml (+171/-0)
tests/qmltests/Greeter/tst_NarrowView.qml (+22/-1)
tests/qmltests/Greeter/tst_WideView.qml (+1/-1)
tests/qmltests/tst_Shell.qml (+27/-0)
To merge this branch: bzr merge lp:~unity-team/unity8/fingerprint
Reviewer Review Type Date Requested Status
Michael Zanetti (community) Approve on 2016-06-22
Unity8 CI Bot continuous-integration Needs Fixing on 2016-06-21
Ken VanDine Approve on 2016-06-17
Albert Astals Cid (community) code looks good 2016-05-03 Approve on 2016-06-17
Review via email: mp+293621@code.launchpad.net

Commit Message

Support unlocking via fingerprint, if one is registered.

Description of the Change

Adds support for the new Biometryd qml module.

Spec details here:
https://docs.google.com/document/d/1d8gEataSjJMRacQbdSy0W4pSFA9q1UKA660CvXk-wNI

Testing instructions are at the end of that document.

I may have one tiny change coming -- disabling the Home button while fingerprint registration is happening. But that's waiting on tvoss. Rest can be reviewed in meantime.

To post a comment you must log in.
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2332
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1431/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/1904/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1930
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1866
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1866
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1866
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1857/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1857/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1857/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1857
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1857/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1857
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1857/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1857
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1857/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1857/console
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1857/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1857
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1857/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1857/console

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1431/rebuild

review: Needs Fixing (continuous-integration)
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2332
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1436/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/1912
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/976/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/976/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/976/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1938
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1874
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1874
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1874
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1865
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1865/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1865
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1865/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1865
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1865/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1865
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1865/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1865
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1865/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1865
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1865/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1865
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1865/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1865
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1865/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1865
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1865/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1436/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

Had a look at the code, looks good, but someone with a fingerprint phone needs to review it.

Not approving since otherwise people won't see it in the "Requested reviews you can do" section of https://code.launchpad.net/~unity-team/unity8/trunk/+activereviews

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2332
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1440/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/1916
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/978/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/978/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/978/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1942
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1878
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1878
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1878
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1869
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1869/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1869
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1869/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1869
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1869/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1869
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1869/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1869
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1869/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1869
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1869/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1869
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1869/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1869
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1869/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1869
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1869/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1440/rebuild

review: Needs Fixing (continuous-integration)
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2333
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1461/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/1949
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/1000/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/1000/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/1000/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1975
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1909
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1909
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1909
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1900
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1900/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1900
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1900/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1900
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1900/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1900
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1900/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1900
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1900/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1900
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1900/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1900
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1900/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1900
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1900/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1900
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1900/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1461/rebuild

review: Needs Fixing (continuous-integration)
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2334
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1500/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/1999/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2027
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1944
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1944
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1944
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1935
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1935/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1935
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1935/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1935
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1935/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1935
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1935/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1935
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1935/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1935
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1935/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1935
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1935/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1935
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1935/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1935
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1935/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1500/rebuild

review: Needs Fixing (continuous-integration)
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2336
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1503/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2003
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/1017/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/1017/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/1017/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2031
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1948
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1948
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1948
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1939
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1939/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1939
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1939/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1939
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1939/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1939
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1939/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1939
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1939/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1939
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1939/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1939
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1939/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1939
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1939/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1939
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1939/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1503/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) :
review: Approve (code looks good)
Ken VanDine (ken-vandine) wrote :

I've test this on my turbo, works well

review: Approve
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2337
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1523/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2026
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/1035/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/1035/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/1035/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2054
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1969
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1969
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1969
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1960
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1960/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1960
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1960/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1960
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1960/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1960
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1960/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1960
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1960/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1960
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1960/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1960
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1960/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1960
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1960/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1960
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1960/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1523/rebuild

review: Needs Fixing (continuous-integration)
Michael Zanetti (mzanetti) wrote :

I've been using this for a while now and have some issues, mainly in combination with the home button:

If I press the button when the screen is off and there is a focused app other than the dash, the behavior is not predictable. Sometimes it just unlocks the screen, leaving me in the app, somethimes however, it unfocuses the app and puts me to the dash.

I would expect this:

Pressing the home button once should wake up the screen. Because the finger is on the reader, it should unlock unity. However, it should *not* unfocus any app. If I want to go back to the dash from there, I should be required to press the home button for another time.

review: Needs Fixing
lp:~unity-team/unity8/fingerprint updated on 2016-06-20
2338. By Michael Terry on 2016-06-20

Add a touch of security to fingerprinting

2339. By Michael Terry on 2016-06-20

Fix tests

2340. By Michael Terry on 2016-06-20

Disable fingerprints when dialog/fullscreen-notification/indicators are up

2341. By Michael Terry on 2016-06-20

Use nicer log message

2342. By Michael Terry on 2016-06-20

Tweak test

2343. By Michael Terry on 2016-06-20

Don't show duplicate passphrase prompts

Michael Terry (mterry) wrote :

OK, might need another review. mzanetti, I think your concern about requiring a finger-lift is being addressed by tvoss in a separate component?

Things changed since last review:

- After three failed attempts for a given user, fingerprints are disabled for that user. They are instead prompted to enter a passphrase/passcode. This was a security request.

- On the first login after booting, fingerprints are disabled for the user. They are instead prompted to enter a passphrase/passcode. This was a security request.

- When a dialog (e.g. power dialog), a fullscreen notification (e.g. pin unlock), or indicators are showing, the fingerprint reader is ignored.

lp:~unity-team/unity8/fingerprint updated on 2016-06-20
2344. By Michael Terry on 2016-06-20

Reset delay timer if we log in with fingerprint

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2342
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1572/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2089
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/1092/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/1092/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/1092/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2117
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2028
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2028
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2028
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2019
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2019/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2019
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2019/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2019
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2019/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2019
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2019/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2019
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2019/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2019
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2019/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2019
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2019/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2019
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2019/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2019
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2019/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1572/rebuild

review: Needs Fixing (continuous-integration)
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2344
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1578/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2097
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/1097/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/1097/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/1097/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2125
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2036
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2036
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2036
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2027
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2027/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2027
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2027/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2027
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2027/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2027
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2027/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2027
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2027/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2027
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2027/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2027
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2027/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2027
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2027/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2027
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2027/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1578/rebuild

review: Needs Fixing (continuous-integration)
Michael Zanetti (mzanetti) wrote :

I've tested this. The issues with unlocking in unexpected situations are resolved now.

Indeed, the lift-finger issue seems to be addressed by Thomas in the lower layers. I suspect, if he enables that again it will bring back the issue here?

Let's see, so far it works great. If the lower layers change we can probably apply another patch on top.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2016-06-17 01:12:57 +0000
3+++ debian/control 2016-06-20 20:23:46 +0000
4@@ -103,6 +103,7 @@
5 libcap2-bin,
6 libglib2.0-bin,
7 qmenumodel-qml (>= 0.2.9),
8+ qml-module-biometryd,
9 qml-module-qt-labs-folderlistmodel,
10 qml-module-qtquick-xmllistmodel,
11 qml-module-qtsysteminfo,
12@@ -192,7 +193,7 @@
13 Architecture: any
14 Multi-Arch: same
15 Pre-Depends: ${misc:Pre-Depends},
16-Depends: accountsservice-ubuntu-schemas (>= 0.0.5),
17+Depends: accountsservice-ubuntu-schemas (>= 0.0.7),
18 gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
19 libhardware2,
20 pay-service,
21
22=== modified file 'plugins/AccountsService/AccountsService.cpp'
23--- plugins/AccountsService/AccountsService.cpp 2016-04-27 15:01:10 +0000
24+++ plugins/AccountsService/AccountsService.cpp 2016-06-20 20:23:46 +0000
25@@ -1,5 +1,5 @@
26 /*
27- * Copyright (C) 2013, 2015 Canonical, Ltd.
28+ * Copyright (C) 2013-2016 Canonical, Ltd.
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32@@ -36,8 +36,10 @@
33 #define PROP_DEMO_EDGES QStringLiteral("demo-edges")
34 #define PROP_DEMO_EDGES_COMPLETED QStringLiteral("DemoEdgesCompleted")
35 #define PROP_EMAIL QStringLiteral("Email")
36+#define PROP_ENABLE_FINGERPRINT_IDENTIFICATION QStringLiteral("EnableFingerprintIdentification")
37 #define PROP_ENABLE_INDICATORS_WHILE_LOCKED QStringLiteral("EnableIndicatorsWhileLocked")
38 #define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked")
39+#define PROP_FAILED_FINGERPRINT_LOGINS QStringLiteral("FailedFingerprintLogins")
40 #define PROP_FAILED_LOGINS QStringLiteral("FailedLogins")
41 #define PROP_INPUT_SOURCES QStringLiteral("InputSources")
42 #define PROP_LICENSE_ACCEPTED QStringLiteral("LicenseAccepted")
43@@ -93,12 +95,14 @@
44 registerProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QStringLiteral("keymapsChanged"));
45 registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, QStringLiteral("hereEnabledChanged"));
46 registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH, QStringLiteral("hereLicensePathChanged"));
47+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION, QStringLiteral("enableFingerprintIdentificationChanged"));
48 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral("enableLauncherWhileLockedChanged"));
49 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral("enableIndicatorsWhileLockedChanged"));
50 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral("passwordDisplayHintChanged"));
51 registerProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN, QStringLiteral("statsWelcomeScreenChanged"));
52 registerProperty(IFACE_UNITY, PROP_DEMO_EDGES, QStringLiteral("demoEdgesChanged"));
53 registerProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED, QStringLiteral("demoEdgesCompletedChanged"));
54+ registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, QStringLiteral("failedFingerprintLoginsChanged"));
55 registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, QStringLiteral("failedLoginsChanged"));
56
57 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_CURSOR_SPEED,
58@@ -176,6 +180,12 @@
59 }
60 }
61
62+bool AccountsService::enableFingerprintIdentification() const
63+{
64+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION);
65+ return value.toBool();
66+}
67+
68 bool AccountsService::enableLauncherWhileLocked() const
69 {
70 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
71@@ -274,6 +284,16 @@
72 return {QStringLiteral("us")};
73 }
74
75+uint AccountsService::failedFingerprintLogins() const
76+{
77+ return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS).toUInt();
78+}
79+
80+void AccountsService::setFailedFingerprintLogins(uint failedFingerprintLogins)
81+{
82+ setProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, failedFingerprintLogins);
83+}
84+
85 uint AccountsService::failedLogins() const
86 {
87 return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS).toUInt();
88
89=== modified file 'plugins/AccountsService/AccountsService.h'
90--- plugins/AccountsService/AccountsService.h 2016-03-29 03:47:39 +0000
91+++ plugins/AccountsService/AccountsService.h 2016-06-20 20:23:46 +0000
92@@ -1,5 +1,5 @@
93 /*
94- * Copyright (C) 2013, 2015 Canonical, Ltd.
95+ * Copyright (C) 2013-2016 Canonical, Ltd.
96 *
97 * This program is free software; you can redistribute it and/or modify
98 * it under the terms of the GNU General Public License as published by
99@@ -41,6 +41,9 @@
100 Q_PROPERTY (QStringList demoEdgesCompleted
101 READ demoEdgesCompleted
102 NOTIFY demoEdgesCompletedChanged)
103+ Q_PROPERTY (bool enableFingerprintIdentification
104+ READ enableFingerprintIdentification
105+ NOTIFY enableFingerprintIdentificationChanged)
106 Q_PROPERTY (bool enableLauncherWhileLocked
107 READ enableLauncherWhileLocked
108 NOTIFY enableLauncherWhileLockedChanged)
109@@ -60,6 +63,10 @@
110 READ failedLogins
111 WRITE setFailedLogins
112 NOTIFY failedLoginsChanged)
113+ Q_PROPERTY (uint failedFingerprintLogins
114+ READ failedFingerprintLogins
115+ WRITE setFailedFingerprintLogins
116+ NOTIFY failedFingerprintLoginsChanged)
117 Q_PROPERTY(bool hereEnabled
118 READ hereEnabled
119 WRITE setHereEnabled
120@@ -91,6 +98,7 @@
121 void setDemoEdges(bool demoEdges);
122 QStringList demoEdgesCompleted() const;
123 Q_INVOKABLE void markDemoEdgeCompleted(const QString &edge);
124+ bool enableFingerprintIdentification() const;
125 bool enableLauncherWhileLocked() const;
126 bool enableIndicatorsWhileLocked() const;
127 QString backgroundFile() const;
128@@ -98,6 +106,8 @@
129 PasswordDisplayHint passwordDisplayHint() const;
130 uint failedLogins() const;
131 void setFailedLogins(uint failedLogins);
132+ uint failedFingerprintLogins() const;
133+ void setFailedFingerprintLogins(uint failedFingerprintLogins);
134 bool hereEnabled() const;
135 void setHereEnabled(bool enabled);
136 QString hereLicensePath() const;
137@@ -112,12 +122,14 @@
138 void userChanged();
139 void demoEdgesChanged();
140 void demoEdgesCompletedChanged();
141+ void enableFingerprintIdentificationChanged();
142 void enableLauncherWhileLockedChanged();
143 void enableIndicatorsWhileLockedChanged();
144 void backgroundFileChanged();
145 void statsWelcomeScreenChanged();
146 void passwordDisplayHintChanged();
147 void failedLoginsChanged();
148+ void failedFingerprintLoginsChanged();
149 void hereEnabledChanged();
150 void hereLicensePathChanged();
151 void realNameChanged();
152
153=== modified file 'plugins/AccountsService/com.canonical.unity.AccountsService.xml'
154--- plugins/AccountsService/com.canonical.unity.AccountsService.xml 2016-03-29 03:47:39 +0000
155+++ plugins/AccountsService/com.canonical.unity.AccountsService.xml 2016-06-20 20:23:46 +0000
156@@ -47,5 +47,9 @@
157 <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
158 </property>
159
160+ <property name="FailedFingerprintLogins" type="u" access="readwrite">
161+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
162+ </property>
163+
164 </interface>
165 </node>
166
167=== modified file 'plugins/IntegratedLightDM/liblightdm/UsersModel.cpp'
168--- plugins/IntegratedLightDM/liblightdm/UsersModel.cpp 2016-03-01 14:09:40 +0000
169+++ plugins/IntegratedLightDM/liblightdm/UsersModel.cpp 2016-06-20 20:23:46 +0000
170@@ -1,5 +1,5 @@
171 /*
172- * Copyright (C) 2013 Canonical, Ltd.
173+ * Copyright (C) 2013-2016 Canonical, Ltd.
174 *
175 * This program is free software; you can redistribute it and/or modify
176 * it under the terms of the GNU General Public License as published by
177@@ -52,6 +52,7 @@
178 roles[SessionRole] = "session";
179 roles[HasMessagesRole] = "hasMessages";
180 roles[ImagePathRole] = "imagePath";
181+ roles[UidRole] = "uid";
182 setRoleNames(roles);
183
184 connect(d_ptr, &UsersModelPrivate::dataChanged, this, [this](int i) {
185@@ -101,6 +102,8 @@
186 return d->entries[row].has_messages;
187 case UsersModel::ImagePathRole:
188 return "";
189+ case UsersModel::UidRole:
190+ return d->entries[row].uid;
191 default:
192 return QVariant();
193 }
194
195=== modified file 'plugins/IntegratedLightDM/liblightdm/UsersModel.h'
196--- plugins/IntegratedLightDM/liblightdm/UsersModel.h 2016-03-01 14:09:40 +0000
197+++ plugins/IntegratedLightDM/liblightdm/UsersModel.h 2016-06-20 20:23:46 +0000
198@@ -50,7 +50,8 @@
199 SessionRole,
200 HasMessagesRole,
201 ImagePathRole,
202- BackgroundPathRole
203+ BackgroundPathRole,
204+ UidRole
205 };
206
207 int rowCount(const QModelIndex &parent) const override;
208
209=== modified file 'plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp'
210--- plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp 2016-03-08 18:07:38 +0000
211+++ plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp 2016-06-20 20:23:46 +0000
212@@ -1,5 +1,5 @@
213 /*
214- * Copyright (C) 2013 Canonical, Ltd.
215+ * Copyright (C) 2013-2016 Canonical, Ltd.
216 *
217 * This program is free software; you can redistribute it and/or modify
218 * it under the terms of the GNU General Public License as published by
219@@ -26,6 +26,7 @@
220 #include <QDir>
221 #include <QSettings>
222 #include <QStringList>
223+#include <unistd.h>
224
225 namespace QLightDM
226 {
227@@ -37,6 +38,7 @@
228 {
229 QFileInfo demoFile(QDir::homePath() + "/.unity8-greeter-demo");
230 QString currentUser = g_get_user_name();
231+ uid_t currentUid = getuid();
232
233 if (demoFile.exists()) {
234 QSettings settings(demoFile.filePath(), QSettings::NativeFormat);
235@@ -46,10 +48,10 @@
236 Q_FOREACH(const QString &user, users)
237 {
238 QString name = settings.value(user + "/name", user).toString();
239- entries.append({user, name, 0, 0, false, false, 0, 0});
240+ entries.append({user, name, 0, 0, false, false, 0, 0, currentUid++});
241 }
242 } else {
243- entries.append({currentUser, 0, 0, 0, false, false, 0, 0});
244+ entries.append({currentUser, 0, 0, 0, false, false, 0, 0, currentUid});
245
246 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
247 this, [this](const QString &user) {
248
249=== modified file 'plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h'
250--- plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h 2016-03-01 14:09:40 +0000
251+++ plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h 2016-06-20 20:23:46 +0000
252@@ -1,5 +1,5 @@
253 /*
254- * Copyright (C) 2013 Canonical, Ltd.
255+ * Copyright (C) 2013-2016 Canonical, Ltd.
256 *
257 * This program is free software; you can redistribute it and/or modify
258 * it under the terms of the GNU General Public License as published by
259@@ -40,6 +40,7 @@
260 bool has_messages;
261 QString session;
262 QString infographic;
263+ uid_t uid;
264 };
265
266 class UsersModelPrivate : public QObject
267
268=== modified file 'qml/Components/DelayedLockscreen.qml'
269--- qml/Components/DelayedLockscreen.qml 2015-07-15 15:07:19 +0000
270+++ qml/Components/DelayedLockscreen.qml 2016-06-20 20:23:46 +0000
271@@ -28,6 +28,7 @@
272 signal cancel() // unused
273
274 function clear(playAnimation) {}
275+ function showText(text) {}
276
277 Column {
278 anchors.left: parent.left
279
280=== modified file 'qml/Components/Lockscreen.qml'
281--- qml/Components/Lockscreen.qml 2016-03-31 03:15:03 +0000
282+++ qml/Components/Lockscreen.qml 2016-06-20 20:23:46 +0000
283@@ -91,6 +91,14 @@
284 popup.z = Number.MAX_VALUE
285 }
286
287+ function showText(text) {
288+ // Programmatically enters the given text into the lockscreen
289+ if (pinPadLoader.item) {
290+ pinPadLoader.item.showText(text);
291+ pinPadLoader.waiting = true;
292+ }
293+ }
294+
295 Rectangle {
296 // In case background fails to load
297 id: backgroundBackup
298
299=== modified file 'qml/Components/PassphraseLockscreen.qml'
300--- qml/Components/PassphraseLockscreen.qml 2016-02-26 16:12:00 +0000
301+++ qml/Components/PassphraseLockscreen.qml 2016-06-20 20:23:46 +0000
302@@ -43,6 +43,10 @@
303 }
304 }
305
306+ function showText(text) {
307+ pinentryField.text = text;
308+ }
309+
310 Column {
311 id: shakeContainer
312 anchors.horizontalCenter: parent.horizontalCenter
313
314=== modified file 'qml/Components/PinLockscreen.qml'
315--- qml/Components/PinLockscreen.qml 2016-04-13 15:20:50 +0000
316+++ qml/Components/PinLockscreen.qml 2016-06-20 20:23:46 +0000
317@@ -46,6 +46,10 @@
318 }
319 }
320
321+ function showText(text) {
322+ pinentryField.text = text;
323+ }
324+
325 Keys.onPressed: {
326 if (pinentryField.text.length == root.maxPinLength)
327 return;
328
329=== modified file 'qml/Greeter/CoverPage.qml'
330--- qml/Greeter/CoverPage.qml 2016-05-18 13:38:27 +0000
331+++ qml/Greeter/CoverPage.qml 2016-06-20 20:23:46 +0000
332@@ -41,9 +41,16 @@
333 hide();
334 }
335
336+ function showErrorMessage(msg) {
337+ d.errorMessage = msg;
338+ showLabelAnimation.start();
339+ errorMessageAnimation.start();
340+ }
341+
342 QtObject {
343 id: d
344 property bool forceRightOnNextHideAnimation: false
345+ property string errorMessage
346 }
347
348 prepareToHide: function () {
349@@ -111,15 +118,18 @@
350
351 Label {
352 id: swipeHint
353+ objectName: "swipeHint"
354 property real baseOpacity: 0.5
355 opacity: 0.0
356 anchors.horizontalCenter: parent.horizontalCenter
357 anchors.bottom: parent.bottom
358 anchors.bottomMargin: units.gu(5)
359- text: "《 " + i18n.tr("Unlock") + " 》"
360+ text: "《 " + (d.errorMessage ? d.errorMessage : i18n.tr("Unlock")) + " 》"
361 color: "white"
362 font.weight: Font.Light
363
364+ readonly property var opacityAnimation: showLabelAnimation // for testing
365+
366 SequentialAnimation on opacity {
367 id: showLabelAnimation
368 running: false
369@@ -136,9 +146,20 @@
370 to: 0.0
371 duration: UbuntuAnimation.SleepyDuration
372 }
373+
374+ onRunningChanged: {
375+ if (!running)
376+ d.errorMessage = "";
377+ }
378 }
379 }
380
381+ WrongPasswordAnimation {
382+ id: errorMessageAnimation
383+ objectName: "errorMessageAnimation"
384+ target: swipeHint
385+ }
386+
387 DragHandle {
388 id: dragHandle
389 objectName: "coverPageDragHandle"
390
391=== modified file 'qml/Greeter/Greeter.qml'
392--- qml/Greeter/Greeter.qml 2016-06-17 01:18:17 +0000
393+++ qml/Greeter/Greeter.qml 2016-06-20 20:23:46 +0000
394@@ -16,7 +16,9 @@
395
396 import QtQuick 2.4
397 import AccountsService 0.1
398+import Biometryd 0.0
399 import GSettings 1.0
400+import Powerd 0.1
401 import Ubuntu.Components 1.3
402 import Ubuntu.SystemImage 0.1
403 import Unity.Launcher 0.1
404@@ -37,6 +39,8 @@
405 readonly property bool active: required || hasLockedApp
406 readonly property bool fullyShown: loader.item ? loader.item.fullyShown : false
407
408+ property bool allowFingerprint: true
409+
410 // True when the greeter is waiting for PAM or other setup process
411 readonly property alias waiting: d.waiting
412
413@@ -52,6 +56,7 @@
414 property int maxFailedLogins: -1 // disabled by default for now, will enable via settings in future
415 property int failedLoginsDelayAttempts: 7 // number of failed logins
416 property real failedLoginsDelayMinutes: 5 // minutes of forced waiting
417+ property int failedFingerprintLoginsDisableAttempts: 3 // number of failed fingerprint logins
418
419 readonly property bool animating: loader.item ? loader.item.animating : false
420
421@@ -60,6 +65,9 @@
422 signal emergencyCall()
423
424 function forceShow() {
425+ if (!active) {
426+ d.isLockscreen = true;
427+ }
428 forcedUnlock = false;
429 if (!required) {
430 showNow(); // loader.onLoaded will select a user
431@@ -119,6 +127,11 @@
432 readonly property bool multiUser: lightDM.users.count > 1
433 property int currentIndex
434 property bool waiting
435+ property bool isLockscreen // true when we are locking an active session, rather than first user login
436+ readonly property bool secureFingerprint: isLockscreen &&
437+ AccountsService.failedFingerprintLogins <
438+ root.failedFingerprintLoginsDisableAttempts
439+ readonly property bool alphanumeric: AccountsService.passwordDisplayHint === AccountsService.Keyboard
440
441 // We want 'launcherOffset' to animate down to zero. But not to animate
442 // while being dragged. So ideally we change this only when the user
443@@ -151,7 +164,7 @@
444 if (lightDM.greeter.startSessionSync()) {
445 sessionStarted();
446 if (loader.item) {
447- loader.item.notifyAuthenticationSucceeded();
448+ loader.item.notifyAuthenticationSucceeded(false /* showFakePassword */);
449 }
450 } else if (loader.item) {
451 loader.item.notifyAuthenticationFailed();
452@@ -170,7 +183,7 @@
453 function checkForcedUnlock(hideNow) {
454 if (forcedUnlock && shown && loader.item) {
455 // pretend we were just authenticated
456- loader.item.notifyAuthenticationSucceeded();
457+ loader.item.notifyAuthenticationSucceeded(false /* showFakePassword */);
458 loader.item.hide();
459 if (hideNow) {
460 root.hideNow(); // skip hide animation
461@@ -188,6 +201,17 @@
462 onForcedUnlockChanged: d.checkForcedUnlock(false /* hideNow */)
463 Component.onCompleted: d.checkForcedUnlock(true /* hideNow */)
464
465+ onLockedChanged: {
466+ if (!locked) {
467+ AccountsService.failedLogins = 0;
468+ AccountsService.failedFingerprintLogins = 0;
469+
470+ // Stop delay timer if they logged in with fingerprint
471+ forcedDelayTimer.stop();
472+ forcedDelayTimer.delayMinutes = 0;
473+ }
474+ }
475+
476 onRequiredChanged: {
477 if (required) {
478 d.waiting = true;
479@@ -349,7 +373,7 @@
480 Binding {
481 target: loader.item
482 property: "alphanumeric"
483- value: AccountsService.passwordDisplayHint === AccountsService.Keyboard
484+ value: d.alphanumeric
485 }
486
487 Binding {
488@@ -408,7 +432,6 @@
489 d.waiting = false;
490
491 if (lightDM.greeter.authenticated) {
492- AccountsService.failedLogins = 0;
493 d.login();
494 if (!lightDM.greeter.promptless) {
495 loader.item.hide();
496@@ -474,4 +497,74 @@
497 target: i18n
498 onLanguageChanged: lightDM.infographic.readyForDataChange()
499 }
500+
501+ Observer {
502+ id: biometryd
503+ objectName: "biometryd"
504+
505+ property var operation: null
506+ readonly property bool idEnabled: root.active &&
507+ root.allowFingerprint &&
508+ Powerd.status === Powerd.On &&
509+ Biometryd.available &&
510+ AccountsService.enableFingerprintIdentification
511+
512+ function cancelOperation() {
513+ if (operation) {
514+ operation.cancel();
515+ operation = null;
516+ }
517+ }
518+
519+ function restartOperation() {
520+ cancelOperation();
521+
522+ if (idEnabled) {
523+ var identifier = Biometryd.defaultDevice.identifier;
524+ operation = identifier.identifyUser();
525+ operation.start(biometryd);
526+ }
527+ }
528+
529+ function failOperation(reason) {
530+ console.log("Failed to identify user by fingerprint:", reason);
531+ restartOperation();
532+ if (!d.secureFingerprint) {
533+ d.startUnlock(false /* toTheRight */); // use normal login instead
534+ }
535+ if (loader.item) {
536+ var msg = d.secureFingerprint ? i18n.tr("Try again") : "";
537+ loader.item.showErrorMessage(msg);
538+ }
539+ }
540+
541+ Component.onCompleted: restartOperation()
542+ Component.onDestruction: cancelOperation()
543+ onIdEnabledChanged: restartOperation()
544+
545+ onSucceeded: {
546+ if (!d.secureFingerprint) {
547+ failOperation("fingerprint reader is locked");
548+ return;
549+ }
550+ if (result !== lightDM.users.data(d.currentIndex, lightDM.userRoles.UidRole)) {
551+ AccountsService.failedFingerprintLogins++;
552+ failOperation("not the selected user");
553+ return;
554+ }
555+ console.log("Identified user by fingerprint:", result);
556+ if (loader.item)
557+ loader.item.notifyAuthenticationSucceeded(true /* showFakePassword */);
558+ if (root.active)
559+ root.forcedUnlock = true;
560+ }
561+ onFailed: {
562+ if (!d.secureFingerprint) {
563+ failOperation("fingerprint reader is locked");
564+ } else {
565+ AccountsService.failedFingerprintLogins++;
566+ failOperation(reason);
567+ }
568+ }
569+ }
570 }
571
572=== modified file 'qml/Greeter/NarrowView.qml'
573--- qml/Greeter/NarrowView.qml 2016-05-18 13:38:27 +0000
574+++ qml/Greeter/NarrowView.qml 2016-06-20 20:23:46 +0000
575@@ -65,15 +65,28 @@
576 coverPage.hide();
577 }
578
579- function notifyAuthenticationSucceeded() {
580+ function notifyAuthenticationSucceeded(showFakePassword) {
581+ // When using an alternate log in mechanism like fingerprints, the
582+ // design is it looks like the user entered a passcode.
583+ if (!alphanumeric && showFakePassword) {
584+ lockscreen.showText("...."); // actual text doesn't matter, we show bullets
585+ }
586 lockscreen.hide();
587 }
588
589 function notifyAuthenticationFailed() {
590+ lockscreen.customError = "";
591+ lockscreen.clear(true);
592+ }
593+
594+ function showErrorMessage(msg) {
595+ coverPage.showErrorMessage(msg);
596+ lockscreen.customError = msg ? msg : " "; // avoid default message
597 lockscreen.clear(true);
598 }
599
600 function reset() {
601+ lockscreen.customError = "";
602 coverPage.show();
603 }
604
605@@ -116,7 +129,10 @@
606 infoText: promptText !== "" ? i18n.tr("Enter %1").arg(promptText) :
607 alphaNumeric ? i18n.tr("Enter passphrase") :
608 i18n.tr("Enter passcode")
609- errorText: promptText !== "" ? i18n.tr("Sorry, incorrect %1").arg(promptText) :
610+
611+ property string customError
612+ errorText: customError !== "" ? customError :
613+ promptText !== "" ? i18n.tr("Sorry, incorrect %1").arg(promptText) :
614 alphaNumeric ? i18n.tr("Sorry, incorrect passphrase") + "\n" +
615 i18n.ctr("passphrase", "Please re-enter") :
616 i18n.tr("Sorry, incorrect passcode")
617
618=== modified file 'qml/Greeter/WideView.qml'
619--- qml/Greeter/WideView.qml 2016-05-27 15:20:22 +0000
620+++ qml/Greeter/WideView.qml 2016-06-20 20:23:46 +0000
621@@ -58,7 +58,7 @@
622 coverPage.hide();
623 }
624
625- function notifyAuthenticationSucceeded() {
626+ function notifyAuthenticationSucceeded(showFakePassword) {
627 // Nothing needed
628 }
629
630@@ -66,6 +66,10 @@
631 loginList.showError();
632 }
633
634+ function showErrorMessage(msg) {
635+ coverPage.showErrorMessage(msg);
636+ }
637+
638 function reset() {
639 loginList.reset();
640 }
641
642=== modified file 'qml/Shell.qml'
643--- qml/Shell.qml 2016-06-17 01:18:17 +0000
644+++ qml/Shell.qml 2016-06-20 20:23:46 +0000
645@@ -421,6 +421,9 @@
646 launcherOffset: launcher.progress
647 forcedUnlock: wizard.active || shell.mode === "full-shell"
648 background: wallpaperResolver.background
649+ allowFingerprint: !dialogs.hasActiveDialog &&
650+ !notifications.topmostIsFullscreen &&
651+ !panel.indicators.shown
652
653 // avoid overlapping with Launcher's edge drag area
654 // FIXME: Fix TouchRegistry & friends and remove this workaround
655
656=== modified file 'tests/mocks/AccountsService/AccountsService.cpp'
657--- tests/mocks/AccountsService/AccountsService.cpp 2016-03-29 03:47:39 +0000
658+++ tests/mocks/AccountsService/AccountsService.cpp 2016-06-20 20:23:46 +0000
659@@ -20,11 +20,13 @@
660
661 AccountsService::AccountsService(QObject* parent)
662 : QObject(parent),
663+ m_enableFingerprintIdentification(true),
664 m_enableLauncherWhileLocked(true),
665 m_enableIndicatorsWhileLocked(true),
666 m_backgroundFile(qmlDirectory() + "/graphics/phone_background.jpg"),
667 m_statsWelcomeScreen(true),
668 m_failedLogins(0),
669+ m_failedFingerprintLogins(0),
670 m_demoEdges(false),
671 m_demoEdgesCompleted(),
672 m_hereEnabled(false),
673@@ -74,6 +76,17 @@
674 Q_EMIT demoEdgesCompletedChanged();
675 }
676
677+bool AccountsService::enableFingerprintIdentification() const
678+{
679+ return m_enableFingerprintIdentification;
680+}
681+
682+void AccountsService::setEnableFingerprintIdentification(bool enableFingerprintIdentification)
683+{
684+ m_enableFingerprintIdentification = enableFingerprintIdentification;
685+ Q_EMIT enableFingerprintIdentificationChanged();
686+}
687+
688 bool AccountsService::enableLauncherWhileLocked() const
689 {
690 return m_enableLauncherWhileLocked;
691@@ -137,6 +150,17 @@
692 failedLoginsChanged();
693 }
694
695+uint AccountsService::failedFingerprintLogins() const
696+{
697+ return m_failedFingerprintLogins;
698+}
699+
700+void AccountsService::setFailedFingerprintLogins(uint failedFingerprintLogins)
701+{
702+ m_failedFingerprintLogins = failedFingerprintLogins;
703+ failedFingerprintLoginsChanged();
704+}
705+
706 bool AccountsService::hereEnabled() const
707 {
708 return m_hereEnabled;
709
710=== modified file 'tests/mocks/AccountsService/AccountsService.h'
711--- tests/mocks/AccountsService/AccountsService.h 2016-03-29 03:47:39 +0000
712+++ tests/mocks/AccountsService/AccountsService.h 2016-06-20 20:23:46 +0000
713@@ -38,6 +38,10 @@
714 READ demoEdgesCompleted
715 WRITE setDemoEdgesCompleted // only available in mock
716 NOTIFY demoEdgesCompletedChanged)
717+ Q_PROPERTY (bool enableFingerprintIdentification
718+ READ enableFingerprintIdentification
719+ WRITE setEnableFingerprintIdentification // only available in mock
720+ NOTIFY enableFingerprintIdentificationChanged)
721 Q_PROPERTY (bool enableLauncherWhileLocked
722 READ enableLauncherWhileLocked
723 WRITE setEnableLauncherWhileLocked // only available in mock
724@@ -61,6 +65,10 @@
725 READ failedLogins
726 WRITE setFailedLogins
727 NOTIFY failedLoginsChanged)
728+ Q_PROPERTY (uint failedFingerprintLogins
729+ READ failedFingerprintLogins
730+ WRITE setFailedFingerprintLogins
731+ NOTIFY failedFingerprintLoginsChanged)
732 Q_PROPERTY(bool hereEnabled
733 READ hereEnabled
734 WRITE setHereEnabled
735@@ -94,6 +102,8 @@
736 QStringList demoEdgesCompleted() const;
737 void setDemoEdgesCompleted(const QStringList &demoEdges);
738 Q_INVOKABLE void markDemoEdgeCompleted(const QString &edge);
739+ bool enableFingerprintIdentification() const;
740+ void setEnableFingerprintIdentification(bool enableFingerprintIdentification);
741 bool enableLauncherWhileLocked() const;
742 void setEnableLauncherWhileLocked(bool enableLauncherWhileLocked);
743 bool enableIndicatorsWhileLocked() const;
744@@ -105,6 +115,8 @@
745 PasswordDisplayHint passwordDisplayHint() const;
746 uint failedLogins() const;
747 void setFailedLogins(uint failedLogins);
748+ uint failedFingerprintLogins() const;
749+ void setFailedFingerprintLogins(uint failedFingerprintLogins);
750 bool hereEnabled() const;
751 void setHereEnabled(bool enabled);
752 QString hereLicensePath() const;
753@@ -121,12 +133,14 @@
754 void userChanged();
755 void demoEdgesChanged();
756 void demoEdgesCompletedChanged();
757+ void enableFingerprintIdentificationChanged();
758 void enableLauncherWhileLockedChanged();
759 void enableIndicatorsWhileLockedChanged();
760 void backgroundFileChanged();
761 void statsWelcomeScreenChanged();
762 void passwordDisplayHintChanged();
763 void failedLoginsChanged();
764+ void failedFingerprintLoginsChanged();
765 void hereEnabledChanged();
766 void hereLicensePathChanged();
767 void realNameChanged();
768@@ -134,12 +148,14 @@
769 void keymapsChanged();
770
771 private:
772+ bool m_enableFingerprintIdentification;
773 bool m_enableLauncherWhileLocked;
774 bool m_enableIndicatorsWhileLocked;
775 QString m_backgroundFile;
776 QString m_user;
777 bool m_statsWelcomeScreen;
778 uint m_failedLogins;
779+ uint m_failedFingerprintLogins;
780 bool m_demoEdges;
781 QStringList m_demoEdgesCompleted;
782 bool m_hereEnabled;
783
784=== added directory 'tests/mocks/Biometryd'
785=== added file 'tests/mocks/Biometryd/CMakeLists.txt'
786--- tests/mocks/Biometryd/CMakeLists.txt 1970-01-01 00:00:00 +0000
787+++ tests/mocks/Biometryd/CMakeLists.txt 2016-06-20 20:23:46 +0000
788@@ -0,0 +1,14 @@
789+set(MOCK_BIOMETRYD_SOURCES
790+ plugin.cpp
791+ MockBiometryd.cpp
792+ MockDevice.cpp
793+ MockIdentifier.cpp
794+ MockObserver.cpp
795+ MockOperation.cpp
796+)
797+
798+add_library(MockBiometryd MODULE ${MOCK_BIOMETRYD_SOURCES})
799+
800+qt5_use_modules(MockBiometryd Qml Quick Core)
801+
802+add_unity8_mock(Biometryd 0.0 Biometryd TARGETS MockBiometryd)
803
804=== added file 'tests/mocks/Biometryd/MockBiometryd.cpp'
805--- tests/mocks/Biometryd/MockBiometryd.cpp 1970-01-01 00:00:00 +0000
806+++ tests/mocks/Biometryd/MockBiometryd.cpp 2016-06-20 20:23:46 +0000
807@@ -0,0 +1,43 @@
808+/*
809+ * Copyright (C) 2016 Canonical, Ltd.
810+ *
811+ * This program is free software; you can redistribute it and/or modify
812+ * it under the terms of the GNU General Public License as published by
813+ * the Free Software Foundation; version 3.
814+ *
815+ * This program is distributed in the hope that it will be useful,
816+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
817+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
818+ * GNU General Public License for more details.
819+ *
820+ * You should have received a copy of the GNU General Public License
821+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
822+ */
823+
824+#include "MockBiometryd.h"
825+#include "MockDevice.h"
826+
827+MockBiometryd::MockBiometryd(QObject *parent)
828+ : QObject(parent)
829+ , m_device(new MockDevice(this))
830+ , m_available(true)
831+{
832+}
833+
834+MockDevice *MockBiometryd::defaultDevice() const
835+{
836+ return m_device;
837+}
838+
839+bool MockBiometryd::available() const
840+{
841+ return m_available;
842+}
843+
844+void MockBiometryd::setAvailable(bool available)
845+{
846+ if (m_available != available) {
847+ m_available = available;
848+ Q_EMIT availableChanged();
849+ }
850+}
851
852=== added file 'tests/mocks/Biometryd/MockBiometryd.h'
853--- tests/mocks/Biometryd/MockBiometryd.h 1970-01-01 00:00:00 +0000
854+++ tests/mocks/Biometryd/MockBiometryd.h 2016-06-20 20:23:46 +0000
855@@ -0,0 +1,50 @@
856+/*
857+ * Copyright (C) 2016 Canonical, Ltd.
858+ *
859+ * This program is free software; you can redistribute it and/or modify
860+ * it under the terms of the GNU General Public License as published by
861+ * the Free Software Foundation; version 3.
862+ *
863+ * This program is distributed in the hope that it will be useful,
864+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
865+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
866+ * GNU General Public License for more details.
867+ *
868+ * You should have received a copy of the GNU General Public License
869+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
870+ */
871+
872+#ifndef MOCK_BIOMETRYD_H
873+#define MOCK_BIOMETRYD_H
874+
875+#include <QObject>
876+
877+#include "MockDevice.h"
878+
879+class MockBiometryd : public QObject
880+{
881+ Q_OBJECT
882+ Q_DISABLE_COPY(MockBiometryd)
883+ Q_PROPERTY(MockDevice *defaultDevice READ defaultDevice CONSTANT)
884+ Q_PROPERTY(bool available
885+ READ available
886+ WRITE setAvailable // only in mock
887+ NOTIFY availableChanged)
888+
889+public:
890+ explicit MockBiometryd(QObject *parent = 0);
891+
892+ MockDevice *defaultDevice() const;
893+
894+ bool available() const;
895+ void setAvailable(bool available);
896+
897+Q_SIGNALS:
898+ void availableChanged();
899+
900+private:
901+ MockDevice *m_device;
902+ bool m_available;
903+};
904+
905+#endif // MOCK_BIOMETRYD_H
906
907=== added file 'tests/mocks/Biometryd/MockDevice.cpp'
908--- tests/mocks/Biometryd/MockDevice.cpp 1970-01-01 00:00:00 +0000
909+++ tests/mocks/Biometryd/MockDevice.cpp 2016-06-20 20:23:46 +0000
910@@ -0,0 +1,29 @@
911+/*
912+ * Copyright (C) 2016 Canonical, Ltd.
913+ *
914+ * This program is free software; you can redistribute it and/or modify
915+ * it under the terms of the GNU General Public License as published by
916+ * the Free Software Foundation; version 3.
917+ *
918+ * This program is distributed in the hope that it will be useful,
919+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
920+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
921+ * GNU General Public License for more details.
922+ *
923+ * You should have received a copy of the GNU General Public License
924+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
925+ */
926+
927+#include "MockDevice.h"
928+#include "MockIdentifier.h"
929+
930+MockDevice::MockDevice(QObject *parent)
931+ : QObject(parent)
932+ , m_identifier(new MockIdentifier(this))
933+{
934+}
935+
936+MockIdentifier *MockDevice::identifier() const
937+{
938+ return m_identifier;
939+}
940
941=== added file 'tests/mocks/Biometryd/MockDevice.h'
942--- tests/mocks/Biometryd/MockDevice.h 1970-01-01 00:00:00 +0000
943+++ tests/mocks/Biometryd/MockDevice.h 2016-06-20 20:23:46 +0000
944@@ -0,0 +1,40 @@
945+/*
946+ * Copyright (C) 2016 Canonical, Ltd.
947+ *
948+ * This program is free software; you can redistribute it and/or modify
949+ * it under the terms of the GNU General Public License as published by
950+ * the Free Software Foundation; version 3.
951+ *
952+ * This program is distributed in the hope that it will be useful,
953+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
954+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
955+ * GNU General Public License for more details.
956+ *
957+ * You should have received a copy of the GNU General Public License
958+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
959+ */
960+
961+#ifndef MOCK_DEVICE_H
962+#define MOCK_DEVICE_H
963+
964+#include <QObject>
965+
966+#include "MockIdentifier.h"
967+
968+class MockDevice : public QObject
969+{
970+ Q_OBJECT
971+ Q_PROPERTY(MockIdentifier *identifier READ identifier CONSTANT)
972+
973+public:
974+ explicit MockDevice(QObject *parent = 0);
975+
976+ MockIdentifier *identifier() const;
977+
978+private:
979+ MockIdentifier *m_identifier;
980+};
981+
982+Q_DECLARE_METATYPE(MockDevice*)
983+
984+#endif // MOCK_DEVICE_H
985
986=== added file 'tests/mocks/Biometryd/MockIdentifier.cpp'
987--- tests/mocks/Biometryd/MockIdentifier.cpp 1970-01-01 00:00:00 +0000
988+++ tests/mocks/Biometryd/MockIdentifier.cpp 2016-06-20 20:23:46 +0000
989@@ -0,0 +1,28 @@
990+/*
991+ * Copyright (C) 2016 Canonical, Ltd.
992+ *
993+ * This program is free software; you can redistribute it and/or modify
994+ * it under the terms of the GNU General Public License as published by
995+ * the Free Software Foundation; version 3.
996+ *
997+ * This program is distributed in the hope that it will be useful,
998+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
999+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1000+ * GNU General Public License for more details.
1001+ *
1002+ * You should have received a copy of the GNU General Public License
1003+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1004+ */
1005+
1006+#include "MockIdentifier.h"
1007+#include "MockOperation.h"
1008+
1009+MockIdentifier::MockIdentifier(QObject *parent)
1010+ : QObject(parent)
1011+{
1012+}
1013+
1014+MockOperation *MockIdentifier::identifyUser()
1015+{
1016+ return new MockOperation(this);
1017+}
1018
1019=== added file 'tests/mocks/Biometryd/MockIdentifier.h'
1020--- tests/mocks/Biometryd/MockIdentifier.h 1970-01-01 00:00:00 +0000
1021+++ tests/mocks/Biometryd/MockIdentifier.h 2016-06-20 20:23:46 +0000
1022@@ -0,0 +1,36 @@
1023+/*
1024+ * Copyright (C) 2016 Canonical, Ltd.
1025+ *
1026+ * This program is free software; you can redistribute it and/or modify
1027+ * it under the terms of the GNU General Public License as published by
1028+ * the Free Software Foundation; version 3.
1029+ *
1030+ * This program is distributed in the hope that it will be useful,
1031+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1032+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1033+ * GNU General Public License for more details.
1034+ *
1035+ * You should have received a copy of the GNU General Public License
1036+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1037+ */
1038+
1039+#ifndef MOCK_IDENTIFIER_H
1040+#define MOCK_IDENTIFIER_H
1041+
1042+#include <QObject>
1043+
1044+#include "MockOperation.h"
1045+
1046+class MockIdentifier : public QObject
1047+{
1048+ Q_OBJECT
1049+
1050+public:
1051+ explicit MockIdentifier(QObject *parent = 0);
1052+
1053+ Q_INVOKABLE MockOperation *identifyUser();
1054+};
1055+
1056+Q_DECLARE_METATYPE(MockIdentifier*)
1057+
1058+#endif // MOCK_IDENTIFIER_H
1059
1060=== added file 'tests/mocks/Biometryd/MockObserver.cpp'
1061--- tests/mocks/Biometryd/MockObserver.cpp 1970-01-01 00:00:00 +0000
1062+++ tests/mocks/Biometryd/MockObserver.cpp 2016-06-20 20:23:46 +0000
1063@@ -0,0 +1,22 @@
1064+/*
1065+ * Copyright (C) 2016 Canonical, Ltd.
1066+ *
1067+ * This program is free software; you can redistribute it and/or modify
1068+ * it under the terms of the GNU General Public License as published by
1069+ * the Free Software Foundation; version 3.
1070+ *
1071+ * This program is distributed in the hope that it will be useful,
1072+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1073+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1074+ * GNU General Public License for more details.
1075+ *
1076+ * You should have received a copy of the GNU General Public License
1077+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1078+ */
1079+
1080+#include "MockObserver.h"
1081+
1082+MockObserver::MockObserver(QObject *parent)
1083+ : QObject(parent)
1084+{
1085+}
1086
1087=== added file 'tests/mocks/Biometryd/MockObserver.h'
1088--- tests/mocks/Biometryd/MockObserver.h 1970-01-01 00:00:00 +0000
1089+++ tests/mocks/Biometryd/MockObserver.h 2016-06-20 20:23:46 +0000
1090@@ -0,0 +1,37 @@
1091+/*
1092+ * Copyright (C) 2016 Canonical, Ltd.
1093+ *
1094+ * This program is free software; you can redistribute it and/or modify
1095+ * it under the terms of the GNU General Public License as published by
1096+ * the Free Software Foundation; version 3.
1097+ *
1098+ * This program is distributed in the hope that it will be useful,
1099+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1100+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1101+ * GNU General Public License for more details.
1102+ *
1103+ * You should have received a copy of the GNU General Public License
1104+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1105+ */
1106+
1107+#ifndef MOCK_OBSERVER_H
1108+#define MOCK_OBSERVER_H
1109+
1110+#include <QObject>
1111+#include <QString>
1112+#include <QVariant>
1113+
1114+class MockObserver : public QObject
1115+{
1116+ Q_OBJECT
1117+ Q_DISABLE_COPY(MockObserver)
1118+
1119+public:
1120+ explicit MockObserver(QObject *parent = 0);
1121+
1122+Q_SIGNALS:
1123+ void succeeded(const QVariant &result);
1124+ void failed(const QString &reason);
1125+};
1126+
1127+#endif // MOCK_OBSERVER_H
1128
1129=== added file 'tests/mocks/Biometryd/MockOperation.cpp'
1130--- tests/mocks/Biometryd/MockOperation.cpp 1970-01-01 00:00:00 +0000
1131+++ tests/mocks/Biometryd/MockOperation.cpp 2016-06-20 20:23:46 +0000
1132@@ -0,0 +1,56 @@
1133+/*
1134+ * Copyright (C) 2016 Canonical, Ltd.
1135+ *
1136+ * This program is free software; you can redistribute it and/or modify
1137+ * it under the terms of the GNU General Public License as published by
1138+ * the Free Software Foundation; version 3.
1139+ *
1140+ * This program is distributed in the hope that it will be useful,
1141+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1142+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1143+ * GNU General Public License for more details.
1144+ *
1145+ * You should have received a copy of the GNU General Public License
1146+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1147+ */
1148+
1149+#include <QString>
1150+#include <QVariant>
1151+
1152+#include "MockOperation.h"
1153+
1154+MockOperation::MockOperation(QObject *parent)
1155+ : QObject(parent)
1156+ , m_observer(nullptr)
1157+{
1158+}
1159+
1160+bool MockOperation::running() const
1161+{
1162+ return m_observer != nullptr;
1163+}
1164+
1165+void MockOperation::start(QObject *observer)
1166+{
1167+ if (!m_observer)
1168+ m_observer = observer;
1169+}
1170+
1171+void MockOperation::cancel()
1172+{
1173+ m_observer = nullptr;
1174+}
1175+
1176+void MockOperation::mockSuccess(unsigned int uid)
1177+{
1178+ if (m_observer)
1179+ QMetaObject::invokeMethod(m_observer, "succeeded", Qt::DirectConnection,
1180+ Q_ARG(QVariant, QVariant::fromValue(uid)));
1181+}
1182+
1183+void MockOperation::mockFailure(const QString &reason)
1184+{
1185+ if (m_observer)
1186+ QMetaObject::invokeMethod(m_observer, "failed", Qt::DirectConnection,
1187+ Q_ARG(QString, reason));
1188+}
1189
1190=== added file 'tests/mocks/Biometryd/MockOperation.h'
1191--- tests/mocks/Biometryd/MockOperation.h 1970-01-01 00:00:00 +0000
1192+++ tests/mocks/Biometryd/MockOperation.h 2016-06-20 20:23:46 +0000
1193@@ -0,0 +1,48 @@
1194+/*
1195+ * Copyright (C) 2016 Canonical, Ltd.
1196+ *
1197+ * This program is free software; you can redistribute it and/or modify
1198+ * it under the terms of the GNU General Public License as published by
1199+ * the Free Software Foundation; version 3.
1200+ *
1201+ * This program is distributed in the hope that it will be useful,
1202+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1203+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1204+ * GNU General Public License for more details.
1205+ *
1206+ * You should have received a copy of the GNU General Public License
1207+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1208+ */
1209+
1210+#ifndef MOCK_OPERATION_H
1211+#define MOCK_OPERATION_H
1212+
1213+#include <QObject>
1214+
1215+class MockOperation : public QObject
1216+{
1217+ Q_OBJECT
1218+ Q_PROPERTY(bool running READ running NOTIFY runningChanged) // only in mock
1219+
1220+public:
1221+ explicit MockOperation(QObject *parent = 0);
1222+
1223+ Q_INVOKABLE void start(QObject *observer);
1224+ Q_INVOKABLE void cancel();
1225+
1226+ Q_INVOKABLE void mockSuccess(unsigned int uid); // only in mock
1227+ Q_INVOKABLE void mockFailure(const QString &reason); // only in mock
1228+
1229+ bool running() const; // only in mock
1230+
1231+Q_SIGNALS:
1232+ void runningChanged();
1233+
1234+private:
1235+ QObject *m_observer;
1236+ bool m_running;
1237+};
1238+
1239+Q_DECLARE_METATYPE(MockOperation*)
1240+
1241+#endif // MOCK_OPERATION_H
1242
1243=== added file 'tests/mocks/Biometryd/plugin.cpp'
1244--- tests/mocks/Biometryd/plugin.cpp 1970-01-01 00:00:00 +0000
1245+++ tests/mocks/Biometryd/plugin.cpp 2016-06-20 20:23:46 +0000
1246@@ -0,0 +1,41 @@
1247+/*
1248+ * Copyright (C) 2014 Canonical, Ltd.
1249+ *
1250+ * This program is free software; you can redistribute it and/or modify
1251+ * it under the terms of the GNU General Public License as published by
1252+ * the Free Software Foundation; version 3.
1253+ *
1254+ * This program is distributed in the hope that it will be useful,
1255+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1256+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1257+ * GNU General Public License for more details.
1258+ *
1259+ * You should have received a copy of the GNU General Public License
1260+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1261+ */
1262+
1263+#include "plugin.h"
1264+#include "MockBiometryd.h"
1265+#include "MockDevice.h"
1266+#include "MockIdentifier.h"
1267+#include "MockObserver.h"
1268+#include "MockOperation.h"
1269+
1270+#include <QtQml>
1271+
1272+static QObject *biometryd_provider(QQmlEngine *, QJSEngine *)
1273+{
1274+ return new MockBiometryd();
1275+}
1276+
1277+void BackendPlugin::registerTypes(const char *uri)
1278+{
1279+ Q_ASSERT(uri == QLatin1String("Biometryd"));
1280+
1281+ qmlRegisterType<MockObserver>(uri, 0, 0, "Observer");
1282+ qmlRegisterSingletonType<MockBiometryd>(uri, 0, 0, "Biometryd", biometryd_provider);
1283+
1284+ qRegisterMetaType<MockDevice*>();
1285+ qRegisterMetaType<MockIdentifier*>();
1286+ qRegisterMetaType<MockOperation*>();
1287+}
1288
1289=== added file 'tests/mocks/Biometryd/plugin.h'
1290--- tests/mocks/Biometryd/plugin.h 1970-01-01 00:00:00 +0000
1291+++ tests/mocks/Biometryd/plugin.h 2016-06-20 20:23:46 +0000
1292@@ -0,0 +1,31 @@
1293+/*
1294+ * Copyright (C) 2016 Canonical, Ltd.
1295+ *
1296+ * This program is free software; you can redistribute it and/or modify
1297+ * it under the terms of the GNU General Public License as published by
1298+ * the Free Software Foundation; version 3.
1299+ *
1300+ * This program is distributed in the hope that it will be useful,
1301+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1302+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1303+ * GNU General Public License for more details.
1304+ *
1305+ * You should have received a copy of the GNU General Public License
1306+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1307+ */
1308+
1309+#ifndef MOCK_BIOMETRYD_PLUGIN_H
1310+#define MOCK_BIOMETRYD_PLUGIN_H
1311+
1312+#include <QQmlExtensionPlugin>
1313+
1314+class BackendPlugin : public QQmlExtensionPlugin
1315+{
1316+ Q_OBJECT
1317+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
1318+
1319+public:
1320+ void registerTypes(const char *uri) override;
1321+};
1322+
1323+#endif // MOCK_BIOMETRYD_PLUGIN_H
1324
1325=== added file 'tests/mocks/Biometryd/qmldir'
1326--- tests/mocks/Biometryd/qmldir 1970-01-01 00:00:00 +0000
1327+++ tests/mocks/Biometryd/qmldir 2016-06-20 20:23:46 +0000
1328@@ -0,0 +1,3 @@
1329+module Biometryd
1330+plugin MockBiometryd
1331+typeinfo Biometryd.qmltypes
1332
1333=== modified file 'tests/mocks/CMakeLists.txt'
1334--- tests/mocks/CMakeLists.txt 2015-11-16 14:12:00 +0000
1335+++ tests/mocks/CMakeLists.txt 2016-06-20 20:23:46 +0000
1336@@ -29,6 +29,7 @@
1337 endmacro()
1338
1339 add_subdirectory(AccountsService)
1340+add_subdirectory(Biometryd)
1341 add_subdirectory(Cursor)
1342 add_subdirectory(GSettings.1.0)
1343 add_subdirectory(indicator-service)
1344
1345=== modified file 'tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp'
1346--- tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp 2016-03-01 14:09:40 +0000
1347+++ tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp 2016-06-20 20:23:46 +0000
1348@@ -1,5 +1,5 @@
1349 /*
1350- * Copyright (C) 2013 Canonical, Ltd.
1351+ * Copyright (C) 2013-2016 Canonical, Ltd.
1352 *
1353 * This program is free software; you can redistribute it and/or modify
1354 * it under the terms of the GNU General Public License as published by
1355@@ -46,6 +46,7 @@
1356 roles[SessionRole] = "session";
1357 roles[HasMessagesRole] = "hasMessages";
1358 roles[ImagePathRole] = "imagePath";
1359+ roles[UidRole] = "uid";
1360 setRoleNames(roles);
1361 }
1362
1363@@ -95,6 +96,8 @@
1364 return d->entries[row].has_messages;
1365 case UsersModel::ImagePathRole:
1366 return "";
1367+ case UsersModel::UidRole:
1368+ return d->entries[row].uid;
1369 default:
1370 return QVariant();
1371 }
1372
1373=== modified file 'tests/mocks/IntegratedLightDM/liblightdm/UsersModel.h'
1374--- tests/mocks/IntegratedLightDM/liblightdm/UsersModel.h 2015-04-30 09:31:51 +0000
1375+++ tests/mocks/IntegratedLightDM/liblightdm/UsersModel.h 2016-06-20 20:23:46 +0000
1376@@ -50,7 +50,8 @@
1377 SessionRole,
1378 HasMessagesRole,
1379 ImagePathRole,
1380- BackgroundPathRole
1381+ BackgroundPathRole,
1382+ UidRole
1383 };
1384
1385 int rowCount(const QModelIndex &parent) const override;
1386
1387=== modified file 'tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp'
1388--- tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp 2016-05-18 19:03:11 +0000
1389+++ tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp 2016-06-20 20:23:46 +0000
1390@@ -1,5 +1,5 @@
1391 /*
1392- * Copyright (C) 2014 Canonical, Ltd.
1393+ * Copyright (C) 2014-2016 Canonical, Ltd.
1394 *
1395 * This program is free software; you can redistribute it and/or modify
1396 * it under the terms of the GNU General Public License as published by
1397@@ -47,6 +47,12 @@
1398 resetEntries_full();
1399 }
1400
1401+ // Assign uids in a loop, just to avoid having to muck with them when
1402+ // adding or removing test users.
1403+ for (int i = 0; i < entries.size(); i++) {
1404+ entries[i].uid = i + 1;
1405+ }
1406+
1407 q->endResetModel();
1408 }
1409
1410@@ -54,7 +60,7 @@
1411 {
1412 entries =
1413 {
1414- { "single", "Single User", 0, 0, false, false, 0, 0 },
1415+ { "single", "Single User", 0, 0, false, false, 0, 0, 0 },
1416 };
1417 }
1418
1419@@ -62,7 +68,7 @@
1420 {
1421 entries =
1422 {
1423- { "single", "Single User", 0, 0, false, false, 0, 0 },
1424+ { "single", "Single User", 0, 0, false, false, 0, 0, 0 },
1425 };
1426 }
1427
1428@@ -70,7 +76,7 @@
1429 {
1430 entries =
1431 {
1432- { "has-pin", "Has PIN", 0, 0, false, false, 0, 0 },
1433+ { "has-pin", "Has PIN", 0, 0, false, false, 0, 0, 0 },
1434 };
1435 }
1436
1437@@ -78,26 +84,26 @@
1438 {
1439 entries =
1440 {
1441- { "has-password", "Has Password", 0, 0, false, false, 0, 0 },
1442- { "has-pin", "Has PIN", 0, 0, false, false, 0, 0 },
1443- { "different-prompt", "Different Prompt", 0, 0, false, false, 0, 0 },
1444- { "no-password", "No Password", 0, 0, false, false, 0, 0 },
1445- { "auth-error", "Auth Error", 0, 0, false, false, 0, 0 },
1446- { "two-factor", "Two Factor", 0, 0, false, false, 0, 0 },
1447- { "info-prompt", "Info Prompt", 0, 0, false, false, 0, 0 },
1448- { "html-info-prompt", "HTML Info Prompt", 0, 0, false, false, 0, 0 },
1449- { "long-info-prompt", "Long Info Prompt", 0, 0, false, false, 0, 0 },
1450- { "wide-info-prompt", "Wide Info Prompt", 0, 0, false, false, 0, 0 },
1451- { "multi-info-prompt", "Multi Info Prompt", 0, 0, false, false, 0, 0 },
1452- { "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, 0, 0 },
1453- { "color-background", "Color Background", "#dd4814", 0, false, false, 0, 0 },
1454+ { "has-password", "Has Password", 0, 0, false, false, 0, 0, 0 },
1455+ { "has-pin", "Has PIN", 0, 0, false, false, 0, 0, 0 },
1456+ { "different-prompt", "Different Prompt", 0, 0, false, false, 0, 0, 0 },
1457+ { "no-password", "No Password", 0, 0, false, false, 0, 0, 0 },
1458+ { "auth-error", "Auth Error", 0, 0, false, false, 0, 0, 0 },
1459+ { "two-factor", "Two Factor", 0, 0, false, false, 0, 0, 0 },
1460+ { "info-prompt", "Info Prompt", 0, 0, false, false, 0, 0, 0 },
1461+ { "html-info-prompt", "HTML Info Prompt", 0, 0, false, false, 0, 0, 0 },
1462+ { "long-info-prompt", "Long Info Prompt", 0, 0, false, false, 0, 0, 0 },
1463+ { "wide-info-prompt", "Wide Info Prompt", 0, 0, false, false, 0, 0, 0 },
1464+ { "multi-info-prompt", "Multi Info Prompt", 0, 0, false, false, 0, 0, 0 },
1465+ { "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, 0, 0, 0 },
1466+ { "color-background", "Color Background", "#dd4814", 0, false, false, 0, 0, 0 },
1467 // white and black are a bit redundant, but useful for manually testing if UI is still readable
1468- { "white-background", "White Background", "#ffffff", 0, false, false, 0, 0 },
1469- { "black-background", "Black Background", "#000000", 0, false, false, 0, 0 },
1470- { "no-background", "No Background", "", 0, false, false, 0, 0 },
1471- { "unicode", "가나다라마", 0, 0, false, false, 0, 0 },
1472- { "no-response", "No Response", 0, 0, false, false, 0, 0 },
1473- { "empty-name", "", 0, 0, false, false, 0, 0 },
1474+ { "white-background", "White Background", "#ffffff", 0, false, false, 0, 0, 0 },
1475+ { "black-background", "Black Background", "#000000", 0, false, false, 0, 0, 0 },
1476+ { "no-background", "No Background", "", 0, false, false, 0, 0, 0 },
1477+ { "unicode", "가나다라마", 0, 0, false, false, 0, 0, 0 },
1478+ { "no-response", "No Response", 0, 0, false, false, 0, 0, 0 },
1479+ { "empty-name", "", 0, 0, false, false, 0, 0, 0 },
1480 };
1481 }
1482
1483
1484=== modified file 'tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.h'
1485--- tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.h 2015-01-20 11:50:19 +0000
1486+++ tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.h 2016-06-20 20:23:46 +0000
1487@@ -1,5 +1,5 @@
1488 /*
1489- * Copyright (C) 2014 Canonical, Ltd.
1490+ * Copyright (C) 2014-2016 Canonical, Ltd.
1491 *
1492 * This program is free software; you can redistribute it and/or modify
1493 * it under the terms of the GNU General Public License as published by
1494@@ -35,6 +35,7 @@
1495 bool has_messages;
1496 QString session;
1497 QString infographic;
1498+ uid_t uid;
1499 };
1500
1501 class UsersModelPrivate
1502
1503=== modified file 'tests/qmltests/Components/tst_Lockscreen.qml'
1504--- tests/qmltests/Components/tst_Lockscreen.qml 2016-02-26 16:28:14 +0000
1505+++ tests/qmltests/Components/tst_Lockscreen.qml 2016-06-20 20:23:46 +0000
1506@@ -173,6 +173,7 @@
1507 function cleanup() {
1508 lockscreen.clear(false);
1509 delayMinutesTextField.text = "0"
1510+ enteredLabel.text = "";
1511
1512 // Reset sizing
1513 root.width = units.gu(80)
1514@@ -247,7 +248,6 @@
1515 }
1516
1517 function test_unlock(data) {
1518- enteredLabel.text = ""
1519 minPinLengthTextField.text = data.minPinLength
1520 maxPinLengthTextField.text = data.maxPinLength
1521 pinPadCheckBox.checked = data.alphanumeric
1522@@ -462,6 +462,25 @@
1523 compare(label.text, "Device Locked")
1524 }
1525
1526+ function test_showText_data() {
1527+ return [
1528+ { tag: "alphanumeric", alphanumeric: true },
1529+ { tag: "pinPad", alphanumeric: false },
1530+ ]
1531+ }
1532+
1533+ function test_showText(data) {
1534+ pinPadCheckBox.checked = data.alphanumeric;
1535+ waitForLockscreenReady();
1536+
1537+ lockscreen.showText("test");
1538+
1539+ var pinPadLoader = findChild(lockscreen, "pinPadLoader");
1540+ verify(pinPadLoader.waiting);
1541+ compare(enteredLabel.text, ""); // no entered signal should occur
1542+ compare(lockscreen.passphrase, "test");
1543+ }
1544+
1545 function test_resize_data() {
1546 return [
1547 { tag: "small", width: units.gu(40), height: units.gu(76) },
1548
1549=== modified file 'tests/qmltests/Greeter/TestView.qml'
1550--- tests/qmltests/Greeter/TestView.qml 2015-07-15 15:07:19 +0000
1551+++ tests/qmltests/Greeter/TestView.qml 2016-06-20 20:23:46 +0000
1552@@ -33,9 +33,11 @@
1553 property var infographicModel
1554 readonly property bool fullyShown: _fullyShown
1555 readonly property bool required: _required
1556+ readonly property bool animating: _animating
1557
1558 property bool _fullyShown: true
1559 property bool _required: true
1560+ property bool _animating: true
1561
1562 signal selected(int index)
1563 signal responded(string response)
1564@@ -46,8 +48,9 @@
1565 signal _showPromptCalled(string text, bool isSecret, bool isDefaultPrompt)
1566 signal _showLastChanceCalled()
1567 signal _hideCalled()
1568- signal _notifyAuthenticationSucceededCalled()
1569+ signal _notifyAuthenticationSucceededCalled(bool showFakePassword)
1570 signal _notifyAuthenticationFailedCalled()
1571+ signal _showErrorMessageCalled(string msg)
1572 signal _resetCalled()
1573 signal _tryToUnlockCalled(bool toTheRight)
1574
1575@@ -69,14 +72,18 @@
1576 _fullyShown = false;
1577 }
1578
1579- function notifyAuthenticationSucceeded() {
1580- _notifyAuthenticationSucceededCalled();
1581+ function notifyAuthenticationSucceeded(showFakePassword) {
1582+ _notifyAuthenticationSucceededCalled(showFakePassword);
1583 }
1584
1585 function notifyAuthenticationFailed() {
1586 _notifyAuthenticationFailedCalled();
1587 }
1588
1589+ function showErrorMessage(msg) {
1590+ _showErrorMessageCalled(msg);
1591+ }
1592+
1593 function reset() {
1594 _resetCalled();
1595 }
1596
1597=== modified file 'tests/qmltests/Greeter/tst_Greeter.qml'
1598--- tests/qmltests/Greeter/tst_Greeter.qml 2016-05-02 07:57:07 +0000
1599+++ tests/qmltests/Greeter/tst_Greeter.qml 2016-06-20 20:23:46 +0000
1600@@ -20,6 +20,7 @@
1601 import "../../../qml/Greeter"
1602 import Ubuntu.Components 1.3
1603 import AccountsService 0.1
1604+import Biometryd 0.0
1605 import GSettings 1.0
1606 import IntegratedLightDM 0.1 as LightDM
1607 import Unity.Test 0.1 as UT
1608@@ -126,6 +127,12 @@
1609 }
1610
1611 SignalSpy {
1612+ id: viewShowErrorMessageSpy
1613+ target: testCase.view
1614+ signalName: "_showErrorMessageCalled"
1615+ }
1616+
1617+ SignalSpy {
1618 id: viewResetSpy
1619 target: testCase.view
1620 signalName: "_resetCalled"
1621@@ -143,12 +150,16 @@
1622 teaseSpy.clear();
1623 sessionStartedSpy.clear();
1624 activeChangedSpy.clear();
1625+ Biometryd.available = true;
1626+ AccountsService.enableFingerprintIdentification = true;
1627+ AccountsService.failedFingerprintLogins = 0;
1628 viewShowMessageSpy.clear();
1629 viewShowPromptSpy.clear();
1630 viewShowLastChanceSpy.clear();
1631 viewHideSpy.clear();
1632 viewAuthenticationSucceededSpy.clear();
1633 viewAuthenticationFailedSpy.clear();
1634+ viewShowErrorMessageSpy.clear();
1635 viewResetSpy.clear();
1636 viewTryToUnlockSpy.clear();
1637 tryCompare(greeter, "waiting", false);
1638@@ -200,6 +211,14 @@
1639 compare(greeter.shown, false);
1640 }
1641
1642+ function unlockAndShowGreeter() {
1643+ // useful to enable "lockscreen mode" in greeter
1644+ greeter.forcedUnlock = true;
1645+ LightDM.Greeter.showGreeter();
1646+ tryCompare(greeter, "waiting", false);
1647+ view = findChild(greeter, "testView");
1648+ }
1649+
1650 function test_unlockPass() {
1651 selectUser("has-password");
1652 tryCompare(viewShowPromptSpy, "count", 1);
1653@@ -553,5 +572,157 @@
1654 compare(viewResetSpy.count, 1);
1655 tryCompare(viewShowPromptSpy, "count", 1);
1656 }
1657+
1658+ function test_fingerprintSuccess() {
1659+ var index = selectUser("has-password");
1660+ unlockAndShowGreeter(); // turn on lockscreen mode
1661+
1662+ var biometryd = findInvisibleChild(greeter, "biometryd");
1663+ verify(biometryd.operation);
1664+ verify(biometryd.operation.running);
1665+
1666+ biometryd.operation.mockSuccess(LightDM.Users.data(index, LightDM.UserRoles.UidRole));
1667+ verify(!greeter.active);
1668+ }
1669+
1670+ function test_fingerprintFirstLoginDisabled() {
1671+ var index = selectUser("has-password");
1672+ // don't hide/show greeter, we want to test behavior before lockscreen mode is on
1673+
1674+ var biometryd = findInvisibleChild(greeter, "biometryd");
1675+ verify(biometryd.operation);
1676+ verify(biometryd.operation.running);
1677+
1678+ biometryd.operation.mockSuccess(LightDM.Users.data(index, LightDM.UserRoles.UidRole));
1679+ compare(viewTryToUnlockSpy.count, 1);
1680+ verify(greeter.locked);
1681+ }
1682+
1683+ function test_forcedDisallowedFingerprint() {
1684+ var index = selectUser("has-password");
1685+ unlockAndShowGreeter(); // turn on lockscreen mode
1686+
1687+ var biometryd = findInvisibleChild(greeter, "biometryd");
1688+ verify(biometryd.operation);
1689+ verify(biometryd.operation.running);
1690+
1691+ greeter.allowFingerprint = false;
1692+ verify(!biometryd.operation);
1693+ }
1694+
1695+ function test_fingerprintFailureMessage() {
1696+ var index = selectUser("has-password");
1697+ unlockAndShowGreeter(); // turn on lockscreen mode
1698+
1699+ var biometryd = findInvisibleChild(greeter, "biometryd");
1700+ verify(biometryd.operation);
1701+ verify(biometryd.operation.running);
1702+
1703+ biometryd.operation.mockFailure("error");
1704+ compare(viewShowErrorMessageSpy.count, 1);
1705+ compare(viewShowErrorMessageSpy.signalArguments[0][0], i18n.tr("Try again"));
1706+ }
1707+
1708+ function test_fingerprintTooManyFailures() {
1709+ var index = selectUser("has-password");
1710+ unlockAndShowGreeter(); // turn on lockscreen mode
1711+
1712+ var biometryd = findInvisibleChild(greeter, "biometryd");
1713+ biometryd.operation.mockFailure("error");
1714+ biometryd.operation.mockFailure("error");
1715+ compare(viewTryToUnlockSpy.count, 0);
1716+
1717+ biometryd.operation.mockFailure("error");
1718+ compare(viewTryToUnlockSpy.count, 1);
1719+
1720+ // Confirm that we are stuck in this mode until next login
1721+ biometryd.operation.mockSuccess(LightDM.Users.data(index, LightDM.UserRoles.UidRole));
1722+ compare(viewTryToUnlockSpy.count, 2);
1723+
1724+ unlockAndShowGreeter();
1725+
1726+ biometryd.operation.mockSuccess(LightDM.Users.data(index, LightDM.UserRoles.UidRole));
1727+ verify(!greeter.active);
1728+ }
1729+
1730+ function test_fingerprintFailureCountReset() {
1731+ selectUser("has-password");
1732+ unlockAndShowGreeter(); // turn on lockscreen mode
1733+
1734+ var biometryd = findInvisibleChild(greeter, "biometryd");
1735+ biometryd.operation.mockFailure("error");
1736+ biometryd.operation.mockFailure("error");
1737+ compare(viewTryToUnlockSpy.count, 0);
1738+
1739+ unlockAndShowGreeter();
1740+ biometryd.operation.mockFailure("error");
1741+ biometryd.operation.mockFailure("error");
1742+ compare(viewTryToUnlockSpy.count, 0);
1743+
1744+ biometryd.operation.mockFailure("error");
1745+ compare(viewTryToUnlockSpy.count, 1);
1746+ }
1747+
1748+ function test_fingerprintWrongUid() {
1749+ selectUser("has-password");
1750+ unlockAndShowGreeter(); // turn on lockscreen mode
1751+
1752+ var biometryd = findInvisibleChild(greeter, "biometryd");
1753+ biometryd.operation.mockSuccess(0);
1754+
1755+ verify(greeter.active);
1756+ compare(viewShowErrorMessageSpy.count, 1);
1757+ compare(viewShowErrorMessageSpy.signalArguments[0][0], i18n.tr("Try again"));
1758+ }
1759+
1760+ function test_fingerprintNotEnabled() {
1761+ AccountsService.enableFingerprintIdentification = false;
1762+ selectUser("has-password");
1763+ unlockAndShowGreeter(); // turn on lockscreen mode
1764+
1765+ var biometryd = findInvisibleChild(greeter, "biometryd");
1766+ verify(!biometryd.operation);
1767+
1768+ AccountsService.enableFingerprintIdentification = true;
1769+ verify(biometryd.operation);
1770+ verify(biometryd.operation.running);
1771+
1772+ AccountsService.enableFingerprintIdentification = false;
1773+ verify(!biometryd.operation);
1774+ }
1775+
1776+ function test_fingerprintReaderNotPresent() {
1777+ Biometryd.available = false;
1778+ selectUser("has-password");
1779+ unlockAndShowGreeter(); // turn on lockscreen mode
1780+
1781+ verify(!Biometryd.available);
1782+
1783+ var biometryd = findInvisibleChild(greeter, "biometryd");
1784+ verify(!biometryd.operation);
1785+
1786+ Biometryd.available = true;
1787+ verify(biometryd.operation);
1788+ verify(biometryd.operation.running);
1789+
1790+ Biometryd.available = false;
1791+ verify(!biometryd.operation);
1792+ }
1793+
1794+ function test_fingerprintGreeterNotActive() {
1795+ selectUser("has-password");
1796+ unlockAndShowGreeter(); // turn on lockscreen mode
1797+
1798+ var biometryd = findInvisibleChild(greeter, "biometryd");
1799+ verify(biometryd.operation);
1800+ verify(biometryd.operation.running);
1801+
1802+ greeter.hideNow();
1803+ verify(!biometryd.operation);
1804+
1805+ greeter.showNow();
1806+ verify(biometryd.operation);
1807+ verify(biometryd.operation.running);
1808+ }
1809 }
1810 }
1811
1812=== modified file 'tests/qmltests/Greeter/tst_NarrowView.qml'
1813--- tests/qmltests/Greeter/tst_NarrowView.qml 2016-05-02 07:57:07 +0000
1814+++ tests/qmltests/Greeter/tst_NarrowView.qml 2016-06-20 20:23:46 +0000
1815@@ -128,7 +128,7 @@
1816 text: "Authenticated"
1817 onClicked: {
1818 if (successCheckBox.checked) {
1819- loader.item.notifyAuthenticationSucceeded();
1820+ loader.item.notifyAuthenticationSucceeded(fakePasswordCheckBox.checked);
1821 } else {
1822 loader.item.notifyAuthenticationFailed();
1823 }
1824@@ -140,6 +140,12 @@
1825 Label {
1826 text: "success"
1827 }
1828+ CheckBox {
1829+ id: fakePasswordCheckBox
1830+ }
1831+ Label {
1832+ text: "fake password"
1833+ }
1834 }
1835 Row {
1836 Button {
1837@@ -529,5 +535,20 @@
1838 mouseClick(coverPage, coverPage.width/2, coverPage.height - units.gu(2));
1839 verify(!coverPage.shown);
1840 }
1841+
1842+ function test_showErrorMessage() {
1843+ var coverPage = findChild(view, "coverPage");
1844+ var swipeHint = findChild(coverPage, "swipeHint");
1845+ var errorMessageAnimation = findInvisibleChild(coverPage, "errorMessageAnimation");
1846+
1847+ view.showErrorMessage("hello");
1848+ compare(swipeHint.text, "《 hello 》");
1849+ verify(errorMessageAnimation.running);
1850+ verify(swipeHint.opacityAnimation.running);
1851+
1852+ errorMessageAnimation.complete();
1853+ swipeHint.opacityAnimation.complete();
1854+ tryCompare(swipeHint, "text", "《 " + i18n.tr("Unlock") + " 》");
1855+ }
1856 }
1857 }
1858
1859=== modified file 'tests/qmltests/Greeter/tst_WideView.qml'
1860--- tests/qmltests/Greeter/tst_WideView.qml 2016-06-01 19:37:11 +0000
1861+++ tests/qmltests/Greeter/tst_WideView.qml 2016-06-20 20:23:46 +0000
1862@@ -170,7 +170,7 @@
1863 text: "Authenticated"
1864 onClicked: {
1865 if (successCheckBox.checked) {
1866- loader.item.notifyAuthenticationSucceeded();
1867+ loader.item.notifyAuthenticationSucceeded(false);
1868 } else {
1869 loader.item.notifyAuthenticationFailed();
1870 }
1871
1872=== modified file 'tests/qmltests/tst_Shell.qml'
1873--- tests/qmltests/tst_Shell.qml 2016-06-17 01:18:17 +0000
1874+++ tests/qmltests/tst_Shell.qml 2016-06-20 20:23:46 +0000
1875@@ -334,6 +334,33 @@
1876 }
1877 }
1878
1879+ Label {
1880+ text: "Fingerprint"
1881+ }
1882+ Row {
1883+ Button {
1884+ text: "Success"
1885+ onClicked: {
1886+ var biometryd = testCase.findInvisibleChild(shellContainer, "biometryd");
1887+ var uid = 0;
1888+ for (var i = 0; i < LightDM.Users.count; i++) {
1889+ if (LightDM.Users.data(i, LightDM.UserRoles.NameRole) == AccountsService.user) {
1890+ uid = LightDM.Users.data(i, LightDM.UserRoles.UidRole);
1891+ break;
1892+ }
1893+ }
1894+ biometryd.operation.mockSuccess(uid);
1895+ }
1896+ }
1897+
1898+ Button {
1899+ text: "Failure"
1900+ onClicked: {
1901+ var biometryd = testCase.findInvisibleChild(shellContainer, "biometryd");
1902+ biometryd.operation.mockFailure("error");
1903+ }
1904+ }
1905+ }
1906 }
1907 }
1908 }

Subscribers

People subscribed via source and target branches