Merge lp:~mterry/unity8/wrong-password-handling into lp:unity8

Proposed by Michael Terry
Status: Superseded
Proposed branch: lp:~mterry/unity8/wrong-password-handling
Merge into: lp:unity8
Prerequisite: lp:~mterry/unity8/greeter-misc-cleanups
Diff against target: 1663 lines (+703/-139)
45 files modified
cmake/modules/QmlTest.cmake (+2/-2)
cmake/modules/autopilot.cmake (+2/-2)
debian/control (+2/-1)
debian/unity8-private.install (+0/-2)
plugins/AccountsService/50-com.canonical.unity.AccountsService.pkla (+0/-6)
plugins/AccountsService/AccountsService.cpp (+27/-1)
plugins/AccountsService/AccountsService.h (+9/-0)
plugins/AccountsService/CMakeLists.txt (+0/-10)
plugins/AccountsService/com.canonical.unity.AccountsService.policy (+0/-24)
plugins/AccountsService/com.canonical.unity.AccountsService.xml (+28/-5)
plugins/LightDM/Greeter.cpp (+4/-1)
plugins/LightDM/Greeter.h (+1/-1)
plugins/Ubuntu/CMakeLists.txt (+1/-0)
plugins/Ubuntu/SystemImage/CMakeLists.txt (+10/-0)
plugins/Ubuntu/SystemImage/SystemImage.cpp (+34/-0)
plugins/Ubuntu/SystemImage/SystemImage.h (+38/-0)
plugins/Ubuntu/SystemImage/SystemImage.qmltypes (+17/-0)
plugins/Ubuntu/SystemImage/plugin.cpp (+34/-0)
plugins/Ubuntu/SystemImage/plugin.h (+31/-0)
plugins/Ubuntu/SystemImage/qmldir (+3/-0)
po/unity8.pot (+72/-19)
qml/Components/Lockscreen.qml (+35/-10)
qml/Components/PassphraseLockscreen.qml (+3/-4)
qml/Components/PinLockscreen.qml (+3/-4)
qml/Notifications/NotificationMenuItemFactory.qml (+0/-1)
qml/Shell.qml (+53/-8)
run.sh (+21/-20)
tests/mocks/AccountsService/AccountsService.cpp (+13/-1)
tests/mocks/AccountsService/AccountsService.h (+8/-0)
tests/mocks/LightDM/Greeter.cpp (+11/-0)
tests/mocks/LightDM/Greeter.h (+3/-0)
tests/mocks/LightDM/demo/CMakeLists.txt (+13/-0)
tests/mocks/LightDM/full/GreeterPrivate.cpp (+4/-4)
tests/mocks/LightDM/single-passphrase/GreeterPrivate.cpp (+2/-9)
tests/mocks/LightDM/single-pin/GreeterPrivate.cpp (+3/-2)
tests/mocks/Ubuntu/CMakeLists.txt (+1/-0)
tests/mocks/Ubuntu/SystemImage/CMakeLists.txt (+10/-0)
tests/mocks/Ubuntu/SystemImage/MockSystemImage.cpp (+27/-0)
tests/mocks/Ubuntu/SystemImage/MockSystemImage.h (+36/-0)
tests/mocks/Ubuntu/SystemImage/SystemImage.qmltypes (+18/-0)
tests/mocks/Ubuntu/SystemImage/plugin.cpp (+34/-0)
tests/mocks/Ubuntu/SystemImage/plugin.h (+31/-0)
tests/mocks/Ubuntu/SystemImage/qmldir (+3/-0)
tests/qmltests/Greeter/tst_Lockscreen.qml (+0/-2)
tests/qmltests/tst_ShellWithPin.qml (+56/-0)
To merge this branch: bzr merge lp:~mterry/unity8/wrong-password-handling
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Michael Zanetti (community) Approve
Michał Sawicz Abstain
David Planella (community) Needs Fixing
Albert Astals Cid (community) Needs Fixing
Review via email: mp+229184@code.launchpad.net

This proposal has been superseded by a proposal from 2014-08-14.

Commit message

Make wrong-password handling much nicer by showing a pretty spinner while we wait for PAM, by improving the prompt text to match designs, by forcing the user to wait five seconds after every five failed attemps, and by supporting (but not yet enabling) an opt-in "factory-reset your phone after X failed attemps" feature.

Description of the change

Make wrong-password handling much nicer by showing a pretty spinner while we wait for PAM, by improving the prompt text to match designs, by forcing the user to wait five seconds after every five failed attemps, and by supporting (but not yet enabling) an opt-in "factory-reset your phone after X failed attemps" feature.

For the spec, see the "passcode incorrect" part of:
https://docs.google.com/a/canonical.com/document/d/1VajNkWbBH61iVixXJAmOvNGiG__GWQTMXGNOZijXWJw

It should go without saying, but BE PREPARED TO HAVE YOUR PHONE WIPED while testing the factory-reset bit (which, if you want to test, you have to manually edit the maxFailedLogins field in the qml).

I've added a tiny plugin for calling the system-image daemon's FactoryReset method. Maybe it will be useful for more things in the future.

I also cleaned up the AccountsService field definitions a bit.

== Using AccountsService to store the failedLogins count ==

I thought this might deserve a few words.

My original thought was to take advantage of our PAM infrastructure and use pam_tally2, which can do fancy tallying, login denial, and timeouts. But (A) that does not give any extra security since we'd need to specify a user-writable tally file as long as we don't have a split greeter, (B) it does not give us any warning when we are about to go over our limit, and (C) does not tell us *when* we are delaying due to too many failed logins, so we can't tell the user.

So we needed to store it ourselves. I could have used gsettings or similar, but we want to keep track of this per-user and stuffing a map into a settings backend isn't always convenient.

While AccountsService is mostly designed for data that can be shared between greeters and user sessions, it seemed like not an awful place to store the data and gives us per-user semantics for free. And we can share the data store with the eventually-split greeter (although that is certainly small potatoes).

== Checklist ==

 * Are there any related MPs required for this MP to build/function as expected? Please list.
 - Yes, greeter-misc-cleanups

 * Did you perform an exploratory manual test run of your code change and any related functionality?
 - Yes

 * Did you make sure that your branch does not contain spurious tags?
 - Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
 - I'm on the team

 * If you changed the UI, has there been a design review?
 - Olga and Esti are fine with this for now, but the visuals are all being updated. I just wanted to get the backend work in.

To post a comment you must log in.
1015. By Michael Terry

Switch to 7 attempts, 5 min lockout

1016. By Michael Terry

Handle translated PAM prompts

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1017. By Michael Terry

Merge from trunk

1018. By Michael Terry

Fix whitespace

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Seems like the qmluitests failure may be related to this, no?

review: Needs Fixing
Revision history for this message
David Planella (dpm) wrote :

This merge proposal is introducing a few new translatable strings. Could it provide an updated .pot file as well, so that translators can do their job in time? Thanks!

review: Needs Fixing
Revision history for this message
Michał Sawicz (saviq) wrote :

Indeed, make pot_file please.

We've a plan for a ~push hook that will warn us if stuff like this happens, but... too many higher priority items...

1019. By Michael Terry

Update pot file

1020. By Michael Terry

Fix mocks to use same prompt string as PAM

Revision history for this message
Michael Terry (mterry) wrote :

Updated pot file and fixed the test.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
1021. By Michael Terry

Merge from trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

Please delete tag 7.85+14.10.20140428.2-0ubuntu1 in this branch and any local checkouts you might have.

review: Needs Fixing
Revision history for this message
Michael Terry (mterry) wrote :

Deleted that tag.

Revision history for this message
Michał Sawicz (saviq) :
review: Abstain
Revision history for this message
Michael Zanetti (mzanetti) wrote :

The lockscreen features showInfoPopup(). You should use that one for the wipe warning instead of adding your own Dialog component in order to keep design consistent with the same warning for locking the SIM card etc.

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

On the graphical changes, the Spinner in the lockscreen etc, that doesn't match with the new design... I'll probably have to kill/redo that again when merging the new-lockscreen-design branch.

Revision history for this message
Michael Zanetti (mzanetti) wrote :

I'm curious if there are any downsides of adding all those plugins with just one method. You think it might make sense to merge the SystemImage plugin with e.g. the Powerd plugin into a single "System" plugin supporting Powerd, SystemImage etc?

Revision history for this message
Michael Zanetti (mzanetti) wrote :

some inline comments

Revision history for this message
Michael Terry (mterry) wrote :

I can use the existing dialog support, didn't even notice it.

The spinner can go away. Design didn't like it anyway. I was going to wait until I landed the "nodelay" change so PAM feedback is instant, but it can go away now instead, if it makes the other merge easier.

As for the plugin... It's just a bunch more boilerplate. And maybe some extra binary-size overhead? I worry that a generic "System" plugin would be a bit of a dumping place with little cohesion between the pieces. But I'm not a -1, just a +0 on the idea.

OK, working on the dialog and spinner bits, as well as merging with trunk again.

1022. By Michael Terry

Merge from trunk

1023. By Michael Terry

Remove spinner; design didn't like it and it complicates other UI changes down the line

1024. By Michael Terry

Use the built-in lockscreen dialog rather than a home-brewn one

Revision history for this message
Michael Terry (mterry) wrote :

OK. No spinner and I'm using the built-in lockscreen dialog. Plus merged from trunk.

I didn't address the bevy-of-tiny-plugins issue. How strong did you feel about it?

Revision history for this message
Michael Zanetti (mzanetti) wrote :

2 inline comments. You forgot to update some things after the latest changes.

review: Needs Fixing
1025. By Michael Terry

Update pot

1026. By Michael Terry

update object names

Revision history for this message
Michael Zanetti (mzanetti) wrote :

there's also some more test failures:

FAIL! : qmltestrunner::ShellWithPin::test_factoryReset() function returned unexpected result
   Actual (): false
   Expected (): true
   Loc: [/home/mzanetti/Development/reviews/wrong-password-handling/tests/qmltests/tst_ShellWithPin.qml(223)]
FAIL! : qmltestrunner::ShellWithPin::test_failedLoginsCount() property showProgress
   Actual (): 1
   Expected (): 0
   Loc: [/home/mzanetti/Development/reviews/wrong-password-handling/tests/qmltests/tst_ShellWithPin.qml(106)]
FAIL! : qmltestrunner::ShellWithPin::test_failedLoginsCount() property failedLogins
   Actual (): 0
   Expected (): 1
   Loc: [/home/mzanetti/Development/reviews/wrong-password-handling/tests/qmltests/tst_ShellWithPin.qml(195)]
FAIL! : qmltestrunner::ShellWithPin::test_login() property showProgress
   Actual (): 1
   Expected (): 0
   Loc: [/home/mzanetti/Development/reviews/wrong-password-handling/tests/qmltests/tst_ShellWithPin.qml(106)]
