loginManager: Make API promise-based

The LoginManager abstraction is still mostly callback-based, not
least because the methods are thin wrappers around logind D-Bus
calls.

However as gjs' dbus wrapper now generates promised-based wrappers
as well, we can implement a proper async API just as naturally.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2344>
This commit is contained in:
Florian Müllner 2022-06-23 15:45:44 +02:00 committed by Marge Bot
parent db3916434e
commit a3db909383
5 changed files with 127 additions and 126 deletions

View File

@ -529,7 +529,7 @@ var LoginDialog = GObject.registerClass({
this._realmManager.connectObject('login-format-changed', this._realmManager.connectObject('login-format-changed',
this._showRealmLoginHint.bind(this), this); this._showRealmLoginHint.bind(this), this);
LoginManager.getLoginManager().getCurrentSessionProxy(this._gotGreeterSessionProxy.bind(this)); this._getGreeterSessionProxy();
// If the user list is enabled, it should take key focus; make sure the // 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 // screen shield is initialized first to prevent it from stealing the
@ -982,10 +982,11 @@ var LoginDialog = GObject.registerClass({
}); });
} }
_gotGreeterSessionProxy(proxy) { async _getGreeterSessionProxy() {
this._greeterSessionProxy = proxy; const loginManager = LoginManager.getLoginManager();
proxy.connectObject('g-properties-changed', () => { this._greeterSessionProxy = await loginManager.getCurrentSessionProxy();
if (proxy.Active) this._greeterSessionProxy?.connectObject('g-properties-changed', () => {
if (this._greeterSessionProxy.Active)
this._loginScreenSessionActivated(); this._loginScreenSessionActivated();
}, this); }, this);
} }

View File

