[gnome-builder] flatpak: simplify flatpak runtime management



commit 5a93d9477c0b32132699a789f8cf0ae6681ea697
Author: Christian Hergert <chergert redhat com>
Date:   Mon May 3 17:01:04 2021 -0700

    flatpak: simplify flatpak runtime management
    
    This makes the runtime provider a thin wrapper around the service
    provided via the gnome-builder-flatpak daemon.

 src/libide/foundry/ide-runtime-provider.c          | 116 +--
 src/libide/foundry/ide-runtime-provider.h          |  26 +-
 src/plugins/flatpak/daemon/ipc-flatpak-util.h      |   7 +-
 src/plugins/flatpak/daemon/test-flatpak.c          |   1 +
 src/plugins/flatpak/gbp-flatpak-config-provider.c  |   2 +-
 src/plugins/flatpak/gbp-flatpak-manifest.c         |   7 +-
 src/plugins/flatpak/gbp-flatpak-runtime-provider.c | 913 +++------------------
 src/plugins/flatpak/gbp-flatpak-runtime-provider.h |   2 +-
 src/plugins/flatpak/gbp-flatpak-runtime.c          |  79 +-
 src/plugins/flatpak/gbp-flatpak-runtime.h          |  26 +-
 10 files changed, 175 insertions(+), 1004 deletions(-)
---
diff --git a/src/libide/foundry/ide-runtime-provider.c b/src/libide/foundry/ide-runtime-provider.c
index d340fc173..85c3905ea 100644
--- a/src/libide/foundry/ide-runtime-provider.c
+++ b/src/libide/foundry/ide-runtime-provider.c
@@ -47,72 +47,11 @@ ide_runtime_provider_real_unload (IdeRuntimeProvider *self,
 
 static gboolean
 ide_runtime_provider_real_provides (IdeRuntimeProvider *self,
-                                       const gchar        *runtime_id)
+                                    const gchar        *runtime_id)
 {
   return FALSE;
 }
 
