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 <gcampagna@src.gnome.org>

https://bugzilla.gnome.org/show_bug.cgi?id=676401
This commit is contained in:
Ray Strode 2012-05-20 01:19:25 +02:00
parent 2791d948e9
commit e06ecb8f0c
2 changed files with 131 additions and 52 deletions

View File

@ -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._greeterClient.connect('reset',
Lang.bind(this, this._onReset));
this._greeterClient.connect('default-session-changed',
this._greeter.connect('default-session-name-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',
this._greeter.connect('session-opened',
Lang.bind(this, this._onSessionOpened));
this._greeterClient.connect('timed-login-requested',
this._greeter.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._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;

View File

@ -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);
},