[gnome-builder] flatpak: use service to drive transfer



commit 6aab57f35cb89ca4e54803c74af139f3416a4a37
Author: Christian Hergert <chergert redhat com>
Date:   Tue May 4 16:24:32 2021 -0700

    flatpak: use service to drive transfer
    
    This moves the work of driving the transfer process to the service which
    calls back into the UI process to show the dialog and update notifications
    to the user.

 .../flatpak/daemon/ipc-flatpak-service-impl.c      |  47 +++++-
 src/plugins/flatpak/daemon/test-flatpak.c          |  18 +-
 src/plugins/flatpak/gbp-flatpak-install-dialog.c   |  29 +---
 src/plugins/flatpak/gbp-flatpak-runtime-provider.c | 186 +++++++++------------
 src/plugins/flatpak/ipc-flatpak-transfer-impl.c    | 153 +++++++++++++++++
 src/plugins/flatpak/ipc-flatpak-transfer-impl.h    |  35 ++++
 src/plugins/flatpak/meson.build                    |   1 +
 7 files changed, 325 insertions(+), 144 deletions(-)
---
diff --git a/src/plugins/flatpak/daemon/ipc-flatpak-service-impl.c 
b/src/plugins/flatpak/daemon/ipc-flatpak-service-impl.c
index 3e4f2caa4..8ef546e0c 100644
--- a/src/plugins/flatpak/daemon/ipc-flatpak-service-impl.c
+++ b/src/plugins/flatpak/daemon/ipc-flatpak-service-impl.c
@@ -219,6 +219,26 @@ ipc_flatpak_service_impl_ref_user_installation (IpcFlatpakServiceImpl *self)
   return g_object_ref (install->installation);
 }
 