-static void
-ide_runtime_provider_real_install_async (IdeRuntimeProvider  *self,
-                                         const gchar         *runtime_id,
-                                         GCancellable        *cancellable,
-                                         GAsyncReadyCallback  callback,
-                                         gpointer             user_data)
-{
-  ide_task_report_new_error (self, callback, user_data,
-                             ide_runtime_provider_real_install_async,
-                             G_IO_ERROR,
-                             G_IO_ERROR_NOT_SUPPORTED,
-                             "%s does not support installing runtimes",
-                             G_OBJECT_TYPE_NAME (self));
-}
-
-static gboolean
-ide_runtime_provider_real_install_finish (IdeRuntimeProvider  *self,
-                                          GAsyncResult        *result,
-                                          GError             **error)
-{
-  return ide_task_propagate_boolean (IDE_TASK (result), error);
-}
-
-static void
-ide_runtime_provider_real_bootstrap_cb (GObject      *object,
-                                        GAsyncResult *result,
-                                        gpointer      user_data)
-{
-  IdeRuntimeProvider *self = (IdeRuntimeProvider *)object;
-  g_autoptr(GError) error = NULL;
-  g_autoptr(IdeTask) task = user_data;
-  IdeRuntimeManager *runtime_manager;
-  const gchar *runtime_id;
-  IdeContext *context;
-  IdeRuntime *runtime;
-
-  g_assert (IDE_IS_RUNTIME_PROVIDER (self));
-  g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (IDE_IS_TASK (task));
-
-  if (!ide_runtime_provider_install_finish (self, result, &error))
-    {
-      ide_task_return_error (task, g_steal_pointer (&error));
-      return;
-    }
-
-  runtime_id = ide_task_get_task_data (task);
-  context = ide_object_get_context (IDE_OBJECT (self));
-  runtime_manager = ide_runtime_manager_from_context (context);
-  runtime = ide_runtime_manager_get_runtime (runtime_manager, runtime_id);
-
-  if (runtime == NULL)
-    ide_task_return_new_error (task,
-                               G_IO_ERROR,
-                               G_IO_ERROR_NOT_FOUND,
-                               "No such runtime \"%s\"",
-                               runtime_id);
-  else
-    ide_task_return_pointer (task, g_object_ref (runtime), g_object_unref);
-}
-
 static void
 ide_runtime_provider_real_bootstrap_async (IdeRuntimeProvider  *self,
                                            IdePipeline    *pipeline,
@@ -121,8 +60,6 @@ ide_runtime_provider_real_bootstrap_async (IdeRuntimeProvider  *self,
                                            gpointer             user_data)
 {
   g_autoptr(IdeTask) task = NULL;
-  IdeConfig *config;
-  const gchar *runtime_id;
 
   IDE_ENTRY;
 
@@ -134,21 +71,11 @@ ide_runtime_provider_real_bootstrap_async (IdeRuntimeProvider  *self,
   ide_task_set_source_tag (task, ide_runtime_provider_real_bootstrap_async);
   ide_task_set_priority (task, G_PRIORITY_LOW);
 
-  config = ide_pipeline_get_config (pipeline);
-  runtime_id = ide_config_get_runtime_id (config);
-  ide_task_set_task_data (task, g_strdup (runtime_id), g_free);
-
-  if (runtime_id == NULL)
-    ide_task_return_new_error (task,
-                               G_IO_ERROR,
-                               G_IO_ERROR_FAILED,
-                               "No runtime provided to install");
-  else
-    ide_runtime_provider_install_async (self,
-                                        runtime_id,
-                                        cancellable,
-                                        ide_runtime_provider_real_bootstrap_cb,
-                                        g_steal_pointer (&task));
+  ide_task_return_new_error (task,
+                             G_IO_ERROR,
+                             G_IO_ERROR_NOT_SUPPORTED,
+                             "Bootstrapping runtime not supported for %s",
+                             G_OBJECT_TYPE_NAME (self));
 
   IDE_EXIT;
 }
@@ -158,9 +85,7 @@ ide_runtime_provider_real_bootstrap_finish (IdeRuntimeProvider  *self,
                                             GAsyncResult        *result,
                                             GError             **error)
 {
-  IdeRuntime *ret = ide_task_propagate_pointer (IDE_TASK (result), error);
-  g_return_val_if_fail (!ret || IDE_IS_RUNTIME (ret), NULL);
-  return ret;
+  return ide_task_propagate_pointer (IDE_TASK (result), error);
 }
 
 static void
@@ -169,8 +94,6 @@ ide_runtime_provider_default_init (IdeRuntimeProviderInterface *iface)
   iface->load = ide_runtime_provider_real_load;
   iface->unload = ide_runtime_provider_real_unload;
   iface->provides = ide_runtime_provider_real_provides;
-  iface->install_async = ide_runtime_provider_real_install_async;
-  iface->install_finish = ide_runtime_provider_real_install_finish;
   iface->bootstrap_async = ide_runtime_provider_real_bootstrap_async;
   iface->bootstrap_finish = ide_runtime_provider_real_bootstrap_finish;
 }
@@ -205,31 +128,6 @@ ide_runtime_provider_provides (IdeRuntimeProvider *self,
   return IDE_RUNTIME_PROVIDER_GET_IFACE (self)->provides (self, runtime_id);
 }
 
-void
-ide_runtime_provider_install_async (IdeRuntimeProvider  *self,
-                                    const gchar         *runtime_id,
-                                    GCancellable        *cancellable,
-                                    GAsyncReadyCallback  callback,
-                                    gpointer             user_data)
-{
-  g_return_if_fail (IDE_IS_RUNTIME_PROVIDER (self));
-  g_return_if_fail (runtime_id != NULL);
-  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
-
-  IDE_RUNTIME_PROVIDER_GET_IFACE (self)->install_async (self, runtime_id, cancellable, callback, user_data);
-}
-
-gboolean
-ide_runtime_provider_install_finish (IdeRuntimeProvider  *self,
-                                     GAsyncResult        *result,
-                                     GError             **error)
-{
-  g_return_val_if_fail (IDE_IS_RUNTIME_PROVIDER (self), FALSE);
-  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
-
-  return IDE_RUNTIME_PROVIDER_GET_IFACE (self)->install_finish (self, result, error);
-}
-
 /**
  * ide_runtime_provider_bootstrap_async:
  * @self: a #IdeRuntimeProvider
diff --git a/src/libide/foundry/ide-runtime-provider.h b/src/libide/foundry/ide-runtime-provider.h
index e485b50aa..db6ca9df5 100644
--- a/src/libide/foundry/ide-runtime-provider.h
+++ b/src/libide/foundry/ide-runtime-provider.h
@@ -43,18 +43,10 @@ struct _IdeRuntimeProviderInterface
                                    IdeRuntimeManager    *manager);
   void        (*unload)           (IdeRuntimeProvider   *self,
                                    IdeRuntimeManager    *manager);
-  gboolean    (*provides)      (IdeRuntimeProvider   *self,
+  gboolean    (*provides)         (IdeRuntimeProvider   *self,
                                    const gchar          *runtime_id);
-  void        (*install_async)    (IdeRuntimeProvider   *self,
-                                   const gchar          *runtime_id,
-                                   GCancellable         *cancellable,
-                                   GAsyncReadyCallback   callback,
-                                   gpointer              user_data);
-  gboolean    (*install_finish)   (IdeRuntimeProvider   *self,
-                                   GAsyncResult         *result,
-                                   GError              **error);
   void        (*bootstrap_async)  (IdeRuntimeProvider   *self,
-                                   IdePipeline     *pipeline,
+                                   IdePipeline          *pipeline,
                                    GCancellable         *cancellable,
                                    GAsyncReadyCallback   callback,
                                    gpointer              user_data);
@@ -70,21 +62,11 @@ IDE_AVAILABLE_IN_3_32
 void        ide_runtime_provider_unload           (IdeRuntimeProvider   *self,
                                                    IdeRuntimeManager    *manager);
 IDE_AVAILABLE_IN_3_40
-gboolean    ide_runtime_provider_provides      (IdeRuntimeProvider   *self,
+gboolean    ide_runtime_provider_provides         (IdeRuntimeProvider   *self,
                                                    const gchar          *runtime_id);
 IDE_AVAILABLE_IN_3_32
-void        ide_runtime_provider_install_async    (IdeRuntimeProvider   *self,
-                                                   const gchar          *runtime_id,
-                                                   GCancellable         *cancellable,
-                                                   GAsyncReadyCallback   callback,
-                                                   gpointer              user_data);
-IDE_AVAILABLE_IN_3_32
-gboolean    ide_runtime_provider_install_finish   (IdeRuntimeProvider   *self,
-                                                   GAsyncResult         *result,
-                                                   GError              **error);
-IDE_AVAILABLE_IN_3_32
 void        ide_runtime_provider_bootstrap_async  (IdeRuntimeProvider   *self,
-                                                   IdePipeline     *pipeline,
+                                                   IdePipeline          *pipeline,
                                                    GCancellable         *cancellable,
                                                    GAsyncReadyCallback   callback,
                                                    gpointer              user_data);
diff --git a/src/plugins/flatpak/daemon/ipc-flatpak-util.h b/src/plugins/flatpak/daemon/ipc-flatpak-util.h
index 18c7c3b14..e4f51150c 100644
--- a/src/plugins/flatpak/daemon/ipc-flatpak-util.h
+++ b/src/plugins/flatpak/daemon/ipc-flatpak-util.h
@@ -24,9 +24,10 @@
 
 G_BEGIN_DECLS
 
-#define RUNTIME_VARIANT_STRING     "(sssssssb)"
-#define RUNTIME_VARIANT_TYPE       G_VARIANT_TYPE(RUNTIME_VARIANT_STRING)
-#define RUNTIME_ARRAY_VARIANT_TYPE G_VARIANT_TYPE("a" RUNTIME_VARIANT_STRING)
+#define RUNTIME_VARIANT_STRING       "(sssssssb)"
+#define RUNTIME_VARIANT_TYPE         G_VARIANT_TYPE(RUNTIME_VARIANT_STRING)
+#define RUNTIME_ARRAY_VARIANT_STRING "a"RUNTIME_VARIANT_STRING
+#define RUNTIME_ARRAY_VARIANT_TYPE   G_VARIANT_TYPE("a" RUNTIME_VARIANT_STRING)
 
 static inline gboolean
 complete_wrapped_error (GDBusMethodInvocation *invocation,
diff --git a/src/plugins/flatpak/daemon/test-flatpak.c b/src/plugins/flatpak/daemon/test-flatpak.c
index af3552947..f6a047672 100644
--- a/src/plugins/flatpak/daemon/test-flatpak.c
+++ b/src/plugins/flatpak/daemon/test-flatpak.c
@@ -100,6 +100,7 @@ add_install_cb (GObject      *object,
           g_assert_true (ret);
           g_message ("  %s/%s/%s with SDK %s//%s (Extension: %d) in directory %s",
                      name, arch, branch, sdk_name, sdk_branch, sdk_extension, deploy_dir);
+          g_variant_unref (value);
         }
     }
 
diff --git a/src/plugins/flatpak/gbp-flatpak-config-provider.c 
b/src/plugins/flatpak/gbp-flatpak-config-provider.c
index 857431a9b..c66520814 100644
--- a/src/plugins/flatpak/gbp-flatpak-config-provider.c
+++ b/src/plugins/flatpak/gbp-flatpak-config-provider.c
@@ -467,11 +467,11 @@ gbp_flatpak_config_provider_load_async (IdeConfigProvider   *provider,
                                         gpointer             user_data)
 {
   GbpFlatpakConfigProvider *self = (GbpFlatpakConfigProvider *)provider;
+  g_autoptr(IpcFlatpakService) service = NULL;
   g_autoptr(IdeTask) task = NULL;
   IdeVcsMonitor *monitor;
   IdeContext *context;
   GbpFlatpakClient *client;
-  IpcFlatpakService *service;
   IdeVcs *vcs;
   GFile *workdir;
 
diff --git a/src/plugins/flatpak/gbp-flatpak-manifest.c b/src/plugins/flatpak/gbp-flatpak-manifest.c
index 2da65b5d4..28a339b21 100644
--- a/src/plugins/flatpak/gbp-flatpak-manifest.c
+++ b/src/plugins/flatpak/gbp-flatpak-manifest.c
@@ -554,10 +554,10 @@ find_extension (GbpFlatpakManifest *self,
                 const gchar        *name)
 {
   g_autoptr(FlatpakInstalledRef) ref = NULL;
+  g_autoptr(IpcFlatpakService) service = NULL;
   g_autofree char *resolved = NULL;
   GbpFlatpakApplicationAddin *addin;
   GbpFlatpakRuntime *ret = NULL;
-  IpcFlatpakService *service;
   GbpFlatpakClient *client;
   IdeContext *context;
   g_autoptr(GBytes) bytes = NULL;
@@ -567,10 +567,12 @@ find_extension (GbpFlatpakManifest *self,
 
   context = ide_object_get_context (IDE_OBJECT (self));
 
+#if 0
   if ((client = gbp_flatpak_client_from_context (context)) &&
       (service = gbp_flatpak_client_get_service (client, NULL, NULL)) &&
       ipc_flatpak_service_call_resolve_extension_sync (service, self->sdk, name, &resolved, NULL, NULL))
     {
+
       addin = gbp_flatpak_application_addin_get_default ();
       ref = gbp_flatpak_application_addin_find_extension (addin, self->sdk, name);
       if (ref != NULL)
@@ -581,6 +583,9 @@ find_extension (GbpFlatpakManifest *self,
                                        flatpak_installed_ref_get_deploy_dir (ref),
                                        TRUE, NULL, NULL);
     }
+#endif
+
+  g_printerr ("TODO: fix find_extension()\n");
 
   return IDE_RUNTIME (g_steal_pointer (&ret));
 }
diff --git a/src/plugins/flatpak/gbp-flatpak-runtime-provider.c 
b/src/plugins/flatpak/gbp-flatpak-runtime-provider.c
index e14d2e8a3..bbe920687 100644
--- a/src/plugins/flatpak/gbp-flatpak-runtime-provider.c
+++ b/src/plugins/flatpak/gbp-flatpak-runtime-provider.c
@@ -1,4 +1,4 @@
-/* gbp-flatpak-runtime-provider.c
+/* gbp-flatpak-runtime-provider.h
  *
  * Copyright 2016-2019 Christian Hergert <chergert redhat com>
  *
@@ -20,877 +20,177 @@
 
 #define G_LOG_DOMAIN "gbp-flatpak-runtime-provider"
 
-#include <flatpak.h>
-#include <ostree.h>
-#include <string.h>
+#include "config.h"
 
-#include <libide-gui.h>
+#include <libide-foundry.h>
 
-#include "ide-gui-private.h"
-
-#include "gbp-flatpak-application-addin.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"
-#include "gbp-flatpak-transfer.h"
-#include "gbp-flatpak-util.h"
 
-typedef struct
-{
-  gchar *id;
-  gchar *arch;
-  gchar *branch;
-  gchar *sdk_id;
-  gchar *sdk_arch;
-  gchar *sdk_branch;
-  guint  op_count : 2;
-  guint  failed : 1;
-} InstallRuntime;
-
-typedef struct
-{
-  IdeConfig *config;
-  gchar     *runtime_id;
-  gchar     *name;
-  gchar     *arch;
-  gchar     *branch;
-  gint       count;
-} BootstrapState;
+#include "daemon/ipc-flatpak-service.h"
+#include "daemon/ipc-flatpak-util.h"
 
 struct _GbpFlatpakRuntimeProvider
 {
-  IdeObject          parent_instance;
-  IdeRuntimeManager *manager;
-  GPtrArray         *runtimes;
+  IdeObject parent_instance;
+  GPtrArray *runtimes;
 };
 
-static void runtime_provider_iface_init         (IdeRuntimeProviderInterface *iface);
-static void gbp_flatpak_runtime_provider_load   (IdeRuntimeProvider          *provider,
-                                                 IdeRuntimeManager           *manager);
-static void gbp_flatpak_runtime_provider_unload (IdeRuntimeProvider          *provider,
-                                                 IdeRuntimeManager           *manager);
+static void runtime_provider_iface_init (IdeRuntimeProviderInterface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (GbpFlatpakRuntimeProvider, gbp_flatpak_runtime_provider, IDE_TYPE_OBJECT,
                          G_IMPLEMENT_INTERFACE (IDE_TYPE_RUNTIME_PROVIDER, runtime_provider_iface_init))
 
 static void
-bootstrap_state_free (gpointer data)
-{
-  BootstrapState *state = data;
-
-  g_assert (state != NULL);
-
-  g_clear_object (&state->config);
-  g_clear_pointer (&state->runtime_id, g_free);
-  g_clear_pointer (&state->name, g_free);
-  g_clear_pointer (&state->arch, g_free);
-  g_clear_pointer (&state->branch, g_free);
-  g_slice_free (BootstrapState, state);
-}
-
-static void
-install_runtime_free (gpointer data)
-{
-  InstallRuntime *install = data;
-
-  g_clear_pointer (&install->id, g_free);
-  g_clear_pointer (&install->arch, g_free);
-  g_clear_pointer (&install->branch, g_free);
-  g_clear_pointer (&install->sdk_id, g_free);
-  g_clear_pointer (&install->sdk_arch, g_free);
-  g_clear_pointer (&install->sdk_branch, g_free);
-
-  g_slice_free (InstallRuntime, install);
-}
-
-static gboolean
-is_same_runtime (GbpFlatpakRuntime   *runtime,
-                 FlatpakInstalledRef *ref)
-{
-  g_autofree gchar *arch = NULL;
-
-  return (g_strcmp0 (flatpak_ref_get_name (FLATPAK_REF (ref)),
-                     gbp_flatpak_runtime_get_platform (runtime)) == 0) &&
-         (g_strcmp0 (flatpak_ref_get_arch (FLATPAK_REF (ref)),
-                     arch = ide_runtime_get_arch (IDE_RUNTIME (runtime))) == 0) &&
-         (g_strcmp0 (flatpak_ref_get_branch (FLATPAK_REF (ref)),
-                     gbp_flatpak_runtime_get_branch (runtime)) == 0);
-}
-
-static void
-monitor_transfer (GbpFlatpakRuntimeProvider *self,
-                  GbpFlatpakTransfer        *transfer)
-{
-  g_autoptr(IdeNotification) notif = NULL;
-
-  g_assert (IDE_IS_MAIN_THREAD ());
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (GBP_IS_FLATPAK_TRANSFER (transfer));
-
-  notif = ide_transfer_create_notification (IDE_TRANSFER (transfer));
-  ide_notification_attach (notif, IDE_OBJECT (self));
-}
-
-static void
-runtime_added_cb (GbpFlatpakRuntimeProvider  *self,
-                  FlatpakInstalledRef        *ref,
-                  GbpFlatpakApplicationAddin *app_addin)
-{
-  g_autoptr(GbpFlatpakRuntime) new_runtime = NULL;
-  g_autoptr(GBytes) bytes = NULL;
-  g_autoptr(GError) error = NULL;
-  const gchar *name;
-
-  IDE_ENTRY;
-
-  g_assert (GBP_IS_FLATPAK_APPLICATION_ADDIN (app_addin));
-  g_assert (FLATPAK_IS_INSTALLED_REF (ref));
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (IDE_IS_RUNTIME_MANAGER (self->manager));
-
-  name = flatpak_ref_get_name (FLATPAK_REF (ref));
-  if (gbp_flatpak_is_ignored (name))
-    IDE_EXIT;
-
-  for (guint i = 0; i < self->runtimes->len; i++)
-    {
-      GbpFlatpakRuntime *runtime = g_ptr_array_index (self->runtimes, i);
-
-      /*
-       * If this is the same as a previous runtime, there is no sense in
-       * doing anything about this because our runtime objects don't hold
-       * anything as private state that would matter.
-       */
-      if (is_same_runtime (runtime, ref))
-        IDE_EXIT;
-    }
-
-  /*
-   * We didn't already have this runtime, so go ahead and just
-   * add it now (and keep a copy so we can find it later).
-   */
-  new_runtime = gbp_flatpak_runtime_new (flatpak_ref_get_name (FLATPAK_REF (ref)),
-                                         flatpak_ref_get_arch (FLATPAK_REF (ref)),
-                                         flatpak_ref_get_branch (FLATPAK_REF (ref)),
-                                         (bytes = flatpak_installed_ref_load_metadata (ref, NULL, NULL)),
-                                         flatpak_installed_ref_get_deploy_dir (ref),
-                                         FALSE, NULL, &error);
-
-  if (new_runtime == NULL)
-    {
-      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
-        g_warning ("Failed to create GbpFlatpakRuntime: %s", error->message);
-    }
-  else
-    {
-      ide_object_append (IDE_OBJECT (self), IDE_OBJECT (new_runtime));
-      ide_runtime_manager_add (self->manager, IDE_RUNTIME (new_runtime));
-      g_ptr_array_add (self->runtimes, g_steal_pointer (&new_runtime));
-    }
-
-  IDE_EXIT;
-}
-
-static void
-gbp_flatpak_runtime_provider_load (IdeRuntimeProvider *provider,
-                                   IdeRuntimeManager  *manager)
-{
-  GbpFlatpakRuntimeProvider *self = (GbpFlatpakRuntimeProvider *)provider;
-  GbpFlatpakApplicationAddin *app_addin = gbp_flatpak_application_addin_get_default ();
-  g_autoptr(GPtrArray) refs = NULL;
-
-  IDE_ENTRY;
-
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (IDE_IS_RUNTIME_MANAGER (manager));
-
-  g_set_weak_pointer (&self->manager, manager);
-  self->runtimes = g_ptr_array_new_with_free_func (g_object_unref);
-  refs = gbp_flatpak_application_addin_get_runtimes (app_addin);
-
-  g_signal_connect_object (app_addin,
-                           "runtime-added",
-                           G_CALLBACK (runtime_added_cb),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  for (guint i = 0; i < refs->len; i++)
-    {
-      FlatpakInstalledRef *ref = g_ptr_array_index (refs, i);
-      runtime_added_cb (self, ref, app_addin);
-    }
-
-  IDE_EXIT;
-}
-
-static void
-gbp_flatpak_runtime_provider_unload (IdeRuntimeProvider *provider,
-                                     IdeRuntimeManager  *manager)
+gbp_flatpak_runtime_provider_dispose (GObject *object)
 {
-  GbpFlatpakRuntimeProvider *self = (GbpFlatpakRuntimeProvider *)provider;
-  GbpFlatpakApplicationAddin *app_addin = gbp_flatpak_application_addin_get_default ();
-
-  IDE_ENTRY;
-
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (IDE_IS_RUNTIME_MANAGER (manager));
-
-  if (app_addin != NULL)
-    g_signal_handlers_disconnect_by_func (app_addin,
-                                          G_CALLBACK (runtime_added_cb),
-                                          self);
-
-  if (self->runtimes != NULL)
-    {
-      for (guint i= 0; i < self->runtimes->len; i++)
-        {
-          IdeRuntime *runtime = g_ptr_array_index (self->runtimes, i);
-
-          ide_runtime_manager_remove (manager, runtime);
-        }
-    }
+  GbpFlatpakRuntimeProvider *self = (GbpFlatpakRuntimeProvider *)object;
 
   g_clear_pointer (&self->runtimes, g_ptr_array_unref);
 
-  g_clear_weak_pointer (&self->manager);
-
-  IDE_EXIT;
+  G_OBJECT_CLASS (gbp_flatpak_runtime_provider_parent_class)->dispose (object);
 }
 
 static void
 gbp_flatpak_runtime_provider_class_init (GbpFlatpakRuntimeProviderClass *klass)
 {
-}
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-static void
-gbp_flatpak_runtime_provider_init (GbpFlatpakRuntimeProvider *self)
-{
-}
-
-static gboolean
-gbp_flatpak_runtime_provider_provides (IdeRuntimeProvider *provider,
-                                          const gchar        *runtime_id)
-{
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (provider));
-  g_assert (runtime_id != NULL);
-
-  return g_str_has_prefix (runtime_id, "flatpak:");
+  object_class->dispose = gbp_flatpak_runtime_provider_dispose;
 }
 
 static void