@ -101,11 +101,9 @@ var LoginManagerSystemd = class extends Signals.EventEmitter {
this._prepareForSleep.bind(this)); this._prepareForSleep.bind(this));
} }
getCurrentSessionProxy(callback) { async getCurrentSessionProxy() {
if (this._currentSession) { if (this._currentSession)
callback(this._currentSession); return this._currentSession;
return;
}
let sessionId = GLib.getenv('XDG_SESSION_ID'); let sessionId = GLib.getenv('XDG_SESSION_ID');
if (!sessionId) { if (!sessionId) {
@ -131,63 +129,60 @@ var LoginManagerSystemd = class extends Signals.EventEmitter {
if (!sessionId) { if (!sessionId) {
log('No, failed to get session from logind.'); log('No, failed to get session from logind.');
return; return null;
} }
} }
} }
this._proxy.GetSessionRemote(sessionId, (result, error) => { try {
if (error) { const [objectPath] = await this._proxy.GetSessionAsync(sessionId);
logError(error, 'Could not get a proxy for the current session');
} else {
this._currentSession = new SystemdLoginSession(Gio.DBus.system, this._currentSession = new SystemdLoginSession(Gio.DBus.system,
'org.freedesktop.login1', 'org.freedesktop.login1', objectPath);
result[0]); return this._currentSession;
callback(this._currentSession); } catch (error) {
logError(error, 'Could not get a proxy for the current session');
return null;
} }
});
} }
canSuspend(asyncCallback) { async canSuspend() {
this._proxy.CanSuspendRemote((result, error) => { try {
if (error) { const [result] = await this._proxy.CanSuspendAsync();
asyncCallback(false, false); const needsAuth = result === 'challenge';
} else { const canSuspend = needsAuth || result === 'yes';
let needsAuth = result[0] == 'challenge'; return [canSuspend, needsAuth];
let canSuspend = needsAuth || result[0] == 'yes'; } catch (error) {
asyncCallback(canSuspend, needsAuth); return [false, false];
} }
});
} }
canRebootToBootLoaderMenu(asyncCallback) { async canRebootToBootLoaderMenu() {
this._proxy.CanRebootToBootLoaderMenuRemote((result, error) => { try {
if (error) { const [result] = await this._proxy.CanRebootToBootLoaderMenuAsync();
asyncCallback(false, false);
} else {
const needsAuth = result[0] === 'challenge'; const needsAuth = result[0] === 'challenge';
const canRebootToBootLoaderMenu = needsAuth || result[0] === 'yes'; const canRebootToBootLoaderMenu = needsAuth || result[0] === 'yes';
asyncCallback(canRebootToBootLoaderMenu, needsAuth); return [canRebootToBootLoaderMenu, needsAuth];
} catch (error) {
return [false, false];
} }
});
} }
setRebootToBootLoaderMenu() { setRebootToBootLoaderMenu() {
/* Parameter is timeout in usec, show to menu for 60 seconds */ /* Parameter is timeout in usec, show to menu for 60 seconds */
this._proxy.SetRebootToBootLoaderMenuRemote(60000000); this._proxy.SetRebootToBootLoaderMenuAsync(60000000);
} }
listSessions(asyncCallback) { async listSessions() {
this._proxy.ListSessionsRemote((result, error) => { try {
if (error) const [sessions] = await this._proxy.ListSessionsAsync();
asyncCallback([]); return sessions;
else } catch (e) {
asyncCallback(result[0]); return [];
}); }
} }
suspend() { suspend() {
this._proxy.SuspendRemote(true); this._proxy.SuspendAsync(true);
} }
async inhibit(reason, cancellable) { async inhibit(reason, cancellable) {
@ -206,25 +201,26 @@ var LoginManagerSystemd = class extends Signals.EventEmitter {
}; };
var LoginManagerDummy = class extends Signals.EventEmitter { var LoginManagerDummy = class extends Signals.EventEmitter {
getCurrentSessionProxy(_callback) { getCurrentSessionProxy() {
// we could return a DummySession object that fakes whatever callers // we could return a DummySession object that fakes whatever callers
// expect (at the time of writing: connect() and connectSignal() // expect (at the time of writing: connect() and connectSignal()
// methods), but just never calling the callback should be safer // methods), but just never settling the promise should be safer
return new Promise(() => {});
} }
canSuspend(asyncCallback) { canSuspend() {
asyncCallback(false, false); return new Promise(resolve => resolve([false, false]));
} }
canRebootToBootLoaderMenu(asyncCallback) { canRebootToBootLoaderMenu() {
asyncCallback(false, false); return new Promise(resolve => resolve([false, false]));
} }
setRebootToBootLoaderMenu() { setRebootToBootLoaderMenu() {
} }
listSessions(asyncCallback) { listSessions() {
asyncCallback([]); return new Promise(resolve => resolve([]));
} }
suspend() { suspend() {

View File

@ -347,13 +347,11 @@ const SystemActions = GObject.registerClass({
this.notify('can-restart'); this.notify('can-restart');
} }
_updateHaveSuspend() { async _updateHaveSuspend() {
this._loginManager.canSuspend( const [canSuspend, needsAuth] = await this._loginManager.canSuspend();
(canSuspend, needsAuth) => {
this._canHaveSuspend = canSuspend; this._canHaveSuspend = canSuspend;
this._suspendNeedsAuth = needsAuth; this._suspendNeedsAuth = needsAuth;
this._updateSuspend(); this._updateSuspend();
});
} }
_updateSuspend() { _updateSuspend() {

View File

@ -234,10 +234,8 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}); });
this._loginManager = LoginManager.getLoginManager(); this._loginManager = LoginManager.getLoginManager();
this._loginManager.canRebootToBootLoaderMenu( this._canRebootToBootLoaderMenu = false;
(canRebootToBootLoaderMenu, unusedNeedsAuth) => { this._getCanRebootToBootLoaderMenu();
this._canRebootToBootLoaderMenu = canRebootToBootLoaderMenu;
});
this._userManager = AccountsService.UserManager.get_default(); this._userManager = AccountsService.UserManager.get_default();
this._user = this._userManager.get_user(GLib.get_user_name()); this._user = this._userManager.get_user(GLib.get_user_name());
@ -306,6 +304,11 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog'); this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
} }
async _getCanRebootToBootLoaderMenu() {
const [canRebootToBootLoaderMenu] = await this._loginManager.canRebootToBootLoaderMenu();
this._canRebootToBootLoaderMenu = canRebootToBootLoaderMenu;
}
async _onPkOfflineProxyCreated(proxy, error) { async _onPkOfflineProxyCreated(proxy, error) {
if (error) { if (error) {
log(error.message); log(error.message);
@ -645,27 +648,25 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._sync(); this._sync();
} }
_loadSessions() { async _loadSessions() {
this._loginManager.listSessions(result => {
for (let i = 0; i < result.length; i++) {
let [id_, uid_, userName, seat_, sessionPath] = result[i];
let proxy = new LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath);
if (proxy.Class != 'user')
continue;
if (proxy.State == 'closing')
continue;
let sessionId = GLib.getenv('XDG_SESSION_ID'); let sessionId = GLib.getenv('XDG_SESSION_ID');
if (!sessionId) { if (!sessionId) {
this._loginManager.getCurrentSessionProxy(currentSessionProxy => { const currentSessionProxy = await this._loginManager.getCurrentSessionProxy();
sessionId = currentSessionProxy.Id; sessionId = currentSessionProxy.Id;
log(`endSessionDialog: No XDG_SESSION_ID, fetched from logind: ${sessionId}`); log(`endSessionDialog: No XDG_SESSION_ID, fetched from logind: ${sessionId}`);
});
} }
if (proxy.Id == sessionId) const sessions = await this._loginManager.listSessions();
for (const [id_, uid_, userName, seat_, sessionPath] of sessions) {
let proxy = new LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath);
if (proxy.Class !== 'user')
continue;
if (proxy.State === 'closing')
continue;
if (proxy.Id === sessionId)
continue; continue;
const session = { const session = {
@ -676,18 +677,21 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}; };
const nSessions = this._sessions.push(session); const nSessions = this._sessions.push(session);
let userAvatar = new UserWidget.Avatar(session.user, { iconSize: _ITEM_ICON_SIZE }); let userAvatar = new UserWidget.Avatar(session.user, {
iconSize: _ITEM_ICON_SIZE,
});
userAvatar.update(); userAvatar.update();
userName = session.user.get_real_name() ?? session.username; const displayUserName =
session.user.get_real_name() ?? session.username;
let userLabelText; let userLabelText;
if (session.remote) if (session.remote)
/* Translators: Remote here refers to a remote session, like a ssh login */ /* Translators: Remote here refers to a remote session, like a ssh login */
userLabelText = _('%s (remote)').format(userName); userLabelText = _('%s (remote)').format(displayUserName);
else if (session.type === 'tty') else if (session.type === 'tty')
/* Translators: Console here refers to a tty like a VT console */ /* Translators: Console here refers to a tty like a VT console */
userLabelText = _('%s (console)').format(userName); userLabelText = _('%s (console)').format(displayUserName);
else else
userLabelText = userName; userLabelText = userName;
@ -703,7 +707,6 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
} }
this._sync(); this._sync();
});
} }
async _getUpdateInfo() { async _getUpdateInfo() {

View File

@ -106,15 +106,7 @@ var ScreenShield = class extends Signals.EventEmitter {
this._prepareForSleep.bind(this)); this._prepareForSleep.bind(this));
this._loginSession = null; this._loginSession = null;
this._loginManager.getCurrentSessionProxy(sessionProxy => { this._getLoginSession();
this._loginSession = sessionProxy;
this._loginSession.connectSignal('Lock',
() => this.lock(false));
this._loginSession.connectSignal('Unlock',
() => this.deactivate(false));
this._loginSession.connect('g-properties-changed', this._syncInhibitor.bind(this));
this._syncInhibitor();
});
this._settings = new Gio.Settings({ schema_id: SCREENSAVER_SCHEMA }); this._settings = new Gio.Settings({ schema_id: SCREENSAVER_SCHEMA });
this._settings.connect(`changed::${LOCK_ENABLED_KEY}`, this._syncInhibitor.bind(this)); this._settings.connect(`changed::${LOCK_ENABLED_KEY}`, this._syncInhibitor.bind(this));
@ -152,6 +144,17 @@ var ScreenShield = class extends Signals.EventEmitter {
this._syncInhibitor(); this._syncInhibitor();
} }
async _getLoginSession() {
this._loginSession = await this._loginManager.getCurrentSessionProxy();
this._loginSession.connectSignal('Lock',
() => this.lock(false));
this._loginSession.connectSignal('Unlock',
() => this.deactivate(false));
this._loginSession.connect('g-properties-changed',
() => this._syncInhibitor());
this._syncInhibitor();
}
_setActive(active) { _setActive(active) {
let prevIsActive = this._isActive; let prevIsActive = this._isActive;
this._isActive = active; this._isActive = active;