+static gboolean
+is_installed (IpcFlatpakServiceImpl *self,
+              FlatpakRef            *ref)
+{
+  g_assert (IPC_IS_FLATPAK_SERVICE_IMPL (self));
+  g_assert (FLATPAK_IS_REF (ref));
+
+  for (guint i = 0; i < self->runtimes->len; i++)
+    {
+      const Runtime *r = g_ptr_array_index (self->runtimes, i);
+
+      if (str_equal0 (r->name, flatpak_ref_get_name (ref)) &&
+          str_equal0 (r->arch, flatpak_ref_get_arch (ref)) &&
+          str_equal0 (r->branch, flatpak_ref_get_branch (ref)))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
 static void
 runtime_free (Runtime *runtime)
 {
@@ -476,9 +496,9 @@ is_known_worker (GTask        *task,
             {
               FlatpakRemoteRef *remote_ref = g_ptr_array_index (refs, j);
 
-              if (g_str_equal (ref_name, flatpak_ref_get_name (FLATPAK_REF (remote_ref))) &&
-                  g_str_equal (ref_arch, flatpak_ref_get_arch (FLATPAK_REF (remote_ref))) &&
-                  g_str_equal (ref_branch, flatpak_ref_get_branch (FLATPAK_REF (remote_ref))))
+              if (str_equal0 (ref_name, flatpak_ref_get_name (FLATPAK_REF (remote_ref))) &&
+                  str_equal0 (ref_arch, flatpak_ref_get_arch (FLATPAK_REF (remote_ref))) &&
+                  str_equal0 (ref_branch, flatpak_ref_get_branch (FLATPAK_REF (remote_ref))))
                 {
                   found = TRUE;
                   download_size = flatpak_remote_ref_get_download_size (remote_ref);
@@ -824,7 +844,7 @@ ipc_flatpak_service_impl_install (IpcFlatpakService     *service,
 
   connection = g_dbus_method_invocation_get_connection (invocation);
   transfer = ipc_flatpak_transfer_proxy_new_sync (connection,
-                                                  G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+                                                  G_DBUS_PROXY_FLAGS_NONE,
                                                   NULL,
                                                   transfer_path,
                                                   NULL, NULL);
@@ -845,6 +865,9 @@ ipc_flatpak_service_impl_install (IpcFlatpakService     *service,
       g_autoptr(FlatpakRef) ref = flatpak_ref_parse (full_ref_names[i], NULL);
       InstallRef iref = {0};
 
+      if (ref != NULL && is_installed (self, ref))
+        continue;
+
       if (ref == NULL ||
           !(iref.remote = find_remote_for_ref (self, ref)))
         {
@@ -1136,23 +1159,29 @@ ipc_flatpak_service_impl_resolve_extension (IpcFlatpakService     *service,
   IpcFlatpakServiceImpl *self = (IpcFlatpakServiceImpl *)service;
   ResolveExtensionState *state;
   g_autoptr(GTask) task = NULL;
-  GHashTableIter iter;
-  Install *install;
 
   g_assert (IPC_IS_FLATPAK_SERVICE_IMPL (self));
   g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
   g_assert (sdk != NULL);
   g_assert (extension != NULL);
 
+  if (g_str_has_prefix (sdk, "runtime/"))
+    sdk += strlen ("runtime/");
+
+  if (g_str_has_prefix (extension, "runtime/"))
+    extension += strlen ("runtime/");
+
   state = g_slice_new0 (ResolveExtensionState);
   state->installs = g_ptr_array_new_with_free_func (g_object_unref);
   state->invocation = g_steal_pointer (&invocation);
   state->sdk = g_strdup (sdk);
   state->extension = g_strdup (extension);
 
-  g_hash_table_iter_init (&iter, self->installs);
-  while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&install))
-    g_ptr_array_add (state->installs, g_object_ref (install->installation));
+  for (guint i = 0; i < self->installs_ordered->len; i++)
+    {
+      const Install *install = g_ptr_array_index (self->installs_ordered, i);
+      g_ptr_array_add (state->installs, g_object_ref (install->installation));
+    }
 
   task = g_task_new (self, NULL, NULL, NULL);
   g_task_set_source_tag (task, ipc_flatpak_service_impl_resolve_extension);
diff --git a/src/plugins/flatpak/daemon/test-flatpak.c b/src/plugins/flatpak/daemon/test-flatpak.c
index aa911bb34..82a59cacf 100644
--- a/src/plugins/flatpak/daemon/test-flatpak.c
+++ b/src/plugins/flatpak/daemon/test-flatpak.c
@@ -126,8 +126,22 @@ add_install_cb (GObject      *object,
   g_assert_true (ret);
   g_message ("  Found");
 
-  g_message ("Resolving org.freedesktop.Sdk.Extension.rust-stable for org.gnome.Sdk/x86_64/master");
-  ret = ipc_flatpak_service_call_resolve_extension_sync (service, "org.gnome.Sdk/x86_64/master", 
"org.freedesktop.Sdk.Extension.rust-stable", &resolved, NULL, &error);
+  g_message ("Resolving org.freedesktop.Sdk.Extension.rust-stable for runtime/org.gnome.Sdk/x86_64/40");
+  ret = ipc_flatpak_service_call_resolve_extension_sync (service, "runtime/org.gnome.Sdk/x86_64/40", 
"org.freedesktop.Sdk.Extension.rust-stable", &resolved, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (ret);
+  g_message (" Resolved to %s", resolved);
+  g_assert_cmpstr (resolved, ==, "org.freedesktop.Sdk.Extension.rust-stable/x86_64/20.08");
+  g_clear_pointer (&resolved, g_free);
+
+  g_message ("Resolving org.freedesktop.Sdk.Extension.rust-stable for runtime/org.gnome.Platform/x86_64/40");
+  ret = ipc_flatpak_service_call_resolve_extension_sync (service, "runtime/org.gnome.Platform/x86_64/40", 
"org.freedesktop.Sdk.Extension.rust-stable", &resolved, NULL, &error);
+  g_assert_false (ret);
+  g_clear_pointer (&resolved, g_free);
+  g_clear_error (&error);
+
+  g_message ("Resolving org.freedesktop.Sdk.Extension.rust-stable for org.gnome.Sdk/x86_64/40");
+  ret = ipc_flatpak_service_call_resolve_extension_sync (service, "org.gnome.Sdk/x86_64/40", 
"org.freedesktop.Sdk.Extension.rust-stable", &resolved, NULL, &error);
   g_assert_no_error (error);
   g_assert_true (ret);
   g_message (" Resolved to %s", resolved);
diff --git a/src/plugins/flatpak/gbp-flatpak-install-dialog.c 
b/src/plugins/flatpak/gbp-flatpak-install-dialog.c
index a52e7da1b..bc1db6392 100644
--- a/src/plugins/flatpak/gbp-flatpak-install-dialog.c
+++ b/src/plugins/flatpak/gbp-flatpak-install-dialog.c
@@ -65,6 +65,11 @@ gbp_flatpak_install_dialog_response (GtkDialog *dialog,
 
   if (self->close_task && response_id == GTK_RESPONSE_OK)
     ide_task_return_boolean (self->close_task, TRUE);
+  else
+    ide_task_return_new_error (self->close_task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_CANCELLED,
+                               "User cancelled the request");
 
   if (GTK_DIALOG_CLASS (gbp_flatpak_install_dialog_parent_class)->response)
     GTK_DIALOG_CLASS (gbp_flatpak_install_dialog_parent_class)->response (dialog, response_id);
@@ -119,24 +124,6 @@ gbp_flatpak_install_dialog_init (GbpFlatpakInstallDialog *self)
   dzl_gtk_widget_add_style_class (button, "suggested-action");
 }
 
-static void
-gbp_flatpak_install_dialog_on_close_cb (GbpFlatpakInstallDialog *self,
-                                        IdeTask                 *task)
-{
-  g_assert (GBP_IS_FLATPAK_INSTALL_DIALOG (self));
-  g_assert (IDE_IS_TASK (task));
-
-  g_signal_handlers_disconnect_by_func (self,
-                                        G_CALLBACK (gbp_flatpak_install_dialog_on_close_cb),
-                                        task);
-
-  if (self->response_id != GTK_RESPONSE_OK)
-    ide_task_return_new_error (task,
-                               G_IO_ERROR,
-                               G_IO_ERROR_CANCELLED,
-                               "User cancelled the request");
-}
-
 void
 gbp_flatpak_install_dialog_run_async (GbpFlatpakInstallDialog *self,
                                       GCancellable            *cancellable,
@@ -167,12 +154,6 @@ gbp_flatpak_install_dialog_run_async (GbpFlatpakInstallDialog *self,
                              self,
                              G_CONNECT_SWAPPED);
 
-  g_signal_connect_object (self,
-                           "close",
-                           G_CALLBACK (gbp_flatpak_install_dialog_on_close_cb),
-                           self->close_task,
-                           G_CONNECT_AFTER);
-
   ide_gtk_window_present (GTK_WINDOW (self));
 }
 
diff --git a/src/plugins/flatpak/gbp-flatpak-runtime-provider.c 
b/src/plugins/flatpak/gbp-flatpak-runtime-provider.c
index f1b24a6ab..bcb6b84f2 100644
--- a/src/plugins/flatpak/gbp-flatpak-runtime-provider.c
+++ b/src/plugins/flatpak/gbp-flatpak-runtime-provider.c
@@ -27,7 +27,6 @@
 #include <libide-gui.h>
 
 #include "gbp-flatpak-client.h"
-#include "gbp-flatpak-install-dialog.h"
 #include "gbp-flatpak-manifest.h"
 #include "gbp-flatpak-runtime.h"
 #include "gbp-flatpak-runtime-provider.h"
@@ -37,6 +36,8 @@
 #include "daemon/ipc-flatpak-transfer.h"
 #include "daemon/ipc-flatpak-util.h"
 
+#include "ipc-flatpak-transfer-impl.h"
+
 struct _GbpFlatpakRuntimeProvider
 {
   IdeObject parent_instance;
@@ -199,17 +200,11 @@ gbp_flatpak_runtime_provider_unload (IdeRuntimeProvider *provider,
   g_ptr_array_remove_range (self->runtimes, 0, self->runtimes->len);
 }
 
-typedef struct
-{
-  GbpFlatpakRuntimeProvider *self;
-  GDBusMethodInvocation *invocation;
-  IpcFlatpakTransfer *transfer;
-} Confirm;
-
 typedef struct
 {
   char               *runtime_id;
   char               *transfer_path;
+  char               *sdk;
   GPtrArray          *to_install;
   IpcFlatpakTransfer *transfer;
   IpcFlatpakService  *service;
@@ -220,6 +215,7 @@ static void
 bootstrap_free (Bootstrap *b)
 {
   g_clear_pointer (&b->runtime_id, g_free);
+  g_clear_pointer (&b->sdk, g_free);
   g_clear_pointer (&b->transfer_path, g_free);
   g_clear_object (&b->notif);
   g_clear_object (&b->service);
@@ -228,82 +224,6 @@ bootstrap_free (Bootstrap *b)
   g_slice_free (Bootstrap, b);
 }
 
-static void
-gbp_flatpak_runtime_provider_handle_confirm_cb (GObject      *object,
-                                                GAsyncResult *result,
-                                                gpointer      user_data)
-{
-  GbpFlatpakInstallDialog *dialog = (GbpFlatpakInstallDialog *)object;
-  Confirm *state = user_data;
-  g_autoptr(GError) error = NULL;
-
-  g_assert (GBP_IS_FLATPAK_INSTALL_DIALOG (dialog));
-  g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (state != NULL);
-  g_assert (G_IS_DBUS_METHOD_INVOCATION (state->invocation));
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (state->self));
-  g_assert (IPC_IS_FLATPAK_TRANSFER (state->transfer));
-
-  if (!gbp_flatpak_install_dialog_run_finish (dialog, result, &error))
-    g_dbus_method_invocation_return_error (g_steal_pointer (&state->invocation),
-                                           G_DBUS_ERROR,
-                                           G_DBUS_ERROR_FAILED,
-                                           "Unconfirmed request");
-  else
-    ipc_flatpak_transfer_complete_confirm (state->transfer,
-                                           g_steal_pointer (&state->invocation));
-
-  g_clear_object (&state->invocation);
-  g_clear_object (&state->transfer);
-  g_clear_object (&state->self);
-  g_slice_free (Confirm, state);
-}
-
-static gboolean
-gbp_flatpak_runtime_provider_handle_confirm (GbpFlatpakRuntimeProvider *self,
-                                             GDBusMethodInvocation     *invocation,
-                                             const char * const        *refs,
-                                             IpcFlatpakTransfer        *transfer)
-{
-  g_autoptr(IdeContext) context = NULL;
-  GbpFlatpakInstallDialog *dialog;
-  IdeWorkbench *workbench;
-  IdeWorkspace *workspace;
-  Confirm *state;
-
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
-  g_assert (refs != NULL);
-  g_assert (IPC_IS_FLATPAK_TRANSFER (transfer));
-
-  context = ide_object_ref_context (IDE_OBJECT (self));
-  workbench = ide_workbench_from_context (context);
-  workspace = ide_workbench_get_current_workspace (workbench);
-  dialog = gbp_flatpak_install_dialog_new (GTK_WINDOW (workspace));
-
-  for (guint i = 0; refs[i]; i++)
-    gbp_flatpak_install_dialog_add_runtime (dialog, refs[i]);
-
-  if (gbp_flatpak_install_dialog_is_empty (dialog))
-    {
-      gtk_widget_destroy (GTK_WIDGET (dialog));
-      ipc_flatpak_transfer_complete_confirm (transfer, g_steal_pointer (&invocation));
-      return TRUE;
-    }
-
-  state = g_slice_new0 (Confirm);
-  state->self = g_object_ref (self);
-  state->transfer = g_object_ref (transfer);
-  state->invocation = g_object_ref (invocation);
-
-  gbp_flatpak_install_dialog_run_async (dialog,
-                                        NULL,
-                                        gbp_flatpak_runtime_provider_handle_confirm_cb,
-                                        state);
-
-  return TRUE;
-}
-
 static IdeRuntime *
 find_runtime (GbpFlatpakRuntimeProvider *self,
               const char                *runtime_id)
@@ -357,8 +277,6 @@ gbp_flatpak_runtime_provider_bootstrap_install_cb (GObject      *object,
   else
     ide_task_return_pointer (task, g_steal_pointer (&runtime), g_object_unref);
 
-  ide_notification_withdraw (state->notif);
-
   IDE_EXIT;
 }
 
@@ -378,20 +296,36 @@ gbp_flatpak_runtime_provider_bootstrap_complete (gpointer data)
   state = ide_task_get_task_data (task);
 
   g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (state->to_install != NULL);
-  g_assert (IPC_IS_FLATPAK_SERVICE (state->service));
-  g_assert (state->transfer_path != NULL);
-  g_assert (IDE_IS_NOTIFICATION (state->notif));
-
-  ide_notification_attach (state->notif, IDE_OBJECT (self));
+  g_assert (state != NULL);
+  g_assert (!state->notif || IDE_IS_NOTIFICATION (state->notif));
+  g_assert (!state->service || IPC_IS_FLATPAK_SERVICE (state->service));
+  g_assert (!state->transfer || IPC_IS_FLATPAK_TRANSFER (state->transfer));
 
-  ipc_flatpak_service_call_install (state->service,
-                                    (const char * const *)state->to_install->pdata,
-                                    state->transfer_path,
-                                    "",
-                                    ide_task_get_cancellable (task),
-                                    gbp_flatpak_runtime_provider_bootstrap_install_cb,
-                                    g_object_ref (task));
+  if (state->to_install->len > 0)
+    {
+      g_assert (IDE_IS_NOTIFICATION (state->notif));
+      g_assert (IPC_IS_FLATPAK_SERVICE (state->service));
+      g_assert (IPC_IS_FLATPAK_TRANSFER (state->transfer));
+
+      ide_notification_attach (state->notif, IDE_OBJECT (self));
+      ipc_flatpak_service_call_install (state->service,
+                                        (const char * const *)state->to_install->pdata,
+                                        state->transfer_path,
+                                        "",
+                                        ide_task_get_cancellable (task),
+                                        gbp_flatpak_runtime_provider_bootstrap_install_cb,
+                                        g_object_ref (task));
+    }
+  else
+    {
+      if (!(runtime = find_runtime (self, state->runtime_id)))
+        ide_task_return_new_error (task,
+                                   G_IO_ERROR,
+                                   G_IO_ERROR_CANCELLED,
+                                   "Operation was cancelled");
+      else
+        ide_task_return_pointer (task, g_steal_pointer (&runtime), g_object_unref);
+    }
 
   IDE_RETURN (G_SOURCE_REMOVE);
 }
@@ -431,12 +365,32 @@ gbp_flatpak_runtime_provider_bootstrap (IdeTask      *task,
   /* Filter out anything we can't find or is already installed */
   for (guint i = state->to_install->len; i > 0; i--)
     {
-      const char *id = g_ptr_array_index (state->to_install, i-1);
+      char *id = g_ptr_array_index (state->to_install, i-1);
       gboolean is_known = FALSE;
       gint64 size = 0;
 
+      /* If this is a plain SDK extension name, resolve it now */
+      if (strchr (id, '/') == NULL)
+        {
+          g_autofree char *resolved = NULL;
+
+          if (ipc_flatpak_service_call_resolve_extension_sync (service, state->sdk, id, &resolved, NULL, 
NULL))
+            {
+              g_autofree char *old = g_steal_pointer (&id);
+              g_ptr_array_index (state->to_install, i-1) = id = g_steal_pointer (&resolved);
+            }
+        }
+
+      /* If we're missing runtime/ (or app/) prefix, add it now */
+      if (!g_str_has_prefix (id, "runtime/") && !g_str_has_prefix (id, "app/"))
+        {
+          g_autofree char *old = id;
+          g_ptr_array_index (state->to_install, i-1) = id = g_strdup_printf ("runtime/%s", old);
+        }
+
+      /* Ignore this unless we know it can be installed from a peer */
       if (!ipc_flatpak_service_call_runtime_is_known_sync (service, id, &is_known, &size, NULL, NULL) ||
-          is_known == TRUE)
+          is_known == FALSE)
         g_ptr_array_remove_index (state->to_install, i-1);
     }
 
@@ -448,28 +402,36 @@ gbp_flatpak_runtime_provider_bootstrap (IdeTask      *task,
       g_autoptr(GError) error = NULL;
 
       notif = ide_notification_new ();
-      ide_notification_set_icon_name (notif, "system-software-install");
+      ide_notification_set_icon_name (notif, "system-software-install-symbolic");
       ide_notification_set_title (notif, _("Installing Necessary SDKs"));
       ide_notification_set_body (notif, _("Builder is installing Software Development Kits necessary for 
building your application."));
       ide_notification_set_has_progress (notif, TRUE);
       ide_notification_set_progress_is_imprecise (notif, FALSE);
 
-      transfer = ipc_flatpak_transfer_skeleton_new ();
-      g_signal_connect_object (transfer,
-                               "handle-confirm",
-                               G_CALLBACK (gbp_flatpak_runtime_provider_handle_confirm),
-                               source_object,
+      g_signal_connect_object (task,
+                               "notify::completed",
+                               G_CALLBACK (ide_notification_withdraw),
+                               notif,
                                G_CONNECT_SWAPPED);
+
+      transfer = ipc_flatpak_transfer_impl_new (context);
       g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (transfer),
                                         g_dbus_proxy_get_connection (G_DBUS_PROXY (service)),
                                         transfer_path,
-                                        NULL);
+                                        &error);
+
+      if (error != NULL)
+        {
+          g_warning ("Failed to register transfer object on D-Bus: %s", error->message);
+          g_clear_error (&error);
+        }
 
       g_object_bind_property (transfer, "fraction", notif, "progress", G_BINDING_SYNC_CREATE);
       g_object_bind_property (transfer, "message", notif, "body", G_BINDING_DEFAULT);
 
       state->service = g_object_ref (service);
       state->notif = g_object_ref (notif);
+      state->transfer = g_object_ref (transfer);
       state->transfer_path = g_strdup (transfer_path);
 
       g_ptr_array_add (state->to_install, NULL);
@@ -481,6 +443,8 @@ gbp_flatpak_runtime_provider_bootstrap (IdeTask      *task,
                       g_object_ref (task),
                       g_object_unref);
 
+  IDE_EXIT;
+
 failure:
 
   if (transfer != NULL)
@@ -520,6 +484,8 @@ gbp_flatpak_runtime_provider_bootstrap_async (IdeRuntimeProvider  *provider,
   task = ide_task_new (self, cancellable, callback, user_data);
   ide_task_set_source_tag (task, gbp_flatpak_runtime_provider_bootstrap_async);
   ide_task_set_task_data (task, state, bootstrap_free);
+  ide_task_set_return_on_cancel (task, FALSE);
+  ide_task_set_release_on_propagate (task, FALSE);
 
   /* Collect all of the runtimes that could be needed */
   if (GBP_IS_FLATPAK_MANIFEST (config))
@@ -545,7 +511,7 @@ gbp_flatpak_runtime_provider_bootstrap_async (IdeRuntimeProvider  *provider,
       if (extensions != NULL)
         {
           for (guint i = 0; extensions[i]; i++)
-            g_ptr_array_add (state->to_install, g_strdup_printf ("runtime/%s", extensions[i]));
+            g_ptr_array_add (state->to_install, g_strdup (extensions[i]));
         }
     }
   else
@@ -572,6 +538,8 @@ gbp_flatpak_runtime_provider_bootstrap_async (IdeRuntimeProvider  *provider,
         }
     }
 
+  state->sdk = g_strdup (full_sdk);
+
   if (state->to_install->len == 0)
     {
       ide_task_return_new_error (task,
diff --git a/src/plugins/flatpak/ipc-flatpak-transfer-impl.c b/src/plugins/flatpak/ipc-flatpak-transfer-impl.c
new file mode 100644
index 000000000..58685d788
--- /dev/null
+++ b/src/plugins/flatpak/ipc-flatpak-transfer-impl.c
@@ -0,0 +1,153 @@
+/* ipc-flatpak-transfer-impl.c
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ipc-flatpak-transfer-impl"
+
+#include "config.h"
+
+#include <libide-core.h>
+#include <libide-gui.h>
+
+#include "ipc-flatpak-transfer-impl.h"
+#include "gbp-flatpak-install-dialog.h"
+
+struct _IpcFlatpakTransferImpl
+{
+  IpcFlatpakTransferSkeleton parent_instance;
+  IdeContext *context;
+};
+
+static void transfer_iface_init (IpcFlatpakTransferIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (IpcFlatpakTransferImpl, ipc_flatpak_transfer_impl, 
IPC_TYPE_FLATPAK_TRANSFER_SKELETON,
+                         G_IMPLEMENT_INTERFACE (IPC_TYPE_FLATPAK_TRANSFER, transfer_iface_init))
+
+typedef struct
+{
+  GDBusMethodInvocation *invocation;
+  IpcFlatpakTransfer *transfer;
+} Confirm;
+
+static void
+gbp_flatpak_runtime_provider_handle_confirm_cb (GObject      *object,
+                                                GAsyncResult *result,
+                                                gpointer      user_data)
+{
+  GbpFlatpakInstallDialog *dialog = (GbpFlatpakInstallDialog *)object;
+  Confirm *state = user_data;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (GBP_IS_FLATPAK_INSTALL_DIALOG (dialog));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (state != NULL);
+  g_assert (G_IS_DBUS_METHOD_INVOCATION (state->invocation));
+  g_assert (IPC_IS_FLATPAK_TRANSFER (state->transfer));
+
+  if (!gbp_flatpak_install_dialog_run_finish (dialog, result, &error))
+    g_dbus_method_invocation_return_error (g_steal_pointer (&state->invocation),
+                                           G_DBUS_ERROR,
+                                           G_DBUS_ERROR_FAILED,
+                                           "Unconfirmed request");
+  else
+    ipc_flatpak_transfer_complete_confirm (state->transfer,
+                                           g_steal_pointer (&state->invocation));
+
+  g_clear_object (&state->invocation);
+  g_clear_object (&state->transfer);
+  g_slice_free (Confirm, state);
+}
+
+static gboolean
+ipc_flatpak_transfer_impl_handle_confirm (IpcFlatpakTransfer    *transfer,
+                                          GDBusMethodInvocation *invocation,
+                                          const char * const    *refs)
+{
+  IpcFlatpakTransferImpl *self = (IpcFlatpakTransferImpl *)transfer;
+  GbpFlatpakInstallDialog *dialog;
+  IdeWorkbench *workbench;
+  IdeWorkspace *workspace;
+  Confirm *state;
+
+  g_assert (IPC_IS_FLATPAK_TRANSFER_IMPL (self));
+  g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
+  g_assert (refs != NULL);
+
+  workbench = ide_workbench_from_context (self->context);
+  workspace = ide_workbench_get_current_workspace (workbench);
+  dialog = gbp_flatpak_install_dialog_new (GTK_WINDOW (workspace));
+
+  for (guint i = 0; refs[i]; i++)
+    gbp_flatpak_install_dialog_add_runtime (dialog, refs[i]);
+
+  if (gbp_flatpak_install_dialog_is_empty (dialog))
+    {
+      gtk_widget_destroy (GTK_WIDGET (dialog));
+      ipc_flatpak_transfer_complete_confirm (transfer, g_steal_pointer (&invocation));
+      return TRUE;
+    }
+
+  state = g_slice_new0 (Confirm);
+  state->transfer = g_object_ref (transfer);
+  state->invocation = g_object_ref (invocation);
+
+  gbp_flatpak_install_dialog_run_async (dialog,
+                                        NULL,
+                                        gbp_flatpak_runtime_provider_handle_confirm_cb,
+                                        state);
+
+  return TRUE;
+}
+
+static void
+ipc_flatpak_transfer_impl_finalize (GObject *object)
+{
+  IpcFlatpakTransferImpl *self = (IpcFlatpakTransferImpl *)object;
+
+  g_clear_object (&self->context);
+
+  G_OBJECT_CLASS (ipc_flatpak_transfer_impl_parent_class)->finalize (object);
+}
+
+static void
+ipc_flatpak_transfer_impl_class_init (IpcFlatpakTransferImplClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ipc_flatpak_transfer_impl_finalize;
+}
+
+static void
+ipc_flatpak_transfer_impl_init (IpcFlatpakTransferImpl *self)
+{
+}
+
+IpcFlatpakTransfer *
+ipc_flatpak_transfer_impl_new (IdeContext *context)
+{
+  IpcFlatpakTransferImpl *self = g_object_new (IPC_TYPE_FLATPAK_TRANSFER_IMPL, NULL);
+  g_set_object (&self->context, context);
+  return IPC_FLATPAK_TRANSFER (self);
+}
+
+static void
+transfer_iface_init (IpcFlatpakTransferIface *iface)
+{
+  iface->handle_confirm = ipc_flatpak_transfer_impl_handle_confirm;
+}
diff --git a/src/plugins/flatpak/ipc-flatpak-transfer-impl.h b/src/plugins/flatpak/ipc-flatpak-transfer-impl.h
new file mode 100644
index 000000000..43d735d70
--- /dev/null
+++ b/src/plugins/flatpak/ipc-flatpak-transfer-impl.h
@@ -0,0 +1,35 @@
+/* ipc-flatpak-transfer-impl.h
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-core.h>
+
+#include "daemon/ipc-flatpak-transfer.h"
+
+G_BEGIN_DECLS
+
+#define IPC_TYPE_FLATPAK_TRANSFER_IMPL (ipc_flatpak_transfer_impl_get_type())
+
+G_DECLARE_FINAL_TYPE (IpcFlatpakTransferImpl, ipc_flatpak_transfer_impl, IPC, FLATPAK_TRANSFER_IMPL, 
IpcFlatpakTransferSkeleton)
+
+IpcFlatpakTransfer *ipc_flatpak_transfer_impl_new (IdeContext *context);
+
+G_END_DECLS
diff --git a/src/plugins/flatpak/meson.build b/src/plugins/flatpak/meson.build
index e885c22cc..ce7934ddf 100644
--- a/src/plugins/flatpak/meson.build
+++ b/src/plugins/flatpak/meson.build
@@ -36,6 +36,7 @@ plugins_sources += files([
   'gbp-flatpak-transfer.c',
   'gbp-flatpak-util.c',
   'gbp-flatpak-workbench-addin.c',
+  'ipc-flatpak-transfer-impl.c',
 ])
 
 plugin_flatpak_resources = gnome.compile_resources(


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