-gbp_flatpak_runtime_provider_install_cb (GObject      *object,
-                                         GAsyncResult *result,
-                                         gpointer      user_data)
-{
-  IdeTransferManager *transfer_manager = (IdeTransferManager *)object;
-  g_autoptr(IdeTask) task = user_data;
-  g_autoptr(GError) error = NULL;
-  InstallRuntime *install;
-
-  IDE_ENTRY;
-
-  g_assert (IDE_IS_TRANSFER_MANAGER (transfer_manager));
-  g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (IDE_IS_TASK (task));
-
-  install = ide_task_get_task_data (task);
-
-  if (!ide_transfer_manager_execute_finish (transfer_manager, result, &error))
-    {
-      if (!install->failed)
-        {
-          ide_task_return_error (task, g_steal_pointer (&error));
-          install->failed = TRUE;
-        }
-    }
-
-  install->op_count--;
-
-  if (install->op_count == 0 && !install->failed)
-    ide_task_return_boolean (task, TRUE);
-
-  IDE_EXIT;
-}
-
-static void
-gbp_flatpak_runtime_provider_install_docs_cb (GObject      *object,
-                                              GAsyncResult *result,
-                                              gpointer      user_data)
+gbp_flatpak_runtime_provider_init (GbpFlatpakRuntimeProvider *self)
 {
-  IdeTransferManager *transfer_manager = (IdeTransferManager *)object;
-  g_autoptr(IdeTask) task = user_data;
-  g_autoptr(GError) error = NULL;
-  InstallRuntime *install;
-
-  IDE_ENTRY;
-
-  g_assert (IDE_IS_TRANSFER_MANAGER (transfer_manager));
-  g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (IDE_IS_TASK (task));
-
-  install = ide_task_get_task_data (task);
-
-  /* This error is not fatal */
-  if (!ide_transfer_manager_execute_finish (transfer_manager, result, &error))
-    g_warning ("Failed to install docs: %s", error->message);
-
-  install->op_count--;
-
-  if (install->op_count == 0 && !install->failed)
-    ide_task_return_boolean (task, TRUE);
-
-  IDE_EXIT;
+  self->runtimes = g_ptr_array_new_with_free_func (g_object_unref);
 }
 
 static void
