aboutsummaryrefslogtreecommitdiff
path: root/src/mm-plugin-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-plugin-manager.c')
-rw-r--r--src/mm-plugin-manager.c271
1 files changed, 172 insertions, 99 deletions
diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c
index 2c22ab23..72127296 100644
--- a/src/mm-plugin-manager.c
+++ b/src/mm-plugin-manager.c
@@ -33,8 +33,12 @@
#include "mm-utils.h"
#include "mm-log-object.h"
-#define SHARED_PREFIX "libmm-shared"
-#define PLUGIN_PREFIX "libmm-plugin"
+#if defined WITH_BUILTIN_PLUGINS
+# include "mm-builtin-plugins.h"
+#else
+# define SHARED_PREFIX "libmm-shared"
+# define PLUGIN_PREFIX "libmm-plugin"
+#endif
static void initable_iface_init (GInitableIface *iface);
static void log_object_iface_init (MMLogObjectInterface *iface);
@@ -45,14 +49,19 @@ G_DEFINE_TYPE_EXTENDED (MMPluginManager, mm_plugin_manager, G_TYPE_OBJECT, 0,
enum {
PROP_0,
+#if !defined WITH_BUILTIN_PLUGINS
PROP_PLUGIN_DIR,
+#endif
PROP_FILTER,
LAST_PROP
};
struct _MMPluginManagerPrivate {
+#if !defined WITH_BUILTIN_PLUGINS
/* Path to look for plugins */
gchar *plugin_dir;
+#endif
+
/* Device filter */
MMFilter *filter;
@@ -1681,9 +1690,90 @@ register_plugin_allowlist_subsystem_vendor_ids (MMPluginManager *self,
mm_filter_register_plugin_allowlist_subsystem_vendor_id (self->priv->filter, subsystem_vendor_ids[i].l, subsystem_vendor_ids[i].r);
}
+static gboolean
+track_plugin (MMPluginManager *self,
+ MMPlugin *plugin,
+ GPtrArray **subsystems,
+ GError **error)
+{
+ const gchar **plugin_subsystems;
+ guint i;
+
+ /* Ignore plugins that don't specify subsystems */
+ plugin_subsystems = mm_plugin_get_allowed_subsystems (plugin);
+ if (!plugin_subsystems) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Allowed subsystems not specified");
+ return FALSE;
+ }
+
+ /* Process generic plugin */
+ if (mm_plugin_is_generic (plugin)) {
+ if (self->priv->generic) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Another generic plugin already registered");
+ return FALSE;
+ }
+ self->priv->generic = g_object_ref (plugin);
+ } else
+ self->priv->plugins = g_list_append (self->priv->plugins, g_object_ref (plugin));
+
+ /* Track required subsystems, avoiding duplicates in the list */
+ for (i = 0; plugin_subsystems[i]; i++) {
+ if (!g_ptr_array_find_with_equal_func (*subsystems, plugin_subsystems[i], g_str_equal, NULL))
+ g_ptr_array_add (*subsystems, g_strdup (plugin_subsystems[i]));
+ }
+
+ /* Register plugin allowlist rules in filter, if any */
+ register_plugin_allowlist_tags (self, plugin);
+ register_plugin_allowlist_vendor_ids (self, plugin);
+ register_plugin_allowlist_product_ids (self, plugin);
+ register_plugin_allowlist_subsystem_vendor_ids (self, plugin);
+
+ return TRUE;
+}
+
+static gboolean
+validate_tracked_plugins (MMPluginManager *self,
+ GPtrArray *subsystems_take,
+ GError **error)
+{
+ g_autofree gchar *subsystems_str = NULL;
+
+ /* Check the generic plugin once all looped */
+ if (!self->priv->generic)
+ mm_obj_dbg (self, "generic plugin not loaded");
+
+ /* Treat as error if we don't find any plugin */
+ if (!self->priv->plugins && !self->priv->generic) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NO_PLUGINS, "no plugins found");
+ return FALSE;
+ }
+
+ /* Validate required subsystems */
+ if (!subsystems_take->len) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NO_PLUGINS,
+ "empty list of subsystems required by plugins");
+ return FALSE;
+ }
+
+ /* Add trailing NULL and store as GStrv */
+ g_ptr_array_add (subsystems_take, NULL);
+ self->priv->subsystems = (gchar **) g_ptr_array_free (subsystems_take, FALSE);
+ subsystems_str = g_strjoinv (", ", self->priv->subsystems);
+
+ mm_obj_dbg (self, "successfully loaded %u plugins registering %u subsystems: %s",
+ g_list_length (self->priv->plugins) + !!self->priv->generic,
+ g_strv_length (self->priv->subsystems), subsystems_str);
+
+ return TRUE;
+}
+
+#if !defined WITH_BUILTIN_PLUGINS
+
static MMPlugin *
-load_plugin (MMPluginManager *self,
- const gchar *path)
+load_external_plugin (MMPluginManager *self,
+ const gchar *path)
{
MMPlugin *plugin = NULL;
GModule *module;
@@ -1729,10 +1819,9 @@ load_plugin (MMPluginManager *self,
}
plugin = (*plugin_create_func) ();
- if (plugin) {
+ if (plugin)
mm_obj_dbg (self, "loaded plugin '%s' from '%s'", mm_plugin_get_name (plugin), path_display);
- g_object_weak_ref (G_OBJECT (plugin), (GWeakNotify) g_module_close, module);
- } else
+ else
mm_obj_warn (self, "could not load plugin '%s': initialization failed", path_display);
out:
@@ -1745,8 +1834,8 @@ out:
}
static void
-load_shared (MMPluginManager *self,
- const gchar *path)
+load_external_shared (MMPluginManager *self,
+ const gchar *path)
{
GModule *module;
gchar *path_display;
@@ -1802,8 +1891,8 @@ out:
}
static gboolean
-load_plugins (MMPluginManager *self,
- GError **error)
+load_external_plugins (MMPluginManager *self,
+ GError **error)
{
GDir *dir = NULL;
const gchar *fname;
@@ -1811,8 +1900,8 @@ load_plugins (MMPluginManager *self,
GList *plugin_paths = NULL;
GList *l;
GPtrArray *subsystems = NULL;
- g_autofree gchar *subsystems_str = NULL;
g_autofree gchar *plugindir_display = NULL;
+ gboolean valid_plugins = FALSE;
if (!g_module_supported ()) {
g_set_error (error,
@@ -1828,11 +1917,8 @@ load_plugins (MMPluginManager *self,
mm_obj_dbg (self, "looking for plugins in '%s'", plugindir_display);
dir = g_dir_open (self->priv->plugin_dir, 0, NULL);
if (!dir) {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_NO_PLUGINS,
- "plugin directory '%s' not found",
- plugindir_display);
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NO_PLUGINS,
+ "plugin directory '%s' not found", plugindir_display);
goto out;
}
@@ -1847,81 +1933,23 @@ load_plugins (MMPluginManager *self,
/* Load all shared utils */
for (l = shared_paths; l; l = g_list_next (l))
- load_shared (self, (const gchar *)(l->data));
+ load_external_shared (self, (const gchar *)(l->data));
/* Load all plugins */
subsystems = g_ptr_array_new ();
for (l = plugin_paths; l; l = g_list_next (l)) {
- MMPlugin *plugin;
- const gchar **plugin_subsystems;
- guint i;
+ g_autoptr(MMPlugin) plugin = NULL;
+ g_autoptr(GError) inner_error = NULL;
- plugin = load_plugin (self, (const gchar *)(l->data));
+ plugin = load_external_plugin (self, (const gchar *)(l->data));
if (!plugin)
continue;
- /* Ignore plugins that don't specify subsystems */
- plugin_subsystems = mm_plugin_get_allowed_subsystems (plugin);
- if (!plugin_subsystems) {
- mm_obj_warn (self, "plugin '%s' doesn't specify allowed subsystems: ignored",
- mm_plugin_get_name (plugin));
- continue;
- }
-
- /* Process generic plugin */
- if (mm_plugin_is_generic (plugin)) {
- if (self->priv->generic) {
- mm_obj_warn (self, "plugin '%s' is generic and another one is already registered: ignored",
- mm_plugin_get_name (plugin));
- continue;
- }
- self->priv->generic = plugin;
- } else
- self->priv->plugins = g_list_append (self->priv->plugins, plugin);
-
- /* Track required subsystems, avoiding duplicates in the list */
- for (i = 0; plugin_subsystems[i]; i++) {
- if (!g_ptr_array_find_with_equal_func (subsystems, plugin_subsystems[i], g_str_equal, NULL))
- g_ptr_array_add (subsystems, g_strdup (plugin_subsystems[i]));
- }
-
- /* Register plugin allowlist rules in filter, if any */
- register_plugin_allowlist_tags (self, plugin);
- register_plugin_allowlist_vendor_ids (self, plugin);
- register_plugin_allowlist_product_ids (self, plugin);
- register_plugin_allowlist_subsystem_vendor_ids (self, plugin);
+ if (!track_plugin (self, plugin, &subsystems, &inner_error))
+ mm_obj_warn (self, "ignored plugin '%s': %s", mm_plugin_get_name (plugin), inner_error->message);
}
- /* Check the generic plugin once all looped */
- if (!self->priv->generic)
- mm_obj_dbg (self, "generic plugin not loaded");
-
- /* Treat as error if we don't find any plugin */
- if (!self->priv->plugins && !self->priv->generic) {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_NO_PLUGINS,
- "no plugins found in plugin directory '%s'",
- plugindir_display);
- goto out;
- }
-
- /* Validate required subsystems */
- if (!subsystems->len) {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_NO_PLUGINS,
- "empty list of subsystems required by plugins");
- goto out;
- }
- /* Add trailing NULL and store as GStrv */
- g_ptr_array_add (subsystems, NULL);
- self->priv->subsystems = (gchar **) g_ptr_array_free (subsystems, FALSE);
- subsystems_str = g_strjoinv (", ", self->priv->subsystems);
-
- mm_obj_dbg (self, "successfully loaded %u plugins registering %u subsystems: %s",
- g_list_length (self->priv->plugins) + !!self->priv->generic,
- g_strv_length (self->priv->subsystems), subsystems_str);
+ valid_plugins = validate_tracked_plugins (self, subsystems, error);
out:
g_list_free_full (shared_paths, g_free);
@@ -1929,10 +1957,38 @@ out:
if (dir)
g_dir_close (dir);
- /* Return TRUE if at least one plugin found */
- return (self->priv->plugins || self->priv->generic);
+ return valid_plugins;
+}
+
+#else
+
+static gboolean
+load_builtin_plugins (MMPluginManager *self,
+ GError **error)
+{
+ GList *builtin_plugins;
+ GList *l;
+ GPtrArray *subsystems = NULL;
+
+ subsystems = g_ptr_array_new ();
+
+ builtin_plugins = mm_builtin_plugins_load ();
+ for (l = builtin_plugins; l; l = g_list_next (l)) {
+ gboolean tracked;
+ MMPlugin *plugin;
+
+ plugin = MM_PLUGIN (l->data);
+ mm_obj_dbg (self, "loaded builtin plugin '%s'", mm_plugin_get_name (plugin));
+ tracked = track_plugin (self, plugin, &subsystems, NULL);
+ g_assert (tracked);
+ }
+ g_list_free_full (builtin_plugins, (GDestroyNotify)g_object_unref);
+
+ return validate_tracked_plugins (self, subsystems, error);
}
+#endif /* !WITH_BUILTIN_PLUGINS */
+
/*****************************************************************************/
static gchar *
@@ -1944,15 +2000,19 @@ log_object_build_id (MMLogObject *_self)
/*****************************************************************************/
MMPluginManager *
-mm_plugin_manager_new (const gchar *plugin_dir,
- MMFilter *filter,
+mm_plugin_manager_new (MMFilter *filter,
+#if !defined WITH_BUILTIN_PLUGINS
+ const gchar *plugin_dir,
+#endif
GError **error)
{
return g_initable_new (MM_TYPE_PLUGIN_MANAGER,
NULL,
error,
+ MM_PLUGIN_MANAGER_FILTER, filter,
+#if !defined WITH_BUILTIN_PLUGINS
MM_PLUGIN_MANAGER_PLUGIN_DIR, plugin_dir,
- MM_PLUGIN_MANAGER_FILTER, filter,
+#endif
NULL);
}
@@ -1966,18 +2026,20 @@ mm_plugin_manager_init (MMPluginManager *self)
}
static void
-set_property (GObject *object,
- guint prop_id,
+set_property (GObject *object,
+ guint prop_id,
const GValue *value,
- GParamSpec *pspec)
+ GParamSpec *pspec)
{
MMPluginManagerPrivate *priv = MM_PLUGIN_MANAGER (object)->priv;
switch (prop_id) {
+#if !defined WITH_BUILTIN_PLUGINS
case PROP_PLUGIN_DIR:
g_free (priv->plugin_dir);
priv->plugin_dir = g_value_dup_string (value);
break;
+#endif
case PROP_FILTER:
priv->filter = g_value_dup_object (value);
break;
@@ -1988,17 +2050,19 @@ set_property (GObject *object,
}
static void
-get_property (GObject *object,
- guint prop_id,
- GValue *value,
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
GParamSpec *pspec)
{
MMPluginManagerPrivate *priv = MM_PLUGIN_MANAGER (object)->priv;
switch (prop_id) {
+#if !defined WITH_BUILTIN_PLUGINS
case PROP_PLUGIN_DIR:
g_value_set_string (value, priv->plugin_dir);
break;
+#endif
case PROP_FILTER:
g_value_set_object (value, priv->filter);
break;
@@ -2009,12 +2073,16 @@ get_property (GObject *object,
}
static gboolean
-initable_init (GInitable *initable,
- GCancellable *cancellable,
- GError **error)
+initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
{
- /* Load the list of plugins */
- return load_plugins (MM_PLUGIN_MANAGER (initable), error);
+#if defined WITH_BUILTIN_PLUGINS
+ return load_builtin_plugins (MM_PLUGIN_MANAGER (initable), error);
+#else
+ /* Load the list of plugins from the filesystem*/
+ return load_external_plugins (MM_PLUGIN_MANAGER (initable), error);
+#endif
}
static void
@@ -2024,9 +2092,11 @@ dispose (GObject *object)
g_list_free_full (g_steal_pointer (&self->priv->plugins), g_object_unref);
g_clear_object (&self->priv->generic);
- g_clear_pointer (&self->priv->plugin_dir, g_free);
g_clear_object (&self->priv->filter);
g_clear_pointer (&self->priv->subsystems, g_strfreev);
+#if !defined WITH_BUILTIN_PLUGINS
+ g_clear_pointer (&self->priv->plugin_dir, g_free);
+#endif
G_OBJECT_CLASS (mm_plugin_manager_parent_class)->dispose (object);
}
@@ -2056,6 +2126,7 @@ mm_plugin_manager_class_init (MMPluginManagerClass *manager_class)
object_class->get_property = get_property;
/* Properties */
+#if !defined WITH_BUILTIN_PLUGINS
g_object_class_install_property
(object_class, PROP_PLUGIN_DIR,
g_param_spec_string (MM_PLUGIN_MANAGER_PLUGIN_DIR,
@@ -2063,6 +2134,8 @@ mm_plugin_manager_class_init (MMPluginManagerClass *manager_class)
"Where to look for plugins",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+#endif
+
g_object_class_install_property
(object_class, PROP_FILTER,
g_param_spec_object (MM_PLUGIN_MANAGER_FILTER,