392 lines
11 KiB
JavaScript
392 lines
11 KiB
JavaScript
// -*- 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 = <interface name='org.freedesktop.login1.Manager'>
|
|
<method name='PowerOff'>
|
|
<arg type='b' direction='in'/>
|
|
</method>
|
|
<method name='Reboot'>
|
|
<arg type='b' direction='in'/>
|
|
</method>
|
|
<method name='Suspend'>
|
|
<arg type='b' direction='in'/>
|
|
</method>
|
|
<method name='CanPowerOff'>
|
|
<arg type='s' direction='out'/>
|
|
</method>
|
|
<method name='CanReboot'>
|
|
<arg type='s' direction='out'/>
|
|
</method>
|
|
<method name='CanSuspend'>
|
|
<arg type='s' direction='out'/>
|
|
</method>
|
|
</interface>;
|
|
|
|
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
|
|
<signal name='Lock' />
|
|
<signal name='Unlock' />
|
|
</interface>;
|
|
|
|
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 = <interface name='org.freedesktop.ConsoleKit.Manager'>
|
|
<method name='CanRestart'>
|
|
<arg type='b' direction='out'/>
|
|
</method>
|
|
<method name='CanStop'>
|
|
<arg type='b' direction='out'/>
|
|
</method>
|
|
<method name='Restart' />
|
|
<method name='Stop' />
|
|
<method name='GetCurrentSession'>
|
|
<arg type='o' direction='out' />
|
|
</method>
|
|
</interface>;
|
|
|
|
const ConsoleKitSessionIface = <interface name='org.freedesktop.ConsoleKit.Session'>
|
|
<method name='IsActive'>
|
|
<arg type='b' direction='out' />
|
|
</method>
|
|
<signal name='ActiveChanged'>
|
|
<arg type='b' direction='out' />
|
|
</signal>
|
|
<signal name='Lock' />
|
|
<signal name='Unlock' />
|
|
</interface>;
|
|
|
|
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);
|
|
}
|
|
});
|