-gbp_flatpak_runtime_provider_locate_sdk_cb (GObject      *object,
-                                            GAsyncResult *result,
-                                            gpointer      user_data)
-{
-  GbpFlatpakApplicationAddin *app_addin = (GbpFlatpakApplicationAddin *)object;
-  g_autoptr(IdeTask) task = user_data;
-  g_autoptr(GError) error = NULL;
-  g_autofree gchar *docs_id = NULL;
-  GbpFlatpakRuntimeProvider *self;
-  IdeTransferManager *transfer_manager;
-  InstallRuntime *install;
-  GCancellable *cancellable;
-  gboolean sdk_matches_runtime = FALSE;
-
-  IDE_ENTRY;
-
-  g_assert (GBP_IS_FLATPAK_APPLICATION_ADDIN (app_addin));
-  g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (IDE_IS_TASK (task));
-  g_assert (!ide_task_get_completed (task));
-
-  self = ide_task_get_source_object (task);
-  install = ide_task_get_task_data (task);
-  cancellable = ide_task_get_cancellable (task);
-
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (install != NULL);
-  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
-
-  transfer_manager = ide_transfer_manager_get_default ();
-
-  if (!gbp_flatpak_application_addin_locate_sdk_finish (app_addin,
-                                                        result,
-                                                        &install->sdk_id,
-                                                        &install->sdk_arch,
-                                                        &install->sdk_branch,
-                                                        &error))
-    {
-      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
-        {
-          ide_task_return_error (task, g_steal_pointer (&error));
-          IDE_EXIT;
-        }
-    }
+on_runtime_added_cb (GbpFlatpakRuntimeProvider *self,
+                     GVariant                  *info,
+                     IpcFlatpakService         *service)
 
-  install->op_count = 3;
-
-  /* Make sure the Platform runtime is installed */
-  if (gbp_flatpak_application_addin_has_runtime (app_addin,
-                                                 install->id,
-                                                 install->arch,
-                                                 install->branch))
-    install->op_count--;
-  else
-    {
-      g_autoptr(GbpFlatpakTransfer) transfer = NULL;
-
-      transfer = gbp_flatpak_transfer_new (install->id,
-                                           install->arch,
-                                           install->branch,
-                                           FALSE);
-      monitor_transfer (self, transfer);
-      ide_transfer_manager_execute_async (transfer_manager,
-                                          IDE_TRANSFER (transfer),
-                                          cancellable,
-                                          gbp_flatpak_runtime_provider_install_cb,
-                                          g_object_ref (task));
-    }
-
-  /* Now make sure the SDK is installed */
-  sdk_matches_runtime = (g_strcmp0 (install->sdk_id, install->id) == 0 &&
-                         g_strcmp0 (install->sdk_arch, install->arch) == 0 &&
-                         g_strcmp0 (install->sdk_branch, install->branch) == 0);
-  if (sdk_matches_runtime || install->sdk_id == NULL ||
-      gbp_flatpak_application_addin_has_runtime (app_addin,
-                                                 install->sdk_id,
-                                                 install->sdk_arch,
-                                                 install->sdk_branch))
-    install->op_count--;
-  else
-    {
-      g_autoptr(GbpFlatpakTransfer) transfer = NULL;
-
-      transfer = gbp_flatpak_transfer_new (install->sdk_id,
-                                           install->sdk_arch,
-                                           install->sdk_branch,
-                                           FALSE);
-      monitor_transfer (self, transfer);
-      ide_transfer_manager_execute_async (transfer_manager,
-                                          IDE_TRANSFER (transfer),
-                                          cancellable,
-                                          gbp_flatpak_runtime_provider_install_cb,
-                                          g_object_ref (task));
-    }
-
-  /* If there is a .Docs runtime for the SDK, install that too */
-  if (install->sdk_id == NULL ||
-      !(docs_id = g_strdup_printf ("%s.Docs", install->sdk_id)) ||
-      gbp_flatpak_application_addin_has_runtime (app_addin,
-                                                 docs_id,
-                                                 install->arch,
-                                                 install->branch))
-    install->op_count--;
-  else
-    {
-      g_autoptr(GbpFlatpakTransfer) transfer = NULL;
-
-      transfer = gbp_flatpak_transfer_new (docs_id,
-                                           install->arch,
-                                           install->branch,
-                                           FALSE);
-      monitor_transfer (self, transfer);
-      ide_transfer_manager_execute_async (transfer_manager,
-                                          IDE_TRANSFER (transfer),
-                                          cancellable,
-                                          gbp_flatpak_runtime_provider_install_docs_cb,
-                                          g_object_ref (task));
-    }
-
-  /* Complete the task now if everything is done */
-  if (install->op_count == 0)
-    ide_task_return_boolean (task, TRUE);
-
-  IDE_EXIT;
-}
-
-static void
-install_task_completed_cb (GbpFlatpakRuntimeProvider *self,
-                           GParamSpec                *pspec,
-                           IdeTask                   *task)
 {
+  g_autoptr(GbpFlatpakRuntime) runtime = NULL;
   g_autoptr(IdeContext) context = NULL;
-
-  IDE_ENTRY;
-
-  g_assert (IDE_IS_MAIN_THREAD ());
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (pspec != NULL);
-  g_assert (IDE_IS_TASK (task));
-
-  if (!ide_task_had_error (task))
-    {
-      context = ide_object_ref_context (IDE_OBJECT (self));
-
-      if (context != NULL)
-        ide_build_manager_invalidate (ide_build_manager_from_context (context));
-    }
-
-  IDE_EXIT;
-}
-
-static void
-gbp_flatpak_runtime_provider_install_async (IdeRuntimeProvider  *provider,
-                                            const gchar         *runtime_id,
-                                            GCancellable        *cancellable,
-                                            GAsyncReadyCallback  callback,
-                                            gpointer             user_data)
-{
-  GbpFlatpakRuntimeProvider *self = (GbpFlatpakRuntimeProvider *)provider;
-  g_autoptr(IdeTask) task = NULL;
-  g_autofree gchar *id = NULL;
-  g_autofree gchar *arch = NULL;
-  g_autofree gchar *branch = NULL;
-  InstallRuntime *install;
-
-  IDE_ENTRY;
+  IdeRuntimeManager *manager;
+  const gchar *name;
+  const gchar *arch;
+  const gchar *branch;
+  const gchar *sdk_name;
+  const gchar *sdk_branch;
+  const gchar *deploy_dir;
+  const gchar *metadata;
+  gboolean is_extension;
 
   g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (runtime_id != NULL);
-  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
-
-  /*
-   * The process here is to first locate the SDK for the runtime, and then
-   * to submit transfers for both the runtime and the SDK if they are not
-   * already installed (this is done from the callback). Since we will have
-   * two async operations in flight, we need to keep track of when both are
-   * done before completing the operation.
-   */
-
-  task = ide_task_new (self, cancellable, callback, user_data);
-  ide_task_set_source_tag (task, gbp_flatpak_runtime_provider_install_async);
-
-  /* Track completion so that we can reload the build pipeline. This
-   * may be necessary to pick up new programs like "meson" that are
-   * provided in the SDK which could cause their plugin to not load.
-   */
-  g_signal_connect_object (task,
-                           "notify::completed",
-                           G_CALLBACK (install_task_completed_cb),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  if (!g_str_has_prefix (runtime_id, "flatpak:"))
-    IDE_GOTO (unknown_runtime_id);
-
-  if (!gbp_flatpak_split_id (runtime_id + strlen ("flatpak:"), &id, &arch, &branch))
-    IDE_GOTO (unknown_runtime_id);
-
-  install = g_slice_new0 (InstallRuntime);
-  install->id = g_steal_pointer (&id);
-  install->arch = g_steal_pointer (&arch);
-  install->branch = g_steal_pointer (&branch);
-
-  ide_task_set_task_data (task, install, install_runtime_free);
-
-  gbp_flatpak_application_addin_locate_sdk_async (gbp_flatpak_application_addin_get_default (),
-                                                  install->id,
-                                                  install->arch,
-                                                  install->branch,
-                                                  cancellable,
-                                                  gbp_flatpak_runtime_provider_locate_sdk_cb,
-                                                  g_steal_pointer (&task));
-
-  IDE_EXIT;
-
-unknown_runtime_id:
-  ide_task_return_new_error (task,
-                             G_IO_ERROR,
-                             G_IO_ERROR_NOT_SUPPORTED,
-                             "Unknown runtime_id %s",
-                             runtime_id);
-
-  IDE_EXIT;
-}
+  g_assert (info != NULL);
+  g_assert (IPC_IS_FLATPAK_SERVICE (service));
+  g_assert (g_variant_is_of_type (info, RUNTIME_VARIANT_TYPE));
 
-static gboolean
-gbp_flatpak_runtime_provider_install_finish (IdeRuntimeProvider  *provider,
-                                             GAsyncResult        *result,
-                                             GError             **error)
-{
-  gboolean ret;
-
-  IDE_ENTRY;
-
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (provider));
-  g_assert (IDE_IS_TASK (result));
-
-  ret = ide_task_propagate_boolean (IDE_TASK (result), error);
-
-  IDE_RETURN (ret);
-}
-
-static void
-gbp_flatpak_runtime_provider_bootstrap_complete (IdeTask *task)
-{
-  IdeRuntimeManager *runtime_manager;
-  BootstrapState *state;
-  IdeContext *context;
-  IdeRuntime *runtime;
-  IdeObject *object;
-
-  g_assert (IDE_IS_MAIN_THREAD ());
-  g_assert (IDE_IS_TASK (task));
-
-  state = ide_task_get_task_data (task);
-
-  g_assert (state != NULL);
-  g_assert (state->count == 0);
-
-  object = ide_task_get_source_object (task);
-  context = ide_object_get_context (object);
-  runtime_manager = ide_runtime_manager_from_context (context);
-  runtime = ide_runtime_manager_get_runtime (runtime_manager, state->runtime_id);
-
-  if (runtime != NULL)
-    ide_task_return_pointer (task, g_object_ref (runtime), g_object_unref);
-  else
-    ide_task_return_new_error (task,
-                               G_IO_ERROR,
-                               G_IO_ERROR_FAILED,
-                               "Failed to install runtime for build");
-}
-
-static void
-gbp_flatpak_runtime_provider_bootstrap_install_cb (GObject      *object,
-                                                   GAsyncResult *result,
-                                                   gpointer      user_data)
-{
-  IdeTransferManager *transfer_manager = (IdeTransferManager *)object;
-  g_autoptr(IdeTask) task = user_data;
-  g_autoptr(GError) error = NULL;
-  BootstrapState *state;
-
-  g_assert (IDE_IS_MAIN_THREAD ());
-  g_assert (IDE_IS_TRANSFER_MANAGER (transfer_manager));
-  g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (IDE_IS_TASK (task));
-
-  state = ide_task_get_task_data (task);
-
-  g_assert (state != NULL);
-  g_assert (state->count > 0);
-
-  state->count--;
-
-  /* We might still be able to find the runtime if the transfer fails */
-  ide_transfer_manager_execute_finish (transfer_manager, result, &error);
+  if (self->runtimes == NULL)
+    return;
 
-  if (error != NULL)
-    g_debug ("Transfer failed: %s", error->message);
+  if (!runtime_variant_parse (info,
+                              &name, &arch, &branch,
+                              &sdk_name, &sdk_branch,
+                              &deploy_dir,
+                              &metadata,
+                              &is_extension))
+    return;
 
-  if (!ide_task_had_error (task) && state->count == 0)
-    gbp_flatpak_runtime_provider_bootstrap_complete (task);
-  else if (!ide_task_had_error (task))
-    ide_task_return_error (task, g_steal_pointer (&error));
-}
+  /* Ignore extensions for now */
+  if (is_extension)
+    return;
 
