[gnome-shell] util: Wait for initial name owners in DBusSenderCheck before checking



commit 85609a232d4088b058f23f4922b9a993dea95199
Author: Sebastian Keller <skeller gnome org>
Date:   Tue Nov 23 02:48:04 2021 +0100

    util: Wait for initial name owners in DBusSenderCheck before checking
    
    Otherwise an allowed caller might get rejected if the call is right
    after a gnome-shell restart and the watchers have not finished running
    their callbacks yet.
    
    Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4813
    Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2048>

 js/misc/introspect.js |  8 ++++----
 js/misc/util.js       | 33 ++++++++++++++++++++++++++++-----
 js/ui/screenshot.js   | 18 +++++++++---------
 js/ui/shellDBus.js    | 44 ++++++++++++++++++++++++--------------------
 4 files changed, 65 insertions(+), 38 deletions(-)
---
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
index 22bd8319c4..45eee81ce3 100644
--- a/js/misc/introspect.js
+++ b/js/misc/introspect.js
@@ -117,9 +117,9 @@ var IntrospectService = class {
                 type == Meta.WindowType.UTILITY;
     }
 
-    GetRunningApplicationsAsync(params, invocation) {
+    async GetRunningApplicationsAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -128,13 +128,13 @@ var IntrospectService = class {
         invocation.return_value(new GLib.Variant('(a{sa{sv}})', [this._runningApplications]));
     }
 
-    GetWindowsAsync(params, invocation) {
+    async GetWindowsAsync(params, invocation) {
         let focusWindow = global.display.get_focus_window();
         let apps = this._appSystem.get_running();
         let windowsList = {};
 
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
diff --git a/js/misc/util.js b/js/misc/util.js
index bd57184728..25a5748e90 100644
--- a/js/misc/util.js
+++ b/js/misc/util.js
@@ -486,20 +486,42 @@ var DBusSenderChecker = class {
     constructor(allowList) {
         this._allowlistMap = new Map();
 
+        this._uninitializedNames = new Set(allowList);
+        this._initializedPromise = new Promise(resolve => {
+            this._resolveInitialized = resolve;
+        });
+
         this._watchList = allowList.map(name => {
             return Gio.DBus.watch_name(Gio.BusType.SESSION,
                 name,
                 Gio.BusNameWatcherFlags.NONE,
-                (conn_, name_, owner) => this._allowlistMap.set(name, owner),
-                () => this._allowlistMap.delete(name));
+                (conn_, name_, owner) => {
+                    this._allowlistMap.set(name, owner);
+                    this._checkAndResolveInitialized(name);
+                },
+                () => {
+                    this._allowlistMap.delete(name);
+                    this._checkAndResolveInitialized(name);
+                });
         });
     }
 
     /**
+     * @param {string} name - bus name for which the watcher got initialized
+     */
+    _checkAndResolveInitialized(name) {
+        if (this._uninitializedNames.delete(name) &&
+            this._uninitializedNames.size === 0)
+            this._resolveInitialized();
+    }
+
+    /**
+     * @async
      * @param {string} sender - the bus name that invoked the checked method
      * @returns {bool}
      */
-    _isSenderAllowed(sender) {
+    async _isSenderAllowed(sender) {
+        await this._initializedPromise;
         return [...this._allowlistMap.values()].includes(sender);
     }
 
@@ -507,15 +529,16 @@ var DBusSenderChecker = class {
      * Check whether the bus name that invoked @invocation maps
      * to an entry in the allow list.
      *
+     * @async
      * @throws
      * @param {Gio.DBusMethodInvocation} invocation - the invocation
      * @returns {void}
      */
-    checkInvocation(invocation) {
+    async checkInvocation(invocation) {
         if (global.context.unsafe_mode)
             return;
 
-        if (this._isSenderAllowed(invocation.get_sender()))
+        if (await this._isSenderAllowed(invocation.get_sender()))
             return;
 
         throw new GLib.Error(Gio.DBusError,
diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js
index ae1156f477..97fcfacd01 100644
--- a/js/ui/screenshot.js
+++ b/js/ui/screenshot.js
@@ -37,7 +37,7 @@ var ScreenshotService = class {
         Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null);
     }
 
-    _createScreenshot(invocation, needsDisk = true, restrictCallers = true) {
+    async _createScreenshot(invocation, needsDisk = true, restrictCallers = true) {
         let lockedDown = false;
         if (needsDisk)
             lockedDown = this._lockdownSettings.get_boolean('disable-save-to-disk');
@@ -55,7 +55,7 @@ var ScreenshotService = class {
             return null;
         } else if (restrictCallers) {
             try {
-                this._senderChecker.checkInvocation(invocation);
+                await this._senderChecker.checkInvocation(invocation);
             } catch (e) {
                 invocation.return_gerror(e);
                 return null;
@@ -200,7 +200,7 @@ var ScreenshotService = class {
                                             "Invalid params");
             return;
         }
-        let screenshot = this._createScreenshot(invocation);
+        let screenshot = await this._createScreenshot(invocation);
         if (!screenshot)
             return;
 
@@ -223,7 +223,7 @@ var ScreenshotService = class {
 
     async ScreenshotWindowAsync(params, invocation) {
         let [includeFrame, includeCursor, flash, filename] = params;
-        let screenshot = this._createScreenshot(invocation);
+        let screenshot = await this._createScreenshot(invocation);
         if (!screenshot)
             return;
 
@@ -246,7 +246,7 @@ var ScreenshotService = class {
 
     async ScreenshotAsync(params, invocation) {
         let [includeCursor, flash, filename] = params;
-        let screenshot = this._createScreenshot(invocation);
+        let screenshot = await this._createScreenshot(invocation);
         if (!screenshot)
             return;
 
@@ -269,7 +269,7 @@ var ScreenshotService = class {
 
     async SelectAreaAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -289,9 +289,9 @@ var ScreenshotService = class {
         }
     }
 
-    FlashAreaAsync(params, invocation) {
+    async FlashAreaAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -311,7 +311,7 @@ var ScreenshotService = class {
     }
 
     async PickColorAsync(params, invocation) {
-        const screenshot = this._createScreenshot(invocation, false, false);
+        const screenshot = await this._createScreenshot(invocation, false, false);
         if (!screenshot)
             return;
 
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index a8070eb925..aeabe6d81e 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -81,13 +81,14 @@ var GnomeShell = class {
     /**
      * Focus the overview's search entry
      *
+     * @async
      * @param {...any} params - method parameters
      * @param {Gio.DBusMethodInvocation} invocation - the invocation
      * @returns {void}
      */
-    FocusSearchAsync(params, invocation) {
+    async FocusSearchAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -100,13 +101,14 @@ var GnomeShell = class {
     /**
      * Show OSD with the specified parameters
      *
+     * @async
      * @param {...any} params - method parameters
      * @param {Gio.DBusMethodInvocation} invocation - the invocation
      * @returns {void}
      */
-    ShowOSDAsync([params], invocation) {
+    async ShowOSDAsync([params], invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -138,13 +140,14 @@ var GnomeShell = class {
     /**
      * Focus specified app in the overview's app grid
      *
+     * @async
      * @param {string} id - an application ID
      * @param {Gio.DBusMethodInvocation} invocation - the invocation
      * @returns {void}
      */
-    FocusAppAsync([id], invocation) {
+    async FocusAppAsync([id], invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -157,13 +160,14 @@ var GnomeShell = class {
     /**
      * Show the overview's app grid
      *
+     * @async
      * @param {...any} params - method parameters
      * @param {Gio.DBusMethodInvocation} invocation - the invocation
      * @returns {void}
      */
-    ShowApplicationsAsync(params, invocation) {
+    async ShowApplicationsAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -173,9 +177,9 @@ var GnomeShell = class {
         invocation.return_value(null);
     }
 
-    GrabAcceleratorAsync(params, invocation) {
+    async GrabAcceleratorAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -187,9 +191,9 @@ var GnomeShell = class {
         invocation.return_value(GLib.Variant.new('(u)', [bindingAction]));
     }
 
-    GrabAcceleratorsAsync(params, invocation) {
+    async GrabAcceleratorsAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -205,9 +209,9 @@ var GnomeShell = class {
         invocation.return_value(GLib.Variant.new('(au)', [bindingActions]));
     }
 
-    UngrabAcceleratorAsync(params, invocation) {
+    async UngrabAcceleratorAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -220,9 +224,9 @@ var GnomeShell = class {
         invocation.return_value(GLib.Variant.new('(b)', [ungrabSucceeded]));
     }
 
-    UngrabAcceleratorsAsync(params, invocation) {
+    async UngrabAcceleratorsAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -307,9 +311,9 @@ var GnomeShell = class {
         this._grabbers.delete(name);
     }
 
-    ShowMonitorLabelsAsync(params, invocation) {
+    async ShowMonitorLabelsAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -321,9 +325,9 @@ var GnomeShell = class {
         invocation.return_value(null);
     }
 
-    HideMonitorLabelsAsync(params, invocation) {
+    async HideMonitorLabelsAsync(params, invocation) {
         try {
-            this._senderChecker.checkInvocation(invocation);
+            await this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;


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