gplugin/gplugin

76d43734c071
Parents 583aebab3bac
Children 195cf7537aa9
Add a desired-state property to GPlugin.Plugin

This allows us to track what state the user wanted a plugin to be in. The use
case here is, I want to disable a plugin, but the plugin can't be cleanly
unloaded. The plugin returns FALSE from its unload function with an error
stating as such.

For a GPlugin consuming application this creates a dilema where the user can't
actually disable this plugin, because as far as everyone knows, that plugin
should be loaded. With this new property, the consuming application can then
check if the desired state is set to loaded before saving it to a list of
plugins to that should be loaded at the next launch.

Testing Done:
Updated the loader unit tests to make sure that the property is being set properly by `GPluginLoader`.

Reviewed at https://reviews.imfreedom.org/r/1200/
--- a/gplugin/gplugin-loader-tests.c Mon Dec 27 03:43:14 2021 -0600
+++ b/gplugin/gplugin-loader-tests.c Thu Dec 30 23:45:29 2021 -0600
@@ -78,6 +78,10 @@
gplugin_plugin_get_state(plugin),
==,
GPLUGIN_PLUGIN_STATE_QUERIED);
+ g_assert_cmpint(
+ gplugin_plugin_get_desired_state(plugin),
+ ==,
+ GPLUGIN_PLUGIN_STATE_QUERIED);
gplugin_manager_load_plugin(manager, plugin, &error);
g_assert_no_error(error);
@@ -85,6 +89,10 @@
gplugin_plugin_get_state(plugin),
==,
GPLUGIN_PLUGIN_STATE_LOADED);
+ g_assert_cmpint(
+ gplugin_plugin_get_desired_state(plugin),
+ ==,
+ GPLUGIN_PLUGIN_STATE_LOADED);
gplugin_manager_unload_plugin(manager, plugin, &error);
g_assert_no_error(error);
@@ -92,6 +100,10 @@
gplugin_plugin_get_state(plugin),
==,
GPLUGIN_PLUGIN_STATE_QUERIED);
+ g_assert_cmpint(
+ gplugin_plugin_get_desired_state(plugin),
+ ==,
+ GPLUGIN_PLUGIN_STATE_QUERIED);
g_object_unref(G_OBJECT(plugin));
}
@@ -120,6 +132,10 @@
gplugin_plugin_get_state(plugin),
==,
GPLUGIN_PLUGIN_STATE_LOAD_FAILED);
+ g_assert_cmpint(
+ gplugin_plugin_get_desired_state(plugin),
+ ==,
+ GPLUGIN_PLUGIN_STATE_LOADED);
/* make sure that the plugin's error was set */
error = gplugin_plugin_get_error(plugin);
@@ -153,6 +169,11 @@
==,
GPLUGIN_PLUGIN_STATE_LOAD_FAILED);
+ g_assert_cmpint(
+ gplugin_plugin_get_desired_state(plugin),
+ ==,
+ GPLUGIN_PLUGIN_STATE_LOADED);
+
/* make sure that the plugin's error was set */
error = gplugin_plugin_get_error(plugin);
g_assert_error(error, GPLUGIN_DOMAIN, 0);
@@ -197,6 +218,10 @@
gplugin_plugin_get_state(plugin),
==,
GPLUGIN_PLUGIN_STATE_QUERIED);
+ g_assert_cmpint(
+ gplugin_plugin_get_desired_state(plugin),
+ ==,
+ GPLUGIN_PLUGIN_STATE_QUERIED);
g_object_unref(G_OBJECT(plugin));
}
@@ -233,6 +258,10 @@
gplugin_plugin_get_state(plugin),
==,
GPLUGIN_PLUGIN_STATE_UNLOAD_FAILED);
+ g_assert_cmpint(
+ gplugin_plugin_get_desired_state(plugin),
+ ==,
+ GPLUGIN_PLUGIN_STATE_QUERIED);
/* make sure that the plugin's error was set */
error = gplugin_plugin_get_error(plugin);
--- a/gplugin/gplugin-loader.c Mon Dec 27 03:43:14 2021 -0600
+++ b/gplugin/gplugin-loader.c Thu Dec 30 23:45:29 2021 -0600
@@ -209,6 +209,11 @@
g_return_val_if_fail(filename, NULL);
g_return_val_if_fail(error != NULL, NULL);
+ /* We don't have a plugin instance yet, so we just set the desired-state at
+ * the same time we set the state because that's the first opportunity we
+ * have.
+ */
+
klass = GPLUGIN_LOADER_GET_CLASS(loader);
if(klass != NULL && klass->query != NULL) {
@@ -230,10 +235,14 @@
*/
g_clear_error(&real_error);
- /* Likewise, make sure the plugin's error is set to NULL. */
- g_object_set(G_OBJECT(plugin), "error", NULL, NULL);
-
- gplugin_plugin_set_state(plugin, GPLUGIN_PLUGIN_STATE_QUERIED);
+ /* Set a few properties. */
+ /* clang-format off */
+ g_object_set(G_OBJECT(plugin),
+ "error", NULL,
+ "state", GPLUGIN_PLUGIN_STATE_QUERIED,
+ "desired-state", GPLUGIN_PLUGIN_STATE_QUERIED,
+ NULL);
+ /* clang-format on */
}
return plugin;
@@ -269,6 +278,8 @@
return TRUE;
}
+ gplugin_plugin_set_desired_state(plugin, GPLUGIN_PLUGIN_STATE_LOADED);
+
klass = GPLUGIN_LOADER_GET_CLASS(loader);
if(klass != NULL && klass->load != NULL) {
@@ -340,6 +351,8 @@
return TRUE;
}
+ gplugin_plugin_set_desired_state(plugin, GPLUGIN_PLUGIN_STATE_QUERIED);
+
klass = GPLUGIN_LOADER_GET_CLASS(loader);
if(klass != NULL && klass->unload != NULL) {
--- a/gplugin/gplugin-native-plugin.c Mon Dec 27 03:43:14 2021 -0600
+++ b/gplugin/gplugin-native-plugin.c Thu Dec 30 23:45:29 2021 -0600
@@ -130,6 +130,7 @@
GPluginLoader *loader;
GPluginPluginInfo *info;
GPluginPluginState state;
+ GPluginPluginState desired_state;
GError *error;
};
@@ -147,6 +148,7 @@
PROP_LOADER,
PROP_INFO,
PROP_STATE,
+ PROP_DESIRED_STATE,
PROP_ERROR,
};
static GParamSpec *properties[N_PROPERTIES] = {
@@ -222,6 +224,9 @@
case PROP_STATE:
g_value_set_enum(value, plugin->state);
break;
+ case PROP_DESIRED_STATE:
+ g_value_set_enum(value, plugin->desired_state);
+ break;
case PROP_ERROR:
g_value_set_boxed(value, plugin->error);
break;
@@ -265,6 +270,9 @@
case PROP_STATE:
plugin->state = g_value_get_enum(value);
break;
+ case PROP_DESIRED_STATE:
+ plugin->desired_state = g_value_get_enum(value);
+ break;
case PROP_ERROR:
g_clear_error(&plugin->error);
plugin->error = g_value_dup_boxed(value);
@@ -349,6 +357,10 @@
g_object_class_override_property(obj_class, PROP_LOADER, "loader");
g_object_class_override_property(obj_class, PROP_INFO, "info");
g_object_class_override_property(obj_class, PROP_STATE, "state");
+ g_object_class_override_property(
+ obj_class,
+ PROP_DESIRED_STATE,
+ "desired-state");
g_object_class_override_property(obj_class, PROP_ERROR, "error");
}
--- a/gplugin/gplugin-plugin.c Mon Dec 27 03:43:14 2021 -0600
+++ b/gplugin/gplugin-plugin.c Thu Dec 30 23:45:29 2021 -0600
@@ -126,6 +126,26 @@
g_object_interface_install_property(iface, pspec);
/**
+ * GPluginPlugin:desired-state:
+ *
+ * The desired state of the plugin. Typically this just mirrors the state
+ * property, but if a state change failed this will remain set to the state
+ * that was attempted.
+ *
+ * See [method@GPlugin.Plugin.get_desired_state] for more information.
+ *
+ * Since: 0.38.0
+ */
+ pspec = g_param_spec_enum(
+ "desired-state",
+ "desired-state",
+ "The desired state of the plugin",
+ GPLUGIN_TYPE_PLUGIN_STATE,
+ GPLUGIN_PLUGIN_STATE_UNKNOWN,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ g_object_interface_install_property(iface, pspec);
+
+ /**
* GPluginPlugin:error:
*
* An error that was returned if the plugin failed to load or unload.
@@ -282,6 +302,59 @@
}
/**
+ * gplugin_plugin_get_desired_state:
+ *
+ * Gets the desired state of the plugin. Typically this will hold the same
+ * value of [property@GPlugin.Plugin:state], but if a state change failed this
+ * will remain set to the state that was attempted.
+ *
+ * For example, say a user wants to unload a plugin but the plugin can't be
+ * unloaded for some reason. The state will be set to loaded, but the
+ * desired state will be set to unloaded.
+ *
+ * This behavior can be used to give the user the ability to disable a
+ * plugin that normally isn't unloadabled from being loaded during the next
+ * run of program.
+ *
+ * Returns: The desired state that the user has requested the plugin to be in.
+ *
+ * Since: 0.38.0
+ */
+GPluginPluginState
+gplugin_plugin_get_desired_state(GPluginPlugin *plugin)
+{
+ GPluginPluginState desired_state = GPLUGIN_PLUGIN_STATE_UNKNOWN;
+
+ g_return_val_if_fail(
+ GPLUGIN_IS_PLUGIN(plugin),
+ GPLUGIN_PLUGIN_STATE_UNKNOWN);
+
+ g_object_get(G_OBJECT(plugin), "desired-state", &desired_state, NULL);
+
+ return desired_state;
+}
+
+/**
+ * gplugin_plugin_set_desired_state:
+ * @plugin: The plugin instance.
+ * @state: The desired state.
+ *
+ * Sets the desired state of the plugin. This shouldn't need to be called by
+ * anyone except [class@GPlugin.Loader] which manages the state of plugins.
+ *
+ * Since: 0.38.0
+ */
+void
+gplugin_plugin_set_desired_state(
+ GPluginPlugin *plugin,
+ GPluginPluginState state)
+{
+ g_return_if_fail(GPLUGIN_IS_PLUGIN(plugin));
+
+ g_object_set(G_OBJECT(plugin), "desired-state", state, NULL);
+}
+
+/**
* gplugin_plugin_get_error:
* @plugin: The plugin instance.
*
--- a/gplugin/gplugin-plugin.h Mon Dec 27 03:43:14 2021 -0600
+++ b/gplugin/gplugin-plugin.h Thu Dec 30 23:45:29 2021 -0600
@@ -70,6 +70,11 @@
GPluginPluginState gplugin_plugin_get_state(GPluginPlugin *plugin);
void gplugin_plugin_set_state(GPluginPlugin *plugin, GPluginPluginState state);
+GPluginPluginState gplugin_plugin_get_desired_state(GPluginPlugin *plugin);
+void gplugin_plugin_set_desired_state(
+ GPluginPlugin *plugin,
+ GPluginPluginState state);
+
GError *gplugin_plugin_get_error(GPluginPlugin *plugin);
const gchar *gplugin_plugin_state_to_string(GPluginPluginState state);
--- a/gplugin/tests/test-loader.c Mon Dec 27 03:43:14 2021 -0600
+++ b/gplugin/tests/test-loader.c Thu Dec 30 23:45:29 2021 -0600
@@ -36,6 +36,7 @@
PROP_LOADER,
PROP_INFO,
PROP_STATE,
+ PROP_DESIRED_STATE,
PROP_ERROR,
};
@@ -47,6 +48,7 @@
GPluginLoader *loader;
GPluginPluginInfo *info;
GPluginPluginState state;
+ GPluginPluginState desired_state;
GError *error;
};
@@ -82,6 +84,9 @@
case PROP_STATE:
g_value_set_enum(value, plugin->state);
break;
+ case PROP_DESIRED_STATE:
+ g_value_set_enum(value, plugin->desired_state);
+ break;
case PROP_ERROR:
g_value_set_boxed(value, plugin->error);
break;
@@ -113,6 +118,9 @@
case PROP_STATE:
plugin->state = g_value_get_enum(value);
break;
+ case PROP_DESIRED_STATE:
+ plugin->desired_state = g_value_get_enum(value);
+ break;
case PROP_ERROR:
plugin->error = g_value_dup_boxed(value);
break;
@@ -153,6 +161,10 @@
g_object_class_override_property(obj_class, PROP_LOADER, "loader");
g_object_class_override_property(obj_class, PROP_INFO, "info");
g_object_class_override_property(obj_class, PROP_STATE, "state");
+ g_object_class_override_property(
+ obj_class,
+ PROP_DESIRED_STATE,
+ "desired-state");
g_object_class_override_property(obj_class, PROP_ERROR, "error");
}
--- a/lua/gplugin-lua-plugin.c Mon Dec 27 03:43:14 2021 -0600
+++ b/lua/gplugin-lua-plugin.c Thu Dec 30 23:45:29 2021 -0600
@@ -31,6 +31,7 @@
GPluginLoader *loader;
GPluginPluginInfo *info;
GPluginPluginState state;
+ GPluginPluginState desired_state;
GError *error;
};
@@ -46,6 +47,7 @@
PROP_LOADER,
PROP_INFO,
PROP_STATE,
+ PROP_DESIRED_STATE,
PROP_ERROR,
};
static GParamSpec *properties[N_PROPERTIES] = {
@@ -100,6 +102,9 @@
case PROP_STATE:
g_value_set_enum(value, plugin->state);
break;
+ case PROP_DESIRED_STATE:
+ g_value_set_enum(value, plugin->desired_state);
+ break;
case PROP_ERROR:
g_value_set_boxed(value, plugin->error);
break;
@@ -137,6 +142,9 @@
case PROP_STATE:
plugin->state = g_value_get_enum(value);
break;
+ case PROP_DESIRED_STATE:
+ plugin->desired_state = g_value_get_enum(value);
+ break;
case PROP_ERROR:
plugin->error = g_value_dup_boxed(value);
break;
@@ -193,6 +201,10 @@
g_object_class_override_property(obj_class, PROP_LOADER, "loader");
g_object_class_override_property(obj_class, PROP_INFO, "info");
g_object_class_override_property(obj_class, PROP_STATE, "state");
+ g_object_class_override_property(
+ obj_class,
+ PROP_DESIRED_STATE,
+ "desired-state");
g_object_class_override_property(obj_class, PROP_ERROR, "error");
}
--- a/perl5/gplugin-perl5-plugin.c Mon Dec 27 03:43:14 2021 -0600
+++ b/perl5/gplugin-perl5-plugin.c Thu Dec 30 23:45:29 2021 -0600
@@ -30,6 +30,7 @@
GPluginLoader *loader;
GPluginPluginInfo *info;
GPluginPluginState state;
+ GPluginPluginState desired_state;
GError *error;
};
@@ -45,6 +46,7 @@
PROP_LOADER,
PROP_INFO,
PROP_STATE,
+ PROP_DESIRED_STATE,
PROP_ERROR,
};
static GParamSpec *properties[N_PROPERTIES] = {
@@ -101,6 +103,9 @@
case PROP_STATE:
g_value_set_enum(value, plugin->state);
break;
+ case PROP_DESIRED_STATE:
+ g_value_set_enum(value, plugin->desired_state);
+ break;
case PROP_ERROR:
g_value_set_boxed(value, plugin->error);
break;
@@ -138,6 +143,9 @@
case PROP_STATE:
plugin->state = g_value_get_enum(value);
break;
+ case PROP_DESIRED_STATE:
+ plugin->desired_state = g_value_get_enum(value);
+ break;
case PROP_ERROR:
plugin->error = g_value_dup_boxed(value);
break;
@@ -196,6 +204,10 @@
g_object_class_override_property(obj_class, PROP_LOADER, "loader");
g_object_class_override_property(obj_class, PROP_INFO, "info");
g_object_class_override_property(obj_class, PROP_STATE, "state");
+ g_object_class_override_property(
+ obj_class,
+ PROP_DESIRED_STATE,
+ "desired-state");
g_object_class_override_property(obj_class, PROP_ERROR, "error");
}
--- a/python3/gplugin-python3-plugin.c Mon Dec 27 03:43:14 2021 -0600
+++ b/python3/gplugin-python3-plugin.c Thu Dec 30 23:45:29 2021 -0600
@@ -35,6 +35,7 @@
GPluginLoader *loader;
GPluginPluginInfo *info;
GPluginPluginState state;
+ GPluginPluginState desired_state;
GError *error;
};
@@ -52,6 +53,7 @@
PROP_LOADER,
PROP_INFO,
PROP_STATE,
+ PROP_DESIRED_STATE,
PROP_ERROR,
};
static GParamSpec *properties[N_PROPERTIES] = {
@@ -176,6 +178,9 @@
case PROP_STATE:
g_value_set_enum(value, plugin->state);
break;
+ case PROP_DESIRED_STATE:
+ g_value_set_enum(value, plugin->desired_state);
+ break;
case PROP_ERROR:
g_value_set_boxed(value, plugin->error);
break;
@@ -225,6 +230,9 @@
case PROP_STATE:
plugin->state = g_value_get_enum(value);
break;
+ case PROP_DESIRED_STATE:
+ plugin->desired_state = g_value_get_enum(value);
+ break;
case PROP_ERROR:
plugin->error = g_value_dup_boxed(value);
break;
@@ -297,6 +305,10 @@
g_object_class_override_property(obj_class, PROP_LOADER, "loader");
g_object_class_override_property(obj_class, PROP_INFO, "info");
g_object_class_override_property(obj_class, PROP_STATE, "state");
+ g_object_class_override_property(
+ obj_class,
+ PROP_DESIRED_STATE,
+ "desired-state");
g_object_class_override_property(obj_class, PROP_ERROR, "error");
}