From e06ecb8f0c948aa7043d1703702fbe8fa66835ec Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Sun, 20 May 2012 01:19:25 +0200 Subject: [PATCH] gdm: port from libgdmgreeter to libgdm When GDM was moved over to GDBus it dropped the libgdmgreeter library and introduced a new libgdm library with a somewhat different API. The main differences in the API are: 1) open_connection is now implicit and automatic 2) conversations don't need to be started explicitly, they're started just-in-time when verification is requested 3) The functions are split up between the client, and new helper objects that correspond to the dbus interfaces they were generated from (one for user verification, one for greeter specific operations, and a couple more that aren't used by gnome-shell). 4) libgdm supports reauthenticating in an already running session, so user switching should now affect the users session more like screen unlocking does. This commit moves the shell over to the new library. Based on work by Giovanni Campagna https://bugzilla.gnome.org/show_bug.cgi?id=676401 --- js/gdm/loginDialog.js | 177 ++++++++++++++++++++++++++++++------------ js/ui/userMenu.js | 6 +- 2 files changed, 131 insertions(+), 52 deletions(-) diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js index 6ea415140..53005b7eb 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -30,7 +30,7 @@ const Pango = imports.gi.Pango; const Signals = imports.signals; const Shell = imports.gi.Shell; const St = imports.gi.St; -const GdmGreeter = imports.gi.GdmGreeter; +const Gdm = imports.gi.Gdm; const Batch = imports.gdm.batch; const Fprint = imports.gdm.fingerprint; @@ -703,7 +703,7 @@ const SessionList = new Lang.Class({ this._activeSessionId = null; this._items = {}; - let ids = GdmGreeter.get_session_ids(); + let ids = Gdm.get_session_ids(); ids.sort(); if (ids.length <= 1) { @@ -715,7 +715,7 @@ const SessionList = new Lang.Class({ } for (let i = 0; i < ids.length; i++) { - let [sessionName, sessionDescription] = GdmGreeter.get_session_name_and_description(ids[i]); + let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]); let item = new SessionListItem(ids[i], sessionName); this._itemList.add_actor(item.actor, @@ -749,37 +749,22 @@ const LoginDialog = new Lang.Class({ Lang.bind(this, this._onOpened)); this._userManager = AccountsService.UserManager.get_default() - this._greeterClient = new GdmGreeter.Client(); + this._greeterClient = new Gdm.Client(); - this._greeterClient.open_connection(); + this._greeter = this._greeterClient.get_greeter_sync(null); - this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME); + this._greeter.connect('default-session-name-changed', + Lang.bind(this, this._onDefaultSessionChanged)); - this._greeterClient.connect('reset', - Lang.bind(this, this._onReset)); - this._greeterClient.connect('default-session-changed', - Lang.bind(this, this._onDefaultSessionChanged)); - this._greeterClient.connect('info', - Lang.bind(this, this._onInfo)); - this._greeterClient.connect('problem', - Lang.bind(this, this._onProblem)); - this._greeterClient.connect('info-query', - Lang.bind(this, this._onInfoQuery)); - this._greeterClient.connect('secret-info-query', - Lang.bind(this, this._onSecretInfoQuery)); - this._greeterClient.connect('session-opened', - Lang.bind(this, this._onSessionOpened)); - this._greeterClient.connect('timed-login-requested', - Lang.bind(this, this._onTimedLoginRequested)); - this._greeterClient.connect('authentication-failed', - Lang.bind(this, this._onAuthenticationFailed)); - this._greeterClient.connect('conversation-stopped', - Lang.bind(this, this._onConversationStopped)); + this._greeter.connect('session-opened', + Lang.bind(this, this._onSessionOpened)); + this._greeter.connect('timed-login-requested', + Lang.bind(this, this._onTimedLoginRequested)); this._settings = new Gio.Settings({ schema: _LOGIN_SCREEN_SCHEMA }); this._fprintManager = new Fprint.FprintManager(); - this._startFingerprintConversationIfNeeded(); + this._checkForFingerprintReader(); this._settings.connect('changed::' + _LOGO_KEY, Lang.bind(this, this._updateLogo)); this._settings.connect('changed::' + _BANNER_MESSAGE_KEY, @@ -850,7 +835,7 @@ const LoginDialog = new Lang.Class({ this._sessionList = new SessionList(); this._sessionList.connect('session-activated', Lang.bind(this, function(list, sessionId) { - this._greeterClient.call_select_session (sessionId); + this._greeter.call_select_session_sync (sessionId, null); })); this._promptBox.add(this._sessionList.actor, @@ -898,7 +883,7 @@ const LoginDialog = new Lang.Class({ }, - _startFingerprintConversationIfNeeded: function() { + _checkForFingerprintReader: function() { this._haveFingerprintReader = false; if (!this._settings.get_boolean(_FINGERPRINT_AUTHENTICATION_KEY)) @@ -908,9 +893,6 @@ const LoginDialog = new Lang.Class({ function(device, error) { if (!error && device) this._haveFingerprintReader = true; - - if (this._haveFingerprintReader) - this._greeterClient.call_start_conversation(_FINGERPRINT_SERVICE_NAME); })); }, @@ -941,8 +923,9 @@ const LoginDialog = new Lang.Class({ }, _onReset: function(client, serviceName) { - this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME); - this._startFingerprintConversationIfNeeded(); + this._userVerifier = null; + + this._checkForFingerprintReader(); let tasks = [this._hidePrompt, @@ -1000,7 +983,7 @@ const LoginDialog = new Lang.Class({ }, _onCancel: function(client) { - this._greeterClient.call_cancel(); + this._userVerifier.call_cancel_sync(null); }, _fadeInPrompt: function() { @@ -1107,7 +1090,7 @@ const LoginDialog = new Lang.Class({ let _text = this._promptEntry.get_text(); this._promptEntry.reactive = false; this._promptEntry.add_style_pseudo_class('insensitive'); - this._greeterClient.call_answer_query(serviceName, _text); + this._userVerifier.call_answer_query_sync(serviceName, _text, null); }]; let batch = new Batch.ConsecutiveBatch(this, tasks); @@ -1134,7 +1117,7 @@ const LoginDialog = new Lang.Class({ }, _onSessionOpened: function(client, serviceName) { - this._greeterClient.call_start_session_when_ready(serviceName, true); + this._greeter.call_start_session_when_ready_sync(serviceName, true, null); }, _waitForItemForUser: function(userName) { @@ -1216,7 +1199,7 @@ const LoginDialog = new Lang.Class({ function() { this._timedLoginBatch = null; - this._greeterClient.call_begin_auto_login(userName); + this._greeter.call_begin_auto_login_sync(userName, null); }]; this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks); @@ -1259,16 +1242,12 @@ const LoginDialog = new Lang.Class({ })); }, - _onAuthenticationFailed: function(client) { - this._greeterClient.call_cancel(); - }, - _onConversationStopped: function(client, serviceName) { // 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(); + this._userVerifier.call_cancel_sync(null); } else if (serviceName == _FINGERPRINT_SERVICE_NAME) { _fadeOutActor(this._promptFingerprintMessage); } @@ -1292,7 +1271,16 @@ const LoginDialog = new Lang.Class({ this._fadeOutLogo]), function() { - this._greeterClient.call_begin_verification(_PASSWORD_SERVICE_NAME); + let hold = new Batch.Hold(); + + this._userVerifier.call_begin_verification(_PASSWORD_SERVICE_NAME, + null, + Lang.bind(this, function (userVerifier, result) { + this._userVerifier.call_begin_verification_finish (result); + hold.release(); + })); + + return hold; }]; let batch = new Batch.ConsecutiveBatch(this, tasks); @@ -1331,7 +1319,101 @@ const LoginDialog = new Lang.Class({ return _fadeOutActor(this._notListedButton); }, + _getUserVerifier: function(userName) { + let hold = new Batch.Hold(); + + this._userVerifier = null; + + // If possible, reauthenticate an already running session, + // so any session specific credentials get updated appropriately + this._greeterClient.open_reauthentication_channel(userName, + null, + Lang.bind(this, function(client, result) { + try { + this._userVerifier = this._greeterClient.open_reauthentication_channel_finish(result); + hold.release(); + } catch (e) { + // If there's no session running, or it otherwise fails, then fall back + // to performing verification from this login session + this._greeterClient.get_user_verifier(null, + Lang.bind(this, function(client, result) { + this._userVerifier = this._greeterClient.get_user_verifier_finish(result); + hold.release(); + })); + } + })); + + hold.connect('release', Lang.bind(this, function() { + if (this._userVerifier) { + let ids = []; + let id; + + id = this._userVerifier.connect('info', + Lang.bind(this, this._onInfo)); + ids.push(id); + id = this._userVerifier.connect('problem', + Lang.bind(this, this._onProblem)); + ids.push(id); + id = this._userVerifier.connect('info-query', + Lang.bind(this, this._onInfoQuery)); + ids.push(id); + id = this._userVerifier.connect('secret-info-query', + Lang.bind(this, this._onSecretInfoQuery)); + ids.push(id); + id = this._userVerifier.connect('conversation-stopped', + Lang.bind(this, this._onConversationStopped)); + ids.push(id); + id = this._userVerifier.connect('reset', + Lang.bind(this, function() { + for (let i = 0; i < ids.length; i++) + this._userVerifier.disconnect(ids[i]); + + this._onReset(); + })); + ids.push(id); + } + })); + + return hold; + }, + + _beginVerificationForUser: function(userName) { + let tasks = [function() { + let hold = new Batch.Hold(); + this._userVerifier.call_begin_verification_for_user (_PASSWORD_SERVICE_NAME, + userName, null, + Lang.bind(this, function(userVerifier, result) { + this._userVerifier.call_begin_verification_for_user_finish (result); + hold.release(); + })); + return hold; + }, + + function() { + let hold = new Batch.Hold(); + if (this._haveFingerprintReader) { + this._userVerifier.call_begin_verification_for_user (_FINGERPRINT_SERVICE_NAME, + userName, null, + Lang.bind(this, function(userVerifier, result) { + this._userVerifier.call_begin_verification_for_user_finish (result); + hold.release(); + })); + } else { + hold.release(); + } + + return hold; + }]; + + let batch = new Batch.ConsecutiveBatch(this, [this._getUserVerifier(userName), + new Batch.ConcurrentBatch(this, tasks)]); + + return batch.run(); + }, + _onUserListActivated: function(activatedItem) { + let userName; + let tasks = [function() { this._userList.actor.reactive = false; return this._userList.pinInPlace(); @@ -1358,12 +1440,9 @@ const LoginDialog = new Lang.Class({ }, function() { - let userName = activatedItem.user.get_user_name(); - this._greeterClient.call_begin_verification_for_user(_PASSWORD_SERVICE_NAME, - userName); + userName = activatedItem.user.get_user_name(); - if (this._haveFingerprintReader) - this._greeterClient.call_begin_verification_for_user(_FINGERPRINT_SERVICE_NAME, userName); + return this._beginVerificationForUser(userName); }]; this._user = activatedItem.user; diff --git a/js/ui/userMenu.js b/js/ui/userMenu.js index f535923ae..16395d207 100644 --- a/js/ui/userMenu.js +++ b/js/ui/userMenu.js @@ -1,7 +1,7 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- const AccountsService = imports.gi.AccountsService; -const GdmGreeter = imports.gi.GdmGreeter; +const Gdm = imports.gi.Gdm; const Gio = imports.gi.Gio; const GLib = imports.gi.GLib; const Lang = imports.lang; @@ -562,7 +562,7 @@ const UserMenuButton = new Lang.Class({ _updateSwitchUser: function() { let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY); let multiUser = this._userManager.can_switch() && this._userManager.has_multiple_users; - let multiSession = GdmGreeter.get_session_ids().length > 1; + let multiSession = Gdm.get_session_ids().length > 1; this._loginScreenItem.label.set_text(multiUser ? _("Switch User") : _("Switch Session")); @@ -572,7 +572,7 @@ const UserMenuButton = new Lang.Class({ _updateLogout: function() { let allowLogout = !this._lockdownSettings.get_boolean(DISABLE_LOG_OUT_KEY); let multiUser = this._userManager.has_multiple_users; - let multiSession = GdmGreeter.get_session_ids().length > 1; + let multiSession = Gdm.get_session_ids().length > 1; this._logoutItem.actor.visible = allowLogout && (multiUser || multiSession); },