src/mn-evolution-plugin.c (6866B) - raw
1 /* 2 * Mail Notification 3 * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #include <stdarg.h> 21 #include <string.h> 22 #include <libintl.h> 23 #include <gtk/gtk.h> 24 #include <dbus/dbus.h> 25 #include <dbus/dbus-glib-lowlevel.h> 26 #include <dbus/dbus-glib-bindings.h> 27 #include <camel/camel-folder.h> 28 #include <mail/em-event.h> 29 #include <mail/mail-tools.h> 30 #include "mn-evolution.h" 31 #include "mn-evolution-server.h" 32 #include "mn-evolution-plugin.h" 33 34 #define ENABLE_SUCCESS 0 35 #define ENABLE_FAILURE 1 36 37 static MNEvolutionServer *evo_server = NULL; 38 static DBusGConnection *session_bus = NULL; 39 static DBusGProxy *session_bus_proxy = NULL; 40 41 static void show_error_dialog (const char *primary, const char *format, ...) G_GNUC_PRINTF(2, 3); 42 43 static void 44 show_error_dialog (const char *primary, const char *format, ...) 45 { 46 GtkWidget *dialog; 47 va_list args; 48 char *secondary; 49 50 g_return_if_fail(primary != NULL); 51 g_return_if_fail(format != NULL); 52 53 dialog = gtk_message_dialog_new(NULL, 54 0, 55 GTK_MESSAGE_ERROR, 56 GTK_BUTTONS_OK, 57 "%s", 58 primary); 59 60 va_start(args, format); 61 secondary = g_strdup_vprintf(format, args); 62 va_end(args); 63 64 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", secondary); 65 g_free(secondary); 66 67 gtk_window_set_title(GTK_WINDOW(dialog), ""); /* HIG */ 68 69 g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL); 70 gtk_widget_show(dialog); 71 } 72 73 gboolean 74 mn_evolution_plugin_register_server (GObject *server, 75 const char *service, 76 const char *path, 77 GError **err) 78 { 79 unsigned int name_reply; 80 81 g_return_val_if_fail(G_IS_OBJECT(server), FALSE); 82 g_return_val_if_fail(service != NULL, FALSE); 83 g_return_val_if_fail(path != NULL, FALSE); 84 85 dbus_g_connection_register_g_object(session_bus, path, server); 86 87 if (! org_freedesktop_DBus_request_name(session_bus_proxy, 88 service, 89 DBUS_NAME_FLAG_DO_NOT_QUEUE, 90 &name_reply, 91 err)) 92 return FALSE; 93 94 if (name_reply != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) 95 { 96 /* unlikely to ever happen, not worth a translation */ 97 g_set_error(err, 0, 0, "cannot register name \"%s\"", service); 98 return FALSE; 99 } 100 101 return TRUE; 102 } 103 104 gboolean 105 mn_evolution_plugin_unregister_server (const char *service, GError **err) 106 { 107 unsigned int name_reply; 108 109 g_return_val_if_fail(service != NULL, FALSE); 110 111 if (! org_freedesktop_DBus_release_name(session_bus_proxy, 112 service, 113 &name_reply, 114 err)) 115 return FALSE; 116 117 if (name_reply != DBUS_RELEASE_NAME_REPLY_RELEASED) 118 { 119 /* unlikely to ever happen, not worth a translation */ 120 g_set_error(err, 0, 0, "cannot unregister name \"%s\"", service); 121 return FALSE; 122 } 123 124 return TRUE; 125 } 126 127 static void 128 disable_plugin (void) 129 { 130 g_object_unref(evo_server); 131 evo_server = NULL; 132 133 /* 134 * Do not unref session_bus_proxy, since it might break when the 135 * DBusGProxy memory management issue is fixed 136 * (https://bugs.freedesktop.org/show_bug.cgi?id=14030). 137 */ 138 session_bus_proxy = NULL; 139 140 dbus_g_connection_unref(session_bus); 141 session_bus = NULL; 142 } 143 144 static DBusHandlerResult 145 session_bus_filter_cb (DBusConnection *conn, DBusMessage *message, void *user_data) 146 { 147 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) 148 { 149 GDK_THREADS_ENTER(); 150 151 show_error_dialog(dgettext(GETTEXT_PACKAGE, "A fatal error has occurred in the Evolution Mail Notification plugin"), 152 dgettext(GETTEXT_PACKAGE, "The connection to the D-Bus session bus was lost.")); 153 154 disable_plugin(); 155 156 GDK_THREADS_LEAVE(); 157 158 return DBUS_HANDLER_RESULT_HANDLED; 159 } 160 161 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 162 } 163 164 static gboolean 165 connect_to_session_bus (void) 166 { 167 DBusConnection *raw_bus; 168 GError *err = NULL; 169 170 g_return_val_if_fail(session_bus == NULL, FALSE); 171 172 session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &err); 173 if (! session_bus) 174 { 175 show_error_dialog(dgettext(GETTEXT_PACKAGE, "Unable to initialize the Mail Notification plugin"), 176 dgettext(GETTEXT_PACKAGE, "Unable to connect to the D-Bus session bus: %s."), 177 err->message); 178 g_error_free(err); 179 return FALSE; 180 } 181 182 raw_bus = dbus_g_connection_get_connection(session_bus); 183 184 dbus_connection_set_exit_on_disconnect(raw_bus, FALSE); 185 186 if (! dbus_connection_add_filter(raw_bus, session_bus_filter_cb, NULL, NULL)) 187 { 188 show_error_dialog(dgettext(GETTEXT_PACKAGE, "Unable to initialize the Mail Notification plugin"), 189 /* too unlikely to be worth a translation */ 190 "Unable to add a D-Bus filter: not enough memory."); 191 192 dbus_g_connection_unref(session_bus); 193 session_bus = NULL; 194 195 return FALSE; 196 } 197 198 session_bus_proxy = dbus_g_proxy_new_for_name(session_bus, 199 DBUS_SERVICE_DBUS, 200 DBUS_PATH_DBUS, 201 DBUS_INTERFACE_DBUS); 202 203 return TRUE; 204 } 205 206 int 207 e_plugin_lib_enable (EPlugin *ep, int enable) 208 { 209 static gboolean enabled = FALSE; 210 GError *err = NULL; 211 212 if (! enable || enabled) 213 return ENABLE_SUCCESS; 214 215 enabled = TRUE; 216 217 if (! connect_to_session_bus()) 218 return ENABLE_FAILURE; 219 220 evo_server = mn_evolution_server_new(); 221 if (! mn_evolution_plugin_register_server(G_OBJECT(evo_server), 222 MN_EVOLUTION_SERVER_SERVICE, 223 MN_EVOLUTION_SERVER_PATH, 224 &err)) 225 { 226 show_error_dialog(dgettext(GETTEXT_PACKAGE, "Unable to initialize the Mail Notification plugin"), 227 dgettext(GETTEXT_PACKAGE, "Unable to register the Mail Notification Evolution D-Bus server: %s."), 228 err->message); 229 g_error_free(err); 230 231 disable_plugin(); 232 return ENABLE_FAILURE; 233 } 234 235 return ENABLE_SUCCESS; 236 } 237 238 void 239 org_jylefort_mail_notification_folder_changed (EPlugin *plugin, 240 EMEventTargetFolder *folder) 241 { 242 if (evo_server) 243 mn_evolution_server_folder_changed(evo_server, folder->uri); 244 } 245 246 void 247 org_jylefort_mail_notification_message_reading (EPlugin *plugin, 248 EMEventTargetMessage *message) 249 { 250 if (evo_server) 251 { 252 char *url; 253 254 url = mail_tools_folder_to_url(message->folder); 255 mn_evolution_server_message_reading(evo_server, url); 256 g_free(url); 257 } 258 }