-static void
-gbp_flatpak_runtime_provider_bootstrap_cb (GObject      *object,
-                                           GAsyncResult *result,
-                                           gpointer      user_data)
-{
-  GbpFlatpakInstallDialog *dialog = (GbpFlatpakInstallDialog *)object;
-  GbpFlatpakRuntimeProvider *self;
-  g_autoptr(IdeTask) task = user_data;
+  context = ide_object_ref_context (IDE_OBJECT (self));
+  manager = ide_runtime_manager_from_context (context);
+  runtime = gbp_flatpak_runtime_new (name,
+                                     arch,
+                                     branch,
+                                     sdk_name,
+                                     sdk_branch,
+                                     deploy_dir,
+                                     metadata,
+                                     is_extension);
+  g_ptr_array_add (self->runtimes, g_object_ref (runtime));
+  ide_object_append (IDE_OBJECT (self), IDE_OBJECT (runtime));
+  ide_runtime_manager_add (manager, IDE_RUNTIME (runtime));
+}
+
+static void
+gbp_flatpak_runtime_provider_load_list_runtimes_cb (GObject      *object,
+                                                    GAsyncResult *result,
+                                                    gpointer      user_data)
+{
+  IpcFlatpakService *service = (IpcFlatpakService *)object;
+  g_autoptr(GbpFlatpakRuntimeProvider) self = user_data;
+  g_autoptr(GVariant) runtimes = NULL;
   g_autoptr(GError) error = NULL;
-  g_auto(GStrv) runtimes = NULL;
-  IdeTransferManager *transfer_manager;
-  BootstrapState *state;
+  GVariantIter iter;
+  GVariant *info;
 
-  g_assert (IDE_IS_MAIN_THREAD ());
-  g_assert (GBP_IS_FLATPAK_INSTALL_DIALOG (dialog));
+  g_assert (IPC_IS_FLATPAK_SERVICE (service));
   g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (IDE_IS_TASK (task));
-
-  if (ide_task_had_error (task))
-    return;
-
-  self = ide_task_get_source_object (task);
-  state = ide_task_get_task_data (task);
-
   g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (state != NULL);
 
-  if (!gbp_flatpak_install_dialog_run_finish (dialog, result, &error))
+  if (!ipc_flatpak_service_call_list_runtimes_finish (service, &runtimes, result, &error))
     {
-      gbp_flatpak_runtime_provider_bootstrap_complete (task);
+      g_warning ("Failed to list flatpak runtimes: %s", error->message);
       return;
     }
 
-  runtimes = gbp_flatpak_install_dialog_get_runtimes (dialog);
-  transfer_manager = ide_transfer_manager_get_default ();
-
-  for (guint i = 0; runtimes[i]; i++)
+  g_variant_iter_init (&iter, runtimes);
+  while ((info = g_variant_iter_next_value (&iter)))
     {
-      g_autofree gchar *name = NULL;
-      g_autofree gchar *arch = NULL;
-      g_autofree gchar *branch = NULL;
-
-      if (gbp_flatpak_split_id (runtimes[i], &name, &arch, &branch) && branch != NULL)
-        {
-          g_autoptr(GbpFlatpakTransfer) transfer = NULL;
-          g_autoptr(IdeNotification) notif = NULL;
-
-          state->count++;
-
-          transfer = gbp_flatpak_transfer_new (name, arch, branch, FALSE);
-          notif = ide_transfer_create_notification (IDE_TRANSFER (transfer));
-          ide_notification_attach (notif, IDE_OBJECT (self));
-
-          ide_transfer_manager_execute_async (transfer_manager,
-                                              IDE_TRANSFER (transfer),
-                                              ide_task_get_cancellable (task),
-                                              gbp_flatpak_runtime_provider_bootstrap_install_cb,
-                                              g_object_ref (task));
-        }
+      on_runtime_added_cb (self, info, service);
+      g_variant_unref (info);
     }
-
-  if (state->count == 0)
-    gbp_flatpak_runtime_provider_bootstrap_complete (task);
 }
 
 static void
