Example #1
0
void
ide_application_load_plugins (IdeApplication *self)
{
  PeasEngine *engine;
  const GList *list;

  g_return_if_fail (IDE_IS_APPLICATION (self));

  engine = peas_engine_get_default ();

  list = peas_engine_get_plugin_list (engine);

  for (; list; list = list->next)
    {
      PeasPluginInfo *plugin_info = list->data;
      GSettings *settings;
      const gchar *module_name;

      module_name = peas_plugin_info_get_module_name (plugin_info);
      settings = _ide_application_plugin_get_settings (self, module_name);

      g_object_set_data (G_OBJECT (settings), "PEAS_PLUGIN_INFO", plugin_info);

      g_signal_connect_object (settings,
                               "changed::enabled",
                               G_CALLBACK (ide_application_plugins_enabled_changed),
                               self,
                               G_CONNECT_SWAPPED);

      if (!g_settings_get_boolean (settings, "enabled"))
        continue;

      /*
       * If we are running the unit tests, we don't want to load plugins here,
       * but defer until the test is loading to perform the loading.  However,
       * we do want all of the other machinery above to be setup.
       */
      if (self->mode == IDE_APPLICATION_MODE_TESTS)
        continue;

      if (ide_application_can_load_plugin (self, plugin_info))
        {
          g_debug ("Loading plugin \"%s\"",
                   peas_plugin_info_get_module_name (plugin_info));
          peas_engine_load_plugin (engine, plugin_info);
        }
    }
}
Example #2
0
static void
ide_keybindings_load_plugin (IdeKeybindings *self,
                             PeasPluginInfo *plugin_info,
                             PeasEngine     *engine)
{
  g_autofree gchar *path = NULL;
  const gchar *module_name;
  g_autoptr(GBytes) bytes = NULL;
  g_autoptr(GtkCssProvider) provider = NULL;

  g_assert (IDE_IS_KEYBINDINGS (self));
  g_assert (plugin_info != NULL);
  g_assert (PEAS_IS_ENGINE (engine));

  if (!self->mode || !self->plugin_providers)
    return;

  module_name = peas_plugin_info_get_module_name (plugin_info);
  path = g_strdup_printf ("/org/gnome/builder/plugins/%s/keybindings/%s.css",
                          module_name, self->mode);
  bytes = g_resources_lookup_data (path, 0, NULL);
  if (bytes == NULL)
    return;

  IDE_TRACE_MSG ("Loading %s keybindings for \"%s\" plugin", self->mode, module_name);

  provider = gtk_css_provider_new ();
  gtk_css_provider_load_from_resource (provider, path);
  gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                             GTK_STYLE_PROVIDER (provider),
                                             GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
  g_hash_table_insert (self->plugin_providers,
                       g_strdup (module_name),
                       g_steal_pointer (&provider));
}
Example #3
0
static void
ide_application_unload_plugin_resources (IdeApplication *self,
                                         PeasPluginInfo *plugin_info,
                                         PeasEngine     *engine)
{
  g_autofree gchar *path = NULL;
  const gchar *data_dir;
  const gchar *module_name;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (plugin_info != NULL);
  g_assert (PEAS_IS_ENGINE (engine));

  module_name = peas_plugin_info_get_module_name (plugin_info);
  data_dir = peas_plugin_info_get_data_dir (plugin_info);

  /* Remove embedded gresources */
  path = g_strdup_printf ("resource:///org/gnome/builder/plugins/%s/", module_name);
  dzl_application_remove_resources (DZL_APPLICATION (self), path);

  /* Remove on disk resources */
  if (!g_str_has_prefix (data_dir, "resource://"))
    dzl_application_remove_resources (DZL_APPLICATION (self), data_dir);

  ide_application_plugins_unload_plugin_gresources (self, plugin_info, engine);
}
static PeasPluginInfo *
ide_application_locate_worker (IdeApplication *self,
                               const gchar    *worker_name)
{
  PeasEngine *engine;
  const GList *list;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (worker_name != NULL);

  engine = peas_engine_get_default ();
  list = peas_engine_get_plugin_list (engine);

  for (; list != NULL; list = list->next)
    {
      PeasPluginInfo *plugin_info = list->data;
      const gchar *name;

      name = peas_plugin_info_get_module_name (plugin_info);
      if (g_strcmp0 (name, worker_name) == 0)
        return plugin_info;
    }

  return NULL;
}
static gboolean
peas_plugin_loader_python_load (PeasPluginLoader *loader,
                                PeasPluginInfo   *info)
{
  PeasPluginLoaderPython *pyloader = PEAS_PLUGIN_LOADER_PYTHON (loader);
  PeasPluginLoaderPythonPrivate *priv = GET_PRIV (pyloader);
  const gchar *module_dir, *module_name;
  PyObject *pymodule;
  PyGILState_STATE state = PyGILState_Ensure ();

  module_dir = peas_plugin_info_get_module_dir (info);
  module_name = peas_plugin_info_get_module_name (info);

  pymodule = peas_python_internal_call ("load", &PyModule_Type, "(sss)",
                                        info->filename,
                                        module_dir, module_name);

  if (pymodule != NULL)
    {
      info->loader_data = pymodule;
      priv->n_loaded_plugins += 1;
    }

  PyGILState_Release (state);
  return pymodule != NULL;
}
Example #6
0
static gboolean
ide_application_can_load_plugin (IdeApplication *self,
                                 PeasPluginInfo *plugin_info)
{
  const gchar *module_name;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (plugin_info != NULL);

  module_name = peas_plugin_info_get_module_name (plugin_info);

  for (guint i = 0; i < G_N_ELEMENTS (blacklisted_plugins); i++)
    {
      if (g_strcmp0 (module_name, blacklisted_plugins[i]) == 0)
        return FALSE;
    }

  if (self->mode == IDE_APPLICATION_MODE_WORKER)
    {
      if (self->worker != plugin_info)
        return FALSE;
    }

  if (self->mode == IDE_APPLICATION_MODE_TOOL)
    {
      /*
       * Plugins might provide critical features needed
       * to load a project (build system, vcs, etc).
       */
      return TRUE;
    }

  /*
   * TODO: Do ABI check on external data.
   *
   * Right now, we don't have any way to check that the plugin is implementing
   * the same version of the API/ABI that the application exports. There are a
   * couple ways we could go about doing this.
   *
   * One approach might be to generate UUIDs for each plugin structure,
   * and update it every time the structure changes. However, plenty of changes
   * can be safe for existing modules. So perhaps we need something that has
   * a revision since last break. Then plugins would specify which version
   * and revision of an interface they require.
   *
   * Imagine the scenario that FooIface added the method frobnicate(). Previous
   * extensions for FooIface are perfectly happy to keep on working, but a new
   * addin that requires FooIface may require frobnicate()'s existance. So while
   * the ABI hasn't broken, some plugins will require a newer revision.
   *
   * This is not entirely different from libtool's interface age. Presumably,
   * Gedit's IAge is similar here, but we would need it per-structure.
   */

  return TRUE;
}
static gchar *
get_script_filename_for_plugin_info (PeasPluginInfo *info)
{
  gchar *basename;
  gchar *filename;

  basename = g_strconcat (peas_plugin_info_get_module_name (info), ".js", NULL);
  filename = g_build_filename (peas_plugin_info_get_module_dir (info), basename, NULL);

  g_free (basename);

  return filename;
}
Example #8
0
static void
ide_workbench_addin_added (PeasExtensionSet *set,
                           PeasPluginInfo   *plugin_info,
                           PeasExtension    *extension,
                           gpointer          user_data)
{
  IdeWorkbench *self = user_data;

  g_assert (PEAS_IS_EXTENSION_SET (set));
  g_assert (plugin_info != NULL);
  g_assert (IDE_IS_WORKBENCH_ADDIN (extension));
  g_assert (IDE_IS_WORKBENCH (self));

  IDE_TRACE_MSG ("Loading workbench addin for %s",
                 peas_plugin_info_get_module_name (plugin_info));

  ide_workbench_addin_load (IDE_WORKBENCH_ADDIN (extension), self);
}
static gchar *
get_script_for_plugin_info (PeasPluginInfo   *info,
                            SeedContext       context)
{
  gchar *basename;
  gchar *filename;
  gchar *script = NULL;

  basename = g_strconcat (peas_plugin_info_get_module_name (info), ".js", NULL);
  filename = g_build_filename (peas_plugin_info_get_module_dir (info), basename, NULL);

  g_debug ("Seed script filename is '%s'", filename);

  g_file_get_contents (filename, &script, NULL, NULL);

  g_free (basename);
  g_free (filename);

  return script;
}
static void
ide_preferences_builtin_register_plugins (IdePreferences *preferences)
{
  PeasEngine *engine;
  const GList *list;
  guint i = 0;

  g_assert (IDE_IS_PREFERENCES (preferences));

  engine = peas_engine_get_default ();
  list = peas_engine_get_plugin_list (engine);

  ide_preferences_add_page (preferences, "plugins", _("Extensions"), 700);
  ide_preferences_add_list_group (preferences, "plugins", "installed", _("Installed Extensions"), 0);
  ide_preferences_add_list_group (preferences, "plugins", "builtin", _("Bundled Extensions"), 100);

  for (; list; list = list->next, i++)
    {
      g_autofree gchar *path = NULL;
      PeasPluginInfo *plugin_info = list->data;
      const gchar *desc;
      const gchar *name;
      const gchar *group;

      if (peas_plugin_info_is_hidden (plugin_info))
        continue;

      name = peas_plugin_info_get_name (plugin_info);
      desc = peas_plugin_info_get_description (plugin_info);

      path = g_strdup_printf ("/org/gnome/builder/plugins/%s/",
                              peas_plugin_info_get_module_name (plugin_info));

      if (peas_plugin_info_is_builtin (plugin_info))
        group = "builtin";
      else
        group = "installed";

      ide_preferences_add_switch (preferences, "plugins", group, "org.gnome.builder.plugin", "enabled", path, NULL, name, desc, NULL, i);
    }
}
Example #11
0
void
ide_application_init_plugin_accessories (IdeApplication *self)
{
  const GList *list;
  PeasEngine *engine;

  g_assert (IDE_IS_APPLICATION (self));

  self->plugin_gresources = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
                                                   (GDestroyNotify)g_resource_unref);

  engine = peas_engine_get_default ();

  g_signal_connect_object (engine,
                           "load-plugin",
                           G_CALLBACK (ide_application_load_plugin_resources),
                           self,
                           G_CONNECT_AFTER | G_CONNECT_SWAPPED);

  g_signal_connect_object (engine,
                           "unload-plugin",
                           G_CALLBACK (ide_application_unload_plugin_resources),
                           self,
                           G_CONNECT_SWAPPED);

  list = peas_engine_get_plugin_list (engine);

  for (; list != NULL; list = list->next)
    {
      PeasPluginInfo *plugin_info = list->data;
      const gchar *module_name;
      GSettings *settings;

      module_name = peas_plugin_info_get_module_name (plugin_info);
      settings = _ide_application_plugin_get_settings (self, module_name);
      if (!g_settings_get_boolean (settings, "enabled"))
        continue;

      ide_application_load_plugin_resources (self, plugin_info, engine);
    }
}
Example #12
0
static void
ide_application_plugins_unload_plugin_gresources (IdeApplication *self,
                                                  PeasPluginInfo *plugin_info,
                                                  PeasEngine     *engine)
{
  const gchar *module_name;
  GResource *resources;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (plugin_info != NULL);
  g_assert (PEAS_IS_ENGINE (engine));

  module_name = peas_plugin_info_get_module_name (plugin_info);
  resources = g_hash_table_lookup (self->plugin_gresources, module_name);

  if (resources != NULL)
    {
      g_resources_unregister (resources);
      g_hash_table_remove (self->plugin_gresources, module_name);
    }
}
Example #13
0
static void
ide_keybindings_unload_plugin (IdeKeybindings *self,
                               PeasPluginInfo *plugin_info,
                               PeasEngine     *engine)
{
  GtkStyleProvider *provider;
  const gchar *module_name;

  g_assert (IDE_IS_KEYBINDINGS (self));
  g_assert (plugin_info != NULL);
  g_assert (PEAS_IS_ENGINE (engine));

  if (self->plugin_providers == NULL)
    return;

  module_name = peas_plugin_info_get_module_name (plugin_info);
  provider = g_hash_table_lookup (self->plugin_providers, module_name);
  if (provider == NULL)
    return;

  gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (), provider);
  g_hash_table_remove (self->plugin_providers, module_name);
}
Example #14
0
static void
ide_application_plugins_load_plugin_gresources (IdeApplication *self,
                                                PeasPluginInfo *plugin_info,
                                                PeasEngine     *engine)
{
  g_autofree gchar *gresources_path = NULL;
  g_autofree gchar *gresources_basename = NULL;
  const gchar *module_dir;
  const gchar *module_name;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (plugin_info != NULL);
  g_assert (PEAS_IS_ENGINE (engine));

  module_dir = peas_plugin_info_get_module_dir (plugin_info);
  module_name = peas_plugin_info_get_module_name (plugin_info);
  gresources_basename = g_strdup_printf ("%s.gresource", module_name);
  gresources_path = g_build_filename (module_dir, gresources_basename, NULL);

  if (g_file_test (gresources_path, G_FILE_TEST_IS_REGULAR))
    {
      g_autoptr(GError) error = NULL;
      GResource *resource;

      resource = g_resource_load (gresources_path, &error);

      if (resource == NULL)
        {
          g_warning ("Failed to load gresources: %s", error->message);
          return;
        }

      g_hash_table_insert (self->plugin_gresources, g_strdup (module_name), resource);
      g_resources_register (resource);
    }
}
static void
mnb_home_new_widget_dialog_init (MnbHomeNewWidgetDialog *self)
{
  ClutterActor *table, *itemview;
  MnbHomeNewWidgetDialogItemFactory *factory;
  MnbHomePluginsEngine *engine;
  const GList *l;

  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
      MNB_TYPE_HOME_NEW_WIDGET_DIALOG, MnbHomeNewWidgetDialogPrivate);

  /* set up model and view */
  self->priv->items = clutter_list_model_new (ITEMS_N_COLUMNS,
      G_TYPE_STRING, "Module", /* ITEMS_MODULE */
      G_TYPE_STRING, "Name", /* ITEMS_NAME */
      G_TYPE_STRING, "Icon" /* ITEMS_ICON */);

  table = mx_table_new ();
  mx_bin_set_child (MX_BIN (self), table);

  factory = g_object_new (MNB_TYPE_HOME_NEW_WIDGET_DIALOG_ITEM_FACTORY, NULL);
  factory->dialog = self;

  itemview = mx_item_view_new ();
  mx_table_add_actor (MX_TABLE (table), itemview, 0, 1);
  mx_item_view_set_model (MX_ITEM_VIEW (itemview), self->priv->items);
  mx_item_view_set_factory (MX_ITEM_VIEW (itemview), MX_ITEM_FACTORY (factory));

  mx_item_view_add_attribute (MX_ITEM_VIEW (itemview), "module", ITEMS_MODULE);
  mx_item_view_add_attribute (MX_ITEM_VIEW (itemview), "label", ITEMS_NAME);
  mx_item_view_add_attribute (MX_ITEM_VIEW (itemview), "icon", ITEMS_ICON);

  clutter_actor_show_all (table);

  /* find plugins */
  /* FIXME: should we monitor for new plugins on the fly? */
  engine = mnb_home_plugins_engine_dup ();

  for (l = peas_engine_get_plugin_list (PEAS_ENGINE (engine));
       l != NULL;
       l = g_list_next (l))
    {
      PeasPluginInfo *info = l->data;
      char *icon;

      if (!peas_plugin_info_is_available (info, NULL))
        continue;

      icon = g_build_filename (
          peas_plugin_info_get_module_dir (info),
          peas_plugin_info_get_icon_name (info),
          NULL);

      clutter_model_append (self->priv->items,
          ITEMS_MODULE, peas_plugin_info_get_module_name (info),
          ITEMS_NAME, peas_plugin_info_get_name (info),
          ITEMS_ICON, icon,
          -1);

      g_free (icon);
    }

  /* add actions */
  mx_dialog_add_action (MX_DIALOG (self),
      mx_action_new_full ("cancel", _("Cancel"),
        G_CALLBACK (home_new_widget_dialog_cancel),
        self));

  g_object_unref (engine);
  g_object_unref (factory);
}
static gboolean
peas_plugin_loader_seed_load (PeasPluginLoader *loader,
                              PeasPluginInfo   *info)
{
  PeasPluginLoaderSeed *sloader = PEAS_PLUGIN_LOADER_SEED (loader);
  gchar *filename;
  gchar *content;
  GError *error = NULL;
  SeedContext context;
  SeedScript *script;
  SeedException exc = NULL;
  SeedObject global, extensions;
  SeedInfo *sinfo;

  filename = get_script_filename_for_plugin_info (info);

  g_debug ("Seed script filename is '%s'", filename);

  if (!g_file_get_contents (filename, &content, NULL, &error))
    {
      g_warning ("Error: %s", error->message);
      g_error_free (error);
      g_free (filename);
      return FALSE;
    }

  context = seed_context_create (seed->group, NULL);
  seed_prepare_global_context (context);

  script = seed_make_script (context, content, filename, 0);

  seed_evaluate (context, script, NULL);
  exc = seed_script_exception (script);

  seed_script_destroy (script);
  g_free (content);
  g_free (filename);

  if (exc)
    {
      gchar *exc_string = seed_exception_to_string (context, exc);
      g_warning ("Seed Exception: %s", exc_string);
      g_free (exc_string);
      seed_context_unref (context);
      return FALSE;
    }

  global = seed_context_get_global_object (context);
  extensions = seed_object_get_property (context, global, "extensions");

  if (seed_value_is_object (context, extensions))
    {
      sinfo = (SeedInfo *) g_slice_new (SeedInfo);
      sinfo->context = context;
      sinfo->extensions = extensions;
      seed_value_protect (context, extensions);

      g_hash_table_insert (sloader->loaded_plugins, info, sinfo);
      return TRUE;
    }
  else
    {
      g_warning ("extensions is not an object in plugin '%s'",
                 peas_plugin_info_get_module_name (info));
      seed_context_unref (context);
      return FALSE;
    }
}
static PeasExtension *
peas_plugin_loader_seed_create_extension (PeasPluginLoader *loader,
                                          PeasPluginInfo   *info,
                                          GType             exten_type,
                                          guint             n_parameters,
                                          GParameter       *parameters)
{
  PeasPluginLoaderSeed *sloader = PEAS_PLUGIN_LOADER_SEED (loader);
  SeedInfo *sinfo;
  SeedValue extension_ctor, extension;
  guint i, j;
  SeedValue value;
  GValue gvalue = { 0 };
  GArray *interfaces;
  gchar **property_names;

  sinfo = (SeedInfo *) g_hash_table_lookup (sloader->loaded_plugins, info);

  /* FIXME: instantiate new object and pass the parameters */
  extension_ctor = seed_object_get_property (sinfo->context,
                                             sinfo->extensions,
                                             g_type_name (exten_type));
  if (!extension_ctor ||
      seed_value_is_undefined (sinfo->context, extension_ctor) ||
      seed_value_is_null (sinfo->context, extension_ctor))
    return NULL;

  if (!seed_value_is_object (sinfo->context, extension_ctor))
    {
      g_warning ("Extension '%s' in plugin '%s' is not a Seed object",
                 g_type_name (exten_type), peas_plugin_info_get_module_name (info));
      return NULL;
    }

  /* Instantiate the ctor object into a new specific object. */
  extension = JSObjectCallAsConstructor (sinfo->context, extension_ctor, 0, NULL, NULL);

  if (extension == NULL)
    {
#ifndef PEAS_DISABLE_DEPRECATED_FEATURES
      gchar **property_names;

      g_warning ("DEPRECATION WARNING: Extension '%s' in plugin '%s' is not a valid "
                 "constructor function. Support for extension initialization by array "
                 "copy will be dropped soon.",
                 g_type_name (exten_type), peas_plugin_info_get_module_name (info));

      extension = seed_make_object (sinfo->context, NULL, NULL);
      property_names = seed_object_copy_property_names (sinfo->context,
                                                        extension_ctor);
      for (i = 0; property_names[i] != NULL; i++)
        {
          SeedValue value;
          value = seed_object_get_property (sinfo->context,
                                            extension_ctor,
                                            property_names[i]);
          seed_object_set_property (sinfo->context,
                                    extension,
                                    property_names[i],
                                    value);
        }

        g_strfreev (property_names);
#else
      g_warning ("Extension '%s' in plugin '%s' is not a valid constructor",
                 g_type_name (exten_type), peas_plugin_info_get_module_name (info));
      return NULL;
#endif
    }

  /* Set the properties as well, cannot use
   * g_object_set_property() because it may be construct-only
   */
  for (i = 0; i < n_parameters; i++)
    {
      gchar *key;

      /* We want to normalize the property names to have a '_' instead of the
       * conventional '-', to make them accessible through this.property_name */
      key = g_strdup (parameters[i].name);
      for (j = 0; key[j] != '\0'; j++)
        {
          if (key[j] == '-')
            key[j] = '_';
        }

      value = seed_value_from_gvalue (sinfo->context,
                                      &parameters[i].value,
                                      NULL);
      seed_object_set_property (sinfo->context,
                                extension,
                                key,
                                value);

      g_free (key);
    }

  /* Set the plugin info as an attribute of the instance */
  g_value_init (&gvalue, PEAS_TYPE_PLUGIN_INFO);
  g_value_set_boxed (&gvalue, info);

  value = seed_value_from_gvalue (sinfo->context, &gvalue, NULL);
  seed_object_set_property (sinfo->context, extension, "plugin_info", value);

  g_value_unset (&gvalue);


  /* Do not add exten_type as it will be added below */
  interfaces = g_array_new (TRUE, FALSE, sizeof (GType));

  property_names = seed_object_copy_property_names (sinfo->context,
                                                    sinfo->extensions);

  for (i = 0; property_names[i] != NULL; ++i)
    {
      gchar *property_name = property_names[i];
      SeedValue *prop_extension_ctor;
      GType the_type;

      prop_extension_ctor = seed_object_get_property (sinfo->context,
                                                      sinfo->extensions,
                                                      property_name);

      if (prop_extension_ctor != extension_ctor)
        continue;

      if (!seed_value_is_object (sinfo->context, extension_ctor))
        {
          g_warning ("Extension '%s' in plugin '%s' is not a Seed object",
                     property_name, peas_plugin_info_get_module_name (info));
          continue;
        }

      the_type = peas_gi_get_type_from_name (property_name);

      if (the_type == G_TYPE_INVALID)
        {
          g_warning ("Could not find GType for '%s', "
                     "did you forget to import it?", property_name);
        }
      else
        {
          g_array_append_val (interfaces, the_type);
        }
    }

  g_array_sort (interfaces, (GCompareFunc) prerequisites_sort);

  g_strfreev (property_names);

  return peas_extension_seed_new (exten_type,
                                  (GType *) g_array_free (interfaces, FALSE),
                                  sinfo->context, extension);
}
Example #18
0
void
ide_application_discover_plugins (IdeApplication *self)
{
  PeasEngine *engine = peas_engine_get_default ();
  const GList *list;
  gchar *path;
  g_autoptr(GError) error = NULL;

  g_return_if_fail (IDE_IS_APPLICATION (self));

  if (g_getenv ("GB_IN_TREE_PLUGINS") != NULL)
    {
      GDir *dir;

      g_irepository_prepend_search_path (BUILDDIR"/src/gstyle");
      g_irepository_prepend_search_path (BUILDDIR"/src/libide");

      if ((dir = g_dir_open (BUILDDIR"/src/plugins", 0, NULL)))
        {
          const gchar *name;

          while ((name = g_dir_read_name (dir)))
            {
              path = g_build_filename (BUILDDIR, "src", "plugins", name, NULL);
              peas_engine_prepend_search_path (engine, path, path);
              g_free (path);
            }

          g_dir_close (dir);
        }
    }
  else
    {
      g_irepository_prepend_search_path (PACKAGE_LIBDIR"/gnome-builder/girepository-1.0");

      peas_engine_prepend_search_path (engine,
                                       PACKAGE_LIBDIR"/gnome-builder/plugins",
                                       PACKAGE_DATADIR"/gnome-builder/plugins");
    }

  /*
   * We have access to ~/.local/share/gnome-builder/ for plugins even when we are
   * bundled with flatpak, so might as well use it.
   */
  if (ide_is_flatpak ())
    {
      g_autofree gchar *plugins_dir = g_build_filename (g_get_home_dir (),
                                                        ".local",
                                                        "share",
                                                        "gnome-builder",
                                                        "plugins",
                                                        NULL);
      g_irepository_prepend_search_path (plugins_dir);
      peas_engine_prepend_search_path (engine, plugins_dir, plugins_dir);
    }

  if (!g_irepository_require (NULL, "Ide", "1.0", 0, &error) ||
      !g_irepository_require (NULL, "Gtk", "3.0", 0, &error) ||
      !g_irepository_require (NULL, "Dazzle", "1.0", 0, &error))
    g_warning ("Cannot enable Python 3 plugins: %s", error->message);
  else
    {
      /* Avoid spamming stderr with Ide import tracebacks */
      peas_engine_enable_loader (engine, "python3");
    }

  peas_engine_prepend_search_path (engine, "resource:///org/gnome/builder/plugins/", NULL);

  path = g_build_filename (g_get_user_data_dir (), "gnome-builder", "plugins", NULL);
  peas_engine_prepend_search_path (engine, path, NULL);
  g_free (path);

  list = peas_engine_get_plugin_list (engine);

  for (; list; list = list->next)
    {
      PeasPluginInfo *plugin_info = list->data;

      g_debug ("Discovered plugin \"%s\"",
               peas_plugin_info_get_module_name (plugin_info));
    }
}