1 /*
2 * e-mail-config-service-backend.c
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 #include "e-mail-config-service-backend.h"
19
20 #include <mail/e-mail-config-receiving-page.h>
21 #include <mail/e-mail-config-sending-page.h>
22
23 #define E_MAIL_CONFIG_SERVICE_BACKEND_GET_PRIVATE(obj) \
24 (G_TYPE_INSTANCE_GET_PRIVATE \
25 ((obj), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, EMailConfigServiceBackendPrivate))
26
27 struct _EMailConfigServiceBackendPrivate {
28 ESource *source;
29 ESource *collection;
30 };
31
32 enum {
33 PROP_0,
34 PROP_COLLECTION,
35 PROP_SELECTABLE,
36 PROP_SOURCE
37 };
38
G_DEFINE_ABSTRACT_TYPE(EMailConfigServiceBackend,e_mail_config_service_backend,E_TYPE_EXTENSION)39 G_DEFINE_ABSTRACT_TYPE (
40 EMailConfigServiceBackend,
41 e_mail_config_service_backend,
42 E_TYPE_EXTENSION)
43
44 static void
45 mail_config_service_backend_init_collection (EMailConfigServiceBackend *backend)
46 {
47 EMailConfigServiceBackendClass *class;
48
49 /* Use the new_collection() method to initialize the "collection"
50 * property. This assumes we're editing a new account. If we're
51 * editing an existing account, the initial "collection" property
52 * value should be overridden with the existing collection source. */
53
54 g_return_if_fail (backend->priv->collection == NULL);
55
56 class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
57 g_return_if_fail (class != NULL);
58 g_return_if_fail (class->new_collection != NULL);
59
60 backend->priv->collection = class->new_collection (backend);
61 }
62
63 static void
mail_config_service_backend_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)64 mail_config_service_backend_set_property (GObject *object,
65 guint property_id,
66 const GValue *value,
67 GParamSpec *pspec)
68 {
69 switch (property_id) {
70 case PROP_COLLECTION:
71 e_mail_config_service_backend_set_collection (
72 E_MAIL_CONFIG_SERVICE_BACKEND (object),
73 g_value_get_object (value));
74 return;
75
76 case PROP_SOURCE:
77 e_mail_config_service_backend_set_source (
78 E_MAIL_CONFIG_SERVICE_BACKEND (object),
79 g_value_get_object (value));
80 return;
81 }
82
83 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
84 }
85
86 static void
mail_config_service_backend_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)87 mail_config_service_backend_get_property (GObject *object,
88 guint property_id,
89 GValue *value,
90 GParamSpec *pspec)
91 {
92 switch (property_id) {
93 case PROP_COLLECTION:
94 g_value_set_object (
95 value,
96 e_mail_config_service_backend_get_collection (
97 E_MAIL_CONFIG_SERVICE_BACKEND (object)));
98 return;
99
100 case PROP_SELECTABLE:
101 g_value_set_boolean (
102 value,
103 e_mail_config_service_backend_get_selectable (
104 E_MAIL_CONFIG_SERVICE_BACKEND (object)));
105 return;
106
107 case PROP_SOURCE:
108 g_value_set_object (
109 value,
110 e_mail_config_service_backend_get_source (
111 E_MAIL_CONFIG_SERVICE_BACKEND (object)));
112 return;
113 }
114
115 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
116 }
117
118 static void
mail_config_service_backend_dispose(GObject * object)119 mail_config_service_backend_dispose (GObject *object)
120 {
121 EMailConfigServiceBackendPrivate *priv;
122
123 priv = E_MAIL_CONFIG_SERVICE_BACKEND_GET_PRIVATE (object);
124 g_clear_object (&priv->source);
125 g_clear_object (&priv->collection);
126
127 /* Chain up to parent's dispose() method. */
128 G_OBJECT_CLASS (e_mail_config_service_backend_parent_class)->
129 dispose (object);
130 }
131
132 static void
mail_config_service_backend_constructed(GObject * object)133 mail_config_service_backend_constructed (GObject *object)
134 {
135 EMailConfigServiceBackend *backend;
136
137 backend = E_MAIL_CONFIG_SERVICE_BACKEND (object);
138 mail_config_service_backend_init_collection (backend);
139
140 /* Chain up to parent's constructed() method. */
141 G_OBJECT_CLASS (e_mail_config_service_backend_parent_class)->constructed (object);
142 }
143
144 static gboolean
mail_config_service_backend_get_selectable(EMailConfigServiceBackend * backend)145 mail_config_service_backend_get_selectable (EMailConfigServiceBackend *backend)
146 {
147 EMailConfigServicePage *page;
148 CamelProvider *provider;
149 gboolean selectable = TRUE;
150
151 page = e_mail_config_service_backend_get_page (backend);
152 provider = e_mail_config_service_backend_get_provider (backend);
153
154 if (CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider))
155 selectable = E_IS_MAIL_CONFIG_RECEIVING_PAGE (page);
156
157 return selectable;
158 }
159
160 static ESource *
mail_config_service_backend_new_collection(EMailConfigServiceBackend * backend)161 mail_config_service_backend_new_collection (EMailConfigServiceBackend *backend)
162 {
163 /* This is typically only used for groupware backends. */
164 return NULL;
165 }
166
167 static void
mail_config_service_backend_insert_widgets(EMailConfigServiceBackend * backend,GtkBox * parent)168 mail_config_service_backend_insert_widgets (EMailConfigServiceBackend *backend,
169 GtkBox *parent)
170 {
171 /* does nothing */
172 }
173
174 static void
mail_config_service_backend_setup_defaults(EMailConfigServiceBackend * backend)175 mail_config_service_backend_setup_defaults (EMailConfigServiceBackend *backend)
176 {
177 /* does nothing */
178 }
179
180 static gboolean
mail_config_service_backend_auto_configure(EMailConfigServiceBackend * backend,EConfigLookup * config_lookup,gint * out_priority,gboolean * out_is_complete)181 mail_config_service_backend_auto_configure (EMailConfigServiceBackend *backend,
182 EConfigLookup *config_lookup,
183 gint *out_priority,
184 gboolean *out_is_complete)
185 {
186 return FALSE;
187 }
188
189 static gboolean
mail_config_service_backend_check_complete(EMailConfigServiceBackend * backend)190 mail_config_service_backend_check_complete (EMailConfigServiceBackend *backend)
191 {
192 return TRUE;
193 }
194
195 static void
mail_config_service_backend_commit_changes(EMailConfigServiceBackend * backend)196 mail_config_service_backend_commit_changes (EMailConfigServiceBackend *backend)
197 {
198 /* does nothing */
199 }
200
201 static void
e_mail_config_service_backend_class_init(EMailConfigServiceBackendClass * class)202 e_mail_config_service_backend_class_init (EMailConfigServiceBackendClass *class)
203 {
204 GObjectClass *object_class;
205 EExtensionClass *extension_class;
206
207 g_type_class_add_private (
208 class, sizeof (EMailConfigServiceBackendPrivate));
209
210 object_class = G_OBJECT_CLASS (class);
211 object_class->set_property = mail_config_service_backend_set_property;
212 object_class->get_property = mail_config_service_backend_get_property;
213 object_class->dispose = mail_config_service_backend_dispose;
214 object_class->constructed = mail_config_service_backend_constructed;
215
216 extension_class = E_EXTENSION_CLASS (class);
217 extension_class->extensible_type = E_TYPE_MAIL_CONFIG_SERVICE_PAGE;
218
219 class->get_selectable = mail_config_service_backend_get_selectable;
220 class->new_collection = mail_config_service_backend_new_collection;
221 class->insert_widgets = mail_config_service_backend_insert_widgets;
222 class->setup_defaults = mail_config_service_backend_setup_defaults;
223 class->auto_configure = mail_config_service_backend_auto_configure;
224 class->check_complete = mail_config_service_backend_check_complete;
225 class->commit_changes = mail_config_service_backend_commit_changes;
226
227 g_object_class_install_property (
228 object_class,
229 PROP_COLLECTION,
230 g_param_spec_object (
231 "collection",
232 "Collection",
233 "Optional collection ESource",
234 E_TYPE_SOURCE,
235 G_PARAM_READWRITE |
236 G_PARAM_STATIC_STRINGS));
237
238 g_object_class_install_property (
239 object_class,
240 PROP_SELECTABLE,
241 g_param_spec_boolean (
242 "selectable",
243 "Selectable",
244 "Whether the backend is user selectable",
245 TRUE, /* not applied */
246 G_PARAM_READABLE |
247 G_PARAM_STATIC_STRINGS));
248
249 g_object_class_install_property (
250 object_class,
251 PROP_SOURCE,
252 g_param_spec_object (
253 "source",
254 "Source",
255 "The ESource being edited",
256 E_TYPE_SOURCE,
257 G_PARAM_READWRITE |
258 G_PARAM_STATIC_STRINGS));
259 }
260
261 static void
e_mail_config_service_backend_init(EMailConfigServiceBackend * backend)262 e_mail_config_service_backend_init (EMailConfigServiceBackend *backend)
263 {
264 backend->priv = E_MAIL_CONFIG_SERVICE_BACKEND_GET_PRIVATE (backend);
265 }
266
267 EMailConfigServicePage *
e_mail_config_service_backend_get_page(EMailConfigServiceBackend * backend)268 e_mail_config_service_backend_get_page (EMailConfigServiceBackend *backend)
269 {
270 EExtensible *extensible;
271
272 g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
273
274 extensible = e_extension_get_extensible (E_EXTENSION (backend));
275
276 return E_MAIL_CONFIG_SERVICE_PAGE (extensible);
277 }
278
279 ESource *
e_mail_config_service_backend_get_source(EMailConfigServiceBackend * backend)280 e_mail_config_service_backend_get_source (EMailConfigServiceBackend *backend)
281 {
282 g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
283
284 return backend->priv->source;
285 }
286
287 void
e_mail_config_service_backend_set_source(EMailConfigServiceBackend * backend,ESource * source)288 e_mail_config_service_backend_set_source (EMailConfigServiceBackend *backend,
289 ESource *source)
290 {
291 g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
292
293 if (backend->priv->source == source)
294 return;
295
296 if (source != NULL) {
297 g_return_if_fail (E_IS_SOURCE (source));
298 g_object_ref (source);
299 }
300
301 if (backend->priv->source != NULL)
302 g_object_unref (backend->priv->source);
303
304 backend->priv->source = source;
305
306 g_object_notify (G_OBJECT (backend), "source");
307 }
308
309 ESource *
e_mail_config_service_backend_get_collection(EMailConfigServiceBackend * backend)310 e_mail_config_service_backend_get_collection (EMailConfigServiceBackend *backend)
311 {
312 g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
313
314 return backend->priv->collection;
315 }
316
317 void
e_mail_config_service_backend_set_collection(EMailConfigServiceBackend * backend,ESource * collection)318 e_mail_config_service_backend_set_collection (EMailConfigServiceBackend *backend,
319 ESource *collection)
320 {
321 g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
322
323 if (backend->priv->collection == collection)
324 return;
325
326 if (collection != NULL) {
327 g_return_if_fail (E_IS_SOURCE (collection));
328 g_object_ref (collection);
329 }
330
331 if (backend->priv->collection != NULL)
332 g_object_unref (backend->priv->collection);
333
334 backend->priv->collection = collection;
335
336 g_object_notify (G_OBJECT (backend), "collection");
337 }
338
339 CamelProvider *
e_mail_config_service_backend_get_provider(EMailConfigServiceBackend * backend)340 e_mail_config_service_backend_get_provider (EMailConfigServiceBackend *backend)
341 {
342 EMailConfigServiceBackendClass *class;
343
344 g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
345
346 class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
347 g_return_val_if_fail (class != NULL, NULL);
348 g_return_val_if_fail (class->backend_name != NULL, NULL);
349
350 return camel_provider_get (class->backend_name, NULL);
351 }
352
353 CamelSettings *
e_mail_config_service_backend_get_settings(EMailConfigServiceBackend * backend)354 e_mail_config_service_backend_get_settings (EMailConfigServiceBackend *backend)
355 {
356 ESource *source;
357 ESourceCamel *camel_extension = NULL;
358 EMailConfigServicePage *page;
359 EMailConfigServicePageClass *page_class;
360
361 g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
362
363 page = e_mail_config_service_backend_get_page (backend);
364 page_class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (page);
365
366 /* Which ESource do we pull the CamelSettings from? This is a
367 * little tricky because we have to handle the following cases:
368 *
369 * 1) A stand-alone mail account.
370 *
371 * 2) A collection with a specialized backend (e.g. ews).
372 *
373 * 3) A collection that uses standard backends (e.g. yahoo).
374 *
375 * So the semantics are as follows. They work for now but may
376 * need further tweaking as we support more collection types.
377 *
378 * 1) If the service backend defines a collection source,
379 * assume the CamelSettings will be pulled from there.
380 *
381 * 2) If we have a collection source, try extracting the
382 * ESourceCamel extension for the collection source's
383 * backend name.
384 *
385 * 3) If steps 1 or 2 fail, pull the CamelSettings from
386 * the service backend's own scratch source.
387 */
388
389 source = e_mail_config_service_backend_get_collection (backend);
390 if (source != NULL) {
391 ESourceBackend *backend_extension;
392 const gchar *backend_name;
393 const gchar *extension_name;
394
395 extension_name = E_SOURCE_EXTENSION_COLLECTION;
396 backend_extension =
397 e_source_get_extension (source, extension_name);
398 backend_name =
399 e_source_backend_get_backend_name (backend_extension);
400
401 /* XXX ESourceCollection's default backend name is "none".
402 * Unfortunately so is CamelNullStore's provider name.
403 * Make sure these two misfits don't get paired up! */
404 if (g_strcmp0 (backend_name, "none") != 0) {
405 extension_name =
406 e_source_camel_get_extension_name (backend_name);
407 camel_extension =
408 e_source_get_extension (source, extension_name);
409 }
410 }
411
412 if (camel_extension == NULL) {
413 ESourceBackend *backend_extension;
414 const gchar *backend_name;
415 const gchar *extension_name;
416
417 source = e_mail_config_service_backend_get_source (backend);
418
419 extension_name = page_class->extension_name;
420 backend_extension =
421 e_source_get_extension (source, extension_name);
422 backend_name =
423 e_source_backend_get_backend_name (backend_extension);
424
425 extension_name =
426 e_source_camel_get_extension_name (backend_name);
427 camel_extension =
428 e_source_get_extension (source, extension_name);
429 }
430
431 return e_source_camel_get_settings (camel_extension);
432 }
433
434 gboolean
e_mail_config_service_backend_get_selectable(EMailConfigServiceBackend * backend)435 e_mail_config_service_backend_get_selectable (EMailConfigServiceBackend *backend)
436 {
437 EMailConfigServiceBackendClass *class;
438
439 g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), FALSE);
440
441 class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
442 g_return_val_if_fail (class != NULL, FALSE);
443 g_return_val_if_fail (class->get_selectable != NULL, FALSE);
444
445 return class->get_selectable (backend);
446 }
447
448 void
e_mail_config_service_backend_insert_widgets(EMailConfigServiceBackend * backend,GtkBox * parent)449 e_mail_config_service_backend_insert_widgets (EMailConfigServiceBackend *backend,
450 GtkBox *parent)
451 {
452 EMailConfigServiceBackendClass *class;
453
454 g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
455 g_return_if_fail (GTK_IS_BOX (parent));
456
457 class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
458 g_return_if_fail (class != NULL);
459 g_return_if_fail (class->insert_widgets != NULL);
460
461 class->insert_widgets (backend, parent);
462 }
463
464 void
e_mail_config_service_backend_setup_defaults(EMailConfigServiceBackend * backend)465 e_mail_config_service_backend_setup_defaults (EMailConfigServiceBackend *backend)
466 {
467 EMailConfigServiceBackendClass *class;
468
469 g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
470
471 class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
472 g_return_if_fail (class != NULL);
473 g_return_if_fail (class->setup_defaults != NULL);
474
475 return class->setup_defaults (backend);
476 }
477
478 gboolean
e_mail_config_service_backend_auto_configure(EMailConfigServiceBackend * backend,EConfigLookup * config_lookup,gint * out_priority,gboolean * out_is_complete)479 e_mail_config_service_backend_auto_configure (EMailConfigServiceBackend *backend,
480 EConfigLookup *config_lookup,
481 gint *out_priority,
482 gboolean *out_is_complete)
483 {
484 EMailConfigServiceBackendClass *class;
485
486 g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), FALSE);
487 g_return_val_if_fail (E_IS_CONFIG_LOOKUP (config_lookup), FALSE);
488
489 class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
490 g_return_val_if_fail (class != NULL, FALSE);
491 g_return_val_if_fail (class->auto_configure != NULL, FALSE);
492
493 return class->auto_configure (backend, config_lookup, out_priority, out_is_complete);
494 }
495
496 gboolean
e_mail_config_service_backend_check_complete(EMailConfigServiceBackend * backend)497 e_mail_config_service_backend_check_complete (EMailConfigServiceBackend *backend)
498 {
499 EMailConfigServiceBackendClass *class;
500
501 g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), FALSE);
502
503 class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
504 g_return_val_if_fail (class != NULL, FALSE);
505 g_return_val_if_fail (class->check_complete != NULL, FALSE);
506
507 return class->check_complete (backend);
508 }
509
510 void
e_mail_config_service_backend_commit_changes(EMailConfigServiceBackend * backend)511 e_mail_config_service_backend_commit_changes (EMailConfigServiceBackend *backend)
512 {
513 EMailConfigServiceBackendClass *class;
514
515 g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
516
517 class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
518 g_return_if_fail (class != NULL);
519 g_return_if_fail (class->commit_changes != NULL);
520
521 class->commit_changes (backend);
522 }
523
524 /*
525 * e_mail_config_service_backend_auto_configure_for_kind:
526 * @backend: an #EMailConfigServiceBackend
527 * @config_lookup: an #EConfigLookup
528 * @kind: an #EConfigLookupResultKind
529 * @protocol: (nullable): optional protocol name, or %NULL
530 * @source: (nullable): optional #ESource to configure, or %NULL
531 * @out_priority: (out) (nullable): priority of the chosen lookup result
532 * @out_is_complete: (out) (nullable): whether the config is complete
533 *
534 * Finds a config lookup result for the given @kind and @protocol and
535 * configures the @source with it. The @out_priority is set to the priority
536 * of that lookup result.
537 *
538 * If no @protocol is given, then the backend name of the @backend is used.
539 * If no @source is given, then gets it with e_mail_config_service_backend_get_source().
540 *
541 * Returns: whether applied any changes
542 *
543 * Since: 3.26
544 */
545 gboolean
e_mail_config_service_backend_auto_configure_for_kind(EMailConfigServiceBackend * backend,EConfigLookup * config_lookup,EConfigLookupResultKind kind,const gchar * protocol,ESource * source,gint * out_priority,gboolean * out_is_complete)546 e_mail_config_service_backend_auto_configure_for_kind (EMailConfigServiceBackend *backend,
547 EConfigLookup *config_lookup,
548 EConfigLookupResultKind kind,
549 const gchar *protocol,
550 ESource *source,
551 gint *out_priority,
552 gboolean *out_is_complete)
553 {
554 EMailConfigServiceBackendClass *klass;
555 GSList *results;
556 gboolean changed = FALSE;
557
558 g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), FALSE);
559 g_return_val_if_fail (E_IS_CONFIG_LOOKUP (config_lookup), FALSE);
560 g_return_val_if_fail (kind != E_CONFIG_LOOKUP_RESULT_UNKNOWN, FALSE);
561
562 klass = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
563 g_return_val_if_fail (klass != NULL, FALSE);
564 g_return_val_if_fail (klass->backend_name != NULL, FALSE);
565
566 if (!source)
567 source = e_mail_config_service_backend_get_source (backend);
568 if (!protocol)
569 protocol = klass->backend_name;
570
571 results = e_config_lookup_dup_results (config_lookup, kind, protocol);
572 results = g_slist_sort (results, e_config_lookup_result_compare);
573
574 if (results && results->data) {
575 EConfigLookupResult *lookup_result = results->data;
576
577 changed = e_config_lookup_result_configure_source (lookup_result, config_lookup, source);
578
579 if (changed) {
580 if (out_priority)
581 *out_priority = e_config_lookup_result_get_priority (lookup_result);
582
583 if (out_is_complete)
584 *out_is_complete = e_config_lookup_result_get_is_complete (lookup_result);
585 }
586 }
587
588 g_slist_free_full (results, g_object_unref);
589
590 return changed;
591 }
592