-gbp_flatpak_runtime_provider_bootstrap_async (IdeRuntimeProvider  *provider,
-                                              IdePipeline         *pipeline,
-                                              GCancellable        *cancellable,
-                                              GAsyncReadyCallback  callback,
-                                              gpointer             user_data)
+gbp_flatpak_runtime_provider_load (IdeRuntimeProvider *provider,
+                                   IdeRuntimeManager  *manager)
 {
-  GbpFlatpakRuntimeProvider *self = (GbpFlatpakRuntimeProvider *)provider;
-  g_autofree gchar *name = NULL;
-  g_autofree gchar *arch = NULL;
-  g_autofree gchar *branch = NULL;
-  g_autofree gchar *docs_id = NULL;
-  g_autoptr(IdeTask) task = NULL;
-  g_auto(GStrv) runtimes = NULL;
-  GbpFlatpakApplicationAddin *addin;
-  GbpFlatpakInstallDialog *dialog;
-  BootstrapState *state;
-  IdeWorkbench *workbench;
-  IdeWorkspace *workspace;
-  const gchar *runtime_id;
-  const gchar *build_arch;
-  IdeContext *context;
-  IdeConfig *config;
-
-  IDE_ENTRY;
-
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
-  g_assert (IDE_IS_PIPELINE (pipeline));
-  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
-
-  task = ide_task_new (self, cancellable, callback, user_data);
-  ide_task_set_release_on_propagate (task, FALSE);
-  ide_task_set_source_tag (task, gbp_flatpak_runtime_provider_bootstrap_async);
-
-  context = ide_object_get_context (IDE_OBJECT (self));
-  build_arch = ide_pipeline_get_arch (pipeline);
-  config = ide_pipeline_get_config (pipeline);
-  runtime_id = ide_config_get_runtime_id (config);
-
-  if (runtime_id == NULL ||
-      !g_str_has_prefix (runtime_id, "flatpak:") ||
-      !gbp_flatpak_split_id (runtime_id + strlen ("flatpak:"), &name, &arch, &branch))
-    {
-      ide_task_return_new_error (task,
-                                 G_IO_ERROR,
-                                 G_IO_ERROR_NOT_FOUND,
-                                 "No runtime available");
-      IDE_EXIT;
-    }
-
-  /* Create dialog to potentially query user if we are allowed to install */
-  workbench = ide_workbench_from_context (context);
-  workspace = ide_workbench_get_current_workspace (workbench);
-  dialog = gbp_flatpak_install_dialog_new (GTK_WINDOW (workspace));
-  gtk_window_group_add_window (GTK_WINDOW_GROUP (workbench), GTK_WINDOW (dialog));
-
-  /* Create state for async op */
-  state = g_slice_new0 (BootstrapState);
-  state->config = g_object_ref (config);
-  state->runtime_id = g_strdup_printf ("flatpak:%s/%s/%s", name, build_arch, branch);
-  state->name = g_steal_pointer (&name);
-  state->branch = g_steal_pointer (&branch);
-  state->arch = g_strdup (build_arch);
-  ide_task_set_task_data (task, state, bootstrap_state_free);
-
-  addin = gbp_flatpak_application_addin_get_default ();
-
-  /* Add all the runtimes the manifest needs */
-  if (GBP_IS_FLATPAK_MANIFEST (state->config))
-    {
-      g_auto(GStrv) all = NULL;
-      g_autofree gchar *sdk_full = NULL;
-      g_autofree gchar *platform_full = NULL;
-      const char * const *sdk_extensions;
-      const gchar *sdk;
-      const gchar *platform;
-
-      /* Tell the dialog about the SDK so it can resolve common ancestors for
-       * SDK extensions missing a branch name.
-       */
-      platform = gbp_flatpak_manifest_get_platform (GBP_FLATPAK_MANIFEST (state->config));
-      platform_full = g_strdup_printf ("%s/%s/%s", platform, state->arch, state->branch);
-      sdk = gbp_flatpak_manifest_get_sdk (GBP_FLATPAK_MANIFEST (state->config));
-      sdk_full = g_strdup_printf ("%s/%s/%s", sdk, state->arch, state->branch);
-      sdk_extensions = gbp_flatpak_manifest_get_sdk_extensions (GBP_FLATPAK_MANIFEST (state->config));
-
-      gbp_flatpak_install_dialog_set_sdk (dialog, sdk_full);
-
-      /* Make sure we have the SDK installed (org.gnome.Sdk) */
-      if (!gbp_flatpak_application_addin_has_runtime (addin, sdk, state->arch, state->branch))
-        gbp_flatpak_install_dialog_add_runtime (dialog, sdk_full);
-
-      /* Make sure we have the platform for running it too (org.gnome.Platform) */
-      if (!gbp_flatpak_application_addin_has_runtime (addin, platform, state->arch, state->branch))
-        gbp_flatpak_install_dialog_add_runtime (dialog, platform_full);
-
-      /* The manifest should have already resolved extensions for us by this point */
-      if (sdk_extensions != NULL)
-        {
-          for (guint i = 0; sdk_extensions[i]; i++)
-            {
-              const char *sdk_extension = sdk_extensions[i];
-              g_autofree char *resolved_id = NULL;
-              g_autofree char *resolved_arch = NULL;
-              g_autofree char *resolved_branch = NULL;
-
-              /* Ignore the arch from the sdk_extension (it will be the host) and use the
-               * arch from the configuration instead.
-               */
-              if (gbp_flatpak_split_id (sdk_extension, &resolved_id, &resolved_arch, &resolved_branch) &&
-                  !gbp_flatpak_application_addin_has_runtime (addin, resolved_id, state->arch, 
resolved_branch))
-                {
-                  g_autofree char *for_arch = g_strdup_printf ("%s/%s/%s",
-                                                               resolved_id,
-                                                               state->arch,
-                                                               resolved_branch ? resolved_branch : "");
-                  gbp_flatpak_install_dialog_add_runtime (dialog, for_arch);
-                }
-            }
-        }
-    }
-  else
-    {
-      /* Add runtime specifically (in case no manifest is set) */
-      if (!gbp_flatpak_application_addin_has_runtime (addin, state->name, state->arch, state->branch))
-        gbp_flatpak_install_dialog_add_runtime_full (dialog, state->name, state->arch, state->branch);
-    }
+  g_autoptr(GbpFlatpakClient) client = NULL;
+  g_autoptr(IpcFlatpakService) service = NULL;
+  g_autoptr(IdeContext) context = NULL;
 
-  runtimes = gbp_flatpak_install_dialog_get_runtimes (dialog);
+  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (provider));
+  g_assert (IDE_IS_RUNTIME_MANAGER (manager));
 
