[gnome-shell] js: Promisify async operations



commit 764527c8c9b7659901eb6296a6859ae2b0eabdb8
Author: Florian Müllner <fmuellner gnome org>
Date:   Thu Dec 19 20:50:37 2019 +0100

    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

 js/gdm/util.js                        | 82 +++++++++++++++---------------
 js/misc/ibusManager.js                | 70 ++++++++++++-------------
 js/misc/inputMethod.js                | 13 +++--
 js/misc/loginManager.js               | 64 ++++++++++-------------
 js/misc/objectManager.js              | 61 +++++++++++-----------
 js/misc/weather.js                    | 51 +++++++++----------
 js/ui/appDisplay.js                   | 21 ++++----
 js/ui/calendar.js                     | 71 +++++++++++++-------------
 js/ui/components/networkAgent.js      | 69 ++++++++++++-------------
 js/ui/components/telepathyClient.js   | 51 +++++++++----------
 js/ui/endSessionDialog.js             | 19 +++----
 js/ui/environment.js                  | 13 ++++-
 js/ui/panel.js                        | 18 +++----
 js/ui/remoteSearch.js                 |  2 +-
 js/ui/screenshot.js                   | 96 ++++++++++++++++-------------------
 js/ui/shellDBus.js                    |  3 +-
 js/ui/status/keyboard.js              | 60 +++++++++++-----------
 js/ui/status/network.js               | 24 +++++----
 js/ui/status/thunderbolt.js           | 38 +++++++-------
 subprojects/extensions-app/js/main.js |  5 +-
 20 files changed, 406 insertions(+), 425 deletions(-)
---
diff --git a/js/gdm/util.js b/js/gdm/util.js
index 53b0079f68..cc3fe39345 100644
--- a/js/gdm/util.js
+++ b/js/gdm/util.js
@@ -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 possible, reauthenticate an already running session,
+        // so any session specific credentials get updated appropriately
+        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();
-        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();
-            });
-        } else {
-            this._userVerifier.call_begin_verification(serviceName, this._cancellable, (obj, result) => {
-                try {
-                    obj.call_begin_verification_finish(result);
-                } catch (e) {
-                    if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
-                        return;
-                    this._reportInitError('Failed to start verification', e);
-                    return;
-                }
-
-                this._hold.release();
-            });
+        try {
+            if (this._userName) {
+                await this._userVerifier.call_begin_verification_for_user(
+                    serviceName, this._userName, this._cancellable);
+            } else {
+                await this._userVerifier.call_begin_verification(
+                    serviceName, this._cancellable);
+            }
+        } catch (e) {
+            if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
+                return;
+            this._reportInitError(this._userName
+                ? 'Failed to start verification for user'
+                : 'Failed to start verification', e);
+            return;
         }
+        this._hold.release();
     }
 
     _beginVerification() {
diff --git a/js/misc/ibusManager.js b/js/misc/ibusManager.js
index a55701ed01..e8cfead2ce 100644
--- a/js/misc/ibusManager.js
+++ b/js/misc/ibusManager.js
@@ -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;
-            }
+
+        try {
+            // 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();
+            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);
-                } catch (e) {
-                    if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
-                        logError(e);
-                }
-                if (callback)
-                    callback();
-            });
+        try {
+            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) {
diff --git a/js/misc/inputMethod.js b/js/misc/inputMethod.js
index a3c6bb084e..0bc1462ef1 100644
--- a/js/misc/inputMethod.js
+++ b/js/misc/inputMethod.js
@@ -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);
diff --git a/js/misc/loginManager.js b/js/misc/loginManager.js
index 473ad0758d..0f9ee1703f 100644
--- a/js/misc/loginManager.js
+++ b/js/misc/loginManager.js
@@ -50,25 +50,22 @@ function canLock() {
 }
 
 
-function registerSessionWithGDM() {
+async function registerSessionWithGDM() {
     log("Registering session with GDM");
-    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);
-            } 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?");
-            }
-        }
-    );
+    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);
+    } 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?');
+    }
 }
 
 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;
-                try {
-                    let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result);
-                    fd = fdList.steal_fds()[0];
-                    callback(new Gio.UnixInputStream({ fd }));
-                } catch (e) {
-                    logError(e, "Error getting systemd inhibitor");
-                    callback(null);
-                }
-            });
+    async inhibit(reason, callback) {
+        try {
+            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');
+            callback(null);
+        }
     }
 
     _prepareForSleep(proxy, sender, [aboutToSuspend]) {
diff --git a/js/misc/objectManager.js b/js/misc/objectManager.js
index dfeac0e1e5..4c4e0b6e32 100644
--- a/js/misc/objectManager.js
+++ b/js/misc/objectManager.js
@@ -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,40 +87,38 @@ 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);
-            } catch (e) {
-                logError(e, `could not initialize proxy for interface ${interfaceName}`);
+        try {
+            await proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable);
+        } catch (e) {
+            logError(e, `could not initialize proxy for interface ${interfaceName}`);
 
-                if (onFinished)
-                    onFinished();
-                return;
-            }
+            if (onFinished)
+                onFinished();
+            return;
+        }
 
