[gnome-shell] gdm: add fingerprint support



commit 43f1d0578b2a60788011b0429f8a0e85e879e723
Author: Ray Strode <rstrode redhat com>
Date:   Tue Sep 6 16:17:08 2011 -0400

    gdm: add fingerprint support
    
    This commit adds the ability to log in with a fingerprint instead
    of a password (assuming the user is enrolled and fingerprint
    isn't disabled via gsettings)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=657823

 data/theme/gdm.css    |    4 +++
 js/Makefile.am        |    1 +
 js/gdm/fingerprint.js |   26 ++++++++++++++++++
 js/gdm/loginDialog.js |   69 ++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 99 insertions(+), 1 deletions(-)
---
diff --git a/data/theme/gdm.css b/data/theme/gdm.css
index ae70cca..c77884b 100644
--- a/data/theme/gdm.css
+++ b/data/theme/gdm.css
@@ -30,6 +30,10 @@
     min-width: 350px;
 }
 
+.login-dialog-prompt-fingerprint-message {
+    font-size: 10.5pt;
+}
+
 .login-dialog-user-list-view {
     -st-vfade-offset: 1em;
 }
diff --git a/js/Makefile.am b/js/Makefile.am
index 8924c34..7c72637 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -4,6 +4,7 @@ jsdir = $(pkgdatadir)/js
 nobase_dist_js_DATA = 	\
 	gdm/batch.js		\
 	gdm/consoleKit.js	\
+	gdm/fingerprint.js	\
 	gdm/loginDialog.js	\
 	gdm/powerMenu.js	\
 	misc/config.js		\
diff --git a/js/gdm/fingerprint.js b/js/gdm/fingerprint.js
new file mode 100644
index 0000000..ee08a3a
--- /dev/null
+++ b/js/gdm/fingerprint.js
@@ -0,0 +1,26 @@
+// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
+
+const DBus = imports.dbus;
+const Lang = imports.lang;
+const Shell = imports.gi.Shell;
+const Signals = imports.signals;
+
+const FprintManagerIface = {
+    name: 'net.reactivated.Fprint.Manager',
+    methods: [{ name: 'GetDefaultDevice',
+                inSignature: '',
+                outSignature: 'o' }]
+};
+
+function FprintManager() {
+    this._init();
+};
+
+FprintManager.prototype = {
+    _init: function() {
+        DBus.system.proxifyObject(this,
+                                  'net.reactivated.Fprint',
+                                  '/net/reactivated/Fprint/Manager');
+    }
+};
+DBus.proxifyPrototype(FprintManager.prototype, FprintManagerIface);
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
index 664b3fa..0a1bd29 100644
--- a/js/gdm/loginDialog.js
+++ b/js/gdm/loginDialog.js
@@ -33,17 +33,23 @@ const St = imports.gi.St;
 const GdmGreeter = imports.gi.GdmGreeter;
 
 const Batch = imports.gdm.batch;
+const DBus = imports.dbus;
+const Fprint = imports.gdm.fingerprint;
 const Lightbox = imports.ui.lightbox;
 const Main = imports.ui.main;
 const ModalDialog = imports.ui.modalDialog;
 const Tweener = imports.ui.tweener;
 
 const _PASSWORD_SERVICE_NAME = 'gdm-password';
+const _FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
 const _FADE_ANIMATION_TIME = 0.16;
 const _RESIZE_ANIMATION_TIME = 0.25;
 const _SCROLL_ANIMATION_TIME = 2.0;
 const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
 
+const _LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
+const _FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
+
 let _loginDialog = null;
 
 function _fadeInActor(actor) {
@@ -761,6 +767,11 @@ LoginDialog.prototype = {
         this._greeterClient.connect('conversation-stopped',
                                     Lang.bind(this, this._onConversationStopped));
 
+        this._settings = new Gio.Settings({ schema: _LOGIN_SCREEN_SCHEMA });
+
+        this._fprintManager = new Fprint.FprintManager();
+        this._startFingerprintConversationIfNeeded();
+
         this._titleLabel = new St.Label({ style_class: 'login-dialog-title',
                                           text: C_("title", "Sign In") });
 
@@ -805,6 +816,12 @@ LoginDialog.prototype = {
                               x_fill: true,
                               y_fill: false,
                               x_align: St.Align.START });
+        // translators: this message is shown below the password entry field
+        // to indicate the user can swipe their finger instead
+        this._promptFingerprintMessage = new St.Label({ text: _("(or swipe finger)"),
+                                                        style_class: 'login-dialog-prompt-fingerprint-message' });
+        this._promptFingerprintMessage.hide();
+        this._promptBox.add(this._promptFingerprintMessage);
 
         this._sessionList = new SessionList();
         this._sessionList.connect('session-activated',
@@ -852,10 +869,27 @@ LoginDialog.prototype = {
                                    this._onUserListActivated(item);
                                }));
 