FAIL! : qmltestrunner::ShellWithPin::test_login() property count
   Actual (): 0
   Expected (): 1
   Loc: [/home/mzanetti/Development/reviews/wrong-password-handling/tests/qmltests/tst_ShellWithPin.qml(128)]
FAIL! : qmltestrunner::ShellWithPin::test_wrongEntries() property showProgress
   Actual (): 1
   Expected (): 0
   Loc: [/home/mzanetti/Development/reviews/wrong-password-handling/tests/qmltests/tst_ShellWithPin.qml(106)]
FAIL! : qmltestrunner::ShellWithPin::test_wrongEntries() property text
   Actual (): Enter your passcode
   Expected (): Incorrect passcode
Please re-enter
   Loc: [/home/mzanetti/Development/reviews/wrong-password-handling/tests/qmltests/tst_ShellWithPin.qml(208)]
PASS : qmltestrunner::ShellWithPin::cleanupTestCase()
Totals: 6 passed, 7 failed, 0 skipped

review: Needs Fixing
Revision history for this message
Michael Terry (mterry) wrote :

Ugh, you're right. I was hasty. Pot updated again, and test fixed.

Revision history for this message
Michael Zanetti (mzanetti) wrote :

ok. lookin good now. thanks

 * Did you perform an exploratory manual test run of the code change and any related functionality?

yes

 * Did CI run pass? If not, please explain why.

