@@ -19,7 +19,9 @@ import AccountsService 0.1
19import GSettings 1.0
19import GSettings 1.0
20import Unity.Application 0.1
20import Unity.Application 0.1
21import Ubuntu.Components 0.1
21import Ubuntu.Components 0.1
22+import Ubuntu.Components.Popups 1.0
22import Ubuntu.Gestures 0.1
23import Ubuntu.Gestures 0.1
24+import Ubuntu.SystemImage 0.1
23import Unity.Launcher 0.1
25import Unity.Launcher 0.1
24import Utils 0.1
26import Utils 0.1
25import LightDM 0.1 as LightDM
27import LightDM 0.1 as LightDM
@@ -53,6 +55,10 @@ Item {
53 property bool sideStageEnabled: shell.width >= units.gu(100)
55 property bool sideStageEnabled: shell.width >= units.gu(100)
54 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
56 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
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
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,7 +261,15 @@ Item {
256 onShowPrompt: {
262 onShowPrompt: {
257 if (greeter.narrowMode) {
263 if (greeter.narrowMode) {
264+ var promptText = text.toLowerCase()
265+ if (isDefaultPrompt) {
266+ promptText = lockscreen.alphaNumeric ?
267+ i18n.tr("passphrase") : i18n.tr("passcode")
258− lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text.toLowerCase());
269+ lockscreen.placeholderText = i18n.tr("Enter your %1").arg(promptText)
270+ lockscreen.wrongPlaceholderText = i18n.tr("Incorrect %1").arg(promptText) +
272+ i18n.tr("Please re-enter")
259 lockscreen.show();
273 lockscreen.show();
@@ -270,13 +284,40 @@ Item {
272 onAuthenticationComplete: {
286 onAuthenticationComplete: {
287+ if (LightDM.Greeter.authenticated) {
288+ AccountsService.failedLogins = 0
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
273 if (LightDM.Greeter.promptless) {
294 if (LightDM.Greeter.promptless) {
276 if (LightDM.Greeter.authenticated) {
298 if (LightDM.Greeter.authenticated) {
277 lockscreen.hide();
299 lockscreen.hide();
278 greeter.login();
300 greeter.login();
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!
317+ if (failedLoginsDelayAttempts > 0 && AccountsService.failedLogins % failedLoginsDelayAttempts == 0) {
318+ lockscreen.forceDelay(failedLoginsDelaySeconds * 1000)
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,6 +352,14 @@ Item {
313 property bool fullyShown: showProgress === 1.0
354 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) {
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.authenticated && showProgress === 0) greeter.login()
364 onShowProgressChanged: if (LightDM.Greeter.authenticated && showProgress === 0) greeter.login()
@@ -350,10 +399,6 @@ Item {
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));
353− if (!LightDM.Greeter.authenticated) {
357 greeter.fakeActiveForApp = "";
402 greeter.fakeActiveForApp = "";
358 greeter.forceActiveFocus();
403 greeter.forceActiveFocus();