[nautilus] dbus-launcher: Launch programs via DBUS



commit d219b85d61eeed8ecc8743dfd9fb689894e04e24
Author: Corey Berla <corey berla me>
Date:   Fri Jun 10 09:59:27 2022 -0700

    dbus-launcher: Launch programs via DBUS
    
    Nautilus launches external programs (i.e. Settings & gnome-disks)
    directly via the commandline which doesn't work in flatpaks.
    Create new module nautilus-dbus-launcher to allow for launching
    these programs via DBus.  nautilus-application holds ono a
    singleton instance of the dbus launcher (similar to undo manager
    and tag manager) so we don't need to create proxies over and over again.

 build-aux/flatpak/org.gnome.Nautilus.json |   2 +
 build-aux/flatpak/org.gnome.Nautilus.yml  |   2 +
 src/meson.build                           |   2 +
 src/nautilus-application.c                |   7 +
 src/nautilus-dbus-launcher.c              | 211 ++++++++++++++++++++++++++++++
 src/nautilus-dbus-launcher.h              |  37 ++++++
 6 files changed, 261 insertions(+)
---
diff --git a/build-aux/flatpak/org.gnome.Nautilus.json b/build-aux/flatpak/org.gnome.Nautilus.json
index 91d05dab7..e3610fe3c 100644
--- a/build-aux/flatpak/org.gnome.Nautilus.json
+++ b/build-aux/flatpak/org.gnome.Nautilus.json
@@ -22,6 +22,8 @@
     "--filesystem=xdg-run/dconf",
     "--filesystem=~/.config/dconf:ro",
     "--talk-name=ca.desrt.dconf",
+    "--talk-name=org.gnome.DiskUtility",
+    "--talk-name=org.gnome.Settings",
     "--env=DCONF_USER_CONFIG_DIR=.config/dconf",
     "--add-policy=Tracker3.dbus:org.freedesktop.Tracker3.Miner.Files=tracker:FileSystem;tracker:Documents"
   ],
diff --git a/build-aux/flatpak/org.gnome.Nautilus.yml b/build-aux/flatpak/org.gnome.Nautilus.yml
index d4117d3bc..f38144943 100644
--- a/build-aux/flatpak/org.gnome.Nautilus.yml
+++ b/build-aux/flatpak/org.gnome.Nautilus.yml
@@ -21,6 +21,8 @@ finish-args:
 - "--filesystem=xdg-run/dconf"
 - "--filesystem=~/.config/dconf:ro"
 - "--talk-name=ca.desrt.dconf"
+- "--talk-name=org.gnome.DiskUtility"
+- "--talk-name=org.gnome.Settings"
 - "--env=DCONF_USER_CONFIG_DIR=.config/dconf"
 # Access to host Tracker Miners
 - "--add-policy=Tracker3.dbus:org.freedesktop.Tracker3.Miner.Files=tracker:FileSystem;tracker:Documents"
diff --git a/src/meson.build b/src/meson.build
index edcfe0d91..e76fe7c25 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -151,6 +151,8 @@ libnautilus_sources = [
   'nautilus-column-chooser.h',
   'nautilus-column-utilities.c',
   'nautilus-column-utilities.h',
+  'nautilus-dbus-launcher.c',
+  'nautilus-dbus-launcher.h',
   'nautilus-debug.c',
   'nautilus-debug.h',
   'nautilus-directory-async.c',
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index 05080733e..2898e052c 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -43,6 +43,7 @@
 
 #include "nautilus-bookmark-list.h"
 #include "nautilus-clipboard.h"
+#include "nautilus-dbus-launcher.h"
 #include "nautilus-dbus-manager.h"
 #include "nautilus-directory-private.h"
 #include "nautilus-file.h"
@@ -85,6 +86,8 @@ typedef struct
 
     NautilusTagManager *tag_manager;
 
+    NautilusDBusLauncher *dbus_launcher;
+
     guint previewer_selection_id;
 } NautilusApplicationPrivate;
 
@@ -586,6 +589,8 @@ nautilus_application_finalize (GObject *object)
 
     g_clear_object (&priv->tag_manager);
 
+    g_clear_object (&priv->dbus_launcher);
+
     G_OBJECT_CLASS (nautilus_application_parent_class)->finalize (object);
 }
 
