diff libpurple/plugin.c @ 21269:68d6de0845f9

propagate from branch 'im.pidgin.charkins.dockletgeom' (head 0a163d30bd4e04f722543b3868eb2d934e5e1db8) to branch 'im.pidgin.pidgin.next.minor' (head f286d10af3621cf62257f54718ae194d75be1916)
author Casey Harkins <charkins@pidgin.im>
date Sun, 28 Oct 2007 17:16:42 +0000
parents fb8f9bf86315
children 166b7949be3d
line wrap: on
line diff
--- a/libpurple/plugin.c	Sun Oct 28 17:08:49 2007 +0000
+++ b/libpurple/plugin.c	Sun Oct 28 17:16:42 2007 +0000
@@ -58,13 +58,9 @@
 #ifdef PURPLE_PLUGINS
 static GList *load_queue       = NULL;
 static GList *plugin_loaders   = NULL;
+static GList *plugins_to_disable = NULL;
 #endif
 
-/*
- * TODO: I think the intention was to allow multiple load and unload
- *       callback functions.  Perhaps using a GList instead of a
- *       pointer to a single function.
- */
 static void (*probe_cb)(void *) = NULL;
 static void *probe_cb_data = NULL;
 static void (*load_cb)(PurplePlugin *, void *) = NULL;
@@ -254,7 +250,6 @@
 		 * plugins being added to the global name space.
 		 *
 		 * G_MODULE_BIND_LOCAL was added in glib 2.3.3.
-		 * TODO: I guess there's nothing we can do about that?
 		 */
 #if GLIB_CHECK_VERSION(2,3,3)
 		plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL);
@@ -625,7 +620,6 @@
 
 	plugin->loaded = TRUE;
 
-	/* TODO */
 	if (load_cb != NULL)
 		load_cb(plugin, load_cb_data);
 
@@ -643,43 +637,37 @@
 {
 #ifdef PURPLE_PLUGINS
 	GList *l;
+	GList *ll;
 
 	g_return_val_if_fail(plugin != NULL, FALSE);
-
-	loaded_plugins = g_list_remove(loaded_plugins, plugin);
-	if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin))
-		protocol_plugins = g_list_remove(protocol_plugins, plugin);
-
 	g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE);
 
 	purple_debug_info("plugins", "Unloading plugin %s\n", plugin->info->name);
 
-	/* cancel any pending dialogs the plugin has */
-	purple_request_close_with_handle(plugin);
-	purple_notify_close_with_handle(plugin);
-
-	plugin->loaded = FALSE;
-
 	/* Unload all plugins that depend on this plugin. */
-	while ((l = plugin->dependent_plugins) != NULL)
-	{
+	for (l = plugin->dependent_plugins; l != NULL; l = ll) {
 		const char * dep_name = (const char *)l->data;
 		PurplePlugin *dep_plugin;
 
+		/* Store a pointer to the next element in the list.
+		 * This is because we'll be modifying this list in the loop. */
+		ll = l->next;
+
 		dep_plugin = purple_plugins_find_with_id(dep_name);
 
 		if (dep_plugin != NULL && purple_plugin_is_loaded(dep_plugin))
 		{
 			if (!purple_plugin_unload(dep_plugin))
 			{
-				char *tmp;
-
-				tmp = g_strdup_printf(_("The dependent plugin %s failed to unload."),
-				                      _(dep_plugin->info->name));
-
-				purple_notify_error(NULL, NULL,
-				                  _("There were errors unloading the plugin."), tmp);
-				g_free(tmp);
+				g_free(plugin->error);
+				plugin->error = g_strdup_printf(_("%s requires %s, but it failed to unload."),
+				                                _(plugin->info->name),
+				                                _(dep_plugin->info->name));
+				return FALSE;
+			}
+			else
+			{
+				plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l);
 			}
 		}
 	}
@@ -699,8 +687,8 @@
 	}
 
 	if (plugin->native_plugin) {
-		if (plugin->info->unload != NULL)
-			plugin->info->unload(plugin);
+		if (plugin->info->unload && !plugin->info->unload(plugin))
+			return FALSE;
 
 		if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) {
 			PurplePluginProtocolInfo *prpl_info;
@@ -724,8 +712,7 @@
 				prpl_info->protocol_options = NULL;
 			}
 		}
