Add 'google-backend' module.
[platform/upstream/evolution-data-server.git] / modules / google-backend / module-google-backend.c
1 /*
2  * module-google-backend.c
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) version 3.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
16  *
17  */
18
19 #include <config.h>
20 #include <glib/gi18n-lib.h>
21
22 #include <libedataserver/e-uid.h>
23 #include <libedataserver/e-source-address-book.h>
24 #include <libedataserver/e-source-authentication.h>
25 #include <libedataserver/e-source-calendar.h>
26 #include <libedataserver/e-source-camel.h>
27 #include <libedataserver/e-source-collection.h>
28 #include <libedataserver/e-source-mail-account.h>
29 #include <libedataserver/e-source-mail-identity.h>
30 #include <libedataserver/e-source-mail-transport.h>
31 #include <libedataserver/e-source-security.h>
32 #include <libedataserver/e-source-webdav.h>
33
34 #include <libebackend/e-collection-backend.h>
35 #include <libebackend/e-collection-backend-factory.h>
36 #include <libebackend/e-server-side-source.h>
37 #include <libebackend/e-source-registry-server.h>
38
39 /* Standard GObject macros */
40 #define E_TYPE_GOOGLE_BACKEND \
41         (e_google_backend_get_type ())
42 #define E_GOOGLE_BACKEND(obj) \
43         (G_TYPE_CHECK_INSTANCE_CAST \
44         ((obj), E_TYPE_GOOGLE_BACKEND, EGoogleBackend))
45
46 /* Just for readability... */
47 #define METHOD(x) (CAMEL_NETWORK_SECURITY_METHOD_##x)
48
49 /* IMAP Configuration Details */
50 #define GOOGLE_IMAP_BACKEND_NAME        "imapx"
51 #define GOOGLE_IMAP_HOST                "imap.gmail.com"
52 #define GOOGLE_IMAP_PORT                993
53 #define GOOGLE_IMAP_SECURITY_METHOD     METHOD (SSL_ON_ALTERNATE_PORT)
54
55 /* SMTP Configuration Details */
56 #define GOOGLE_SMTP_BACKEND_NAME        "smtp"
57 #define GOOGLE_SMTP_HOST                "smtp.gmail.com"
58 #define GOOGLE_SMTP_PORT                587
59 #define GOOGLE_SMTP_SECURITY_METHOD     METHOD (STARTTLS_ON_STANDARD_PORT)
60
61 /* Calendar Configuration Details */
62 #define GOOGLE_CALENDAR_BACKEND_NAME    "caldav"
63 #define GOOGLE_CALENDAR_HOST            "www.google.com"
64 #define GOOGLE_CALENDAR_CALDAV_PATH     "/calendar/dav/%s/events"
65
66 /* Contacts Configuration Details */
67 #define GOOGLE_CONTACTS_BACKEND_NAME    "google"
68
69 typedef struct _EGoogleBackend EGoogleBackend;
70 typedef struct _EGoogleBackendClass EGoogleBackendClass;
71
72 typedef struct _EGoogleBackendFactory EGoogleBackendFactory;
73 typedef struct _EGoogleBackendFactoryClass EGoogleBackendFactoryClass;
74
75 struct _EGoogleBackend {
76         ECollectionBackend parent;
77 };
78
79 struct _EGoogleBackendClass {
80         ECollectionBackendClass parent_class;
81 };
82
83 struct _EGoogleBackendFactory {
84         ECollectionBackendFactory parent;
85 };
86
87 struct _EGoogleBackendFactoryClass {
88         ECollectionBackendFactoryClass parent_class;
89 };
90
91 /* Module Entry Points */
92 void e_module_load (GTypeModule *type_module);
93 void e_module_unload (GTypeModule *type_module);
94
95 /* Forward Declarations */
96 GType e_google_backend_get_type (void);
97 GType e_google_backend_factory_get_type (void);
98
99 G_DEFINE_DYNAMIC_TYPE (
100         EGoogleBackend,
101         e_google_backend,
102         E_TYPE_COLLECTION_BACKEND)
103
104 G_DEFINE_DYNAMIC_TYPE (
105         EGoogleBackendFactory,
106         e_google_backend_factory,
107         E_TYPE_COLLECTION_BACKEND_FACTORY)
108
109 static void
110 google_backend_add_calendar (ECollectionBackend *backend)
111 {
112         ESource *source;
113         ESource *collection_source;
114         ESourceRegistryServer *server;
115         ESourceExtension *extension;
116         ESourceCollection *collection_extension;
117         const gchar *backend_name;
118         const gchar *extension_name;
119         const gchar *identity;
120         gchar *path;
121
122         /* FIXME As a future enhancement, we should query Google
123          *       for a list of user calendars and add them to the
124          *       collection with matching display names and colors. */
125
126         collection_source = e_backend_get_source (E_BACKEND (backend));
127
128         source = e_collection_backend_new_child (backend, "Calendar");
129         e_source_set_display_name (source, _("Calendar"));
130
131         collection_extension = e_source_get_extension (
132                 collection_source, E_SOURCE_EXTENSION_COLLECTION);
133
134         /* Configure the calendar source. */
135
136         backend_name = GOOGLE_CALENDAR_BACKEND_NAME;
137
138         extension_name = E_SOURCE_EXTENSION_CALENDAR;
139         extension = e_source_get_extension (source, extension_name);
140
141         e_source_backend_set_backend_name (
142                 E_SOURCE_BACKEND (extension), backend_name);
143
144         extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
145         extension = e_source_get_extension (source, extension_name);
146
147         e_source_authentication_set_host (
148                 E_SOURCE_AUTHENTICATION (extension),
149                 GOOGLE_CALENDAR_HOST);
150
151         g_object_bind_property (
152                 collection_extension, "identity",
153                 extension, "user",
154                 G_BINDING_SYNC_CREATE);
155
156         extension_name = E_SOURCE_EXTENSION_SECURITY;
157         extension = e_source_get_extension (source, extension_name);
158
159         e_source_security_set_secure (
160                 E_SOURCE_SECURITY (extension), TRUE);
161
162         extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
163         extension = e_source_get_extension (source, extension_name);
164
165         identity = e_source_collection_get_identity (collection_extension);
166         path = g_strdup_printf (GOOGLE_CALENDAR_CALDAV_PATH, identity);
167         e_source_webdav_set_resource_path (
168                 E_SOURCE_WEBDAV (extension), path);
169         g_free (path);
170
171         server = e_collection_backend_ref_server (backend);
172         e_source_registry_server_add_source (server, source);
173         g_object_unref (server);
174
175         g_object_unref (source);
176 }
177
178 static void
179 google_backend_add_contacts (ECollectionBackend *backend)
180 {
181         ESource *source;
182         ESource *collection_source;
183         ESourceRegistryServer *server;
184         ESourceExtension *extension;
185         ESourceCollection *collection_extension;
186         const gchar *backend_name;
187         const gchar *extension_name;
188
189         collection_source = e_backend_get_source (E_BACKEND (backend));
190
191         source = e_collection_backend_new_child (backend, "Contacts");
192         e_source_set_display_name (source, _("Contacts"));
193
194         /* Add the address book source to the collection. */
195         collection_extension = e_source_get_extension (
196                 collection_source, E_SOURCE_EXTENSION_COLLECTION);
197
198         /* Configure the address book source. */
199
200         backend_name = GOOGLE_CONTACTS_BACKEND_NAME;
201
202         extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
203         extension = e_source_get_extension (source, extension_name);
204
205         e_source_backend_set_backend_name (
206                 E_SOURCE_BACKEND (extension), backend_name);
207
208         extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
209         extension = e_source_get_extension (source, extension_name);
210
211         g_object_bind_property (
212                 collection_extension, "identity",
213                 extension, "user",
214                 G_BINDING_SYNC_CREATE);
215
216         extension_name = E_SOURCE_EXTENSION_SECURITY;
217         extension = e_source_get_extension (source, extension_name);
218
219         e_source_security_set_secure (
220                 E_SOURCE_SECURITY (extension), TRUE);
221
222         server = e_collection_backend_ref_server (backend);
223         e_source_registry_server_add_source (server, source);
224         g_object_unref (server);
225
226         g_object_unref (source);
227 }
228
229 static void
230 google_backend_populate (ECollectionBackend *backend)
231 {
232         GList *list;
233
234         list = e_collection_backend_list_calendar_sources (backend);
235         if (list == NULL)
236                 google_backend_add_calendar (backend);
237         g_list_free_full (list, (GDestroyNotify) g_object_unref);
238
239         list = e_collection_backend_list_contacts_sources (backend);
240         if (list == NULL)
241                 google_backend_add_contacts (backend);
242         g_list_free_full (list, (GDestroyNotify) g_object_unref);
243
244         /* Chain up to parent's populate() method. */
245         E_COLLECTION_BACKEND_CLASS (e_google_backend_parent_class)->
246                 populate (backend);
247 }
248
249 static void
250 google_backend_child_added (ECollectionBackend *backend,
251                             ESource *child_source)
252 {
253         ESource *collection_source;
254         const gchar *extension_name;
255         gboolean is_mail = FALSE;
256
257         collection_source = e_backend_get_source (E_BACKEND (backend));
258
259         extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
260         is_mail |= e_source_has_extension (child_source, extension_name);
261
262         extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
263         is_mail |= e_source_has_extension (child_source, extension_name);
264
265         extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
266         is_mail |= e_source_has_extension (child_source, extension_name);
267
268         /* Synchronize mail-related display names with the collection. */
269         if (is_mail)
270                 g_object_bind_property (
271                         collection_source, "display-name",
272                         child_source, "display-name",
273                         G_BINDING_SYNC_CREATE);
274
275         /* Synchronize mail-related user with the collection identity. */
276         extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
277         if (is_mail && e_source_has_extension (child_source, extension_name)) {
278                 ESourceAuthentication *auth_child_extension;
279                 ESourceCollection *collection_extension;
280
281                 extension_name = E_SOURCE_EXTENSION_COLLECTION;
282                 collection_extension = e_source_get_extension (
283                         collection_source, extension_name);
284
285                 extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
286                 auth_child_extension = e_source_get_extension (
287                         child_source, extension_name);
288
289                 g_object_bind_property (
290                         collection_extension, "identity",
291                         auth_child_extension, "user",
292                         G_BINDING_SYNC_CREATE);
293         }
294
295         /* Chain up to parent's child_added() method. */
296         E_COLLECTION_BACKEND_CLASS (e_google_backend_parent_class)->
297                 child_added (backend, child_source);
298 }
299
300 static void
301 e_google_backend_class_init (EGoogleBackendClass *class)
302 {
303         ECollectionBackendClass *backend_class;
304
305         backend_class = E_COLLECTION_BACKEND_CLASS (class);
306         backend_class->populate = google_backend_populate;
307         backend_class->child_added = google_backend_child_added;
308 }
309
310 static void
311 e_google_backend_class_finalize (EGoogleBackendClass *class)
312 {
313 }
314
315 static void
316 e_google_backend_init (EGoogleBackend *backend)
317 {
318 }
319
320 static void
321 google_backend_prepare_mail_account_source (ESource *source)
322 {
323         ESourceCamel *camel_extension;
324         ESourceExtension *extension;
325         CamelSettings *settings;
326         const gchar *backend_name;
327         const gchar *extension_name;
328
329         backend_name = GOOGLE_IMAP_BACKEND_NAME;
330
331         extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
332         extension = e_source_get_extension (source, extension_name);
333
334         e_source_backend_set_backend_name (
335                 E_SOURCE_BACKEND (extension), backend_name);
336
337         extension_name = e_source_camel_get_extension_name (backend_name);
338         camel_extension = e_source_get_extension (source, extension_name);
339         settings = e_source_camel_get_settings (camel_extension);
340
341         /* The "auth-mechanism" should be determined elsewhere. */
342
343         camel_network_settings_set_host (
344                 CAMEL_NETWORK_SETTINGS (settings),
345                 GOOGLE_IMAP_HOST);
346
347         camel_network_settings_set_port (
348                 CAMEL_NETWORK_SETTINGS (settings),
349                 GOOGLE_IMAP_PORT);
350
351         camel_network_settings_set_security_method (
352                 CAMEL_NETWORK_SETTINGS (settings),
353                 GOOGLE_IMAP_SECURITY_METHOD);
354 }
355
356 static void
357 google_backend_prepare_mail_transport_source (ESource *source)
358 {
359         ESourceCamel *camel_extension;
360         ESourceExtension *extension;
361         CamelSettings *settings;
362         const gchar *backend_name;
363         const gchar *extension_name;
364
365         /* Configure the mail transport source. */
366
367         backend_name = GOOGLE_SMTP_BACKEND_NAME;
368
369         extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
370         extension = e_source_get_extension (source, extension_name);
371
372         e_source_backend_set_backend_name (
373                 E_SOURCE_BACKEND (extension), backend_name);
374
375         extension_name = e_source_camel_get_extension_name (backend_name);
376         camel_extension = e_source_get_extension (source, extension_name);
377         settings = e_source_camel_get_settings (camel_extension);
378
379         /* The "auth-mechanism" should be determined elsewhere. */
380
381         camel_network_settings_set_host (
382                 CAMEL_NETWORK_SETTINGS (settings),
383                 GOOGLE_SMTP_HOST);
384
385         camel_network_settings_set_port (
386                 CAMEL_NETWORK_SETTINGS (settings),
387                 GOOGLE_SMTP_PORT);
388
389         camel_network_settings_set_security_method (
390                 CAMEL_NETWORK_SETTINGS (settings),
391                 GOOGLE_SMTP_SECURITY_METHOD);
392 }
393
394 static void
395 google_backend_factory_prepare_mail (ECollectionBackendFactory *factory,
396                                      ESource *mail_account_source,
397                                      ESource *mail_identity_source,
398                                      ESource *mail_transport_source)
399 {
400         ECollectionBackendFactoryClass *parent_class;
401
402         /* Chain up to parent's prepare_mail() method. */
403         parent_class =
404                 E_COLLECTION_BACKEND_FACTORY_CLASS (
405                 e_google_backend_factory_parent_class);
406         parent_class->prepare_mail (
407                 factory,
408                 mail_account_source,
409                 mail_identity_source,
410                 mail_transport_source);
411
412         google_backend_prepare_mail_account_source (mail_account_source);
413         google_backend_prepare_mail_transport_source (mail_transport_source);
414 }
415
416 static void
417 e_google_backend_factory_class_init (EGoogleBackendFactoryClass *class)
418 {
419         ECollectionBackendFactoryClass *factory_class;
420
421         factory_class = E_COLLECTION_BACKEND_FACTORY_CLASS (class);
422         factory_class->factory_name = "google";
423         factory_class->backend_type = E_TYPE_GOOGLE_BACKEND;
424         factory_class->prepare_mail = google_backend_factory_prepare_mail;
425 }
426
427 static void
428 e_google_backend_factory_class_finalize (EGoogleBackendFactoryClass *class)
429 {
430 }
431
432 static void
433 e_google_backend_factory_init (EGoogleBackendFactory *factory)
434 {
435 }
436
437 G_MODULE_EXPORT void
438 e_module_load (GTypeModule *type_module)
439 {
440         e_google_backend_register_type (type_module);
441         e_google_backend_factory_register_type (type_module);
442 }
443
444 G_MODULE_EXPORT void
445 e_module_unload (GTypeModule *type_module)
446 {
447 }
448