-            let isNewObject;
-            if (!this._objects[objectPath]) {
-                this._objects[objectPath] = {};
-                isNewObject = true;
-            } else {
-                isNewObject = false;
-            }
+        let isNewObject;
+        if (!this._objects[objectPath]) {
+            this._objects[objectPath] = {};
+            isNewObject = true;
+        } else {
+            isNewObject = false;
+        }
 
-            this._objects[objectPath][interfaceName] = proxy;
+        this._objects[objectPath][interfaceName] = proxy;
 
-            if (!this._interfaces[interfaceName])
-                this._interfaces[interfaceName] = [];
+        if (!this._interfaces[interfaceName])
+            this._interfaces[interfaceName] = [];
 
-            this._interfaces[interfaceName].push(proxy);
+        this._interfaces[interfaceName].push(proxy);
 
-            if (isNewObject)
-                this.emit('object-added', objectPath);
+        if (isNewObject)
+            this.emit('object-added', objectPath);
 
-            this.emit('interface-added', interfaceName, proxy);
+        this.emit('interface-added', interfaceName, proxy);
 
-            if (onFinished)
-                onFinished();
-        });
+        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}`);
 
diff --git a/js/misc/weather.js b/js/misc/weather.js
index c0dc80cf8e..e518f2285b 100644
--- a/js/misc/weather.js
+++ b/js/misc/weather.js
@@ -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,25 +240,23 @@ 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);
-                } catch (e) {
-                    log(`Failed to connect to Geoclue2 service: ${e.message}`);
-                    this._setLocation(this._mostRecentLocation);
-                    return;
-                }
-                this._gclueStarted = true;
-                this._gclueService.get_client().distance_threshold = 100;
-                this._updateLocationMonitoring();
-            });
+        try {
+            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);
+            return;
+        }
+        this._gclueStarted = true;
+        this._gclueService.get_client().distance_threshold = 100;
+        this._updateLocationMonitoring();
     }
 
     _onGClueLocationChanged() {
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 2d57a6df26..4ba4ed67cb 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -2546,19 +2546,18 @@ 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',
-                                 '/org/gnome/Software',
-                                 'org.gtk.Actions', 'Activate',
-                                 GLib.Variant.new('(sava{sv})',
-                                                  ['details', [args], null]),
-                                 null, 0, -1, null, null);
-                        Main.overview.hide();
-                    });
+                    const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
+                    bus.call(
+                        'org.gnome.Software',
+                        '/org/gnome/Software',
+                        'org.gtk.Actions', 'Activate',
+                        new GLib.Variant.new(
+                            '(sava{sv})', ['details', [args], null]),
+                        null, 0, -1, null, null);
+                    Main.overview.hide();
                 });
             }
         }
diff --git a/js/ui/calendar.js b/js/ui/calendar.js
index 9964184176..286aac1e10 100644
--- a/js/ui/calendar.js
+++ b/js/ui/calendar.js
@@ -199,46 +199,47 @@ class DBusEventSource extends EventSourceBase {
 
         this._initialized = false;
         this._dbusProxy = new CalendarServer();
-        this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, (object, result) => {
-            let loaded = false;
-
-            try {
-                this._dbusProxy.init_finish(result);
-                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
-                    //
-                    // (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 {
-                    log('Error loading calendars: %s'.format(e.message));
-                    return;
-                }
+        this._initProxy();
+    }
+
+    async _initProxy() {
+        let loaded = false;
+
+        try {
+            await this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null);
+            loaded = true;
+        } catch (e) {
+            // 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
+            //
+            // (But still _initialized to false, because the proxy does not know
+            // about the HasCalendars property and would cause an exception trying
+            // to read it)
+            if (!e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
+                log('Error loading calendars: %s'.format(e.message));
+                return;
             }
+        }
 
-            this._dbusProxy.connectSignal('Changed', this._onChanged.bind(this));
-
-            this._dbusProxy.connect('notify::g-name-owner', () => {
-                if (this._dbusProxy.g_name_owner)
-                    this._onNameAppeared();
-                else
-                    this._onNameVanished();
-            });
-
-            this._dbusProxy.connect('g-properties-changed', () => {
-                this.notify('has-calendars');
-            });
+        this._dbusProxy.connectSignal('Changed', this._onChanged.bind(this));
 
-            this._initialized = loaded;
-            if (loaded) {
-                this.notify('has-calendars');
+        this._dbusProxy.connect('notify::g-name-owner', () => {
+            if (this._dbusProxy.g_name_owner)
                 this._onNameAppeared();
-            }
+            else
+                this._onNameVanished();
+        });
+
+        this._dbusProxy.connect('g-properties-changed', () => {
+            this.notify('has-calendars');
         });
+
+        this._initialized = loaded;
+        if (loaded) {
+            this.notify('has-calendars');
+            this._onNameAppeared();
+        }
     }
 
     destroy() {
diff --git a/js/ui/components/networkAgent.js b/js/ui/components/networkAgent.js
index 05d52ee868..1033a6de39 100644
--- a/js/ui/components/networkAgent.js
+++ b/js/ui/components/networkAgent.js
@@ -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,39 +483,37 @@ 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) {
-                // end of file
-                this._stdout.close(null);
-                return;
-            }
+        if (line === null) {
+            // end of file
+            this._stdout.close(null);
+            return;
+        }
 
-            this._vpnChildProcessLineOldStyle(line);
+        this._vpnChildProcessLineOldStyle(line);
 
-            // try to read more!
-            this._readStdoutOldStyle();
-        });
+        // 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) {
-                // end of file
-                this._showNewStyleDialog();
+        if (cnt === 0) {
+            // end of file
+            this._showNewStyleDialog();
 
-                this._stdout.close(null);
-                return;
-            }
+            this._stdout.close(null);
+            return;
+        }
 
-            // Try to read more
-            this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
-            this._readStdoutNewStyle();
-        });
+        // 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) => {
-            try {
-                this._native.init_finish(res);
-                this._initialized = true;
-            } catch (e) {
-                this._native = null;
-                logError(e, 'error initializing the NetworkManager Agent');
-            }
-        });
+        this._initNative();
+    }
+
+    async _initNative() {
+        try {
+            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() {
diff --git a/js/ui/components/telepathyClient.js b/js/ui/components/telepathyClient.js
index b4af4388e5..2e0669ac69 100644
--- a/js/ui/components/telepathyClient.js
+++ b/js/ui/components/telepathyClient.js
@@ -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;
         }
 
-        // 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);
-                this._handlingChannels(account, conn, [channel], false);
-            } catch (err) {
-                log('Failed to Claim channel: %s'.format(err.toString()));
-            }
-        });
-
         context.accept();
+
+        // Approve private text channels right away as we are going to handle it
+        try {
+            await dispatchOp.claim_with_async(this);
+            this._handlingChannels(account, conn, [channel], false);
+        } catch (err) {
+            log('Failed to Claim channel: %s'.format(err.toString()));
+        }
     }
 
     _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,
-                                             Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
-                                             null, this._displayPendingMessages.bind(this));
-    }
-
-    _displayPendingMessages(logManager, result) {
-        let [success_, events] = logManager.get_filtered_events_finish(result);
+        const [events] = await logManager.get_filtered_events_async(
+            this._account, entity,
+            Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
+            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) {
diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js
index 44747ea28f..b936352f48 100644
--- a/js/ui/endSessionDialog.js
+++ b/js/ui/endSessionDialog.js
@@ -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);
-                } catch (e) {
-                    log('No permission to trigger offline updates: %s'.format(e.toString()));
-                }
-            });
+        try {
+            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() {
diff --git a/js/ui/environment.js b/js/ui/environment.js
index 6764bd2797..8f23b107e6 100644
--- a/js/ui/environment.js
+++ b/js/ui/environment.js
@@ -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
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 43f2ddc928..d1c314c05b 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -90,18 +90,16 @@ 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',
-                         '/org/gnome/Software',
-                         'org.gtk.Actions', 'Activate',
-                         GLib.Variant.new('(sava{sv})',
-                                          ['details', [args], null]),
-                         null, 0, -1, null, null);
-            });
+            const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
+            bus.call(
+                'org.gnome.Software',
+                '/org/gnome/Software',
+                'org.gtk.Actions', 'Activate',
+                new GLib.Variant('(sava{sv})', ['details', [args], null]),
+                null, 0, -1, null, null);
         });
 
         this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
diff --git a/js/ui/remoteSearch.js b/js/ui/remoteSearch.js
index 62933f7ea8..77ad317e1e 100644
--- a/js/ui/remoteSearch.js
+++ b/js/ui/remoteSearch.js
@@ -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();
diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js
index 7aed8d01b4..0fe5fdff01 100644
--- a/js/ui/screenshot.js
+++ b/js/ui/screenshot.js
@@ -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);
-                } catch (e) {
-                    this._removeShooterForSender(invocation.get_sender());
-                    invocation.return_value(new GLib.Variant('(bs)', [false, '']));
-                }
-            });
+        try {
+            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);
-                } catch (e) {
-                    this._removeShooterForSender(invocation.get_sender());
-                    invocation.return_value(new GLib.Variant('(bs)', [false, '']));
-                }
-            });
+        try {
+            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);
-                } catch (e) {
-                    this._removeShooterForSender(invocation.get_sender());
-                    invocation.return_value(new GLib.Variant('(bs)', [false, '']));
-                }
-            });
+        try {
+            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,19 +267,17 @@ 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})', [{
-                    color: GLib.Variant.new('(ddd)', [
-                        red / 255.0,
-                        green / 255.0,
-                        blue / 255.0,
-                    ]),
-                }]);
-                this._removeShooterForSender(invocation.get_sender());
-                invocation.return_value(retval);
-            });
+            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,
+                    blue / 255.0,
+                ]),
+            }]);
+            this._removeShooterForSender(invocation.get_sender());
+            invocation.return_value(retval);
         } catch (e) {
             invocation.return_error_literal(
                 Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index f64081b24a..c413df291e 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -325,8 +325,7 @@ var GnomeShellExtensions = class {
             null,
             Gio.DBusCallFlags.NONE,
             -1,
-            null,
-            (conn, res) => conn.call_finish(res));
+            null);
     }
 
     ReloadExtensionAsync(params, invocation) {
diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js
index b2e16bc485..4a83705a3d 100644
--- a/js/ui/status/keyboard.js
+++ b/js/ui/status/keyboard.js
@@ -199,36 +199,36 @@ var InputSourceSystemSettings = class extends InputSourceSettings {
                                          this._reload.bind(this));
     }
 
-    _reload() {
-        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];
-                                 } 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) {
-                                     this._layouts = layouts;
-                                     this._variants = variants;
-                                     this._emitInputSourcesChanged();
-                                 }
-                                 if (options != this._options) {
-                                     this._options = options;
-                                     this._emitKeyboardOptionsChanged();
-                                 }
-                             });
+    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);
+            [props] = result.deep_unpack();
+        } catch (e) {
+            log('Could not get properties from %s'.format(this._BUS_NAME));
+            return;
+        }
+
+        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) {
+            this._options = options;
+            this._emitKeyboardOptionsChanged();
+        }
     }
 
     get inputSources() {
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
index 65cb722ffb..5bd81f1870 100644
--- a/js/ui/status/network.js
+++ b/js/ui/status/network.js
@@ -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);
-                    if (state >= NM.ConnectivityState.FULL)
-                        this._closeConnectivityCheck(path);
-                } catch (e) { }
-            });
+            try {
+                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));
         }
diff --git a/js/ui/status/thunderbolt.js b/js/ui/status/thunderbolt.js
index 52be975839..d98355deeb 100644
--- a/js/ui/status/thunderbolt.js
+++ b/js/ui/status/thunderbolt.js
@@ -52,22 +52,21 @@ const BOLT_DBUS_PATH = '/org/freedesktop/bolt';
 var Client = class {
     constructor() {
         this._proxy = null;
-        let nodeInfo = Gio.DBusNodeInfo.new_for_xml(BoltClientInterface);
-        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;
+        this._getProxy();
     }
 
-    _onProxyReady(o, res) {
+    async _getProxy() {
+        let nodeInfo = Gio.DBusNodeInfo.new_for_xml(BoltClientInterface);
         try {
-            this._proxy = Gio.DBusProxy.new_finish(res);
+            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);
         } 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) => {
-            try {
-                this._perm = Polkit.Permission.new_finish(res);
-            } catch (e) {
-                log('Failed to get PolKit permission: %s'.format(e.toString()));
-            }
-        });
+    async _createPermission() {
+        try {
+            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() {
diff --git a/subprojects/extensions-app/js/main.js b/subprojects/extensions-app/js/main.js
index d25df9c576..00b6c047db 100644
--- a/subprojects/extensions-app/js/main.js
+++ b/subprojects/extensions-app/js/main.js
@@ -201,10 +201,7 @@ var ExtensionsWindow = GObject.registerClass({
             null,
             Gio.DBusCallFlags.NONE,
             -1,
-            null,
-            (o, res) => {
-                o.call_finish(res);
-            });
+            null);
     }
 
     _sortList(row1, row2) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]