comparison libpurple/plugin.c @ 21199:fb8f9bf86315

* Add purple_plugin_disable() to prevent plugins from loading on the next startup. A UI would call this when purple_plugin_unload() returns FALSE. * Make purple_plugin_unload() set plugin->error instead of popping up a notification if a dependent plugin can't be unloaded.
author Richard Laager <rlaager@wiktel.com>
date Sun, 07 Oct 2007 16:02:55 +0000
parents a4a55a096ac8
children 166b7949be3d
comparison
equal deleted inserted replaced
21198:b6136fd465a0 21199:fb8f9bf86315
56 static GList *loaded_plugins = NULL; 56 static GList *loaded_plugins = NULL;
57 static GList *protocol_plugins = NULL; 57 static GList *protocol_plugins = NULL;
58 #ifdef PURPLE_PLUGINS 58 #ifdef PURPLE_PLUGINS
59 static GList *load_queue = NULL; 59 static GList *load_queue = NULL;
60 static GList *plugin_loaders = NULL; 60 static GList *plugin_loaders = NULL;
61 static GList *plugins_to_disable = NULL;
61 #endif 62 #endif
62 63
63 static void (*probe_cb)(void *) = NULL; 64 static void (*probe_cb)(void *) = NULL;
64 static void *probe_cb_data = NULL; 65 static void *probe_cb_data = NULL;
65 static void (*load_cb)(PurplePlugin *, void *) = NULL; 66 static void (*load_cb)(PurplePlugin *, void *) = NULL;
656 657
657 if (dep_plugin != NULL && purple_plugin_is_loaded(dep_plugin)) 658 if (dep_plugin != NULL && purple_plugin_is_loaded(dep_plugin))
658 { 659 {
659 if (!purple_plugin_unload(dep_plugin)) 660 if (!purple_plugin_unload(dep_plugin))
660 { 661 {
661 char *tmp; 662 g_free(plugin->error);
662 663 plugin->error = g_strdup_printf(_("%s requires %s, but it failed to unload."),
663 tmp = g_strdup_printf(_("The dependent plugin %s failed to unload."), 664 _(plugin->info->name),
664 _(dep_plugin->info->name)); 665 _(dep_plugin->info->name));
665
666 purple_notify_error(NULL, NULL,
667 _("There were errors unloading the plugin."), tmp);
668 g_free(tmp);
669
670 return FALSE; 666 return FALSE;
671 } 667 }
672 else 668 else
673 { 669 {
674 plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l); 670 plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l);
689 else 685 else
690 purple_debug_error("plugins", "Unable to remove from dependency list for %s\n", dep_name); 686 purple_debug_error("plugins", "Unable to remove from dependency list for %s\n", dep_name);
691 } 687 }
692 688
693 if (plugin->native_plugin) { 689 if (plugin->native_plugin) {
694 if (plugin->info->unload != NULL) 690 if (plugin->info->unload && !plugin->info->unload(plugin))
695 if (!plugin->info->unload(plugin)) 691 return FALSE;
696 return FALSE;
697 692
698 if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) { 693 if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) {
699 PurplePluginProtocolInfo *prpl_info; 694 PurplePluginProtocolInfo *prpl_info;
700 GList *l; 695 GList *l;
701 696
726 if (loader == NULL) 721 if (loader == NULL)
727 return FALSE; 722 return FALSE;
728 723
729 loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); 724 loader_info = PURPLE_PLUGIN_LOADER_INFO(loader);
730 725
731 if (loader_info->unload != NULL) 726 if (loader_info->unload && !loader_info->unload(plugin))
732 if (!loader_info->unload(plugin)) 727 return FALSE;
733 return FALSE;
734 } 728 }
735 729
736 /* cancel any pending dialogs the plugin has */ 730 /* cancel any pending dialogs the plugin has */
737 purple_request_close_with_handle(plugin); 731 purple_request_close_with_handle(plugin);
738 purple_notify_close_with_handle(plugin); 732 purple_notify_close_with_handle(plugin);
741 purple_plugin_ipc_unregister_all(plugin); 735 purple_plugin_ipc_unregister_all(plugin);
742 736
743 loaded_plugins = g_list_remove(loaded_plugins, plugin); 737 loaded_plugins = g_list_remove(loaded_plugins, plugin);
744 if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin)) 738 if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin))
745 protocol_plugins = g_list_remove(protocol_plugins, plugin); 739 protocol_plugins = g_list_remove(protocol_plugins, plugin);
740 plugins_to_disable = g_list_remove(plugins_to_disable, plugin);
746 plugin->loaded = FALSE; 741 plugin->loaded = FALSE;
742
743 /* We wouldn't be anywhere near here if the plugin wasn't loaded, so
744 * if plugin->error is set at all, it had to be from a previous
745 * unload failure. It's obviously okay now.
746 */
747 g_free(plugin->error);
748 plugin->error = NULL;
747 749
748 if (unload_cb != NULL) 750 if (unload_cb != NULL)
749 unload_cb(plugin, unload_cb_data); 751 unload_cb(plugin, unload_cb_data);
750 752
751 purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin); 753 purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin);
754 756
755 return TRUE; 757 return TRUE;
756 #else 758 #else
757 return TRUE; 759 return TRUE;
758 #endif /* PURPLE_PLUGINS */ 760 #endif /* PURPLE_PLUGINS */
761 }
762
763 void
764 purple_plugin_disable(PurplePlugin *plugin)
765 {
766 g_return_if_fail(plugin != NULL);
767
768 if (!g_list_find(plugins_to_disable, plugin))
769 plugins_to_disable = g_list_prepend(plugins_to_disable, plugin);
759 } 770 }
760 771
761 gboolean 772 gboolean
762 purple_plugin_reload(PurplePlugin *plugin) 773 purple_plugin_reload(PurplePlugin *plugin)
763 { 774 {
1221 purple_plugins_save_loaded(const char *key) 1232 purple_plugins_save_loaded(const char *key)
1222 { 1233 {
1223 #ifdef PURPLE_PLUGINS 1234 #ifdef PURPLE_PLUGINS
1224 GList *pl; 1235 GList *pl;
1225 GList *files = NULL; 1236 GList *files = NULL;
1226 PurplePlugin *p;
1227 1237
1228 for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) { 1238 for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) {
1229 p = pl->data; 1239 PurplePlugin *plugin = pl->data;
1230 1240
1231 if (p->info->type != PURPLE_PLUGIN_PROTOCOL && 1241 if (plugin->info->type != PURPLE_PLUGIN_PROTOCOL &&
1232 p->info->type != PURPLE_PLUGIN_LOADER) { 1242 plugin->info->type != PURPLE_PLUGIN_LOADER &&
1233 files = g_list_append(files, p->path); 1243 !g_list_find(plugins_to_disable, plugin)) {
1244 files = g_list_append(files, plugin->path);
1234 } 1245 }
1235 } 1246 }
1236 1247
1237 purple_prefs_set_path_list(key, files); 1248 purple_prefs_set_path_list(key, files);
1238 g_list_free(files); 1249 g_list_free(files);