[gnome-shell/wip/wayland-gdm-cleanup: 1/3] gdm: Integrate username asking into the ShellUserVerifier flow



commit fb824131ae4b12cd7a2cb9cdc0e53ae47196fa5b
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Mar 7 19:09:48 2014 -0500

    gdm: Integrate username asking into the ShellUserVerifier flow
    
    Currently, prompting for the username on the login screen is done
    "out-of-band". This leads to subtle bugs where we're trying to
    integrate two different state machines, or interpret results from
    one state machine as part of another.
    
    It also complicates the logic, as the ability to know whether we
    need or want a username is currently in the UI layer rather than
    the logic layer.
    
    Move this into the verifier proper.

 js/gdm/authPrompt.js  |   38 +++++++++++++-----------------------
 js/gdm/loginDialog.js |   51 ++++++++++++++++++++++++-------------------------
 js/gdm/util.js        |   51 ++++++++++++++++++++++++++++++++++++------------
 js/ui/unlockDialog.js |    7 +++++-
 4 files changed, 83 insertions(+), 64 deletions(-)
---
diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js
index a0420a6..fb85004 100644
--- a/js/gdm/authPrompt.js
+++ b/js/gdm/authPrompt.js
@@ -24,11 +24,6 @@ const AuthPromptMode = {
     UNLOCK_OR_LOG_IN: 1
 };
 
-const BeginRequestType = {
-    PROVIDE_USERNAME: 0,
-    DONT_PROVIDE_USERNAME: 1
-};
-
 const AuthPrompt = new Lang.Class({
     Name: 'AuthPrompt',
 
@@ -44,6 +39,7 @@ const AuthPrompt = new Lang.Class({
 
         this._userVerifier = new GdmUtil.ShellUserVerifier(this._gdmClient, { reauthenticationOnly: 
reauthenticationOnly });
 
+        this._userVerifier.connect('needs-username', Lang.bind(this, this._onNeedsUserName));
         this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion));
         this._userVerifier.connect('show-message', Lang.bind(this, this._onShowMessage));
         this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed));
@@ -186,6 +182,14 @@ const AuthPrompt = new Lang.Class({
         }));
     },
 
