[geary/mjog/user-plugins: 23/26] Make plugin activation and deactivation async and throw errors
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/mjog/user-plugins: 23/26] Make plugin activation and deactivation async and throw errors
- Date: Tue, 17 Mar 2020 08:26:10 +0000 (UTC)
commit df7889d7326dfc0e04f1e3225a1d0d323ef0fb27
Author: Michael Gratton <mike vee net>
Date: Wed Mar 11 12:09:43 2020 +1100
Make plugin activation and deactivation async and throw errors
This makes plugin implementation substatially less verbose.
.../application/application-plugin-manager.vala | 110 ++++++++++++++++++---
.../desktop-notifications.vala | 50 +++-------
.../plugin/messaging-menu/messaging-menu.vala | 38 +++----
.../notification-badge/notification-badge.vala | 70 +++++--------
src/client/plugin/plugin-plugin-base.vala | 19 +++-
5 files changed, 165 insertions(+), 122 deletions(-)
---
diff --git a/src/client/application/application-plugin-manager.vala
b/src/client/application/application-plugin-manager.vala
index 0299727c..bc2e809f 100644
--- a/src/client/application/application-plugin-manager.vala
+++ b/src/client/application/application-plugin-manager.vala
@@ -19,6 +19,29 @@ public class Application.PluginManager : GLib.Object {
};
+ private class PluginContext {
+
+
+ public Peas.PluginInfo info { get; private set; }
+ public Plugin.PluginBase plugin { get; private set; }
+
+
+ public PluginContext(Peas.PluginInfo info, Plugin.PluginBase plugin) {
+ this.info = info;
+ this.plugin = plugin;
+ }
+
+ public async void activate() throws GLib.Error {
+ yield this.plugin.activate();
+ }
+
+ public async void deactivate(bool is_shutdown) throws GLib.Error {
+ yield this.plugin.deactivate(is_shutdown);
+ }
+
+ }
+
+
private class ApplicationImpl : Geary.BaseObject, Plugin.Application {
@@ -42,6 +65,21 @@ public class Application.PluginManager : GLib.Object {
}
+ /** Emitted when a plugin is successfully loaded and activated. */
+ public signal void plugin_activated(Peas.PluginInfo info);
+
+ /** Emitted when a plugin raised an error loading or activating. */
+ public signal void plugin_error(Peas.PluginInfo info, GLib.Error error);
+
+ /**
+ * Emitted when a plugin was unloaded.
+ *
+ * If the given error is not null, it was raised on deactivate.
+ */
+ public signal void plugin_deactivated(Peas.PluginInfo info,
+ GLib.Error? error);
+
+
private Client application;
private Peas.Engine plugins;
private bool is_shutdown = false;
@@ -49,8 +87,8 @@ public class Application.PluginManager : GLib.Object {
private FolderStoreFactory folders_factory;
- private Gee.Map<Peas.PluginInfo,Plugin.PluginBase> plugin_set =
- new Gee.HashMap<Peas.PluginInfo,Plugin.PluginBase>();
+ private Gee.Map<Peas.PluginInfo,PluginContext> plugin_set =
+ new Gee.HashMap<Peas.PluginInfo,PluginContext>();
private Gee.Map<Peas.PluginInfo,NotificationContext> notification_contexts =
new Gee.HashMap<Peas.PluginInfo,NotificationContext>();
@@ -193,8 +231,10 @@ public class Application.PluginManager : GLib.Object {
}
if (do_activate) {
- this.plugin_set.set(info, plugin);
- plugin.activate();
+ var plugin_context = new PluginContext(info, plugin);
+ plugin_context.activate.begin((obj, res) => {
+ on_plugin_activated(plugin_context, res);
+ });
}
} else {
warning(
@@ -204,21 +244,59 @@ public class Application.PluginManager : GLib.Object {
}
private void on_unload_plugin(Peas.PluginInfo info) {
- var plugin = this.plugin_set.get(info);
- if (plugin != null) {
- plugin.deactivate(this.is_shutdown);
-
- var notification = plugin as Plugin.NotificationExtension;
- if (notification != null) {
- var context = this.notification_contexts.get(info);
- if (context != null) {
- this.notification_contexts.unset(info);
- context.destroy();
+ var plugin_context = this.plugin_set.get(info);
+ if (plugin_context != null) {
+ plugin_context.deactivate.begin(
+ this.is_shutdown,
+ (obj, res) => {
+ on_plugin_deactivated(plugin_context, res);
}
- }
+ );
+ }
+ }
+
+ private void on_plugin_activated(PluginContext context,
+ GLib.AsyncResult result) {
+ try {
+ context.activate.end(result);
+ this.plugin_set.set(context.info, context);
+ plugin_activated(context.info);
+ } catch (GLib.Error err) {
+ plugin_error(context.info, err);
+ warning(
+ "Activating plugin %s threw error, unloading: %s",
+ context.info.get_module_name(),
+ err.message
+ );
+ this.plugins.unload_plugin(context.info);
+ }
+ }
- this.plugin_set.unset(info);
+ private void on_plugin_deactivated(PluginContext context,
+ GLib.AsyncResult result) {
+ GLib.Error? error = null;
+ try {
+ context.deactivate.end(result);
+ } catch (GLib.Error err) {
+ warning(
+ "Deactivating plugin %s threw error: %s",
+ context.info.get_module_name(),
+ err.message
+ );
+ error = err;
}
+
+ var notification = context.plugin as Plugin.NotificationExtension;
+ if (notification != null) {
+ var notifications = this.notification_contexts.get(context.info);
+ if (notifications != null) {
+ this.notification_contexts.unset(context.info);
+ notifications.destroy();
+ }
+ }
+
+ plugin_deactivated(context.info, error);
+ this.plugin_set.unset(context.info);
}
}
diff --git a/src/client/plugin/desktop-notifications/desktop-notifications.vala
b/src/client/plugin/desktop-notifications/desktop-notifications.vala
index 24769fc8..4f533795 100644
--- a/src/client/plugin/desktop-notifications/desktop-notifications.vala
+++ b/src/client/plugin/desktop-notifications/desktop-notifications.vala
@@ -45,14 +45,26 @@ public class Plugin.DesktopNotifications :
private GLib.Cancellable? cancellable = null;
- public override void activate() {
- this.notifications.new_messages_arrived.connect(on_new_messages_arrived);
+ public override async void activate() throws GLib.Error {
this.cancellable = new GLib.Cancellable();
+ this.email = yield this.notifications.get_email();
+
+ this.notifications.new_messages_arrived.connect(on_new_messages_arrived);
- this.connect_signals.begin();
+ FolderStore folders = yield this.notifications.get_folders();
+ folders.folders_available.connect(
+ (folders) => check_folders(folders)
+ );
+ folders.folders_unavailable.connect(
+ (folders) => check_folders(folders)
+ );
+ folders.folders_type_changed.connect(
+ (folders) => check_folders(folders)
+ );
+ check_folders(folders.get_folders());
}
- public override void deactivate(bool is_shutdown) {
+ public override async void deactivate(bool is_shutdown) throws GLib.Error {
this.cancellable.cancel();
// Keep existing notifications if shutting down since they are
@@ -62,36 +74,6 @@ public class Plugin.DesktopNotifications :
}
}
- private async void connect_signals() {
- try {
- this.email = yield this.notifications.get_email();
- } catch (GLib.Error error) {
- warning(
- "Unable to get folders for plugin: %s",
- error.message
- );
- }
-
- try {
- FolderStore folders = yield this.notifications.get_folders();
- folders.folders_available.connect(
- (folders) => check_folders(folders)
- );
- folders.folders_unavailable.connect(
- (folders) => check_folders(folders)
- );
- folders.folders_type_changed.connect(
- (folders) => check_folders(folders)
- );
- check_folders(folders.get_folders());
- } catch (GLib.Error error) {
- warning(
- "Unable to get folders for plugin: %s",
- error.message
- );
- }
- }
-
private void clear_arrived_notification() {
this.client_application.withdraw_notification(ARRIVED_ID);
this.arrived_notification = null;
diff --git a/src/client/plugin/messaging-menu/messaging-menu.vala
b/src/client/plugin/messaging-menu/messaging-menu.vala
index 29f65fdd..7ce36ee8 100644
--- a/src/client/plugin/messaging-menu/messaging-menu.vala
+++ b/src/client/plugin/messaging-menu/messaging-menu.vala
@@ -28,7 +28,7 @@ public class Plugin.MessagingMenu : PluginBase, NotificationExtension {
private FolderStore? folders = null;
- public override void activate() {
+ public override async void activate() throws GLib.Error {
this.app = new global::MessagingMenu.App(
"%s.desktop".printf(global::Application.Client.APP_ID)
);
@@ -37,36 +37,26 @@ public class Plugin.MessagingMenu : PluginBase, NotificationExtension {
this.notifications.new_messages_arrived.connect(on_new_messages_changed);
this.notifications.new_messages_retired.connect(on_new_messages_changed);
- this.connect_folders.begin();
+
+ this.folders = yield this.notifications.get_folders();
+ folders.folders_available.connect(
+ (folders) => check_folders(folders)
+ );
+ folders.folders_unavailable.connect(
+ (folders) => check_folders(folders)
+ );
+ folders.folders_type_changed.connect(
+ (folders) => check_folders(folders)
+ );
+ check_folders(folders.get_folders());
}
- public override void deactivate(bool is_shutdown) {
+ public override async void deactivate(bool is_shutdown) throws GLib.Error {
this.app.activate_source.disconnect(on_activate_source);
this.app.unregister();
this.app = null;
}
- private async void connect_folders() {
- try {
- this.folders = yield this.notifications.get_folders();
- folders.folders_available.connect(
- (folders) => check_folders(folders)
- );
- folders.folders_unavailable.connect(
- (folders) => check_folders(folders)
- );
- folders.folders_type_changed.connect(
- (folders) => check_folders(folders)
- );
- check_folders(folders.get_folders());
- } catch (GLib.Error error) {
- warning(
- "Unable to get folders for plugin: %s",
- error.message
- );
- }
- }
-
private void show_new_messages_count(Folder folder, int count) {
if (this.notifications.should_notify_new_messages(folder)) {
string source_id = get_source_id(folder);
diff --git a/src/client/plugin/notification-badge/notification-badge.vala
b/src/client/plugin/notification-badge/notification-badge.vala
index 58438f5c..304249a1 100644
--- a/src/client/plugin/notification-badge/notification-badge.vala
+++ b/src/client/plugin/notification-badge/notification-badge.vala
@@ -39,61 +39,43 @@ public class Plugin.NotificationBadge :
private UnityLauncherEntry? entry = null;
- public override void activate() {
- try {
- var connection = this.client_application.get_dbus_connection();
- var path = this.client_application.get_dbus_object_path();
- if (connection == null || path == null) {
- throw new GLib.IOError.NOT_CONNECTED(
- "Application does not have a DBus connection or path"
- );
- }
- this.entry = new UnityLauncherEntry(
- connection,
- path + "/plugin/notificationbadge",
- global::Application.Client.APP_ID + ".desktop"
- );
- } catch (GLib.Error error) {
- warning(
- "Failed to register Unity Launcher Entry: %s",
- error.message
+ public override async void activate() throws GLib.Error {
+ var connection = this.client_application.get_dbus_connection();
+ var path = this.client_application.get_dbus_object_path();
+ if (connection == null || path == null) {
+ throw new GLib.IOError.NOT_CONNECTED(
+ "Application does not have a DBus connection or path"
);
}
+ this.entry = new UnityLauncherEntry(
+ connection,
+ path + "/plugin/notificationbadge",
+ global::Application.Client.APP_ID + ".desktop"
+ );
+
+ FolderStore folders = yield this.notifications.get_folders();
+ folders.folders_available.connect(
+ (folders) => check_folders(folders)
+ );
+ folders.folders_unavailable.connect(
+ (folders) => check_folders(folders)
+ );
+ folders.folders_type_changed.connect(
+ (folders) => check_folders(folders)
+ );
+ check_folders(folders.get_folders());
- connect_folders.begin();
+ this.notifications.notify["total-new-messages"].connect(on_total_changed);
+ update_count();
}
- public override void deactivate(bool is_shutdown) {
+ public override async void deactivate(bool is_shutdown) throws GLib.Error {
this.notifications.notify["total-new-messages"].disconnect(
on_total_changed
);
this.entry = null;
}
- public async void connect_folders() {
- try {
- FolderStore folders = yield this.notifications.get_folders();
- folders.folders_available.connect(
- (folders) => check_folders(folders)
- );
- folders.folders_unavailable.connect(
- (folders) => check_folders(folders)
- );
- folders.folders_type_changed.connect(
- (folders) => check_folders(folders)
- );
- check_folders(folders.get_folders());
- } catch (GLib.Error error) {
- warning(
- "Unable to get folders for plugin: %s",
- error.message
- );
- }
-
- this.notifications.notify["total-new-messages"].connect(on_total_changed);
- update_count();
- }
-
private void check_folders(Gee.Collection<Folder> folders) {
foreach (Folder folder in folders) {
if (folder.folder_type in MONITORED_TYPES) {
diff --git a/src/client/plugin/plugin-plugin-base.vala b/src/client/plugin/plugin-plugin-base.vala
index c7f0c5b2..0be37b0e 100644
--- a/src/client/plugin/plugin-plugin-base.vala
+++ b/src/client/plugin/plugin-plugin-base.vala
@@ -27,10 +27,21 @@ public abstract class Plugin.PluginBase : Geary.BaseObject {
get; construct;
}
- /** Invoked to activate the plugin, after loading. */
- public abstract void activate();
+ /**
+ * Invoked to activate the plugin, after loading.
+ *
+ * If this method raises an error, it will be unloaded without
+ * deactivating.
+ */
+ public abstract async void activate() throws GLib.Error;
- /** Invoked to deactivate the plugin, prior to unloading */
- public abstract void deactivate(bool is_shutdown);
+ /**
+ * Invoked to deactivate the plugin, prior to unloading.
+ *
+ * If `is_shutdown` is true, the plugin is being unloaded because
+ * the client application is quitting. Otherwise, the plugin is
+ * being unloaded at end-user request.
+ */
+ public abstract async void deactivate(bool is_shutdown) throws GLib.Error;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]