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 }