+    _onNeedsUserName: function() {
+        this.emit('needs-username');
+    },
+
+    gotUserName: function(userName) {
+        this._userVerifier.gotUserName(userName);
+    },
+
     _onAskQuestion: function(verifier, serviceName, question, passwordChar) {
         if (this._preemptiveAnswer) {
             if (this._queryingService)
@@ -403,24 +407,7 @@ const AuthPrompt = new Lang.Class({
         this.setUser(null);
         this.stopSpinning();
 
-        let beginRequestType;
-
-        if (this._mode == AuthPromptMode.UNLOCK_ONLY) {
-            // The user is constant at the unlock screen, so it will immediately
-            // respond to the request with the username
-            beginRequestType = BeginRequestType.PROVIDE_USERNAME;
-        } else if (this._userVerifier.serviceIsForeground(GdmUtil.OVIRT_SERVICE_NAME) ||
-                   (this.smartcardDetected &&
-                    this._userVerifier.serviceIsForeground(GdmUtil.SMARTCARD_SERVICE_NAME))) {
-            // We don't need to know the username if the user preempted the login screen
-            // with a smartcard or with preauthenticated oVirt credentials
-            beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME;
-        } else {
-            // In all other cases, we should get the username up front.
-            beginRequestType = BeginRequestType.PROVIDE_USERNAME;
-        }
-
-        this.emit('reset', beginRequestType);
+        this.emit('reset');
     },
 
     addCharacter: function(unichar) {
@@ -431,9 +418,12 @@ const AuthPrompt = new Lang.Class({
         this._entry.clutter_text.insert_unichar(unichar);
     },
 
-    begin: function(userName) {
+    begin: function() {
         this.updateSensitivity(false);
+        this._userVerifier.begin();
+    },
 
+    needsUsername: function() {
         this._userVerifier.begin(userName);
     },
 
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
index 84a38a6..b4953b9 100644
--- a/js/gdm/loginDialog.js
+++ b/js/gdm/loginDialog.js
@@ -421,6 +421,7 @@ const LoginDialog = new Lang.Class({
         this._authPrompt = new AuthPrompt.AuthPrompt(gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
         this._authPrompt.connect('prompted', Lang.bind(this, this._onPrompted));
         this._authPrompt.connect('reset', Lang.bind(this, this._onReset));
+        this._authPrompt.connect('needs-username', Lang.bind(this, this._onNeedsUserName));
         this._authPrompt.hide();
         this.actor.add_child(this._authPrompt.actor);
 
@@ -469,14 +470,13 @@ const LoginDialog = new Lang.Class({
         this._sessionMenuButton.actor.show();
         this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor);
 
-        this._disableUserList = undefined;
+        this._updateDisableUserList();
         this._userListLoaded = false;
 
         // If the user list is enabled, it should take key focus; make sure the
         // screen shield is initialized first to prevent it from stealing the
         // focus later
-        Main.layoutManager.connect('startup-complete',
-                                   Lang.bind(this, this._updateDisableUserList));
+        Main.layoutManager.connect('startup-complete', Lang.bind(this, this._reset));
     },
 
     _ensureUserListLoaded: function() {
@@ -493,15 +493,20 @@ const LoginDialog = new Lang.Class({
             GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, this._loadUserList));
     },
 
+    _reset: function() {
+        this._authPrompt.reset();
+        this._authPrompt.begin();
+    },
+
     _updateDisableUserList: function() {
         let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
+        if (disableUserList == this._disableUserList)
+            return;
 
-        if (disableUserList != this._disableUserList) {
-            this._disableUserList = disableUserList;
+        this._disableUserList = disableUserList;
 
-            if (this._authPrompt.verificationStatus == GdmUtil.VerificationStatus.NOT_VERIFYING)
-                this._authPrompt.reset();
-        }
+        if (this._authPrompt.verificationStatus == GdmUtil.VerificationStatus.ASKING_FOR_USERNAME)
+            this._reset();
     },
 
     _updateCancelButton: function() {
@@ -509,7 +514,7 @@ const LoginDialog = new Lang.Class({
 
         // Hide the cancel button if the user list is disabled and we're asking for
         // a username
-        if (this._authPrompt.verificationStatus == GdmUtil.VerificationStatus.NOT_VERIFYING && 
this._disableUserList)
+        if (this._authPrompt.verificationStatus == GdmUtil.VerificationStatus.ASKING_FOR_USERNAME && 
this._disableUserList)
             cancelVisible = false;
         else
             cancelVisible = true;
@@ -554,19 +559,18 @@ const LoginDialog = new Lang.Class({
         this._showPrompt();
     },
 
-    _onReset: function(authPrompt, beginRequest) {
+    _onReset: function() {
         this._sessionMenuButton.updateSensitivity(true);
-
         this._user = null;
 
-        if (beginRequest == AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
-            if (!this._disableUserList)
-                this._showUserList();
-            else
-                this._hideUserListAskForUsernameAndBeginVerification();
-        } else {
-            this._hideUserListAndBeginVerification();
-        }
+        this._reset();
+    },
+
+    _onNeedsUserName: function() {
+        if (!this._disableUserList)
+            this._showUserList();
+        else
+            this._hideUserListAskForUsernameAndBeginVerification();
     },
 
     _onDefaultSessionChanged: function(client, sessionId) {
@@ -625,7 +629,7 @@ const LoginDialog = new Lang.Class({
                                                         this._user = this._userManager.get_user(answer);
                                                         this._authPrompt.clear();
                                                         this._authPrompt.startSpinning();
-                                                        this._authPrompt.begin(answer);
+                                                        this._authPrompt.gotUserName(answer);
                                                         this._updateCancelButton();
 
                                                         realmManager.disconnect(realmSignalId)
@@ -805,11 +809,6 @@ const LoginDialog = new Lang.Class({
         this._askForUsernameAndBeginVerification();
     },
 
-    _hideUserListAndBeginVerification: function() {
-        this._hideUserList();
-        this._authPrompt.begin();
-    },
-
     _showUserList: function() {
         this._ensureUserListLoaded();
         this._authPrompt.hide();
@@ -823,7 +822,7 @@ const LoginDialog = new Lang.Class({
         this._authPrompt.setUser(item.user);
 
         let userName = item.user.get_user_name();
-        this._authPrompt.begin(userName);
+        this._authPrompt.gotUserName(userName);
     },
 
     _onUserListActivated: function(activatedItem) {
diff --git a/js/gdm/util.js b/js/gdm/util.js
index 076007e..24c70e2 100644
--- a/js/gdm/util.js
+++ b/js/gdm/util.js
@@ -121,9 +121,10 @@ function cloneAndFadeOutActor(actor) {
 
 const VerificationStatus = {
     NOT_VERIFYING: 0,
-    VERIFYING: 1,
-    VERIFICATION_FAILED: 2,
-    VERIFICATION_SUCCEEDED: 3
+    ASKING_FOR_USERNAME: 1,
+    VERIFYING: 2,
+    VERIFICATION_FAILED: 3,
+    VERIFICATION_SUCCEEDED: 4,
 };
 
 const ShellUserVerifier = new Lang.Class({
@@ -169,24 +170,52 @@ const ShellUserVerifier = new Lang.Class({
     _reset: function() {
         // Clear previous attempts to authenticate
         this.verificationStatus = VerificationStatus.NOT_VERIFYING;
+        this._userName = null;
         this._failCounter = 0;
         this._updateDefaultService();
         this.emit('reset');
     },
 
-    begin: function(userName) {
-        this.verificationStatus = VerificationStatus.VERIFYING;
+    begin: function() {
+        if (this._mode == AuthPromptMode.UNLOCK_ONLY) {
+            // The user is constant at the unlock screen, so it will immediately
+            // respond to the request with the username
+            needsUsername = true;
+        } else if (this.serviceIsForeground(GdmUtil.OVIRT_SERVICE_NAME) ||
+                   (this.smartcardDetected &&
+                    this.serviceIsForeground(GdmUtil.SMARTCARD_SERVICE_NAME))) {
+            // We don't need to know the username if the user preempted the login screen
+            // with a smartcard or with preauthenticated oVirt credentials
+            needsUsername = false;
+        } else {
+            // In all other cases, we should get the username up front.
+            needsUsername = true;
+        }
 
-        this._cancellable = new Gio.Cancellable();
+        if (needsUsername) {
+            this.verificationStatus = VerificationStatus.ASKING_FOR_USERNAME;
+            this.emit('needs-username');
+        } else {
+            this._beginAuthentication();
+        }
+    },
+
+    gotUserName: function(userName) {
         this._userName = userName;
+        this._beginAuthentication();
+    },
+
+    _beginAuthentication: function() {
+        this.verificationStatus = VerificationStatus.VERIFYING;
+        this._cancellable = new Gio.Cancellable();
         this.reauthenticating = false;
 
         this._checkForFingerprintReader();
 
-        if (userName) {
+        if (this._userName) {
             // If possible, reauthenticate an already running session,
             // so any session specific credentials get updated appropriately
-            this._client.open_reauthentication_channel(userName, this._cancellable,
+            this._client.open_reauthentication_channel(this._userName, this._cancellable,
                                                        Lang.bind(this, this._reauthenticationChannelOpened));
         } else {
             this._client.get_user_verifier(this._cancellable, Lang.bind(this, this._userVerifierGot));
@@ -501,10 +530,6 @@ const ShellUserVerifier = new Lang.Class({
         this.verificationStatus = VerificationStatus.VERIFICATION_SUCCEEDED;
     },
 
-    _retry: function() {
-        this.begin(this._userName);
-    },
-
     _verificationFailed: function(retry) {
         // For Not Listed / enterprise logins, immediately reset
         // the dialog
@@ -520,7 +545,7 @@ const ShellUserVerifier = new Lang.Class({
 
         this._doAfterPendingMessages(Lang.bind(this, function() {
             if (canRetry)
-                this._retry();
+                this._beginAuthentication();
             else
                 this.clear();
         }));
diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js
index 001aabc..84d7250 100644
--- a/js/ui/unlockDialog.js
+++ b/js/ui/unlockDialog.js
@@ -54,6 +54,7 @@ const UnlockDialog = new Lang.Class({
         this._authPrompt = new AuthPrompt.AuthPrompt(new Gdm.Client(), 
AuthPrompt.AuthPromptMode.UNLOCK_ONLY);
         this._authPrompt.connect('failed', Lang.bind(this, this._fail));
         this._authPrompt.connect('reset', Lang.bind(this, this._onReset));
+        this._authPrompt.connect('needs-username', Lang.bind(this, this._onNeedsUserName));
         this._authPrompt.setPasswordChar('\u25cf');
         this._authPrompt.nextButton.label = _("Unlock");
 
@@ -100,6 +101,10 @@ const UnlockDialog = new Lang.Class({
     },
 
     _onReset: function(authPrompt, beginRequest) {
+        this._authPrompt.begin();
+    },
+
+    _onNeedsUserName: function() {
         let userName;
         if (beginRequest == AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
             this._authPrompt.setUser(this._user);
@@ -108,7 +113,7 @@ const UnlockDialog = new Lang.Class({
             userName = null;
         }
 
-        this._authPrompt.begin(userName);
+        this._authPrompt.gotUserName(userName);
     },
 
     _escape: function() {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]