@@ -1039,6 +1044,8 @@ nautilus_application_init (NautilusApplication *self)
     priv->undo_manager = nautilus_file_undo_manager_new ();
     priv->tag_manager = nautilus_tag_manager_new ();
 
+    priv->dbus_launcher = nautilus_dbus_launcher_new ();
+
     g_application_add_main_option_entries (G_APPLICATION (self), options);
 
     nautilus_ensure_extension_points ();
diff --git a/src/nautilus-dbus-launcher.c b/src/nautilus-dbus-launcher.c
new file mode 100644
index 000000000..df27bd7ee
--- /dev/null
+++ b/src/nautilus-dbus-launcher.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2022 Corey Berla <corey berla me>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "nautilus-dbus-launcher.h"
+
+#include <glib/gi18n.h>
+
+#include "nautilus-file.h"
+#include "nautilus-ui-utilities.h"
+
+
+typedef struct
+{
+    GDBusProxy *proxy;
+    GError *error;
+    gboolean ping_on_creation;
+} NautilusDBusLauncherData;
+
+struct _NautilusDBusLauncher
+{
+    GObject parent;
+
+    NautilusDBusLauncherData *data[NAUTILUS_DBUS_LAUNCHER_N_APPS];
+};
+
+G_DEFINE_TYPE (NautilusDBusLauncher, nautilus_dbus_launcher, G_TYPE_OBJECT)
+
+static NautilusDBusLauncher *launcher = NULL;
+
+static void
+on_nautilus_dbus_launcher_call_finished   (GObject      *source_object,
+                                           GAsyncResult *res,
+                                           gpointer      user_data)
+{
+    GtkWindow *window = user_data;
+    g_autoptr (GError) error = NULL;
+    g_autofree char *message = NULL;
+
+    g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+    if (error != NULL)
+    {
+        g_warning ("Error calling proxy %s", error->message);
+        message = g_strdup_printf (_("Details: %s"), error->message);
+        show_dialog (_("There was an error launching the application."),
+                     message,
+                     window,
+                     GTK_MESSAGE_ERROR);
+    }
+}
+
+static void
+on_nautilus_dbus_launcher_ping_finished   (GObject      *source_object,
+                                           GAsyncResult *res,
+                                           gpointer      user_data)
+{
+    NautilusDBusLauncherData *data = user_data;
+    GError *error = NULL;
+
+    g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+
+    data->error = error;
+}
+
+void
+nautilus_dbus_launcher_call (NautilusDBusLauncher    *self,
+                             NautilusDBusLauncherApp  app,
+                             const gchar             *method_name,
+                             GVariant                *parameters,
+                             GtkWindow               *window)
+{
+    if (self->data[app]->proxy != NULL)
+    {
+        g_dbus_proxy_call (self->data[app]->proxy,
+                           method_name,
+                           parameters,
+                           G_DBUS_CALL_FLAGS_NONE,
+                           G_MAXINT,
+                           NULL,
+                           on_nautilus_dbus_launcher_call_finished,
+                           window);
+    }
+    else if (window != NULL)
+    {
+        show_dialog (_("There was an error launching the application."),
+                     _("Details: The proxy has not been created."),
+                     window,
+                     GTK_MESSAGE_ERROR);
+    }
+}
+
+static void
+on_nautilus_dbus_proxy_ready (GObject      *source_object,
+                              GAsyncResult *res,
+                              gpointer      user_data)
+{
+    NautilusDBusLauncherData *data = user_data;
+    GError *error = NULL;
+
+    data->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+
+    if (error != NULL)
+    {
+        g_warning ("Error creating proxy %s", error->message);
+        data->error = error;
+    }
+    else if (data->ping_on_creation)
+    {
+        g_dbus_proxy_call (data->proxy,
+                           "org.freedesktop.DBus.Peer.Ping", NULL,
+                           G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL,
+                           on_nautilus_dbus_launcher_ping_finished, data);
+    }
+}
+
+static void
+nautilus_dbus_launcher_create_proxy (NautilusDBusLauncherData *data,
+                                     const gchar              *name,
+                                     const gchar              *object_path,
+                                     const gchar              *interface)
+{
+    g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                              G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION,
+                              NULL,
+                              name,
+                              object_path,
+                              interface,
+                              NULL,
+                              on_nautilus_dbus_proxy_ready,
+                              data);
+}
+
+gboolean nautilus_dbus_launcher_is_available (NautilusDBusLauncher   *self,
+                                              NautilusDBusLauncherApp app)
+{
+    return self->data[app]->error == NULL;
+}
+
+NautilusDBusLauncher *
+nautilus_dbus_launcher_get (void)
+{
+    return launcher;
+}
+
+NautilusDBusLauncher *
+nautilus_dbus_launcher_new (void)
+{
+    if (launcher != NULL)
+    {
+        return g_object_ref (launcher);
+    }
+    launcher = g_object_new (NAUTILUS_TYPE_DBUS_LAUNCHER, NULL);
+    g_object_add_weak_pointer (G_OBJECT (launcher), (gpointer) & launcher);
+
+    return launcher;
+}
+
+static void
+nautilus_dbus_launcher_finalize (GObject *object)
+{
+    NautilusDBusLauncher *self = NAUTILUS_DBUS_LAUNCHER (object);
+
+    for (gint i = 0; i < NAUTILUS_DBUS_LAUNCHER_N_APPS - 1; i++)
+    {
+        g_clear_object (&self->data[i]->proxy);
+        g_clear_object (&self->data[i]->error);
+        g_free (self->data[i]);
+    }
+
+    G_OBJECT_CLASS (nautilus_dbus_launcher_parent_class)->finalize (object);
+}
+
+static void
+nautilus_dbus_launcher_class_init (NautilusDBusLauncherClass *klass)
+{
+    GObjectClass *object_class;
+
+    object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = nautilus_dbus_launcher_finalize;
+}
+
+static NautilusDBusLauncherData *
+nautilus_dbus_launcher_data_new (gboolean ping_on_creation)
+{
+    NautilusDBusLauncherData *data;
+
+    data = g_new0 (NautilusDBusLauncherData, 1);
+    data->proxy = NULL;
+    data->error = NULL;
+    data->ping_on_creation = ping_on_creation;
+
+    return data;
+}
+
+static void
+nautilus_dbus_launcher_init (NautilusDBusLauncher *self)
+{
+    self->data[NAUTILUS_DBUS_LAUNCHER_SETTINGS] = nautilus_dbus_launcher_data_new (FALSE);
+    self->data[NAUTILUS_DBUS_LAUNCHER_DISKS] = nautilus_dbus_launcher_data_new (TRUE);
+
+    nautilus_dbus_launcher_create_proxy (self->data[NAUTILUS_DBUS_LAUNCHER_SETTINGS],
+                                         "org.gnome.Settings", "/org/gnome/Settings",
+                                         "org.gtk.Actions");
+
+    nautilus_dbus_launcher_create_proxy (self->data[NAUTILUS_DBUS_LAUNCHER_DISKS],
+                                         "org.gnome.DiskUtility", "/org/gnome/DiskUtility",
+                                         "org.gtk.Application");
+}
diff --git a/src/nautilus-dbus-launcher.h b/src/nautilus-dbus-launcher.h
new file mode 100644
index 000000000..60f4233c7
--- /dev/null
+++ b/src/nautilus-dbus-launcher.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 Corey Berla <corey berla me>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include "nautilus-file.h"
+
+#define NAUTILUS_TYPE_DBUS_LAUNCHER (nautilus_dbus_launcher_get_type())
+
+G_DECLARE_FINAL_TYPE (NautilusDBusLauncher, nautilus_dbus_launcher, NAUTILUS, DBUS_LAUNCHER, GObject)
+
+
+typedef enum {
+    NAUTILUS_DBUS_LAUNCHER_SETTINGS,
+    NAUTILUS_DBUS_LAUNCHER_DISKS,
+    NAUTILUS_DBUS_LAUNCHER_N_APPS
+} NautilusDBusLauncherApp;
+
+NautilusDBusLauncher * nautilus_dbus_launcher_new (void); //to be called on `NautilusApplication::startup` 
only
+
+NautilusDBusLauncher * nautilus_dbus_launcher_get (void); //to be called by consumers; doesn't change 
reference count.
+
+gboolean nautilus_dbus_launcher_is_available (NautilusDBusLauncher    *self,
+                                              NautilusDBusLauncherApp  app);
+
+void nautilus_dbus_launcher_call (NautilusDBusLauncher    *self,
+                                  NautilusDBusLauncherApp  app,
+                                  const gchar             *method_name,
+                                  GVariant                *parameters,
+                                  GtkWindow               *window);
+


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