diff --git a/pressure-vessel/launcher.c b/pressure-vessel/launcher.c
index d22b5a26db3b501cc44fa0d71acca31331e7b5df..146fb1300c85df20a3e1c2b57011af7d96589e39 100644
--- a/pressure-vessel/launcher.c
+++ b/pressure-vessel/launcher.c
@@ -47,6 +47,7 @@
 
 #include "flatpak-utils-base-private.h"
 #include "launcher.h"
+#include "portal-listener.h"
 #include "utils.h"
 
 typedef GCredentials AutoCredentials;
@@ -58,6 +59,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(AutoDBusAuthObserver, g_object_unref)
 typedef GDBusServer AutoDBusServer;
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(AutoDBusServer, g_object_unref)
 
+static PvPortalListener *global_listener;
 static const char * const *global_original_environ = NULL;
 static FILE *original_stdout = NULL;
 static FILE *info_fh = NULL;
@@ -1119,6 +1121,7 @@ main (int argc,
 
   my_pid = getpid ();
 
+  global_listener = pv_portal_listener_new ();
   original_environ = g_get_environ ();
   global_original_environ = (const char * const *) original_environ;
   pv_get_current_dirs (NULL, &original_cwd_l);
@@ -1431,6 +1434,7 @@ out:
   g_free (opt_socket);
   g_free (opt_socket_directory);
   g_clear_object (&session_bus);
+  g_clear_object (&global_listener);
   g_hash_table_destroy (lock_env_hash);
 
   if (local_error == NULL)
diff --git a/pressure-vessel/meson.build b/pressure-vessel/meson.build
index e6de0fb184a995359d7e9846ca478b87eab8e077..df74607764ce93bb1c4da5c960258cabddda045b 100644
--- a/pressure-vessel/meson.build
+++ b/pressure-vessel/meson.build
@@ -167,6 +167,8 @@ executable(
   'pressure-vessel-launcher',
   sources: [
     'launcher.c',
+    'portal-listener.c',
+    'portal-listener.h',
   ],
   c_args : pv_c_args,
   dependencies : [
diff --git a/pressure-vessel/portal-listener.c b/pressure-vessel/portal-listener.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f9786fbe8835ff0d57a74c79de174e66098ccfa
--- /dev/null
+++ b/pressure-vessel/portal-listener.c
@@ -0,0 +1,78 @@
+/*
+ * Common code for portal-like services
+ *
+ * Copyright © 2018 Red Hat, Inc.
+ * Copyright © 2020 Collabora Ltd.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Based on xdg-desktop-portal, flatpak-portal and flatpak-spawn.
+ * Authors:
+ *       Alexander Larsson <alexl@redhat.com>
+ */
+
+#include "config.h"
+#include "subprojects/libglnx/config.h"
+
+#include "portal-listener.h"
+
+struct _PvPortalListenerClass
+{
+  GObjectClass parent;
+};
+
+G_DEFINE_TYPE (PvPortalListener, pv_portal_listener, G_TYPE_OBJECT)
+
+void
+pv_portal_listener_init (PvPortalListener *self)
+{
+}
+
+static void
+pv_portal_listener_dispose (GObject *object)
+{
+  PvPortalListener *self = PV_PORTAL_LISTENER (object);
+
+  (void) self;
+
+  G_OBJECT_CLASS (pv_portal_listener_parent_class)->dispose (object);
+}
+
+static void
+pv_portal_listener_finalize (GObject *object)
+{
+  PvPortalListener *self = PV_PORTAL_LISTENER (object);
+
+  (void) self;
+
+  G_OBJECT_CLASS (pv_portal_listener_parent_class)->finalize (object);
+}
+
+static void
+pv_portal_listener_class_init (PvPortalListenerClass *cls)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (cls);
+
+  object_class->dispose = pv_portal_listener_dispose;
+  object_class->finalize = pv_portal_listener_finalize;
+}
+
+PvPortalListener *
+pv_portal_listener_new (void)
+{
+  return g_object_new (PV_TYPE_PORTAL_LISTENER,
+                       NULL);
+}
diff --git a/pressure-vessel/portal-listener.h b/pressure-vessel/portal-listener.h
new file mode 100644
index 0000000000000000000000000000000000000000..4be8bbe1cd68ed9033806d529d1d30342ec5d5cc
--- /dev/null
+++ b/pressure-vessel/portal-listener.h
@@ -0,0 +1,57 @@
+/*
+ * Common code for portal-like services
+ *
+ * Copyright © 2018 Red Hat, Inc.
+ * Copyright © 2020 Collabora Ltd.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Based on xdg-desktop-portal, flatpak-portal and flatpak-spawn.
+ * Authors:
+ *       Alexander Larsson <alexl@redhat.com>
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "steam-runtime-tools/glib-backports-internal.h"
+#include "libglnx/libglnx.h"
+
+typedef struct _PvPortalListener PvPortalListener;
+typedef struct _PvPortalListenerClass PvPortalListenerClass;
+
+#define PV_TYPE_PORTAL_LISTENER (pv_portal_listener_get_type ())
+#define PV_PORTAL_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_PORTAL_LISTENER, PvPortalListener))
+#define PV_PORTAL_LISTENER_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST ((cls), PV_TYPE_PORTAL_LISTENER, PvPortalListenerClass))
+#define PV_IS_PORTAL_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_PORTAL_LISTENER))
+#define PV_IS_PORTAL_LISTENER_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE ((cls), PV_TYPE_PORTAL_LISTENER))
+#define PV_PORTAL_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PV_TYPE_PORTAL_LISTENER, PvPortalListenerClass)
+GType pv_portal_listener_get_type (void);
+
+struct _PvPortalListener
+{
+  GObject parent;
+};
+
+PvPortalListener *pv_portal_listener_new (void);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (PvPortalListener, g_object_unref)