+   },
+
+   _startFingerprintConversationIfNeeded: function() {
+        this._haveFingerprintReader = false;
+
+        if (!this._settings.get_boolean(_FINGERPRINT_AUTHENTICATION_KEY))
+            return;
+
+        this._fprintManager.GetDefaultDeviceRemote(DBus.CALL_FLAG_START, Lang.bind(this,
+            function(device, error) {
+                if (!error && device)
+                    this._haveFingerprintReader = true;
+
+                if (this._haveFingerprintReader)
+                    this._greeterClient.call_start_conversation(_FINGERPRINT_SERVICE_NAME);
+            }));
     },
 
     _onReset: function(client, serviceName) {
         this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME);
+        this._startFingerprintConversationIfNeeded();
 
         let tasks = [this._hidePrompt,
 
@@ -885,10 +919,17 @@ LoginDialog.prototype = {
     },
 
     _onInfo: function(client, serviceName, info) {
+        // we don't want fingerprint messages with the word UPEK in them
+        if (serviceName != _PASSWORD_SERVICE_NAME)
+            return;
         Main.notifyError(info);
     },
 
     _onProblem: function(client, serviceName, problem) {
+        // we don't want to show auth failed messages to
+        // users who haven't enrolled their fingerprint.
+        if (serviceName != _PASSWORD_SERVICE_NAME)
+            return;
         Main.notifyError(problem);
     },
 
@@ -906,6 +947,13 @@ LoginDialog.prototype = {
                      },
 
                      function() {
+                         if (!this._haveFingerprintReader)
+                             return null;
+
+                         return _fadeInActor(this._promptFingerprintMessage);
+                     },
+
+                     function() {
                          return _fadeInActor(this._promptBox);
                      },
 
@@ -973,6 +1021,7 @@ LoginDialog.prototype = {
                      },
 
                      function() {
+                         this._promptFingerprintMessage.hide();
                          this._promptEntry.set_text('');
                      }];
 
@@ -996,12 +1045,20 @@ LoginDialog.prototype = {
         return batch.run();
     },
     _onInfoQuery: function(client, serviceName, question) {
+        // We only expect questions to come from the main auth service
+        if (serviceName != _PASSWORD_SERVICE_NAME)
+            return;
+
         this._promptEntry.set_text('');
         this._promptEntry.clutter_text.set_password_char('');
         this._askQuestion(serviceName, question);
     },
 
     _onSecretInfoQuery: function(client, serviceName, secretQuestion) {
+        // We only expect secret requests to come from the main auth service
+        if (serviceName != _PASSWORD_SERVICE_NAME)
+            return;
+
         this._promptEntry.set_text('');
         this._promptEntry.clutter_text.set_password_char('\u25cf');
         this._askQuestion(serviceName, secretQuestion);
@@ -1138,7 +1195,14 @@ LoginDialog.prototype = {
     },
 
     _onConversationStopped: function(client, serviceName) {
-        this._greeterClient.call_cancel();
+        // if the password service fails, then cancel everything.
+        // But if, e.g., fingerprint fails, still give
+        // password authentication a chance to succeed
+        if (serviceName == _PASSWORD_SERVICE_NAME) {
+            this._greeterClient.call_cancel();
+        } else if (serviceName == _FINGERPRINT_SERVICE_NAME) {
+            _fadeOutActor(this._promptFingerprintMessage);
+        }
     },
 
     _onNotListedClicked: function(user) {
@@ -1210,6 +1274,9 @@ LoginDialog.prototype = {
                          let userName = activatedItem.user.get_user_name();
                          this._greeterClient.call_begin_verification_for_user(_PASSWORD_SERVICE_NAME,
                                                                               userName);
+
+                         if (this._haveFingerprintReader)
+                             this._greeterClient.call_begin_verification_for_user(_FINGERPRINT_SERVICE_NAME, userName);
                      }];
 
         this._user = activatedItem.user;



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