waiting on the latest run, but there seem to be general problems with tests atm.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'cmake/modules/QmlTest.cmake'
--- cmake/modules/QmlTest.cmake 2014-08-06 12:59:59 +0000
+++ cmake/modules/QmlTest.cmake 2014-08-13 18:12:02 +0000
@@ -103,7 +103,7 @@
103 endif()103 endif()
104104
105 set(qmltest_command105 set(qmltest_command
106 env ${qmltest_ENVIRONMENT}106 env ${qmltest_ENVIRONMENT} UNITY_TESTING=1
107 ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml107 ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
108 ${qmltestrunner_imports}108 ${qmltestrunner_imports}
109 ${ITERATIONS_STRING}109 ${ITERATIONS_STRING}
@@ -117,7 +117,7 @@
117 set(LD_PRELOAD_PATH "LD_PRELOAD=/usr/lib/${ARCH_TRIPLET}/mesa/libGL.so.1")117 set(LD_PRELOAD_PATH "LD_PRELOAD=/usr/lib/${ARCH_TRIPLET}/mesa/libGL.so.1")
118 endif()118 endif()
119 set(qmltest_xvfb_command119 set(qmltest_xvfb_command
120 env ${qmltest_ENVIRONMENT} ${LD_PRELOAD_PATH}120 env ${qmltest_ENVIRONMENT} ${LD_PRELOAD_PATH} UNITY_TESTING=1
121 xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum121 xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
122 ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml122 ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
123 ${qmltestrunner_imports}123 ${qmltestrunner_imports}
124124
=== modified file 'cmake/modules/autopilot.cmake'
--- cmake/modules/autopilot.cmake 2014-03-17 14:27:05 +0000
+++ cmake/modules/autopilot.cmake 2014-08-13 18:12:02 +0000
@@ -2,7 +2,7 @@
22
3function(declare_autopilot_test TEST_NAME TEST_SUITE WORKING_DIR)3function(declare_autopilot_test TEST_NAME TEST_SUITE WORKING_DIR)
4 add_custom_target(autopilot-${TEST_NAME}4 add_custom_target(autopilot-${TEST_NAME}
5 COMMAND LANG=C QML2_IMPORT_PATH=${SHELL_INSTALL_QML}/mocks python3 -m autopilot.run run ${TEST_SUITE}5 COMMAND UNITY_TESTING=1 LANG=C QML2_IMPORT_PATH=${SHELL_INSTALL_QML}/mocks python3 -m autopilot.run run ${TEST_SUITE}
6 WORKING_DIRECTORY ${WORKING_DIR}6 WORKING_DIRECTORY ${WORKING_DIR}
7 DEPENDS fake_install7 DEPENDS fake_install
8 )8 )
@@ -14,7 +14,7 @@
14 add_dependencies(autopilot autopilot-${TEST_NAME})14 add_dependencies(autopilot autopilot-${TEST_NAME})
1515
16 add_custom_target(autopilot2-${TEST_NAME}16 add_custom_target(autopilot2-${TEST_NAME}
17 COMMAND LANG=C QML2_IMPORT_PATH=${SHELL_INSTALL_QML}/mocks python2 -m autopilot.run run ${TEST_SUITE}17 COMMAND UNITY_TESTING=1 LANG=C QML2_IMPORT_PATH=${SHELL_INSTALL_QML}/mocks python2 -m autopilot.run run ${TEST_SUITE}
18 WORKING_DIRECTORY ${WORKING_DIR}18 WORKING_DIRECTORY ${WORKING_DIR}
19 DEPENDS fake_install19 DEPENDS fake_install
20 )20 )
2121
=== modified file 'debian/control'
--- debian/control 2014-08-11 19:02:49 +0000
+++ debian/control 2014-08-13 18:12:02 +0000
@@ -165,7 +165,8 @@
165Architecture: any165Architecture: any
166Multi-Arch: same166Multi-Arch: same
167Pre-Depends: ${misc:Pre-Depends},167Pre-Depends: ${misc:Pre-Depends},
168Depends: gsettings-ubuntu-schemas,168Depends: accountsservice-ubuntu-schemas,
169 gsettings-ubuntu-schemas,
169 libhardware2,170 libhardware2,
170 libunity-core-6.0-9,171 libunity-core-6.0-9,
171 pay-service,172 pay-service,
172173
=== modified file 'debian/unity8-private.install'
--- debian/unity8-private.install 2014-06-27 20:48:38 +0000
+++ debian/unity8-private.install 2014-08-13 18:12:02 +0000
@@ -10,5 +10,3 @@
10usr/lib/*/unity8/qml/Utils10usr/lib/*/unity8/qml/Utils
11usr/share/accountsservice/interfaces11usr/share/accountsservice/interfaces
12usr/share/dbus-1/interfaces12usr/share/dbus-1/interfaces
13usr/share/polkit-1
14var/lib/polkit-1
1513
=== removed file 'plugins/AccountsService/50-com.canonical.unity.AccountsService.pkla'
--- plugins/AccountsService/50-com.canonical.unity.AccountsService.pkla 2013-08-12 18:41:45 +0000
+++ plugins/AccountsService/50-com.canonical.unity.AccountsService.pkla 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
1[Allow LightDM to set Unity AccountsService fields]
2Identity=unix-user:lightdm
3Action=com.canonical.unity.AccountsService.ModifyAnyUser
4ResultActive=yes
5ResultInactive=yes
6ResultAny=yes
70
=== modified file 'plugins/AccountsService/AccountsService.cpp'
--- plugins/AccountsService/AccountsService.cpp 2014-07-02 16:17:14 +0000
+++ plugins/AccountsService/AccountsService.cpp 2014-08-13 18:12:02 +0000
@@ -27,7 +27,8 @@
27 m_user(qgetenv("USER")),27 m_user(qgetenv("USER")),
28 m_demoEdges(false),28 m_demoEdges(false),
29 m_statsWelcomeScreen(false),29 m_statsWelcomeScreen(false),
30 m_passwordDisplayHint(Keyboard)30 m_passwordDisplayHint(Keyboard),
31 m_failedLogins(0)
31{32{
32 connect(m_service, SIGNAL(propertiesChanged(const QString &, const QString &, const QStringList &)),33 connect(m_service, SIGNAL(propertiesChanged(const QString &, const QString &, const QStringList &)),
33 this, SLOT(propertiesChanged(const QString &, const QString &, const QStringList &)));34 this, SLOT(propertiesChanged(const QString &, const QString &, const QStringList &)));
@@ -49,6 +50,7 @@
49 updateBackgroundFile();50 updateBackgroundFile();
50 updateStatsWelcomeScreen();51 updateStatsWelcomeScreen();
51 updatePasswordDisplayHint();52 updatePasswordDisplayHint();
53 updateFailedLogins();
52}54}
5355
54bool AccountsService::demoEdges() const56bool AccountsService::demoEdges() const
@@ -113,6 +115,26 @@
113 }115 }
114}116}
115117
118void AccountsService::updateFailedLogins()
119{
120 uint failedLogins = m_service->getUserProperty(m_user, "com.canonical.unity.AccountsService.Private", "FailedLogins").toUInt();
121 if (m_failedLogins != failedLogins) {
122 m_failedLogins = failedLogins;
123 Q_EMIT failedLoginsChanged();
124 }
125}
126
127uint AccountsService::failedLogins() const
128{
129 return m_failedLogins;
130}
131
132void AccountsService::setFailedLogins(uint failedLogins)
133{
134 m_failedLogins = failedLogins;
135 m_service->setUserProperty(m_user, "com.canonical.unity.AccountsService.Private", "FailedLogins", failedLogins);
136}
137
116void AccountsService::propertiesChanged(const QString &user, const QString &interface, const QStringList &changed)138void AccountsService::propertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
117{139{
118 if (m_user != user) {140 if (m_user != user) {
@@ -123,6 +145,10 @@
123 if (changed.contains("demo-edges")) {145 if (changed.contains("demo-edges")) {
124 updateDemoEdges();146 updateDemoEdges();
125 }147 }
148 } else if (interface == "com.canonical.unity.AccountsService.Private") {
149 if (changed.contains("FailedLogins")) {
150 updateFailedLogins();
151 }
126 } else if (interface == "com.ubuntu.touch.AccountsService.SecurityPrivacy") {152 } else if (interface == "com.ubuntu.touch.AccountsService.SecurityPrivacy") {
127 if (changed.contains("StatsWelcomeScreen")) {153 if (changed.contains("StatsWelcomeScreen")) {
128 updateStatsWelcomeScreen();154 updateStatsWelcomeScreen();
129155
=== modified file 'plugins/AccountsService/AccountsService.h'
--- plugins/AccountsService/AccountsService.h 2014-07-02 16:17:14 +0000
+++ plugins/AccountsService/AccountsService.h 2014-08-13 18:12:02 +0000
@@ -45,6 +45,10 @@
45 Q_PROPERTY (PasswordDisplayHint passwordDisplayHint45 Q_PROPERTY (PasswordDisplayHint passwordDisplayHint
46 READ passwordDisplayHint46 READ passwordDisplayHint
47 NOTIFY passwordDisplayHintChanged)47 NOTIFY passwordDisplayHintChanged)
48 Q_PROPERTY (uint failedLogins
49 READ failedLogins
50 WRITE setFailedLogins
51 NOTIFY failedLoginsChanged)
4852
49public:53public:
50 enum PasswordDisplayHint {54 enum PasswordDisplayHint {
@@ -61,6 +65,8 @@
61 QString backgroundFile() const;65 QString backgroundFile() const;
62 bool statsWelcomeScreen() const;66 bool statsWelcomeScreen() const;
63 PasswordDisplayHint passwordDisplayHint() const;67 PasswordDisplayHint passwordDisplayHint() const;
68 uint failedLogins() const;
69 void setFailedLogins(uint failedLogins);
6470
65Q_SIGNALS:71Q_SIGNALS:
66 void userChanged();72 void userChanged();
@@ -68,6 +74,7 @@
68 void backgroundFileChanged();74 void backgroundFileChanged();
69 void statsWelcomeScreenChanged();75 void statsWelcomeScreenChanged();
70 void passwordDisplayHintChanged();76 void passwordDisplayHintChanged();
77 void failedLoginsChanged();
7178
72private Q_SLOTS:79private Q_SLOTS:
73 void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);80 void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
@@ -78,6 +85,7 @@
78 void updateBackgroundFile();85 void updateBackgroundFile();
79 void updateStatsWelcomeScreen();86 void updateStatsWelcomeScreen();
80 void updatePasswordDisplayHint();87 void updatePasswordDisplayHint();
88 void updateFailedLogins();
8189
82 AccountsServiceDBusAdaptor *m_service;90 AccountsServiceDBusAdaptor *m_service;
83 QString m_user;91 QString m_user;
@@ -85,6 +93,7 @@
85 QString m_backgroundFile;93 QString m_backgroundFile;
86 bool m_statsWelcomeScreen;94 bool m_statsWelcomeScreen;
87 PasswordDisplayHint m_passwordDisplayHint;95 PasswordDisplayHint m_passwordDisplayHint;
96 uint m_failedLogins;
88};97};
8998
90#endif99#endif
91100
=== modified file 'plugins/AccountsService/CMakeLists.txt'
--- plugins/AccountsService/CMakeLists.txt 2014-05-02 22:57:00 +0000
+++ plugins/AccountsService/CMakeLists.txt 2014-08-13 18:12:02 +0000
@@ -10,8 +10,6 @@
1010
11add_unity8_plugin(AccountsService 0.1 AccountsService TARGETS AccountsService-qml)11add_unity8_plugin(AccountsService 0.1 AccountsService TARGETS AccountsService-qml)
1212
13set(POLKIT_LIB_DIR "${CMAKE_INSTALL_LOCALSTATEDIR}/lib/polkit-1")
14set(POLKIT_DATA_DIR "${CMAKE_INSTALL_PREFIX}/share/polkit-1")
15set(DBUS_IFACE_DIR "${CMAKE_INSTALL_PREFIX}/share/dbus-1/interfaces")13set(DBUS_IFACE_DIR "${CMAKE_INSTALL_PREFIX}/share/dbus-1/interfaces")
16set(ACCOUNTS_IFACE_DIR "${CMAKE_INSTALL_PREFIX}/share/accountsservice/interfaces")14set(ACCOUNTS_IFACE_DIR "${CMAKE_INSTALL_PREFIX}/share/accountsservice/interfaces")
1715
@@ -24,11 +22,3 @@
24execute_process(COMMAND mkdir -p \"\$ENV{DESTDIR}${ACCOUNTS_IFACE_DIR}\")22execute_process(COMMAND mkdir -p \"\$ENV{DESTDIR}${ACCOUNTS_IFACE_DIR}\")
25execute_process(COMMAND ln -sf ../../dbus-1/interfaces/com.canonical.unity.AccountsService.xml \"\$ENV{DESTDIR}${ACCOUNTS_IFACE_DIR}\")23execute_process(COMMAND ln -sf ../../dbus-1/interfaces/com.canonical.unity.AccountsService.xml \"\$ENV{DESTDIR}${ACCOUNTS_IFACE_DIR}\")
26 ")24 ")
27
28install(FILES com.canonical.unity.AccountsService.policy
29 DESTINATION "${POLKIT_DATA_DIR}/actions"
30 )
31
32install(FILES 50-com.canonical.unity.AccountsService.pkla
33 DESTINATION "${POLKIT_LIB_DIR}/localauthority/10-vendor.d"
34 )
3525
=== removed file 'plugins/AccountsService/com.canonical.unity.AccountsService.policy'
--- plugins/AccountsService/com.canonical.unity.AccountsService.policy 2013-08-12 18:41:45 +0000
+++ plugins/AccountsService/com.canonical.unity.AccountsService.policy 1970-01-01 00:00:00 +0000
@@ -1,24 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2
3<policyconfig>
4 <action id="com.canonical.unity.AccountsService.ModifyOwnUser">
5 <description>Set properties of own user</description>
6 <message>Authentication is required to set one's own unity properties.</message>
7 <defaults>
8 <allow_any>yes</allow_any>
9 <allow_inactive>yes</allow_inactive>
10 <allow_active>yes</allow_active>
11 </defaults>
12 </action>
13
14 <action id="com.canonical.unity.AccountsService.ModifyAnyUser">
15 <description>Set properties of any user</description>
16 <message>Authentication is required to set another user's unity
17properties.</message>
18 <defaults>
19 <allow_any>no</allow_any>
20 <allow_inactive>no</allow_inactive>
21 <allow_active>no</allow_active>
22 </defaults>
23 </action>
24</policyconfig>
250
=== modified file 'plugins/AccountsService/com.canonical.unity.AccountsService.xml'
--- plugins/AccountsService/com.canonical.unity.AccountsService.xml 2013-08-23 19:49:18 +0000
+++ plugins/AccountsService/com.canonical.unity.AccountsService.xml 2014-08-13 18:12:02 +0000
@@ -3,22 +3,45 @@
33
4 <annotation name="org.freedesktop.Accounts.VendorExtension" value="true"/>4 <annotation name="org.freedesktop.Accounts.VendorExtension" value="true"/>
55
6 <annotation name="org.freedesktop.Accounts.Authentication.ChangeOwn"
7 value="com.canonical.unity.AccountsService.ModifyOwnUser"/>
8
9 <annotation name="org.freedesktop.Accounts.Authentication.ReadAny"6 <annotation name="org.freedesktop.Accounts.Authentication.ReadAny"
10 value="com.canonical.unity.AccountsService.ModifyAnyUser"/>7 value="com.ubuntu.AccountsService.GreeterReadAny"/>
118
12 <annotation name="org.freedesktop.Accounts.Authentication.ChangeAny"9 <annotation name="org.freedesktop.Accounts.Authentication.ChangeAny"
13 value="com.canonical.unity.AccountsService.ModifyAnyUser"/>10 value="com.ubuntu.AccountsService.GreeterChangeAny"/>
1411
12 <!-- Should have been named DemoEdges, sorry folks. -mterry -->
15 <property name="demo-edges" type="b" access="readwrite">13 <property name="demo-edges" type="b" access="readwrite">
16 <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>14 <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
17 </property>15 </property>
1816
17 <!-- Should have been named LauncherItems, sorry folks. -mterry -->
19 <property name="launcher-items" type="aa{sv}" access="readwrite">18 <property name="launcher-items" type="aa{sv}" access="readwrite">
20 <annotation name="org.freedesktop.Accounts.DefaultValue" value="[{'defaults': <true>}]"/>19 <annotation name="org.freedesktop.Accounts.DefaultValue" value="[{'defaults': <true>}]"/>
21 </property>20 </property>
2221
23 </interface>22 </interface>
23
24 <!-- This interface is for bits of data that the greeter wants to track
25 per-user in a persistent way, but that users shouldn't be able to edit
26 in an ideal world.
27
28 This interface is identical in permissions to the above one for now,
29 but once we stop running the greeter in user-space, we should
30 disallow org.freedesktop.Accounts.Authentication.ChangeOwn from the
31 Private inteface. -->
32 <interface name="com.canonical.unity.AccountsService.Private">
33
34 <annotation name="org.freedesktop.Accounts.VendorExtension" value="true"/>
35
36 <annotation name="org.freedesktop.Accounts.Authentication.ReadAny"
37 value="com.ubuntu.AccountsService.GreeterReadAny"/>
38
39 <annotation name="org.freedesktop.Accounts.Authentication.ChangeAny"
40 value="com.ubuntu.AccountsService.GreeterChangeAny"/>
41
42 <property name="FailedLogins" type="u" access="readwrite">
43 <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
44 </property>
45
46 </interface>
24</node>47</node>
2548
=== modified file 'plugins/LightDM/Greeter.cpp'
--- plugins/LightDM/Greeter.cpp 2014-06-18 19:49:22 +0000
+++ plugins/LightDM/Greeter.cpp 2014-08-13 18:12:02 +0000
@@ -17,6 +17,7 @@
17 */17 */
1818
19#include "Greeter.h"19#include "Greeter.h"
20#include <libintl.h>
20#include <QLightDM/Greeter>21#include <QLightDM/Greeter>
2122
22class GreeterPrivate23class GreeterPrivate
@@ -125,13 +126,15 @@
125 Q_D(Greeter);126 Q_D(Greeter);
126 d->wasPrompted = true;127 d->wasPrompted = true;
127128
129 bool isDefaultPrompt = (text == dgettext("Linux-PAM", "Password: "));
130
128 // Strip prompt of any colons at the end131 // Strip prompt of any colons at the end
129 QString trimmedText = text.trimmed();132 QString trimmedText = text.trimmed();
130 if (trimmedText.endsWith(":") || trimmedText.endsWith(":")) {133 if (trimmedText.endsWith(":") || trimmedText.endsWith(":")) {
131 trimmedText.chop(1);134 trimmedText.chop(1);
132 }135 }
133136
134 Q_EMIT showPrompt(trimmedText, type == QLightDM::Greeter::PromptTypeSecret);137 Q_EMIT showPrompt(trimmedText, type == QLightDM::Greeter::PromptTypeSecret, isDefaultPrompt);
135}138}
136139
137void Greeter::showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type)140void Greeter::showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type)
138141
=== modified file 'plugins/LightDM/Greeter.h'
--- plugins/LightDM/Greeter.h 2014-06-27 22:08:19 +0000
+++ plugins/LightDM/Greeter.h 2014-08-13 18:12:02 +0000
@@ -55,7 +55,7 @@
5555
56Q_SIGNALS:56Q_SIGNALS:
57 void showMessage(const QString &text, bool isError);57 void showMessage(const QString &text, bool isError);
58 void showPrompt(const QString &text, bool isSecret);58 void showPrompt(const QString &text, bool isSecret, bool isDefaultPrompt);
59 void authenticationComplete();59 void authenticationComplete();
60 void authenticationUserChanged(const QString &user);60 void authenticationUserChanged(const QString &user);
61 void isActiveChanged();61 void isActiveChanged();
6262
=== modified file 'plugins/Ubuntu/CMakeLists.txt'
--- plugins/Ubuntu/CMakeLists.txt 2014-05-29 14:36:21 +0000
+++ plugins/Ubuntu/CMakeLists.txt 2014-08-13 18:12:02 +0000
@@ -1,3 +1,4 @@
1add_subdirectory(Gestures)1add_subdirectory(Gestures)
2add_subdirectory(DownloadDaemonListener)2add_subdirectory(DownloadDaemonListener)
3add_subdirectory(Payments)3add_subdirectory(Payments)
4add_subdirectory(SystemImage)
45
=== added directory 'plugins/Ubuntu/SystemImage'
=== added file 'plugins/Ubuntu/SystemImage/CMakeLists.txt'
--- plugins/Ubuntu/SystemImage/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/SystemImage/CMakeLists.txt 2014-08-13 18:12:02 +0000
@@ -0,0 +1,10 @@
1set(SYSTEMIMAGE_SOURCES
2 plugin.cpp
3 SystemImage.cpp
4)
5
6add_library(SystemImage MODULE ${SYSTEMIMAGE_SOURCES})
7
8qt5_use_modules(SystemImage Qml DBus Core)
9
10add_unity8_plugin(Ubuntu.SystemImage 0.1 Ubuntu/SystemImage TARGETS SystemImage)
011
=== added file 'plugins/Ubuntu/SystemImage/SystemImage.cpp'
--- plugins/Ubuntu/SystemImage/SystemImage.cpp 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/SystemImage/SystemImage.cpp 2014-08-13 18:12:02 +0000
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "SystemImage.h"
18#include <QDBusConnection>
19#include <QDBusInterface>
20
21SystemImage::SystemImage(QObject *parent)
22 : QObject(parent),
23 m_interface(new QDBusInterface("com.canonical.SystemImage",
24 "/Service",
25 "com.canonical.SystemImage",
26 QDBusConnection::systemBus(),
27 this))
28{
29}
30
31void SystemImage::factoryReset()
32{
33 m_interface->call("FactoryReset");
34}
035
=== added file 'plugins/Ubuntu/SystemImage/SystemImage.h'
--- plugins/Ubuntu/SystemImage/SystemImage.h 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/SystemImage/SystemImage.h 2014-08-13 18:12:02 +0000
@@ -0,0 +1,38 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef SYSTEMIMAGE_H
18#define SYSTEMIMAGE_H
19
20#include <QObject>
21
22class QDBusInterface;
23
24class SystemImage : public QObject
25{
26 Q_OBJECT
27 Q_DISABLE_COPY(SystemImage)
28
29public:
30 explicit SystemImage(QObject *parent = 0);
31
32 Q_INVOKABLE void factoryReset();
33
34private:
35 QDBusInterface *m_interface;
36};
37
38#endif // SYSTEMIMAGE_H
039
=== added file 'plugins/Ubuntu/SystemImage/SystemImage.qmltypes'
--- plugins/Ubuntu/SystemImage/SystemImage.qmltypes 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/SystemImage/SystemImage.qmltypes 2014-08-13 18:12:02 +0000
@@ -0,0 +1,17 @@
1import QtQuick.tooling 1.1
2
3// This file describes the plugin-supplied types contained in the library.
4// It is used for QML tooling purposes only.
5//
6// This file was auto-generated by:
7// 'qmlplugindump -notrelocatable Ubuntu.SystemImage 0.1 plugins'
8
9Module {
10 Component {
11 name: "SystemImage"
12 prototype: "QObject"
13 exports: ["Ubuntu.SystemImage/SystemImage 0.1"]
14 exportMetaObjectRevisions: [0]
15 Method { name: "factoryReset" }
16 }
17}
018
=== added file 'plugins/Ubuntu/SystemImage/plugin.cpp'
--- plugins/Ubuntu/SystemImage/plugin.cpp 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/SystemImage/plugin.cpp 2014-08-13 18:12:02 +0000
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "plugin.h"
18#include "SystemImage.h"
19
20#include <QtQml>
21
22static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
23{
24 Q_UNUSED(engine)
25 Q_UNUSED(scriptEngine)
26 return new SystemImage();
27}
28
29void BackendPlugin::registerTypes(const char *uri)
30{
31 Q_ASSERT(uri == QLatin1String("Ubuntu.SystemImage"));
32
33 qmlRegisterSingletonType<SystemImage>(uri, 0, 1, "SystemImage", service_provider);
34}
035
=== added file 'plugins/Ubuntu/SystemImage/plugin.h'
--- plugins/Ubuntu/SystemImage/plugin.h 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/SystemImage/plugin.h 2014-08-13 18:12:02 +0000
@@ -0,0 +1,31 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef SYSTEMIMAGE_PLUGIN_H
18#define SYSTEMIMAGE_PLUGIN_H
19
20#include <QQmlExtensionPlugin>
21
22class BackendPlugin : public QQmlExtensionPlugin
23{
24 Q_OBJECT
25 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
26
27public:
28 void registerTypes(const char *uri);
29};
30
31#endif // SYSTEMIMAGE_PLUGIN_H
032
=== added file 'plugins/Ubuntu/SystemImage/qmldir'
--- plugins/Ubuntu/SystemImage/qmldir 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/SystemImage/qmldir 2014-08-13 18:12:02 +0000
@@ -0,0 +1,3 @@
1module Ubuntu.SystemImage
2plugin SystemImage
3typeinfo SystemImage.qmltypes
04
=== modified file 'po/unity8.pot'
--- po/unity8.pot 2014-08-08 09:17:29 +0000
+++ po/unity8.pot 2014-08-13 18:12:02 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: unity8\n"9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2014-08-08 11:17+0200\n"11"POT-Creation-Date: 2014-08-13 14:09-0400\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,6 +17,10 @@
17"Content-Type: text/plain; charset=UTF-8\n"17"Content-Type: text/plain; charset=UTF-8\n"
18"Content-Transfer-Encoding: 8bit\n"18"Content-Transfer-Encoding: 8bit\n"
1919
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
22msgstr ""
23
20#: plugins/Unity/Launcher/launcheritem.cpp:4324#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:7325#: plugins/Unity/Launcher/launcheritem.cpp:73
22msgid "Pin shortcut"26msgid "Pin shortcut"
@@ -88,39 +92,51 @@
88"phone<br><br>Tap on the screen to start"92"phone<br><br>Tap on the screen to start"
89msgstr ""93msgstr ""
9094
91#: qml/Components/Lockscreen.qml:22095#: qml/Components/Lockscreen.qml:161
96msgid "Too many incorrect attempts"
97msgstr ""
98
99#: qml/Components/Lockscreen.qml:163
100msgid "Please wait"
101msgstr ""
102
103#: qml/Components/Lockscreen.qml:245
92msgid "Emergency Call"104msgid "Emergency Call"
93msgstr ""105msgstr ""
94106
95#: qml/Components/Lockscreen.qml:243107#: qml/Components/Lockscreen.qml:268
96msgid "OK"108msgid "OK"
97msgstr ""109msgstr ""
98110
99#: qml/Components/PassphraseLockscreen.qml:62111#: qml/Components/PassphraseLockscreen.qml:61
100#, qt-format112#, qt-format
101msgid "Hello %1"113msgid "Hello %1"
102msgstr ""114msgstr ""
103115
104#: qml/Components/PassphraseLockscreen.qml:62116#: qml/Components/PassphraseLockscreen.qml:61
105msgid "Hello"117msgid "Hello"
106msgstr ""118msgstr ""
107119
108#: qml/Components/PinLockscreen.qml:198120#: qml/Components/PinLockscreen.qml:197
109msgid "CANCEL"121msgid "CANCEL"
110msgstr ""122msgstr ""
111123
112#: qml/Components/PinLockscreen.qml:216124#: qml/Components/PinLockscreen.qml:215
113msgid "DONE"125msgid "DONE"
114msgstr ""126msgstr ""
115127
116#: qml/Dash/GenericScopeView.qml:358128#: qml/Dash/GenericScopeView.qml:360
117msgid "See less"129msgid "See less"
118msgstr ""130msgstr ""
119131
120#: qml/Dash/GenericScopeView.qml:358132#: qml/Dash/GenericScopeView.qml:360
121msgid "See all"133msgid "See all"
122msgstr ""134msgstr ""
123135
136#: qml/Dash/GenericScopeView.qml:423 qml/Panel/SearchIndicator.qml:27
137msgid "Search"
138msgstr ""
139
124#: qml/Dash/Previews/PreviewActionCombo.qml:34140#: qml/Dash/Previews/PreviewActionCombo.qml:34
125msgid "More..."141msgid "More..."
126msgstr ""142msgstr ""
@@ -141,15 +157,15 @@
141msgid "Send"157msgid "Send"
142msgstr ""158msgstr ""
143159
144#: qml/Dash/ScopesOverview.qml:200160#: qml/Dash/ScopesOverview.qml:201
145msgid "Manage Dash"161msgid "Manage Dash"
146msgstr ""162msgstr ""
147163
148#: qml/Dash/ScopesOverview.qml:405164#: qml/Dash/ScopesOverview.qml:408
149msgid "Done"165msgid "Done"
150msgstr ""166msgstr ""
151167
152#: qml/Dash/ScopesOverview.qml:431168#: qml/Dash/ScopesOverview.qml:434
153msgid "Store"169msgid "Store"
154msgstr ""170msgstr ""
155171
@@ -233,11 +249,48 @@
233msgid "Roaming"249msgid "Roaming"
234msgstr ""250msgstr ""
235251
236#: qml/Panel/SearchIndicator.qml:27252#: qml/Shell.qml:267
237msgid "Search"253msgid "passphrase"
238msgstr ""254msgstr ""
239255
240#: qml/Shell.qml:256256#: qml/Shell.qml:267
241#, qt-format257msgid "passcode"
242msgid "Please enter %1"258msgstr ""
259
260#: qml/Shell.qml:269
261#, qt-format
262msgid "Enter your %1"
263msgstr ""
264
265#: qml/Shell.qml:270
266#, qt-format
267msgid "Incorrect %1"
268msgstr ""
269
270#: qml/Shell.qml:272
271msgid "Please re-enter"
272msgstr ""
273
274#: qml/Shell.qml:306
275msgid "Sorry, incorrect passphrase."
276msgstr ""
277
278#: qml/Shell.qml:307
279msgid "Sorry, incorrect passcode."
280msgstr ""
281
282#: qml/Shell.qml:308
283msgid "This will be your last attempt."
284msgstr ""
285
286#: qml/Shell.qml:310
287msgid ""
288"If passphrase is entered incorrectly, your phone will conduct a factory "
289"reset and all personal data will be deleted."
290msgstr ""
291
292#: qml/Shell.qml:311
293msgid ""
294"If passcode is entered incorrectly, your phone will conduct a factory reset "
295"and all personal data will be deleted."
243msgstr ""296msgstr ""
244297
=== modified file 'qml/Components/Lockscreen.qml'
--- qml/Components/Lockscreen.qml 2014-07-22 14:46:01 +0000
+++ qml/Components/Lockscreen.qml 2014-08-13 18:12:02 +0000
@@ -57,10 +57,15 @@
5757
58 onRequiredChanged: {58 onRequiredChanged: {
59 if (required && pinPadLoader.item) {59 if (required && pinPadLoader.item) {
60 pinPadLoader.item.clear(false);60 clear(false)
61 }61 }
62 }62 }
6363
64 function forceDelay(delay) {
65 forcedDelayTimer.interval = delay
66 forcedDelayTimer.start()
67 }
68
64 function reset() {69 function reset() {
65 // This causes the loader below to destry and recreate the source70 // This causes the loader below to destry and recreate the source
66 pinPadLoader.resetting = true;71 pinPadLoader.resetting = true;
@@ -68,13 +73,22 @@
68 }73 }
6974
70 function clear(showAnimation) {75 function clear(showAnimation) {
71 pinPadLoader.item.clear(showAnimation);76 if (pinPadLoader.item) {
77 pinPadLoader.item.clear(showAnimation);
78 }
79 pinPadLoader.showWrongText = showAnimation
80 pinPadLoader.waiting = false
72 }81 }
7382
74 function showInfoPopup(title, text) {83 function showInfoPopup(title, text) {
75 PopupUtils.open(infoPopupComponent, root, {title: title, text: text})84 PopupUtils.open(infoPopupComponent, root, {title: title, text: text})
76 }85 }
7786
87 Timer {
88 id: forcedDelayTimer
89 onTriggered: pinPadLoader.showWrongText = false
90 }
91
78 Rectangle {92 Rectangle {
79 // In case background fails to load or is undefined93 // In case background fails to load or is undefined
80 id: backgroundBackup94 id: backgroundBackup
@@ -131,8 +145,6 @@
131 }145 }
132 }146 }
133147
134
135
136 Loader {148 Loader {
137 id: pinPadLoader149 id: pinPadLoader
138 objectName: "pinPadLoader"150 objectName: "pinPadLoader"
@@ -143,13 +155,24 @@
143 verticalCenterOffset: root.alphaNumeric ? -units.gu(10) : -units.gu(4)155 verticalCenterOffset: root.alphaNumeric ? -units.gu(10) : -units.gu(4)
144 }156 }
145 property bool resetting: false157 property bool resetting: false
158 property bool waiting: false
159 property bool showWrongText: false
160
161 readonly property string forcedDelayText: i18n.tr("Too many incorrect attempts") +
162 "\n" +
163 i18n.tr("Please wait")
146164
147 source: (!resetting && root.required) ? (root.alphaNumeric ? "PassphraseLockscreen.qml" : "PinLockscreen.qml") : ""165 source: (!resetting && root.required) ? (root.alphaNumeric ? "PassphraseLockscreen.qml" : "PinLockscreen.qml") : ""
166 onSourceChanged: {
167 waiting = false
168 showWrongText = false
169 }
148170
149 Connections {171 Connections {
150 target: pinPadLoader.item172 target: pinPadLoader.item
151173
152 onEntered: {174 onEntered: {
175 pinPadLoader.waiting = true
153 root.entered(passphrase);176 root.entered(passphrase);
154 }177 }
155178
@@ -171,18 +194,20 @@
171 Binding {194 Binding {
172 target: pinPadLoader.item195 target: pinPadLoader.item
173 property: "placeholderText"196 property: "placeholderText"
174 value: root.placeholderText197 value: forcedDelayTimer.running ? pinPadLoader.forcedDelayText :
175 }198 (pinPadLoader.showWrongText ? root.wrongPlaceholderText :
176 Binding {199 root.placeholderText)
177 target: pinPadLoader.item
178 property: "wrongPlaceholderText"
179 value: root.wrongPlaceholderText
180 }200 }
181 Binding {201 Binding {
182 target: pinPadLoader.item202 target: pinPadLoader.item
183 property: "username"203 property: "username"
184 value: root.username204 value: root.username
185 }205 }
206 Binding {
207 target: pinPadLoader.item
208 property: "entryEnabled"
209 value: !pinPadLoader.waiting && !forcedDelayTimer.running
210 }
186 }211 }
187212
188 Column {213 Column {
189214
=== modified file 'qml/Components/PassphraseLockscreen.qml'
--- qml/Components/PassphraseLockscreen.qml 2014-07-02 18:40:30 +0000
+++ qml/Components/PassphraseLockscreen.qml 2014-08-13 18:12:02 +0000
@@ -23,15 +23,14 @@
23 height: highlightItem.height23 height: highlightItem.height
2424
25 property string placeholderText25 property string placeholderText
26 property string wrongPlaceholderText
27 property string username: ""26 property string username: ""
27 property bool entryEnabled: true
2828
29 signal entered(string passphrase)29 signal entered(string passphrase)
30 signal cancel()30 signal cancel()
3131
32 function clear(playAnimation) {32 function clear(playAnimation) {
33 pinentryField.text = "";33 pinentryField.text = "";
34 pinentryField.enabled = true
35 if (playAnimation) {34 if (playAnimation) {
36 wrongPasswordAnimation.start();35 wrongPasswordAnimation.start();
37 pinentryField.forceActiveFocus();36 pinentryField.forceActiveFocus();
@@ -76,11 +75,11 @@
76 echoMode: TextInput.Password75 echoMode: TextInput.Password
77 opacity: 0.976 opacity: 0.9
78 hasClearButton: false77 hasClearButton: false
79 placeholderText: wrongPasswordAnimation.running ? root.wrongPlaceholderText : root.placeholderText78 enabled: entryEnabled
79 placeholderText: root.placeholderText
8080
81 onAccepted: {81 onAccepted: {
82 if (pinentryField.text) {82 if (pinentryField.text) {
83 pinentryField.enabled = false;
84 root.entered(pinentryField.text);83 root.entered(pinentryField.text);
85 }84 }
86 }85 }
8786
=== modified file 'qml/Components/PinLockscreen.qml'
--- qml/Components/PinLockscreen.qml 2014-06-06 11:37:55 +0000
+++ qml/Components/PinLockscreen.qml 2014-08-13 18:12:02 +0000
@@ -25,7 +25,6 @@
25 spacing: units.gu(3.5)25 spacing: units.gu(3.5)
2626
27 property alias placeholderText: pinentryField.placeholderText27 property alias placeholderText: pinentryField.placeholderText
28 property alias wrongPlaceholderText: pinentryField.wrongPlaceholderText
29 property int padWidth: units.gu(34)28 property int padWidth: units.gu(34)
30 property int padHeight: units.gu(28)29 property int padHeight: units.gu(28)
31 property int minPinLength: -130 property int minPinLength: -1
@@ -58,7 +57,6 @@
58 radius: "medium"57 radius: "medium"
59 property string text: ""58 property string text: ""
60 property string placeholderText: ""59 property string placeholderText: ""
61 property string wrongPlaceholderText: ""
6260
63 function appendChar(character) {61 function appendChar(character) {
64 if (root.maxPinLength == -1 || pinentryField.text.length < root.maxPinLength) {62 if (root.maxPinLength == -1 || pinentryField.text.length < root.maxPinLength) {
@@ -90,9 +88,10 @@
90 id: pinentryFieldPlaceHolder88 id: pinentryFieldPlaceHolder
91 objectName: "pinentryFieldPlaceHolder"89 objectName: "pinentryFieldPlaceHolder"
92 anchors.centerIn: parent90 anchors.centerIn: parent
91 horizontalAlignment: Text.AlignHCenter
93 color: "#f3f3e7"92 color: "#f3f3e7"
94 opacity: 0.693 opacity: 0.6
95 text: wrongPasswordAnimation.running ? parent.wrongPlaceholderText : parent.placeholderText94 text: parent.placeholderText
96 visible: pinentryFieldLabel.text.length == 095 visible: pinentryFieldLabel.text.length == 0
97 }96 }
9897
@@ -107,7 +106,7 @@
107 bottom: parent.bottom106 bottom: parent.bottom
108 bottomMargin: units.gu(1)107 bottomMargin: units.gu(1)
109 }108 }
110 visible: !priv.autoConfirm109 visible: entryEnabled && !priv.autoConfirm
111 width: height110 width: height
112 name: "erase"111 name: "erase"
113 color: "#f3f3e7"112 color: "#f3f3e7"
114113
=== modified file 'qml/Notifications/NotificationMenuItemFactory.qml'
--- qml/Notifications/NotificationMenuItemFactory.qml 2014-07-22 12:13:02 +0000
+++ qml/Notifications/NotificationMenuItemFactory.qml 2014-08-13 18:12:02 +0000
@@ -117,7 +117,6 @@
117117
118 onEntered: {118 onEntered: {
119 menuModel.changeState(menuIndex, passphrase);119 menuModel.changeState(menuIndex, passphrase);
120 entryEnabled = false;
121 }120 }
122121
123 onCancel: {122 onCancel: {
124123
=== modified file 'qml/Shell.qml'
--- qml/Shell.qml 2014-08-11 19:02:49 +0000
+++ qml/Shell.qml 2014-08-13 18:12:02 +0000
@@ -19,7 +19,9 @@
19import GSettings 1.019import GSettings 1.0
20import Unity.Application 0.120import Unity.Application 0.1
21import Ubuntu.Components 0.121import Ubuntu.Components 0.1
22import Ubuntu.Components.Popups 1.0
22import Ubuntu.Gestures 0.123import Ubuntu.Gestures 0.1
24import Ubuntu.SystemImage 0.1
23import Unity.Launcher 0.125import Unity.Launcher 0.1
24import Utils 0.126import Utils 0.1
25import LightDM 0.1 as LightDM27import LightDM 0.1 as LightDM
@@ -53,6 +55,10 @@
53 property bool sideStageEnabled: shell.width >= units.gu(100)55 property bool sideStageEnabled: shell.width >= units.gu(100)
54 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId56 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
5557
58 property int maxFailedLogins: -1 // disabled by default for now, will enable via settings in future
59 property int failedLoginsDelayAttempts: 7 // number of failed logins
60 property int failedLoginsDelaySeconds: 5 * 60 // seconds of forced waiting
61
56 function activateApplication(appId) {62 function activateApplication(appId) {
57 if (ApplicationManager.findApplication(appId)) {63 if (ApplicationManager.findApplication(appId)) {
58 ApplicationManager.requestFocusApplication(appId);64 ApplicationManager.requestFocusApplication(appId);
@@ -255,13 +261,21 @@
255261
256 onShowPrompt: {262 onShowPrompt: {
257 if (greeter.narrowMode) {263 if (greeter.narrowMode) {
258 lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text.toLowerCase());264 var promptText = text.toLowerCase()
265 if (isDefaultPrompt) {
266 promptText = lockscreen.alphaNumeric ?
267 i18n.tr("passphrase") : i18n.tr("passcode")
268 }
269 lockscreen.placeholderText = i18n.tr("Enter your %1").arg(promptText)
270 lockscreen.wrongPlaceholderText = i18n.tr("Incorrect %1").arg(promptText) +
271 "\n" +
272 i18n.tr("Please re-enter")
259 lockscreen.show();273 lockscreen.show();
260 }274 }
261 }275 }
262276
263 onPromptlessChanged: {277 onPromptlessChanged: {
264 if (LightDM.Greeter.promptless) {278 if (LightDM.Greeter.promptless && LightDM.Greeter.authenticated) {
265 lockscreen.hide()279 lockscreen.hide()
266 } else {280 } else {
267 lockscreen.reset();281 lockscreen.reset();
@@ -270,13 +284,40 @@
270 }284 }
271285
272 onAuthenticationComplete: {286 onAuthenticationComplete: {
287 if (LightDM.Greeter.authenticated) {
288 AccountsService.failedLogins = 0
289 }
290 // Else only penalize user for a failed login if they actually were
291 // prompted for a password. We do this below after the promptless
292 // early exit.
293
273 if (LightDM.Greeter.promptless) {294 if (LightDM.Greeter.promptless) {
274 return;295 return;
275 }296 }
297
276 if (LightDM.Greeter.authenticated) {298 if (LightDM.Greeter.authenticated) {
277 lockscreen.hide();299 lockscreen.hide();
278 greeter.login();300 greeter.login();
279 } else {301 } else {
302 AccountsService.failedLogins++
303 if (maxFailedLogins >= 2) { // require at least a warning
304 if (AccountsService.failedLogins === maxFailedLogins - 1) {
305 var title = lockscreen.alphaNumeric ?
306 i18n.tr("Sorry, incorrect passphrase.") :
307 i18n.tr("Sorry, incorrect passcode.")
308 var text = i18n.tr("This will be your last attempt.") + " " +
309 (lockscreen.alphaNumeric ?
310 i18n.tr("If passphrase is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted.") :
311 i18n.tr("If passcode is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted."))
312 lockscreen.showInfoPopup(title, text)
313 } else if (AccountsService.failedLogins >= maxFailedLogins) {
314 SystemImage.factoryReset() // Ouch!
315 }
316 }
317 if (failedLoginsDelayAttempts > 0 && AccountsService.failedLogins % failedLoginsDelayAttempts == 0) {
318 lockscreen.forceDelay(failedLoginsDelaySeconds * 1000)
319 }
320
280 lockscreen.clear(true);321 lockscreen.clear(true);
281 if (greeter.narrowMode) {322 if (greeter.narrowMode) {
282 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))323 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
@@ -311,8 +352,16 @@
311 }352 }
312353
313 property bool fullyShown: showProgress === 1.0354 property bool fullyShown: showProgress === 1.0
355 onFullyShownChanged: {
356 // Wait until the greeter is completely covering lockscreen before resetting it.
357 if (fullyShown && !LightDM.Greeter.authenticated) {
358 lockscreen.reset();
359 lockscreen.show();
360 }
361 }
362
314 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)363 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
315 onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()364 onShowProgressChanged: if (LightDM.Greeter.authenticated && showProgress === 0) greeter.login()
316365
317 Greeter {366 Greeter {
318 id: greeter367 id: greeter
@@ -350,10 +399,6 @@
350 if (greeter.narrowMode) {399 if (greeter.narrowMode) {
351 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));400 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
352 }401 }
353 if (!LightDM.Greeter.promptless) {
354 lockscreen.reset();
355 lockscreen.show();
356 }
357 greeter.fakeActiveForApp = "";402 greeter.fakeActiveForApp = "";
358 greeter.forceActiveFocus();403 greeter.forceActiveFocus();
359 }404 }
@@ -403,7 +448,7 @@
403 }448 }
404449
405 if (LightDM.Greeter.active) {450 if (LightDM.Greeter.active) {
406 if (!LightDM.Greeter.promptless) {451 if (!LightDM.Greeter.authenticated) {
407 lockscreen.show()452 lockscreen.show()
408 }453 }
409 greeter.hide()454 greeter.hide()
410455
=== modified file 'run.sh'
--- run.sh 2014-07-16 14:37:21 +0000
+++ run.sh 2014-08-13 18:12:02 +0000
@@ -18,6 +18,7 @@
18 echo " -f, --fake Force use of fake Qml modules." >&218 echo " -f, --fake Force use of fake Qml modules." >&2
19 echo " -p, --pinlock Use a pin protected user." >&219 echo " -p, --pinlock Use a pin protected user." >&2
20 echo " -k, --keylock Use a passphrase protected user." >&220 echo " -k, --keylock Use a passphrase protected user." >&2
21 echo " -l, --lightdm Use the specified lightdm mock." >&2
21 echo " -g, --gdb Run through gdb." >&222 echo " -g, --gdb Run through gdb." >&2
22 echo " -h, --help Show this help." >&223 echo " -h, --help Show this help." >&2
23 echo " -m, --nomousetouch Run without -mousetouch argument." >&224 echo " -m, --nomousetouch Run without -mousetouch argument." >&2
@@ -25,16 +26,20 @@
25 exit 126 exit 1
26}27}
2728
28ARGS=`getopt -n$0 -u -a --longoptions="fake,pinlock,keylock,gdb,help,nomousetouch" -o "fpkghm" -- "$@"`29ARGS=`getopt -n$0 -u -a --longoptions="fake,pinlock,keylock,gdb,help,lightdm:,nomousetouch" -o "fpkl:ghm" -- "$@"`
29[ $? -ne 0 ] && usage30[ $? -ne 0 ] && usage
30eval set -- "$ARGS"31eval set -- "$ARGS"
3132
32while [ $# -gt 0 ]33while [ $# -gt 0 ]
33do34do
34 case "$1" in35 case "$1" in
35 -f|--fake) FAKE=true; USE_MOCKS=true;;36 -f|--fake) USE_MOCKS=true;;
36 -p|--pinlock) PINLOCK=true; USE_MOCKS=true;;37 -p|--pinlock) USE_MOCKS=true; LIGHTDM_MOCK=single-pin;;
37 -k|--keylock) KEYLOCK=true; USE_MOCKS=true;;38 -k|--keylock) USE_MOCKS=true; LIGHTDM_MOCK=single-passphrase;;
39 -l|--lightdm) LIGHTDM_MOCK=$2; shift;
40 if [ -z "$LIGHTDM_MOCK" ]; then
41 echo "Please specify an argument to --lightdm"
42 fi;;
38 -g|--gdb) GDB=true;;43 -g|--gdb) GDB=true;;
39 -h|--help) usage;;44 -h|--help) usage;;
40 -m|--nomousetouch) MOUSE_TOUCH=false;;45 -m|--nomousetouch) MOUSE_TOUCH=false;;
@@ -43,27 +48,23 @@
43 shift48 shift
44done49done
4550
46if $FAKE; then51if [ -z "$LIGHTDM_MOCK" ]; then
47 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single52 LIGHTDM_MOCK=single
48fi53fi
4954
50if $PINLOCK; then55# Even without USE_MOCKS set, we want to fake our lightdm backend, because it's
51 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single-pin56# annoying to be prompted for your password when testing. To get the same
52fi57# backend used in production, pass '--lightdm=demo'.
5358export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/LightDM/$LIGHTDM_MOCK
54if $KEYLOCK; then
55 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single-passphrase
56fi
5759
58if $USE_MOCKS; then60if $USE_MOCKS; then
59 rm -f $PWD/builddir/nonmirplugins/LightDM # undo symlink (from below) for cleanliness61 rm -f $PWD/builddir/nonmirplugins/LightDM # undo symlink (from below) for cleanliness
60 export QML2_IMPORT_PATH=$QML2_IMPORT_PATH:$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules62 export QML2_IMPORT_PATH=$QML2_IMPORT_PATH:$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules
63 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics
61else64else
62 # Still fake no-login user for convenience (it's annoying to be prompted for your password when testing)65 # Just link our LightDM mock into the nonmirplugins folder. We don't want
63 # And in particular, just link our LightDM mock into the nonmirplugins folder. We don't want the rest of66 # the rest of our plugins to be used.
64 # our plugins to be used.67 ln -sf $PWD/builddir/tests/mocks/LightDM $PWD/builddir/nonmirplugins/
65 ln -s $PWD/builddir/tests/mocks/LightDM $PWD/builddir/nonmirplugins/
66 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/LightDM/single
67fi68fi
6869
69QML_PHONE_SHELL_ARGS=""70QML_PHONE_SHELL_ARGS=""
7071
=== modified file 'tests/mocks/AccountsService/AccountsService.cpp'
--- tests/mocks/AccountsService/AccountsService.cpp 2014-07-02 16:17:14 +0000
+++ tests/mocks/AccountsService/AccountsService.cpp 2014-08-13 18:12:02 +0000
@@ -23,7 +23,8 @@
23AccountsService::AccountsService(QObject* parent)23AccountsService::AccountsService(QObject* parent)
24 : QObject(parent),24 : QObject(parent),
25 m_backgroundFile(qmlDirectory() + "graphics/phone_background.jpg"),25 m_backgroundFile(qmlDirectory() + "graphics/phone_background.jpg"),
26 m_statsWelcomeScreen(true)26 m_statsWelcomeScreen(true),
27 m_failedLogins(0)
27{28{
28}29}
2930
@@ -78,3 +79,14 @@
78 else79 else
79 return PasswordDisplayHint::Keyboard;80 return PasswordDisplayHint::Keyboard;
80}81}
82
83uint AccountsService::failedLogins() const
84{
85 return m_failedLogins;
86}
87
88void AccountsService::setFailedLogins(uint failedLogins)
89{
90 m_failedLogins = failedLogins;
91 failedLoginsChanged();
92}
8193
=== modified file 'tests/mocks/AccountsService/AccountsService.h'
--- tests/mocks/AccountsService/AccountsService.h 2014-07-02 16:17:14 +0000
+++ tests/mocks/AccountsService/AccountsService.h 2014-08-13 18:12:02 +0000
@@ -47,6 +47,10 @@
47 Q_PROPERTY (PasswordDisplayHint passwordDisplayHint47 Q_PROPERTY (PasswordDisplayHint passwordDisplayHint
48 READ passwordDisplayHint48 READ passwordDisplayHint
49 NOTIFY passwordDisplayHintChanged)49 NOTIFY passwordDisplayHintChanged)
50 Q_PROPERTY (uint failedLogins
51 READ failedLogins
52 WRITE setFailedLogins
53 NOTIFY failedLoginsChanged)
5054
51public:55public:
52 enum PasswordDisplayHint {56 enum PasswordDisplayHint {
@@ -65,6 +69,8 @@
65 bool statsWelcomeScreen() const;69 bool statsWelcomeScreen() const;
66 void setStatsWelcomeScreen(bool statsWelcomeScreen);70 void setStatsWelcomeScreen(bool statsWelcomeScreen);
67 PasswordDisplayHint passwordDisplayHint() const;71 PasswordDisplayHint passwordDisplayHint() const;
72 uint failedLogins() const;
73 void setFailedLogins(uint failedLogins);
6874
69Q_SIGNALS:75Q_SIGNALS:
70 void userChanged();76 void userChanged();
@@ -72,11 +78,13 @@
72 void backgroundFileChanged();78 void backgroundFileChanged();
73 void statsWelcomeScreenChanged();79 void statsWelcomeScreenChanged();
74 void passwordDisplayHintChanged();80 void passwordDisplayHintChanged();
81 void failedLoginsChanged();
7582
76private:83private:
77 QString m_backgroundFile;84 QString m_backgroundFile;
78 QString m_user;85 QString m_user;
79 bool m_statsWelcomeScreen;86 bool m_statsWelcomeScreen;
87 uint m_failedLogins;
80};88};
8189
82#endif90#endif
8391
=== modified file 'tests/mocks/LightDM/Greeter.cpp'
--- tests/mocks/LightDM/Greeter.cpp 2014-06-11 15:36:51 +0000
+++ tests/mocks/LightDM/Greeter.cpp 2014-08-13 18:12:02 +0000
@@ -19,6 +19,7 @@
19#include "Greeter.h"19#include "Greeter.h"
20#include "GreeterPrivate.h"20#include "GreeterPrivate.h"
21#include <QtCore/QCoreApplication>21#include <QtCore/QCoreApplication>
22#include <QTimer>
2223
23namespace QLightDM24namespace QLightDM
24{25{
@@ -164,4 +165,14 @@
164 d->handleRespond(response);165 d->handleRespond(response);
165}166}
166167
168void Greeter::sendAuthenticationComplete()
169{
170 if (qgetenv("UNITY_TESTING").isEmpty()) {
171 // simulate PAM's delay
172 QTimer::singleShot(1000, this, SIGNAL(authenticationComplete()));
173 } else {
174 Q_EMIT authenticationComplete();
175 }
176}
177
167}178}
168179
=== modified file 'tests/mocks/LightDM/Greeter.h'
--- tests/mocks/LightDM/Greeter.h 2014-06-11 15:36:51 +0000
+++ tests/mocks/LightDM/Greeter.h 2014-08-13 18:12:02 +0000
@@ -96,6 +96,9 @@
96 void authenticationComplete();96 void authenticationComplete();
97 void autologinTimerExpired();97 void autologinTimerExpired();
9898
99protected:
100 void sendAuthenticationComplete();
101
99private:102private:
100 GreeterPrivate *d_ptr;103 GreeterPrivate *d_ptr;
101 Q_DECLARE_PRIVATE(Greeter)104 Q_DECLARE_PRIVATE(Greeter)
102105
=== modified file 'tests/mocks/LightDM/demo/CMakeLists.txt'
--- tests/mocks/LightDM/demo/CMakeLists.txt 2014-07-01 20:21:23 +0000
+++ tests/mocks/LightDM/demo/CMakeLists.txt 2014-08-13 18:12:02 +0000
@@ -9,6 +9,7 @@
9 )9 )
1010
11add_library(MockLightDM-demo STATIC ${LibLightDM_SOURCES})11add_library(MockLightDM-demo STATIC ${LibLightDM_SOURCES})
12add_library(MockLightDM-demo-shared SHARED ${LibLightDM_SOURCES})
1213
13include_directories(14include_directories(
14 ${CMAKE_CURRENT_BINARY_DIR}15 ${CMAKE_CURRENT_BINARY_DIR}
@@ -19,5 +20,17 @@
19 ${LIBUSERMETRICSOUTPUT_LDFLAGS}20 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
20 -lpam21 -lpam
21)22)
23target_link_libraries(MockLightDM-demo-shared
24 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
25 -lpam
26)
2227
23qt5_use_modules(MockLightDM-demo Concurrent Gui)28qt5_use_modules(MockLightDM-demo Concurrent Gui)
29qt5_use_modules(MockLightDM-demo-shared Concurrent Gui)
30
31set_target_properties(MockLightDM-demo-shared PROPERTIES
32 OUTPUT_NAME lightdm-qt5-2)
33
34install(TARGETS MockLightDM-demo-shared
35 DESTINATION ${SHELL_INSTALL_QML}/mocks/LightDM/demo
36 )
2437
=== modified file 'tests/mocks/LightDM/full/GreeterPrivate.cpp'
--- tests/mocks/LightDM/full/GreeterPrivate.cpp 2014-07-02 16:17:14 +0000
+++ tests/mocks/LightDM/full/GreeterPrivate.cpp 2014-08-13 18:12:02 +0000
@@ -54,7 +54,7 @@
54 authenticated = true;54 authenticated = true;
55 Q_EMIT q->authenticationComplete();55 Q_EMIT q->authenticationComplete();
56 } else if (authenticationUser == "has-pin"){56 } else if (authenticationUser == "has-pin"){
57 Q_EMIT q->showPrompt("Password:", Greeter::PromptTypeSecret);57 Q_EMIT q->showPrompt("Password: ", Greeter::PromptTypeSecret);
58 } else if (authenticationUser == "auth-error") {58 } else if (authenticationUser == "auth-error") {
59 authenticated = false;59 authenticated = false;
60 Q_EMIT q->authenticationComplete();60 Q_EMIT q->authenticationComplete();
@@ -78,11 +78,11 @@
78 Q_EMIT q->showPrompt("otp", Greeter::PromptTypeQuestion);78 Q_EMIT q->showPrompt("otp", Greeter::PromptTypeQuestion);
79 } else {79 } else {
80 authenticated = false;80 authenticated = false;
81 Q_EMIT q->authenticationComplete();81 q->sendAuthenticationComplete();
82 }82 }
83 } else {83 } else {
84 authenticated = (response == "otp");84 authenticated = (response == "otp");
85 Q_EMIT q->authenticationComplete();85 q->sendAuthenticationComplete();
86 }86 }
87 return;87 return;
88 }88 }
@@ -92,7 +92,7 @@
92 } else {92 } else {
93 authenticated = (response == "password");93 authenticated = (response == "password");
94 }94 }
95 Q_EMIT q->authenticationComplete();95 q->sendAuthenticationComplete();
96}96}
9797
98}98}
9999
=== modified file 'tests/mocks/LightDM/single-passphrase/GreeterPrivate.cpp'
--- tests/mocks/LightDM/single-passphrase/GreeterPrivate.cpp 2013-06-06 12:18:34 +0000
+++ tests/mocks/LightDM/single-passphrase/GreeterPrivate.cpp 2014-08-13 18:12:02 +0000
@@ -19,8 +19,6 @@
19#include "../Greeter.h"19#include "../Greeter.h"
20#include "../GreeterPrivate.h"20#include "../GreeterPrivate.h"
2121
22#include <QDebug>
23
24namespace QLightDM22namespace QLightDM
25{23{
2624
@@ -34,20 +32,15 @@
34void GreeterPrivate::handleAuthenticate()32void GreeterPrivate::handleAuthenticate()
35{33{
36 Q_Q(Greeter);34 Q_Q(Greeter);
3735 Q_EMIT q->showPrompt("Password: ", Greeter::PromptTypeSecret);
38 qDebug() << "handleAuthentication called!" << authenticationUser;
39
40 Q_EMIT q->showPrompt("Password:", Greeter::PromptTypeSecret);
41}36}
4237
43void GreeterPrivate::handleRespond(const QString &response)38void GreeterPrivate::handleRespond(const QString &response)
44{39{
45 Q_Q(Greeter);40 Q_Q(Greeter);
4641
47
48 authenticated = (response == "password");42 authenticated = (response == "password");
49 qDebug() << "responding" << response << authenticated;43 q->sendAuthenticationComplete();
50 Q_EMIT q->authenticationComplete();
51}44}
5245
53}46}
5447
=== modified file 'tests/mocks/LightDM/single-pin/GreeterPrivate.cpp'
--- tests/mocks/LightDM/single-pin/GreeterPrivate.cpp 2014-07-02 16:17:14 +0000
+++ tests/mocks/LightDM/single-pin/GreeterPrivate.cpp 2014-08-13 18:12:02 +0000
@@ -32,14 +32,15 @@
32void GreeterPrivate::handleAuthenticate()32void GreeterPrivate::handleAuthenticate()
33{33{
34 Q_Q(Greeter);34 Q_Q(Greeter);
35 Q_EMIT q->showPrompt("Password:", Greeter::PromptTypeSecret);35 Q_EMIT q->showPrompt("Password: ", Greeter::PromptTypeSecret);
36}36}
3737
38void GreeterPrivate::handleRespond(const QString &response)38void GreeterPrivate::handleRespond(const QString &response)
39{39{
40 Q_Q(Greeter);40 Q_Q(Greeter);
41
41 authenticated = (response == "1234");42 authenticated = (response == "1234");
42 Q_EMIT q->authenticationComplete();43 q->sendAuthenticationComplete();
43}44}
4445
45}46}
4647
=== modified file 'tests/mocks/Ubuntu/CMakeLists.txt'
--- tests/mocks/Ubuntu/CMakeLists.txt 2014-07-07 08:51:33 +0000
+++ tests/mocks/Ubuntu/CMakeLists.txt 2014-08-13 18:12:02 +0000
@@ -1,4 +1,5 @@
1add_subdirectory(DownloadDaemonListener)1add_subdirectory(DownloadDaemonListener)
2add_subdirectory(Payments)2add_subdirectory(Payments)
3add_subdirectory(SystemImage)
3add_subdirectory(Telephony)4add_subdirectory(Telephony)
4add_subdirectory(Thumbnailer)5add_subdirectory(Thumbnailer)
56
=== added directory 'tests/mocks/Ubuntu/SystemImage'
=== added file 'tests/mocks/Ubuntu/SystemImage/CMakeLists.txt'
--- tests/mocks/Ubuntu/SystemImage/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/mocks/Ubuntu/SystemImage/CMakeLists.txt 2014-08-13 18:12:02 +0000
@@ -0,0 +1,10 @@
1set(MOCK_SYSTEMIMAGE_SOURCES
2 plugin.cpp
3 MockSystemImage.cpp
4)
5
6add_library(MockSystemImage MODULE ${MOCK_SYSTEMIMAGE_SOURCES})
7
8qt5_use_modules(MockSystemImage Qml Quick Core)
9
10add_unity8_mock(Ubuntu.SystemImage 0.1 Ubuntu/SystemImage TARGETS MockSystemImage)
011
=== added file 'tests/mocks/Ubuntu/SystemImage/MockSystemImage.cpp'
--- tests/mocks/Ubuntu/SystemImage/MockSystemImage.cpp 1970-01-01 00:00:00 +0000
+++ tests/mocks/Ubuntu/SystemImage/MockSystemImage.cpp 2014-08-13 18:12:02 +0000
@@ -0,0 +1,27 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "MockSystemImage.h"
18
19MockSystemImage::MockSystemImage(QObject *parent)
20 : QObject(parent)
21{
22}
23
24void MockSystemImage::factoryReset()
25{
26 Q_EMIT resettingDevice();
27}
028
=== added file 'tests/mocks/Ubuntu/SystemImage/MockSystemImage.h'
--- tests/mocks/Ubuntu/SystemImage/MockSystemImage.h 1970-01-01 00:00:00 +0000
+++ tests/mocks/Ubuntu/SystemImage/MockSystemImage.h 2014-08-13 18:12:02 +0000
@@ -0,0 +1,36 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef MOCK_SYSTEMIMAGE_H
18#define MOCK_SYSTEMIMAGE_H
19
20#include <QObject>
21
22class MockSystemImage : public QObject
23{
24 Q_OBJECT
25 Q_DISABLE_COPY(MockSystemImage)
26
27public:
28 explicit MockSystemImage(QObject *parent = 0);
29
30 Q_INVOKABLE void factoryReset();
31
32Q_SIGNALS:
33 void resettingDevice(); // only for mock
34};
35
36#endif // MOCK_SYSTEMIMAGE_H
037
=== added file 'tests/mocks/Ubuntu/SystemImage/SystemImage.qmltypes'
--- tests/mocks/Ubuntu/SystemImage/SystemImage.qmltypes 1970-01-01 00:00:00 +0000
+++ tests/mocks/Ubuntu/SystemImage/SystemImage.qmltypes 2014-08-13 18:12:02 +0000
@@ -0,0 +1,18 @@
1import QtQuick.tooling 1.1
2
3// This file describes the plugin-supplied types contained in the library.
4// It is used for QML tooling purposes only.
5//
6// This file was auto-generated by:
7// 'qmlplugindump -notrelocatable Ubuntu.SystemImage 0.1 plugins'
8
9Module {
10 Component {
11 name: "MockSystemImage"
12 prototype: "QObject"
13 exports: ["Ubuntu.SystemImage/SystemImage 0.1"]
14 exportMetaObjectRevisions: [0]
15 Signal { name: "resettingDevice" }
16 Method { name: "factoryReset" }
17 }
18}
019
=== added file 'tests/mocks/Ubuntu/SystemImage/plugin.cpp'
--- tests/mocks/Ubuntu/SystemImage/plugin.cpp 1970-01-01 00:00:00 +0000
+++ tests/mocks/Ubuntu/SystemImage/plugin.cpp 2014-08-13 18:12:02 +0000
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "plugin.h"
18#include "MockSystemImage.h"
19
20#include <QtQml>
21
22static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
23{
24 Q_UNUSED(engine)
25 Q_UNUSED(scriptEngine)
26 return new MockSystemImage();
27}
28
29void BackendPlugin::registerTypes(const char *uri)
30{
31 Q_ASSERT(uri == QLatin1String("Ubuntu.SystemImage"));
32
33 qmlRegisterSingletonType<MockSystemImage>(uri, 0, 1, "SystemImage", service_provider);
34}
035
=== added file 'tests/mocks/Ubuntu/SystemImage/plugin.h'
--- tests/mocks/Ubuntu/SystemImage/plugin.h 1970-01-01 00:00:00 +0000
+++ tests/mocks/Ubuntu/SystemImage/plugin.h 2014-08-13 18:12:02 +0000
@@ -0,0 +1,31 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef MOCK_SYSTEMIMAGE_PLUGIN_H
18#define MOCK_SYSTEMIMAGE_PLUGIN_H
19
20#include <QQmlExtensionPlugin>
21
22class BackendPlugin : public QQmlExtensionPlugin
23{
24 Q_OBJECT
25 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
26
27public:
28 void registerTypes(const char *uri);
29};
30
31#endif // MOCK_SYSTEMIMAGE_PLUGIN_H
032
=== added file 'tests/mocks/Ubuntu/SystemImage/qmldir'
--- tests/mocks/Ubuntu/SystemImage/qmldir 1970-01-01 00:00:00 +0000
+++ tests/mocks/Ubuntu/SystemImage/qmldir 2014-08-13 18:12:02 +0000
@@ -0,0 +1,3 @@
1module Ubuntu.SystemImage
2plugin MockSystemImage
3typeinfo SystemImage.qmltypes
04
=== modified file 'tests/qmltests/Greeter/tst_Lockscreen.qml'
--- tests/qmltests/Greeter/tst_Lockscreen.qml 2014-07-02 16:17:14 +0000
+++ tests/qmltests/Greeter/tst_Lockscreen.qml 2014-08-13 18:12:02 +0000
@@ -319,11 +319,9 @@
319 if (data.animation) {319 if (data.animation) {
320 if (data.alphanumeric) {320 if (data.alphanumeric) {
321 tryCompare(inputField, "placeholderText", lockscreen.wrongPlaceholderText)321 tryCompare(inputField, "placeholderText", lockscreen.wrongPlaceholderText)
322 tryCompare(inputField, "placeholderText", lockscreen.placeholderText)
323 } else {322 } else {
324 var label = findChild(lockscreen, "pinentryFieldPlaceHolder");323 var label = findChild(lockscreen, "pinentryFieldPlaceHolder");
325 tryCompare(label, "text", lockscreen.wrongPlaceholderText)324 tryCompare(label, "text", lockscreen.wrongPlaceholderText)
326 tryCompare(label, "text", lockscreen.placeholderText)
327 }325 }
328 }326 }
329327
330328
=== modified file 'tests/qmltests/tst_ShellWithPin.qml'
--- tests/qmltests/tst_ShellWithPin.qml 2014-08-05 18:18:09 +0000
+++ tests/qmltests/tst_ShellWithPin.qml 2014-08-13 18:12:02 +0000
@@ -16,8 +16,10 @@
1616
17import QtQuick 2.017import QtQuick 2.0
18import QtTest 1.018import QtTest 1.0
19import AccountsService 0.1
19import GSettings 1.020import GSettings 1.0
20import LightDM 0.1 as LightDM21import LightDM 0.1 as LightDM
22import Ubuntu.SystemImage 0.1
21import Unity.Application 0.123import Unity.Application 0.1
22import Unity.Test 0.1 as UT24import Unity.Test 0.1 as UT
23import Powerd 0.125import Powerd 0.1
@@ -25,6 +27,7 @@
25import "../../qml"27import "../../qml"
2628
27Item {29Item {
30 id: root
28 width: shell.width31 width: shell.width
29 height: shell.height32 height: shell.height
3033
@@ -53,6 +56,12 @@
53 signalName: "sessionStarted"56 signalName: "sessionStarted"
54 }57 }
5558
59 SignalSpy {
60 id: resetSpy
61 target: SystemImage
62 signalName: "resettingDevice"
63 }
64
56 UT.UnityTestCase {65 UT.UnityTestCase {
57 name: "ShellWithPin"66 name: "ShellWithPin"
58 when: windowShown67 when: windowShown
@@ -64,6 +73,8 @@
6473
65 function init() {74 function init() {
66 swipeAwayGreeter()75 swipeAwayGreeter()
76 shell.failedLoginsDelayAttempts = -1
77 shell.maxFailedLogins = -1
67 }78 }
6879
69 function cleanup() {80 function cleanup() {
@@ -111,6 +122,7 @@
111 }122 }
112123
113 function test_login() {124 function test_login() {
125 sessionSpy.clear()
114 tryCompare(sessionSpy, "count", 0)126 tryCompare(sessionSpy, "count", 0)
115 enterPin("1234")127 enterPin("1234")
116 tryCompare(sessionSpy, "count", 1)128 tryCompare(sessionSpy, "count", 1)
@@ -175,5 +187,49 @@
175 ApplicationManager.startApplication("gallery-app", ApplicationManager.NoFlag)187 ApplicationManager.startApplication("gallery-app", ApplicationManager.NoFlag)
176 tryCompare(lockscreen, "shown", true)188 tryCompare(lockscreen, "shown", true)
177 }189 }
190
191 function test_failedLoginsCount() {
192 AccountsService.failedLogins = 0
193
194 enterPin("1111")
195 tryCompare(AccountsService, "failedLogins", 1)
196
197 enterPin("1234")
198 tryCompare(AccountsService, "failedLogins", 0)
199 }
200
201 function test_wrongEntries() {
202 shell.failedLoginsDelayAttempts = 3
203
204 var placeHolder = findChild(shell, "pinentryFieldPlaceHolder")
205 tryCompare(placeHolder, "text", "Enter your passcode")
206
207 enterPin("1111")
208 tryCompare(placeHolder, "text", "Incorrect passcode\nPlease re-enter")
209
210 enterPin("1111")
211 tryCompare(placeHolder, "text", "Incorrect passcode\nPlease re-enter")
212
213 enterPin("1111")
214 tryCompare(placeHolder, "text", "Too many incorrect attempts\nPlease wait")
215 }
216
217 function test_factoryReset() {
218 shell.maxFailedLogins = 3
219 resetSpy.clear()
220
221 enterPin("1111")
222 enterPin("1111")
223 tryCompareFunction(function() {return findChild(root, "infoPopup") !== null}, true)
224
225 var dialog = findChild(root, "infoPopup")
226 var button = findChild(dialog, "infoPopupOkButton")
227 mouseClick(button, units.gu(1), units.gu(1))
228 tryCompareFunction(function() {return findChild(root, "infoPopup")}, null)
229
230 tryCompare(resetSpy, "count", 0)
231 enterPin("1111")
232 tryCompare(resetSpy, "count", 1)
233 }
178 }234 }
179}235}

Subscribers

People subscribed via source and target branches