-  if (runtimes == NULL || runtimes[0] == NULL)
+  if ((context = ide_object_ref_context (IDE_OBJECT (provider))) &&
+      (client = gbp_flatpak_client_ensure (context)) &&
+      (service = gbp_flatpak_client_get_service (client, NULL, NULL)))
     {
-      gtk_widget_destroy (GTK_WIDGET (dialog));
-      gbp_flatpak_runtime_provider_bootstrap_complete (task);
-    }
-  else
-    {
-      /* We need to invalidate the pipeline if there are runtimes
-       * to install after they've been installed or we risk having
-       * missing bits like meson not found.
-       */
-      g_signal_connect_object (task,
-                               "notify::completed",
-                               G_CALLBACK (install_task_completed_cb),
-                               self,
+      g_signal_connect_object (service,
+                               "runtime-added",
+                               G_CALLBACK (on_runtime_added_cb),
+                               provider,
                                G_CONNECT_SWAPPED);
-
-      /* Do not propagate cancellable to this operation or we risk cancelling
-       * in-flight operations that the user is expecting to complete.
-       */
-      gbp_flatpak_install_dialog_run_async (dialog,
-                                            NULL,
-                                            gbp_flatpak_runtime_provider_bootstrap_cb,
-                                            g_object_ref (task));
+      ipc_flatpak_service_call_list_runtimes (service,
+                                              NULL,
+                                              gbp_flatpak_runtime_provider_load_list_runtimes_cb,
+                                              g_object_ref (provider));
     }
-
-  IDE_EXIT;
 }
 
-static IdeRuntime *
-gbp_flatpak_runtime_provider_bootstrap_finish (IdeRuntimeProvider  *provider,
-                                               GAsyncResult        *result,
-                                               GError             **error)
+static void
+gbp_flatpak_runtime_provider_unload (IdeRuntimeProvider *provider,
+                                     IdeRuntimeManager  *manager)
 {
-  IdeRuntime *ret;
-
-  IDE_ENTRY;
+  GbpFlatpakRuntimeProvider *self = (GbpFlatpakRuntimeProvider *)provider;
 
-  g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (provider));
-  g_assert (IDE_IS_TASK (result));
+  g_assert (IDE_IS_RUNTIME_PROVIDER (provider));
+  g_assert (IDE_IS_RUNTIME_MANAGER (manager));
 
-  ret = ide_task_propagate_pointer (IDE_TASK (result), error);
+  if (self->runtimes == NULL || self->runtimes->len == 0)
+    return;
 
-  IDE_RETURN (ret);
+  for (guint i = 0; i < self->runtimes->len; i++)
+    ide_runtime_manager_remove (manager, g_ptr_array_index (self->runtimes, i));
+  g_ptr_array_remove_range (self->runtimes, 0, self->runtimes->len);
 }
 
 static void
@@ -898,9 +198,4 @@ runtime_provider_iface_init (IdeRuntimeProviderInterface *iface)
 {
   iface->load = gbp_flatpak_runtime_provider_load;
   iface->unload = gbp_flatpak_runtime_provider_unload;
-  iface->provides = gbp_flatpak_runtime_provider_provides;
-  iface->install_async = gbp_flatpak_runtime_provider_install_async;
-  iface->install_finish = gbp_flatpak_runtime_provider_install_finish;
-  iface->bootstrap_async = gbp_flatpak_runtime_provider_bootstrap_async;
-  iface->bootstrap_finish = gbp_flatpak_runtime_provider_bootstrap_finish;
 }
diff --git a/src/plugins/flatpak/gbp-flatpak-runtime-provider.h 
b/src/plugins/flatpak/gbp-flatpak-runtime-provider.h
index 25aab0cb2..79c60ea49 100644
--- a/src/plugins/flatpak/gbp-flatpak-runtime-provider.h
+++ b/src/plugins/flatpak/gbp-flatpak-runtime-provider.h
@@ -20,7 +20,7 @@
 
 #pragma once
 
-#include <glib-object.h>
+#include <libide-core.h>
 
 G_BEGIN_DECLS
 
