Mercurial > pidgin
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); |
