// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- const GLib = imports.gi.GLib; const Gio = imports.gi.Gio; const GObject = imports.gi.GObject; const Lang = imports.lang; const Mainloop = imports.mainloop; const Shell = imports.gi.Shell; const UPowerGlib = imports.gi.UPowerGlib; const SystemdLoginManagerIface = ; const SystemdLoginSessionIface = ; const SystemdLoginManager = new Gio.DBusProxyClass({ Name: 'SystemdLoginManager', Interface: SystemdLoginManagerIface, _init: function() { this.parent({ g_bus_type: Gio.BusType.SYSTEM, g_name: 'org.freedesktop.login1', g_object_path: '/org/freedesktop/login1' }); } }); const SystemdLoginSession = new Gio.DBusProxyClass({ Name: 'SystemdLoginSession', Interface: SystemdLoginSessionIface, _init: function(session) { this.parent({ g_bus_type: Gio.BusType.SYSTEM, g_name: 'org.freedesktop.login1', g_object_path: session }); } }); const ConsoleKitManagerIface = ; const ConsoleKitSessionIface = ; const ConsoleKitSession = new Gio.DBusProxyClass({ Name: 'ConsoleKitSession', Interface: ConsoleKitSessionIface, _init: function(session) { this.parent({ g_bus_type: Gio.BusType.SYSTEM, g_name: 'org.freedesktop.ConsoleKit', g_object_path: session }); } }); const ConsoleKitManager = new Gio.DBusProxyClass({ Name: 'ConsoleKitManager', Interface: ConsoleKitManagerIface, _init: function() { this.parent({ g_bus_type: Gio.BusType.SYSTEM, g_name: 'org.freedesktop.ConsoleKit', g_object_path: '/org/freedesktop/ConsoleKit/Manager' }); } }); function haveSystemd() { return GLib.access("/sys/fs/cgroup/systemd", 0) >= 0; } let _loginManager = null; let _pendingAsyncCallbacks = []; /** * LoginManager: * An abstraction over systemd/logind and ConsoleKit. * */ function getLoginManager(asyncCallback) { if (_loginManager == null) { if (_pendingAsyncCallbacks.length == 0) { let manager; if (haveSystemd()) manager = new LoginManagerSystemd(); else manager = new LoginManagerConsoleKit(); manager.initAsync(null, function(obj, result) { obj.initFinish(result); _loginManager = manager; _pendingAsyncCallbacks.forEach(function (f) { f(obj) }); _pendingAsyncCallbacks = []; }); _pendingAsyncCallbacks = [asyncCallback]; } else { _pendingAsyncCallbacks.push(asyncCallback); } } else { GLib.idle_add(GLib.PRIORITY_DEFAULT, function() { asyncCallback(_loginManager); }); } } const LoginManagerSystemd = new Lang.Class({ Name: 'LoginManagerSystemd', Extends: GObject.Object, _init: function() { this.parent(); this._proxy = new SystemdLoginManager(); }, initAsync: function(cancellable, asyncCallback) { let simpleResult = Gio.SimpleAsyncResult.new(this, asyncCallback, null); simpleResult.set_check_cancellable(cancellable); this._proxy.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) { try { proxy.init_finish(result); if (cancellable && cancellable.is_cancelled()) return; this._fetchCurrentSession(cancellable, simpleResult); } catch(e if e instanceof GLib.Error) { simpleResult.set_from_error(e); simpleResult.complete(); } })); }, initFinish: function(simpleResult) { if (!simpleResult.propagate_error()) return simpleResult.get_op_res_gboolean(); return true; }, _fetchCurrentSession: function(cancellable, simpleResult) { this._currentSession = new SystemdLoginSession('/org/freedesktop/login1/session/' + GLib.getenv('XDG_SESSION_ID')); this._currentSession.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) { try { proxy.init_finish(result); simpleResult.set_op_res_gboolean(true); } catch(e if e instanceof GLib.Error) { simpleResult.set_from_error(e); } simpleResult.complete(); })); }, // Having this function is a bit of a hack since the Systemd and ConsoleKit // session objects have different interfaces - but in both cases there are // Lock/Unlock signals, and that's all we count upon at the moment. // // This is only valid after async initialization getCurrentSessionProxy: function() { return this._currentSession; }, get sessionActive() { return Shell.session_is_active_for_systemd(); }, canPowerOff: function(asyncCallback) { this._proxy.CanPowerOffRemote(null, function(proxy, result) { let val = false; try { val = proxy.CanPowerOffFinish(result)[0] != 'no'; } catch(e) { } asyncCallback(val); }); }, canReboot: function(asyncCallback) { this._proxy.CanRebootRemote(null, function(proxy, result) { let val = false; try { val = proxy.CanRebootFinish(result)[0] != 'no'; } catch(e) { } asyncCallback(val); }); }, canSuspend: function(asyncCallback) { this._proxy.CanSuspendRemote(null, function(proxy, result) { let val = false; try { val = proxy.CanRebootFinish(result)[0] != 'no'; } catch(e) { } asyncCallback(val); }); }, powerOff: function() { this._proxy.PowerOffRemote(true, null, null); }, reboot: function() { this._proxy.RebootRemote(true, null, null); }, suspend: function() { this._proxy.SuspendRemote(true, null, null); } }); const LoginManagerConsoleKit = new Lang.Class({ Name: 'LoginManagerConsoleKit', Extends: GObject.Object, _init: function() { this.parent(); this._proxy = new ConsoleKitManager(); this._upClient = new UPowerGlib.Client(); }, initAsync: function(cancellable, asyncCallback) { let simpleResult = Gio.SimpleAsyncResult.new(this, asyncCallback, null); simpleResult.set_check_cancellable(cancellable); this._proxy.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) { try { proxy.init_finish(result); if (cancellable && cancellable.is_cancelled()) return; this._fetchCurrentSession(cancellable, simpleResult); } catch(e if e instanceof GLib.Error) { simpleResult.set_from_error(e); simpleResult.complete(); } })); }, initFinish: function(simpleResult) { if (!simpleResult.propagate_error()) return simpleResult.get_op_res_gboolean(); return true; }, _fetchCurrentSession: function(cancellable, simpleResult) { this._proxy.GetCurrentSessionRemote(cancellable, Lang.bind(this, function(proxy, result) { try { let [currentSessionId] = proxy.GetCurrentSessionFinish(result); if (cancellable && cancellable.is_cancelled()) return; this._createSessionProxy(currentSessionId, cancellable, simpleResult); } catch(e if e instanceof GLib.Error) { simpleResult.set_from_error(e); simpleResult.complete(); } })); }, _createSessionProxy: function(currentSessionId, cancellable, simpleResult) { this._currentSession = new ConsoleKitSession(currentSessionId); this._currentSession.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) { try { proxy.init_finish(result); simpleResult.set_op_res_gboolean(true); } catch(e if e instanceof GLib.Error) { simpleResult.set_from_error(e); } simpleResult.complete(); })); }, // Having this function is a bit of a hack since the Systemd and ConsoleKit // session objects have different interfaces - but in both cases there are // Lock/Unlock signals, and that's all we count upon at the moment. getCurrentSessionProxy: function() { return this._currentSession; }, get sessionActive() { if (this._sessionActive !== undefined) return this._sessionActive; let session = this.getCurrentSessionProxy(); session.connectSignal('ActiveChanged', Lang.bind(this, function(object, senderName, [isActive]) { this._sessionActive = isActive; })); [this._sessionActive] = session.IsActiveSync(null); return this._sessionActive; }, canPowerOff: function(asyncCallback) { this._proxy.CanStopRemote(null, function(proxy, result) { let val = false; try { [val] = proxy.CanStopFinish(result); } catch(e) { } asyncCallback(val); }); }, canReboot: function(asyncCallback) { this._proxy.CanRestartRemote(null, function(proxy, result) { let val = false; try { [val] = proxy.CanRestartFinish(result); } catch(e) { } asyncCallback(val); }); }, canSuspend: function(asyncCallback) { Mainloop.idle_add(Lang.bind(this, function() { asyncCallback(this._upClient.get_can_suspend()); return false; })); }, powerOff: function() { this._proxy.StopRemote(null, null); }, reboot: function() { this._proxy.RestartRemote(null, null); }, suspend: function() { this._upClient.suspend_sync(null); } });