js: Promisify async operations

Promises make asynchronous operations easier to manage, in particular
when used through the async/await syntax that allows for asynchronous
code to closely resemble synchronous one.

gjs has included a Gio._promisify() helper for a while now, which
monkey-patches methods that follow GIO's async pattern to return a
Promise when called without a callback argument.

Use that to get rid of all those GAsyncReadyCallbacks!

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1126
This commit is contained in:
Florian Müllner 2019-12-19 20:50:37 +01:00 committed by Florian Müllner
parent 18742fcc32
commit 764527c8c9
20 changed files with 409 additions and 428 deletions

View File

@ -2,7 +2,7 @@
/* exported BANNER_MESSAGE_KEY, BANNER_MESSAGE_TEXT_KEY, LOGO_KEY,
DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor */
const { Clutter, Gio, GLib } = imports.gi;
const { Clutter, Gdm, Gio, GLib } = imports.gi;
const Signals = imports.signals;
const Batch = imports.gdm.batch;
@ -12,6 +12,15 @@ const Main = imports.ui.main;
const Params = imports.misc.params;
const SmartcardManager = imports.misc.smartcardManager;
Gio._promisify(Gdm.Client.prototype,
'open_reauthentication_channel', 'open_reauthentication_channel_finish');
Gio._promisify(Gdm.Client.prototype,
'get_user_verifier', 'get_user_verifier_finish');
Gio._promisify(Gdm.UserVerifierProxy.prototype,
'call_begin_verification_for_user', 'call_begin_verification_for_user_finish');
Gio._promisify(Gdm.UserVerifierProxy.prototype,
'call_begin_verification', 'call_begin_verification_finish');
var PASSWORD_SERVICE_NAME = 'gdm-password';
var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
var SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
@ -168,14 +177,12 @@ var ShellUserVerifier = class {
this._checkForFingerprintReader();
if (userName) {
// If possible, reauthenticate an already running session,
// so any session specific credentials get updated appropriately
this._client.open_reauthentication_channel(userName, this._cancellable,
this._reauthenticationChannelOpened.bind(this));
} else {
this._client.get_user_verifier(this._cancellable, this._userVerifierGot.bind(this));
}
if (userName)
this._openReauthenticationChannel(userName);
else
this._getUserVerifier();
}
cancel() {
@ -339,10 +346,11 @@ var ShellUserVerifier = class {
this._verificationFailed(false);
}
_reauthenticationChannelOpened(client, result) {
async _openReauthenticationChannel(userName) {
try {
this._clearUserVerifier();
this._userVerifier = client.open_reauthentication_channel_finish(result);
this._userVerifier = await this._client.open_reauthentication_channel(
userName, this._cancellable);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
@ -351,8 +359,7 @@ var ShellUserVerifier = class {
// Gdm emits org.freedesktop.DBus.Error.AccessDenied when there
// is no session to reauthenticate. Fall back to performing
// verification from this login session
client.get_user_verifier(this._cancellable,
this._userVerifierGot.bind(this));
this._getUserVerifier();
return;
}
@ -366,10 +373,11 @@ var ShellUserVerifier = class {
this._hold.release();
}
_userVerifierGot(client, result) {
async _getUserVerifier() {
try {
this._clearUserVerifier();
this._userVerifier = client.get_user_verifier_finish(result);
this._userVerifier =
await this._client.get_user_verifier(this._cancellable);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
@ -421,35 +429,25 @@ var ShellUserVerifier = class {
}
}
_startService(serviceName) {
async _startService(serviceName) {
this._hold.acquire();
try {
if (this._userName) {
this._userVerifier.call_begin_verification_for_user(serviceName, this._userName, this._cancellable, (obj, result) => {
try {
obj.call_begin_verification_for_user_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification for user', e);
return;
}
this._hold.release();
});
await this._userVerifier.call_begin_verification_for_user(
serviceName, this._userName, this._cancellable);
} else {
this._userVerifier.call_begin_verification(serviceName, this._cancellable, (obj, result) => {
try {
obj.call_begin_verification_finish(result);
await this._userVerifier.call_begin_verification(
serviceName, this._cancellable);
}
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification', e);
this._reportInitError(this._userName
? 'Failed to start verification for user'
: 'Failed to start verification', e);
return;
}
this._hold.release();
});
}
}
_beginVerification() {

View File

@ -6,6 +6,15 @@ const Signals = imports.signals;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
Gio._promisify(IBus.Bus.prototype,
'list_engines_async', 'list_engines_async_finish');
Gio._promisify(IBus.Bus.prototype,
'request_name_async', 'request_name_async_finish');
Gio._promisify(IBus.Bus.prototype,
'get_global_engine_async', 'get_global_engine_async_finish');
Gio._promisify(IBus.Bus.prototype,
'set_global_engine_async', 'set_global_engine_async_finish');
// Ensure runtime version matches
_checkIBusVersion(1, 5, 2);
@ -102,16 +111,14 @@ var IBusManager = class {
_onConnected() {
this._cancellable = new Gio.Cancellable();
this._ibus.list_engines_async(-1, this._cancellable,
this._initEngines.bind(this));
this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable,
this._initPanelService.bind(this));
this._initEngines();
this._initPanelService();
}
_initEngines(ibus, result) {
async _initEngines() {
try {
let enginesList = this._ibus.list_engines_async_finish(result);
const enginesList =
await this._ibus.list_engines_async(-1, this._cancellable);
for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name();
this._engines.set(name, enginesList[i]);
@ -126,9 +133,10 @@ var IBusManager = class {
}
}
_initPanelService(ibus, result) {
async _initPanelService() {
try {
this._ibus.request_name_async_finish(result);
await this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);
@ -163,19 +171,15 @@ var IBusManager = class {
this._panelService.connect('set-content-type', this._setContentType.bind(this));
} catch (e) {
}
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, res) => {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(res);
if (!engine)
return;
} catch (e) {
return;
}
// If an engine is already active we need to get its properties
const engine =
await this._ibus.get_global_engine_async(-1, this._cancellable);
this._engineChanged(this._ibus, engine.get_name());
});
this._updateReadiness();
} catch (e) {
}
}
_updateReadiness() {
@ -223,7 +227,7 @@ var IBusManager = class {
return this._engines.get(id);
}
setEngine(id, callback) {
async setEngine(id, callback) {
// Send id even if id == this._currentEngineName
// because 'properties-registered' signal can be emitted
// while this._ibusSources == null on a lock screen.
@ -233,18 +237,16 @@ var IBusManager = class {
return;
}
this._ibus.set_global_engine_async(id,
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
this._cancellable, (_bus, res) => {
try {
this._ibus.set_global_engine_async_finish(res);
await this._ibus.set_global_engine_async(id,
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
this._cancellable);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e);
}
if (callback)
callback();
});
}
preloadEngines(ids) {

View File

@ -4,6 +4,9 @@ const { Clutter, GLib, Gio, GObject, IBus } = imports.gi;
const Keyboard = imports.ui.status.keyboard;
Gio._promisify(IBus.Bus.prototype,
'create_input_context_async', 'create_input_context_async_finish');
var HIDE_PANEL_TIME = 50;
var InputMethod = GObject.registerClass(
@ -46,15 +49,11 @@ class InputMethod extends Clutter.InputMethod {
this._currentSource = this._inputSourceManager.currentSource;
}
_onConnected() {
async _onConnected() {
this._cancellable = new Gio.Cancellable();
this._ibus.create_input_context_async('gnome-shell', -1,
this._cancellable, this._setContext.bind(this));
}
_setContext(bus, res) {
try {
this._context = this._ibus.create_input_context_async_finish(res);
this._context = await this._ibus.create_input_context_async(
'gnome-shell', -1, this._cancellable);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);

View File

@ -50,25 +50,22 @@ function canLock() {
}
function registerSessionWithGDM() {
async function registerSessionWithGDM() {
log("Registering session with GDM");
Gio.DBus.system.call('org.gnome.DisplayManager',
try {
await Gio.DBus.system.call(
'org.gnome.DisplayManager',
'/org/gnome/DisplayManager/Manager',
'org.gnome.DisplayManager.Manager',
'RegisterSession',
GLib.Variant.new('(a{sv})', [{}]), null,
Gio.DBusCallFlags.NONE, -1, null,
(source, result) => {
try {
source.call_finish(result);
Gio.DBusCallFlags.NONE, -1, null);
} catch (e) {
if (!e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD))
log(`Error registering session with GDM: ${e.message}`);
else
log("Not calling RegisterSession(): method not exported, GDM too old?");
log('Not calling RegisterSession(): method not exported, GDM too old?');
}
}
);
}
let _loginManager = null;
@ -174,24 +171,19 @@ var LoginManagerSystemd = class {
this._proxy.SuspendRemote(true);
}
inhibit(reason, callback) {
let inVariant = GLib.Variant.new('(ssss)',
['sleep',
'GNOME Shell',
reason,
'delay']);
this._proxy.call_with_unix_fd_list('Inhibit', inVariant, 0, -1, null, null,
(proxy, result) => {
let fd = -1;
async inhibit(reason, callback) {
try {
let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0];
const inVariant = new GLib.Variant('(ssss)',
['sleep', 'GNOME Shell', reason, 'delay']);
const [outVariant_, fdList] =
await this._proxy.call_with_unix_fd_list('Inhibit',
inVariant, 0, -1, null, null);
const [fd] = fdList.steal_fds();
callback(new Gio.UnixInputStream({ fd }));
} catch (e) {
logError(e, "Error getting systemd inhibitor");
logError(e, 'Error getting systemd inhibitor');
callback(null);
}
});
}
_prepareForSleep(proxy, sender, [aboutToSuspend]) {

View File

@ -57,9 +57,7 @@ var ObjectManager = class {
// Start out inhibiting load until at least the proxy
// manager is loaded and the remote objects are fetched
this._numLoadInhibitors = 1;
this._managerProxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
this._onManagerProxyLoaded.bind(this));
this._initManagerProxy();
}
_tryToCompleteLoad() {
@ -73,7 +71,7 @@ var ObjectManager = class {
}
}
_addInterface(objectPath, interfaceName, onFinished) {
async _addInterface(objectPath, interfaceName, onFinished) {
let info = this._interfaceInfos[interfaceName];
if (!info) {
@ -89,9 +87,8 @@ var ObjectManager = class {
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable, (initable, result) => {
try {
initable.init_finish(result);
await proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable);
} catch (e) {
logError(e, `could not initialize proxy for interface ${interfaceName}`);
@ -122,7 +119,6 @@ var ObjectManager = class {
if (onFinished)
onFinished();
});
}
_removeInterface(objectPath, interfaceName) {
@ -151,9 +147,10 @@ var ObjectManager = class {
}
}
_onManagerProxyLoaded(initable, result) {
async _initManagerProxy() {
try {
initable.init_finish(result);
await this._managerProxy.init_async(
GLib.PRIORITY_DEFAULT, this._cancellable);
} catch (e) {
logError(e, `could not initialize object manager for object ${this._serviceName}`);

View File

@ -7,6 +7,8 @@ const PermissionStore = imports.misc.permissionStore;
const { loadInterfaceXML } = imports.misc.fileUtils;
Gio._promisify(Geoclue.Simple, 'new', 'new_finish');
const WeatherIntegrationIface = loadInterfaceXML('org.gnome.Shell.WeatherIntegration');
const WEATHER_BUS_NAME = 'org.gnome.Weather';
@ -79,16 +81,7 @@ var WeatherClient = class {
this._weatherApp = null;
this._weatherProxy = null;
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
Gio.DBusProxy.new(
Gio.DBus.session,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
WEATHER_BUS_NAME,
WEATHER_OBJECT_PATH,
WEATHER_INTEGRATION_IFACE,
null,
this._onWeatherProxyReady.bind(this));
this._createWeatherProxy();
this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.weather',
@ -146,9 +139,17 @@ var WeatherClient = class {
(!this._needsAuth || this._weatherAuthorized);
}
_onWeatherProxyReady(o, res) {
async _createWeatherProxy() {
const nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
try {
this._weatherProxy = Gio.DBusProxy.new_finish(res);
this._weatherProxy = await Gio.DBusProxy.new(
Gio.DBus.session,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
WEATHER_BUS_NAME,
WEATHER_OBJECT_PATH,
WEATHER_INTEGRATION_IFACE,
null);
} catch (e) {
log(`Failed to create GNOME Weather proxy: ${e}`);
return;
@ -239,16 +240,15 @@ var WeatherClient = class {
}
}
_startGClueService() {
async _startGClueService() {
if (this._gclueStarting)
return;
this._gclueStarting = true;
Geoclue.Simple.new('org.gnome.Shell', Geoclue.AccuracyLevel.CITY, null,
(o, res) => {
try {
this._gclueService = Geoclue.Simple.new_finish(res);
this._gclueService = await Geoclue.Simple.new(
'org.gnome.Shell', Geoclue.AccuracyLevel.CITY, null);
} catch (e) {
log(`Failed to connect to Geoclue2 service: ${e.message}`);
this._setLocation(this._mostRecentLocation);
@ -257,7 +257,6 @@ var WeatherClient = class {
this._gclueStarted = true;
this._gclueService.get_client().distance_threshold = 100;
this._updateLocationMonitoring();
});
}
_onGClueLocationChanged() {

View File

@ -2546,20 +2546,19 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) {
this._appendSeparator();
let item = this._appendMenuItem(_("Show Details"));
item.connect('activate', () => {
item.connect('activate', async () => {
let id = this._source.app.get_id();
let args = GLib.Variant.new('(ss)', [id, '']);
Gio.DBus.get(Gio.BusType.SESSION, null, (o, res) => {
let bus = Gio.DBus.get_finish(res);
bus.call('org.gnome.Software',
const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
bus.call(
'org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
new GLib.Variant.new(
'(sava{sv})', ['details', [args], null]),
null, 0, -1, null, null);
Main.overview.hide();
});
});
}
}
}

View File

@ -199,14 +199,16 @@ class DBusEventSource extends EventSourceBase {
this._initialized = false;
this._dbusProxy = new CalendarServer();
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, (object, result) => {
this._initProxy();
}
async _initProxy() {
let loaded = false;
try {
this._dbusProxy.init_finish(result);
await this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null);
loaded = true;
} catch (e) {
if (e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
// Ignore timeouts and install signals as normal, because with high
// probability the service will appear later on, and we will get a
// NameOwnerChanged which will finish loading
@ -214,7 +216,7 @@ class DBusEventSource extends EventSourceBase {
// (But still _initialized to false, because the proxy does not know
// about the HasCalendars property and would cause an exception trying
// to read it)
} else {
if (!e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
log('Error loading calendars: %s'.format(e.message));
return;
}
@ -238,7 +240,6 @@ class DBusEventSource extends EventSourceBase {
this.notify('has-calendars');
this._onNameAppeared();
}
});
}
destroy() {

View File

@ -10,6 +10,7 @@ const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
Gio._promisify(Shell.NetworkAgent.prototype, 'init_async', 'init_finish');
Gio._promisify(Shell.NetworkAgent.prototype,
'search_vpn_plugin', 'search_vpn_plugin_finish');
@ -482,11 +483,11 @@ var VPNRequestHandler = class {
}
}
_readStdoutOldStyle() {
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => {
let [line, len_] = this._dataStdout.read_line_finish_utf8(result);
async _readStdoutOldStyle() {
const [line, len_] =
await this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null);
if (line == null) {
if (line === null) {
// end of file
this._stdout.close(null);
return;
@ -496,14 +497,13 @@ var VPNRequestHandler = class {
// try to read more!
this._readStdoutOldStyle();
});
}
_readStdoutNewStyle() {
this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, (stream, result) => {
let cnt = this._dataStdout.fill_finish(result);
async _readStdoutNewStyle() {
const cnt =
await this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null);
if (cnt == 0) {
if (cnt === 0) {
// end of file
this._showNewStyleDialog();
@ -514,7 +514,6 @@ var VPNRequestHandler = class {
// Try to read more
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
this._readStdoutNewStyle();
});
}
_showNewStyleDialog() {
@ -621,15 +620,17 @@ var NetworkAgent = class {
this._native.connect('cancel-request', this._cancelRequest.bind(this));
this._initialized = false;
this._native.init_async(GLib.PRIORITY_DEFAULT, null, (o, res) => {
this._initNative();
}
async _initNative() {
try {
this._native.init_finish(res);
await this._native.init_async(GLib.PRIORITY_DEFAULT, null);
this._initialized = true;
} catch (e) {
this._native = null;
logError(e, 'error initializing the NetworkManager Agent');
}
});
}
enable() {

View File

@ -7,6 +7,14 @@ var Tpl = null;
var Tp = null;
try {
({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi);
Gio._promisify(Tp.Channel.prototype, 'close_async', 'close_finish');
Gio._promisify(Tp.Channel.prototype,
'send_message_async', 'send_message_finish');
Gio._promisify(Tp.ChannelDispatchOperation.prototype,
'claim_with_async', 'claim_with_finish');
Gio._promisify(Tpl.LogManager.prototype,
'get_filtered_events_async', 'get_filtered_events_finish');
} catch (e) {
log('Telepathy is not available, chat integration will be disabled.');
}
@ -215,7 +223,7 @@ class TelepathyClient extends Tp.BaseClient {
// We can only handle text channel, so close any other channel
if (!(channel instanceof Tp.TextChannel)) {
channel.close_async(null);
channel.close_async();
continue;
}
@ -261,7 +269,7 @@ class TelepathyClient extends Tp.BaseClient {
}
}
_approveTextChannel(account, conn, channel, dispatchOp, context) {
async _approveTextChannel(account, conn, channel, dispatchOp, context) {
let [targetHandle_, targetHandleType] = channel.get_handle();
if (targetHandleType != Tp.HandleType.CONTACT) {
@ -270,17 +278,15 @@ class TelepathyClient extends Tp.BaseClient {
return;
}
context.accept();
// Approve private text channels right away as we are going to handle it
dispatchOp.claim_with_async(this, (o, result) => {
try {
dispatchOp.claim_with_finish(result);
await dispatchOp.claim_with_async(this);
this._handlingChannels(account, conn, [channel], false);
} catch (err) {
log('Failed to Claim channel: %s'.format(err.toString()));
}
});
context.accept();
}
_delegatedChannelsCb(_client, _channels) {
@ -441,17 +447,14 @@ class ChatSource extends MessageTray.Source {
}
}
_getLogMessages() {
async _getLogMessages() {
let logManager = Tpl.LogManager.dup_singleton();
let entity = Tpl.Entity.new_from_tp_contact(this._contact, Tpl.EntityType.CONTACT);
logManager.get_filtered_events_async(this._account, entity,
const [events] = await logManager.get_filtered_events_async(
this._account, entity,
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
null, this._displayPendingMessages.bind(this));
}
_displayPendingMessages(logManager, result) {
let [success_, events] = logManager.get_filtered_events_finish(result);
null);
let logMessages = events.map(e => ChatMessage.newFromTplTextEvent(e));
this._ensureNotification();
@ -509,9 +512,7 @@ class ChatSource extends MessageTray.Source {
this._ackMessages();
// The chat box has been destroyed so it can't
// handle the channel any more.
this._channel.close_async((channel, result) => {
channel.close_finish(result);
});
this._channel.close_async();
} else {
// Don't indicate any unread messages when the notification
// that represents them has been destroyed.
@ -609,9 +610,7 @@ class ChatSource extends MessageTray.Source {
}
let msg = Tp.ClientMessage.new_text(type, text);
this._channel.send_message_async(msg, 0, (src, result) => {
this._channel.send_message_finish(result);
});
this._channel.send_message_async(msg, 0);
}
setChatState(state) {

View File

@ -29,8 +29,6 @@ const UserWidget = imports.ui.userWidget;
const { loadInterfaceXML } = imports.misc.fileUtils;
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
const _ITEM_ICON_SIZE = 64;
const EndSessionDialogIface = loadInterfaceXML('org.gnome.SessionManager.EndSessionDialog');
@ -280,7 +278,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
}
_onPkOfflineProxyCreated(proxy, error) {
async _onPkOfflineProxyCreated(proxy, error) {
if (error) {
log(error.message);
return;
@ -295,15 +293,12 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}
// It only makes sense to check for this permission if PackageKit is available.
Polkit.Permission.new(
'org.freedesktop.packagekit.trigger-offline-update', null, null,
(source, res) => {
try {
this._updatesPermission = Polkit.Permission.new_finish(res);
this._updatesPermission = await Polkit.Permission.new(
'org.freedesktop.packagekit.trigger-offline-update', null, null);
} catch (e) {
log('No permission to trigger offline updates: %s'.format(e.toString()));
}
});
}
_onDestroy() {

View File

@ -10,10 +10,21 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Meta, Polkit, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const System = imports.system;
Gio._promisify(Gio.DataInputStream.prototype, 'fill_async', 'fill_finish');
Gio._promisify(Gio.DataInputStream.prototype,
'read_line_async', 'read_line_finish');
Gio._promisify(Gio.DBus, 'get', 'get_finish');
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
Gio._promisify(Gio.DBusProxy, 'new', 'new_finish');
Gio._promisify(Gio.DBusProxy.prototype, 'init_async', 'init_finish');
Gio._promisify(Gio.DBusProxy.prototype,
'call_with_unix_fd_list', 'call_with_unix_fd_list_finish');
Gio._promisify(Polkit.Permission, 'new', 'new_finish');
let _localTimeZone = null;
// We can't import shell JS modules yet, because they may have

View File

@ -90,19 +90,17 @@ class AppMenu extends PopupMenu.PopupMenu {
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._detailsItem = this.addAction(_("Show Details"), () => {
this._detailsItem = this.addAction(_('Show Details'), async () => {
let id = this._app.get_id();
let args = GLib.Variant.new('(ss)', [id, '']);
Gio.DBus.get(Gio.BusType.SESSION, null, (o, res) => {
let bus = Gio.DBus.get_finish(res);
bus.call('org.gnome.Software',
const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
bus.call(
'org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
new GLib.Variant('(sava{sv})', ['details', [args], null]),
null, 0, -1, null, null);
});
});
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());

View File

@ -204,7 +204,7 @@ var RemoteSearchProvider = class {
g_interface_info: proxyInfo,
g_interface_name: proxyInfo.name,
gFlags });
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null, null);
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null);
this.appInfo = appInfo;
this.id = appInfo.get_id();

View File

@ -7,6 +7,13 @@ const GrabHelper = imports.ui.grabHelper;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
Gio._promisify(Shell.Screenshot.prototype, 'pick_color', 'pick_color_finish');
Gio._promisify(Shell.Screenshot.prototype, 'screenshot', 'screenshot_finish');
Gio._promisify(Shell.Screenshot.prototype,
'screenshot_window', 'screenshot_window_finish');
Gio._promisify(Shell.Screenshot.prototype,
'screenshot_area', 'screenshot_area_finish');
const { loadInterfaceXML } = imports.misc.fileUtils;
const ScreenshotIface = loadInterfaceXML('org.gnome.Shell.Screenshot');
@ -156,7 +163,7 @@ var ScreenshotService = class {
return [x, y, width, height];
}
ScreenshotAreaAsync(params, invocation) {
async ScreenshotAreaAsync(params, invocation) {
let [x, y, width, height, flash, filename] = params;
[x, y, width, height] = this._scaleArea(x, y, width, height);
if (!this._checkArea(x, y, width, height)) {
@ -173,21 +180,17 @@ var ScreenshotService = class {
if (!stream)
return;
screenshot.screenshot_area(x, y, width, height, stream,
(o, res) => {
try {
let [success_, area] =
screenshot.screenshot_area_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
let [area] =
await screenshot.screenshot_area(x, y, width, height, stream);
this._onScreenshotComplete(area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
});
}
ScreenshotWindowAsync(params, invocation) {
async ScreenshotWindowAsync(params, invocation) {
let [includeFrame, includeCursor, flash, filename] = params;
let screenshot = this._createScreenshot(invocation);
if (!screenshot)
@ -197,21 +200,17 @@ var ScreenshotService = class {
if (!stream)
return;
screenshot.screenshot_window(includeFrame, includeCursor, stream,
(o, res) => {
try {
let [success_, area] =
screenshot.screenshot_window_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
let [area] =
await screenshot.screenshot_window(includeFrame, includeCursor, stream);
this._onScreenshotComplete(area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
});
}
ScreenshotAsync(params, invocation) {
async ScreenshotAsync(params, invocation) {
let [includeCursor, flash, filename] = params;
let screenshot = this._createScreenshot(invocation);
if (!screenshot)
@ -221,18 +220,13 @@ var ScreenshotService = class {
if (!stream)
return;
screenshot.screenshot(includeCursor, stream,
(o, res) => {
try {
let [success_, area] =
screenshot.screenshot_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
let [area] = await screenshot.screenshot(includeCursor, stream);
this._onScreenshotComplete(area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
});
}
async SelectAreaAsync(params, invocation) {
@ -273,10 +267,9 @@ var ScreenshotService = class {
if (!screenshot)
return;
screenshot.pick_color(coords.x, coords.y, (_o, res) => {
let [success_, color] = screenshot.pick_color_finish(res);
let { red, green, blue } = color;
let retval = GLib.Variant.new('(a{sv})', [{
const [color] = await screenshot.pick_color(coords.x, coords.y);
const { red, green, blue } = color;
const retval = GLib.Variant.new('(a{sv})', [{
color: GLib.Variant.new('(ddd)', [
red / 255.0,
green / 255.0,
@ -285,7 +278,6 @@ var ScreenshotService = class {
}]);
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(retval);
});
} catch (e) {
invocation.return_error_literal(
Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,

View File

@ -325,8 +325,7 @@ var GnomeShellExtensions = class {
null,
Gio.DBusCallFlags.NONE,
-1,
null,
(conn, res) => conn.call_finish(res));
null);
}
ReloadExtensionAsync(params, invocation) {

View File

@ -199,36 +199,36 @@ var InputSourceSystemSettings = class extends InputSourceSettings {
this._reload.bind(this));
}
_reload() {
Gio.DBus.system.call(this._BUS_NAME,
async _reload() {
let props;
try {
const result = await Gio.DBus.system.call(
this._BUS_NAME,
this._BUS_PATH,
this._BUS_PROPS_IFACE,
'GetAll',
new GLib.Variant('(s)', [this._BUS_IFACE]),
null, Gio.DBusCallFlags.NONE, -1, null,
(conn, result) => {
let props;
try {
props = conn.call_finish(result).deep_unpack()[0];
null, Gio.DBusCallFlags.NONE, -1, null);
[props] = result.deep_unpack();
} catch (e) {
log('Could not get properties from %s'.format(this._BUS_NAME));
return;
}
let layouts = props['X11Layout'].unpack();
let variants = props['X11Variant'].unpack();
let options = props['X11Options'].unpack();
if (layouts != this._layouts ||
variants != this._variants) {
const layouts = props['X11Layout'].unpack();
const variants = props['X11Variant'].unpack();
const options = props['X11Options'].unpack();
if (layouts !== this._layouts ||
variants !== this._variants) {
this._layouts = layouts;
this._variants = variants;
this._emitInputSourcesChanged();
}
if (options != this._options) {
if (options !== this._options) {
this._options = options;
this._emitKeyboardOptionsChanged();
}
});
}
get inputSources() {

View File

@ -15,6 +15,10 @@ const Util = imports.misc.util;
const { loadInterfaceXML } = imports.misc.fileUtils;
Gio._promisify(NM.Client, 'new_async', 'new_finish');
Gio._promisify(NM.Client.prototype,
'check_connectivity_async', 'check_connectivity_finish');
const NMConnectionCategory = {
INVALID: 'invalid',
WIRED: 'wired',
@ -1627,11 +1631,11 @@ class Indicator extends PanelMenu.SystemIndicator {
this._ctypes[NM.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NM.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
NM.Client.new_async(null, this._clientGot.bind(this));
this._getClient();
}
_clientGot(obj, result) {
this._client = NM.Client.new_finish(result);
async _getClient() {
this._client = await NM.Client.new_async(null);
this._activeConnections = [];
this._connections = [];
@ -1982,7 +1986,7 @@ class Indicator extends PanelMenu.SystemIndicator {
}
}
_portalHelperDone(proxy, emitter, parameters) {
async _portalHelperDone(proxy, emitter, parameters) {
let [path, result] = parameters;
if (result == PortalHelperResult.CANCELLED) {
@ -1993,13 +1997,11 @@ class Indicator extends PanelMenu.SystemIndicator {
} else if (result == PortalHelperResult.COMPLETED) {
this._closeConnectivityCheck(path);
} else if (result == PortalHelperResult.RECHECK) {
this._client.check_connectivity_async(null, (client, res) => {
try {
let state = client.check_connectivity_finish(res);
const state = await this._client.check_connectivity_async(null);
if (state >= NM.ConnectivityState.FULL)
this._closeConnectivityCheck(path);
} catch (e) { }
});
} else {
log('Invalid result from portal helper: %s'.format(result));
}

View File

@ -52,22 +52,21 @@ const BOLT_DBUS_PATH = '/org/freedesktop/bolt';
var Client = class {
constructor() {
this._proxy = null;
this.probing = false;
this._getProxy();
}
async _getProxy() {
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(BoltClientInterface);
Gio.DBusProxy.new(Gio.DBus.system,
try {
this._proxy = await Gio.DBusProxy.new(
Gio.DBus.system,
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
nodeInfo.lookup_interface(BOLT_DBUS_CLIENT_IFACE),
BOLT_DBUS_NAME,
BOLT_DBUS_PATH,
BOLT_DBUS_CLIENT_IFACE,
null,
this._onProxyReady.bind(this));
this.probing = false;
}
_onProxyReady(o, res) {
try {
this._proxy = Gio.DBusProxy.new_finish(res);
null);
} catch (e) {
log('error creating bolt proxy: %s'.format(e.message));
return;
@ -243,14 +242,15 @@ class Indicator extends PanelMenu.SystemIndicator {
this._source = null;
this._perm = null;
this._createPermission();
}
Polkit.Permission.new('org.freedesktop.bolt.enroll', null, null, (source, res) => {
async _createPermission() {
try {
this._perm = Polkit.Permission.new_finish(res);
this._perm = await Polkit.Permission.new('org.freedesktop.bolt.enroll', null, null);
} catch (e) {
log('Failed to get PolKit permission: %s'.format(e.toString()));
}
});
}
_onDestroy() {

View File

@ -201,10 +201,7 @@ var ExtensionsWindow = GObject.registerClass({
null,
Gio.DBusCallFlags.NONE,
-1,
null,
(o, res) => {
o.call_finish(res);
});
null);
}
_sortList(row1, row2) {