-	}
-	else {
+	} else {
 		PurplePlugin *loader;
 		PurplePluginLoaderInfo *loader_info;
 
@@ -736,14 +723,30 @@
 
 		loader_info = PURPLE_PLUGIN_LOADER_INFO(loader);
 
-		if (loader_info->unload != NULL)
-			loader_info->unload(plugin);
+		if (loader_info->unload && !loader_info->unload(plugin))
+			return FALSE;
 	}
 
+	/* cancel any pending dialogs the plugin has */
+	purple_request_close_with_handle(plugin);
+	purple_notify_close_with_handle(plugin);
+
 	purple_signals_disconnect_by_handle(plugin);
 	purple_plugin_ipc_unregister_all(plugin);
 
-	/* TODO */
+	loaded_plugins = g_list_remove(loaded_plugins, plugin);
+	if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin))
+		protocol_plugins = g_list_remove(protocol_plugins, plugin);
+	plugins_to_disable = g_list_remove(plugins_to_disable, plugin);
+	plugin->loaded = FALSE;
+
+	/* We wouldn't be anywhere near here if the plugin wasn't loaded, so
+	 * if plugin->error is set at all, it had to be from a previous
+	 * unload failure.  It's obviously okay now.
+	 */
+	g_free(plugin->error);
+	plugin->error = NULL;
+
 	if (unload_cb != NULL)
 		unload_cb(plugin, unload_cb_data);
 
@@ -757,6 +760,15 @@
 #endif /* PURPLE_PLUGINS */
 }
 
+void
+purple_plugin_disable(PurplePlugin *plugin)
+{
+	g_return_if_fail(plugin != NULL);
+
+	if (!g_list_find(plugins_to_disable, plugin))
+		plugins_to_disable = g_list_prepend(plugins_to_disable, plugin);
+}
+
 gboolean
 purple_plugin_reload(PurplePlugin *plugin)
 {
@@ -1222,14 +1234,14 @@
 #ifdef PURPLE_PLUGINS
 	GList *pl;
 	GList *files = NULL;
-	PurplePlugin *p;
 
 	for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) {
-		p = pl->data;
+		PurplePlugin *plugin = pl->data;
 
-		if (p->info->type != PURPLE_PLUGIN_PROTOCOL &&
-			p->info->type != PURPLE_PLUGIN_LOADER) {
-				files = g_list_append(files, p->path);
+		if (plugin->info->type != PURPLE_PLUGIN_PROTOCOL &&
+		    plugin->info->type != PURPLE_PLUGIN_LOADER &&
+		    !g_list_find(plugins_to_disable, plugin)) {
+			files = g_list_append(files, plugin->path);
 		}
 	}
 
@@ -1391,6 +1403,7 @@
 
 	if (probe_cb != NULL)
 		probe_cb(probe_cb_data);
+
 #endif /* PURPLE_PLUGINS */
 }
 
@@ -1464,7 +1477,6 @@
 void
 purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data)
 {
-	/* TODO */
 	probe_cb = func;
 	probe_cb_data = data;
 }
@@ -1472,7 +1484,6 @@
 void
 purple_plugins_unregister_probe_notify_cb(void (*func)(void *))
 {
-	/* TODO */
 	probe_cb = NULL;
 	probe_cb_data = NULL;
 }
@@ -1481,7 +1492,6 @@
 purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *),
 									 void *data)
 {
-	/* TODO */
 	load_cb = func;
 	load_cb_data = data;
 }
@@ -1489,7 +1499,6 @@
 void
 purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *))
 {
-	/* TODO */
 	load_cb = NULL;
 	load_cb_data = NULL;
 }
@@ -1498,7 +1507,6 @@
 purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *),
 									   void *data)
 {
-	/* TODO */
 	unload_cb = func;
 	unload_cb_data = data;
 }
@@ -1506,7 +1514,6 @@
 void
 purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *, void *))
 {
-	/* TODO */
 	unload_cb = NULL;
 	unload_cb_data = NULL;
 }