diff --git a/src/plugins/flatpak/gbp-flatpak-runtime.c b/src/plugins/flatpak/gbp-flatpak-runtime.c
index 273416492..62f1e4c23 100644
--- a/src/plugins/flatpak/gbp-flatpak-runtime.c
+++ b/src/plugins/flatpak/gbp-flatpak-runtime.c
@@ -120,6 +120,22 @@ gbp_flatpak_runtime_contains_program_in_path (IdeRuntime   *runtime,
         }
     }
 
+  /* If we have an SDK, we might need to check that runtime */
+  if (ret == FALSE &&
+      self->sdk != NULL &&
+      !ide_str_equal0 (self->platform, self->sdk))
+    {
+      g_autoptr(IdeContext) context = ide_object_ref_context (IDE_OBJECT (self));
+      g_autoptr(IdeRuntimeManager) manager = ide_object_ensure_child_typed (IDE_OBJECT (context), 
IDE_TYPE_RUNTIME_MANAGER);
+      g_autofree char *arch = ide_runtime_get_arch (runtime);
+      g_autofree char *sdk_id = g_strdup_printf ("flatpak:%s/%s/%s", self->sdk, arch, self->branch);
+      IdeRuntime *sdk = ide_runtime_manager_get_runtime (manager, sdk_id);
+
+      if (sdk != NULL && sdk != runtime)
+        ret = ide_runtime_contains_program_in_path (sdk, program, cancellable);
+    }
+
+  /* Cache both positive and negative lookups */
   g_hash_table_insert (self->program_paths_cache,
                        (gchar *)g_intern_string (program),
                        GUINT_TO_POINTER (ret));
@@ -714,30 +730,16 @@ gbp_flatpak_runtime_init (GbpFlatpakRuntime *self)
   self->program_paths_cache = g_hash_table_new (g_str_hash, g_str_equal);
 }
 
-static gchar *
-locate_deploy_dir (const gchar *sdk_id)
-{
-  g_auto(GStrv) parts = g_strsplit (sdk_id, "/", 3);
-
-  if (g_strv_length (parts) == 3)
-    return gbp_flatpak_application_addin_get_deploy_dir (gbp_flatpak_application_addin_get_default (),
-                                                         parts[0], parts[1], parts[2]);
-  return NULL;
-}
-
 GbpFlatpakRuntime *
-gbp_flatpak_runtime_new (const char    *name,
-                         const char    *arch,
-                         const char    *branch,
-                         GBytes        *metadata,
-                         const char    *deploy_dir,
-                         gboolean       is_extension,
-                         GCancellable  *cancellable,
-                         GError       **error)
+gbp_flatpak_runtime_new (const char *name,
+                         const char *arch,
+                         const char *branch,
+                         const char *sdk_name,
+                         const char *sdk_branch,
+                         const char *deploy_dir,
+                         const char *metadata,
+                         gboolean    is_extension)
 {
-  g_autofree gchar *sdk_deploy_dir = NULL;
-  g_autoptr(GKeyFile) keyfile = NULL;
-  g_autofree gchar *sdk = NULL;
   g_autofree gchar *id = NULL;
   g_autofree gchar *display_name = NULL;
   g_autofree gchar *triplet = NULL;
@@ -746,10 +748,15 @@ gbp_flatpak_runtime_new (const char    *name,
   g_autoptr(GString) category = NULL;
 
   g_return_val_if_fail (name != NULL, NULL);
-  g_return_val_if_fail (branch != NULL, NULL);
   g_return_val_if_fail (arch != NULL, NULL);
+  g_return_val_if_fail (branch != NULL, NULL);
   g_return_val_if_fail (deploy_dir != NULL, NULL);
-  g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+
+  if (sdk_name == NULL)
+    sdk_name = name;
+
+  if (sdk_branch == NULL)
+    sdk_branch = branch;
 
   triplet_object = ide_triplet_new (arch);
   triplet = g_strdup_printf ("%s/%s/%s", name, arch, branch);
@@ -769,21 +776,6 @@ gbp_flatpak_runtime_new (const char    *name,
   else
     g_string_append_printf (category, "%s (%s)", name, arch);
 
-  keyfile = g_key_file_new ();
-  if (!g_key_file_load_from_bytes (keyfile, metadata, 0, error))
-    return NULL;
-
-  if (g_key_file_has_group (keyfile, "ExtensionOf") && !is_extension)
-    {
-      g_set_error (error,
-                   G_IO_ERROR,
-                   G_IO_ERROR_NOT_SUPPORTED,
-                   "Runtime is an extension");
-      return NULL;
-    }
-
-  sdk = g_key_file_get_string (keyfile, "Runtime", "sdk", NULL);
-
   if (g_str_equal (arch, flatpak_get_default_arch ()))
     display_name = g_strdup_printf (_("%s <b>%s</b>"), name, branch);
   else
@@ -792,14 +784,11 @@ gbp_flatpak_runtime_new (const char    *name,
   runtime_name = g_strdup_printf ("%s %s", _("Flatpak"), triplet);
 
   /*
+   * TODO:
+   *
    * If we have an SDK that is different from this runtime, we need to locate
    * the SDK deploy-dir instead (for things like includes, pkg-config, etc).
    */
-  if (!is_extension)
-    {
-      if (sdk != NULL && !g_str_equal (sdk, triplet) && NULL != (sdk_deploy_dir = locate_deploy_dir (sdk)))
-        deploy_dir = sdk_deploy_dir;
-    }
 
   return g_object_new (GBP_TYPE_FLATPAK_RUNTIME,
                        "id", id,
@@ -810,6 +799,6 @@ gbp_flatpak_runtime_new (const char    *name,
                        "deploy-dir", deploy_dir,
                        "display-name", display_name,
                        "platform", name,
-                       "sdk", sdk,
+                       "sdk", sdk_name,
                        NULL);
 }
diff --git a/src/plugins/flatpak/gbp-flatpak-runtime.h b/src/plugins/flatpak/gbp-flatpak-runtime.h
index a5ed8949f..dd9a35473 100644
--- a/src/plugins/flatpak/gbp-flatpak-runtime.h
+++ b/src/plugins/flatpak/gbp-flatpak-runtime.h
@@ -28,18 +28,18 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (GbpFlatpakRuntime, gbp_flatpak_runtime, GBP, FLATPAK_RUNTIME, IdeRuntime)
 
-GbpFlatpakRuntime   *gbp_flatpak_runtime_new          (const char           *name,
-                                                       const char           *arch,
-                                                       const char           *branch,
-                                                       GBytes               *metadata,
-                                                       const char           *deploy_dir,
-                                                       gboolean              is_extension,
-                                                       GCancellable         *cancellable,
-                                                       GError              **error);
-IdeTriplet          *gbp_flatpak_runtime_get_triplet  (GbpFlatpakRuntime    *self);
-const gchar         *gbp_flatpak_runtime_get_branch   (GbpFlatpakRuntime    *self);
-const gchar         *gbp_flatpak_runtime_get_platform (GbpFlatpakRuntime    *self);
-const gchar         *gbp_flatpak_runtime_get_sdk      (GbpFlatpakRuntime    *self);
-gchar               *gbp_flatpak_runtime_get_sdk_name (GbpFlatpakRuntime    *self);
+GbpFlatpakRuntime   *gbp_flatpak_runtime_new          (const char        *name,
+                                                       const char        *arch,
+                                                       const char        *branch,
+                                                       const char        *sdk_name,
+                                                       const char        *sdk_branch,
+                                                       const char        *deploy_dir,
+                                                       const char        *metadata,
+                                                       gboolean           is_extension);
+IdeTriplet          *gbp_flatpak_runtime_get_triplet  (GbpFlatpakRuntime *self);
+const gchar         *gbp_flatpak_runtime_get_branch   (GbpFlatpakRuntime *self);
+const gchar         *gbp_flatpak_runtime_get_platform (GbpFlatpakRuntime *self);
+const gchar         *gbp_flatpak_runtime_get_sdk      (GbpFlatpakRuntime *self);
+gchar               *gbp_flatpak_runtime_get_sdk_name (GbpFlatpakRuntime *self);
 
 G_END_DECLS


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