Added is_supported method to account protocol.
[modest] / src / modest-account-protocol.c
1 /* Copyright (c) 2008, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <tny-simple-list.h>
31 #include "modest-account-protocol.h"
32 #include "modest-account-mgr-helpers.h"
33 #include "widgets/modest-default-account-settings-dialog.h"
34 #include "modest-runtime.h"
35
36 enum {
37         PROP_0,
38         PROP_PORT,
39         PROP_ALTERNATE_PORT,
40         PROP_ACCOUNT_G_TYPE,
41 };
42
43 typedef struct _ModestAccountProtocolPrivate ModestAccountProtocolPrivate;
44 struct _ModestAccountProtocolPrivate {
45         guint port;
46         guint alternate_port;
47         TnyList *account_options;
48         GHashTable *custom_auth_mechs;
49         GType account_g_type;
50
51         GHashTable *account_dialogs;
52 };
53
54 /* 'private'/'protected' functions */
55 static void   modest_account_protocol_class_init (ModestAccountProtocolClass *klass);
56 static void   modest_account_protocol_finalize   (GObject *obj);
57 static void   modest_account_protocol_get_property (GObject *obj,
58                                             guint property_id,
59                                             GValue *value,
60                                             GParamSpec *pspec);
61 static void   modest_account_protocol_set_property (GObject *obj,
62                                             guint property_id,
63                                             const GValue *value,
64                                             GParamSpec *pspec);
65 static void   modest_account_protocol_instance_init (ModestAccountProtocol *obj);
66
67 #define MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE(o)     (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
68                                                                                  MODEST_TYPE_ACCOUNT_PROTOCOL, \
69                                                                                  ModestAccountProtocolPrivate))
70
71 static TnyAccount *modest_account_protocol_create_account_default (ModestAccountProtocol *self);
72
73 static ModestAccountSettingsDialog *modest_account_protocol_create_account_settings_dialog_default (ModestAccountProtocol *self);
74
75 static ModestPairList* modest_account_protocol_get_easysetupwizard_tabs_default (ModestAccountProtocol *self);
76
77 static void modest_account_protocol_save_settings_default (ModestAccountProtocol *self, 
78                                                            ModestAccountSettingsDialog *dialog,
79                                                            ModestAccountSettings *settings);
80
81 static void modest_account_protocol_save_wizard_settings_default (ModestAccountProtocol *self, 
82                                                                   GList *wizard_pages,
83                                                                   ModestAccountSettings *settings);
84
85 static ModestWizardDialogResponseOverrideFunc 
86 modest_account_protocol_get_wizard_response_override_default (ModestAccountProtocol *self);
87
88 static gboolean modest_account_protocol_is_supported_default (ModestAccountProtocol *self);
89
90 /* globals */
91 static GObjectClass *parent_class = NULL;
92
93 GType
94 modest_account_protocol_get_type (void)
95 {
96         static GType my_type = 0;
97
98         if (!my_type) {
99                 static const GTypeInfo my_info = {
100                         sizeof(ModestAccountProtocolClass),
101                         NULL,   /* base init */
102                         NULL,   /* base finalize */
103                         (GClassInitFunc) modest_account_protocol_class_init,
104                         NULL,   /* class finalize */
105                         NULL,   /* class data */
106                         sizeof(ModestAccountProtocol),
107                         0,      /* n_preallocs */
108                         (GInstanceInitFunc) modest_account_protocol_instance_init,
109                         NULL
110                 };
111
112                 my_type = g_type_register_static (MODEST_TYPE_PROTOCOL,
113                                                   "ModestAccountProtocol",
114                                                   &my_info, 0);
115         }
116         return my_type;
117 }
118
119 static void
120 modest_account_protocol_class_init (ModestAccountProtocolClass *klass)
121 {
122         GObjectClass *object_class;
123         ModestAccountProtocolClass *account_class;
124
125         object_class = (GObjectClass *) klass;
126         account_class = MODEST_ACCOUNT_PROTOCOL_CLASS (klass);
127         parent_class = g_type_class_peek_parent (klass);
128         object_class->finalize = modest_account_protocol_finalize;
129         object_class->set_property = modest_account_protocol_set_property;
130         object_class->get_property = modest_account_protocol_get_property;
131
132         g_object_class_install_property (object_class,
133                                          PROP_PORT,
134                                          g_param_spec_uint ("port",
135                                                            _("Standard port"),
136                                                            _("The standard port for the protocol"),
137                                                            0, G_MAXINT, 0,
138                                                            G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
139
140         g_object_class_install_property (object_class,
141                                          PROP_ALTERNATE_PORT,
142                                          g_param_spec_uint ("alternate-port",
143                                                            _("Alternate port"),
144                                                            _("The alternate port for the protocol (usually used in SSL)"),
145                                                            0, G_MAXINT, 0,
146                                                            G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
147
148         g_object_class_install_property (object_class,
149                                          PROP_ACCOUNT_G_TYPE,
150                                          g_param_spec_gtype ("account-g-type",
151                                                              _("Account factory GType"),
152                                                              _("Account factory GType used for creating new instances."),
153                                                              TNY_TYPE_ACCOUNT,
154                                                              G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
155
156         g_type_class_add_private (object_class,
157                                   sizeof(ModestAccountProtocolPrivate));
158
159         /* Virtual methods */
160         account_class->create_account_settings_dialog = 
161                 modest_account_protocol_create_account_settings_dialog_default;
162         account_class->get_easysetupwizard_tabs = 
163                 modest_account_protocol_get_easysetupwizard_tabs_default;
164         account_class->save_settings = 
165                 modest_account_protocol_save_settings_default;
166         account_class->save_wizard_settings = 
167                 modest_account_protocol_save_wizard_settings_default;
168         account_class->create_account =
169                 modest_account_protocol_create_account_default;
170         account_class->get_wizard_response_override =
171                 modest_account_protocol_get_wizard_response_override_default;
172         account_class->is_supported =
173                 modest_account_protocol_is_supported_default;
174 }
175
176 static void
177 modest_account_protocol_instance_init (ModestAccountProtocol *obj)
178 {
179         ModestAccountProtocolPrivate *priv;
180
181         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (obj);
182
183         priv->port = 0;
184         priv->alternate_port = 0;
185         priv->account_g_type = 0;
186         priv->account_options = tny_simple_list_new ();
187         priv->custom_auth_mechs = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
188
189         priv->account_dialogs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
190 }
191
192 static gboolean
193 remove_account (const gchar *account_name, GObject *account, GObject *account_to_remove)
194 {
195         return (account == account_to_remove);
196 }
197
198 static void
199 account_dialog_weak_handler (ModestAccountProtocol *self, GObject *where_the_object_was)
200 {
201         ModestAccountProtocolPrivate *priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);
202
203         g_hash_table_foreach_remove (priv->account_dialogs, (GHRFunc) remove_account, where_the_object_was);
204 }
205
206 static gboolean
207 dialogs_remove (const gchar *account_name, GObject *account_dialog, ModestAccountProtocol *self)
208 {
209         g_object_weak_unref (account_dialog, (GWeakNotify) account_dialog_weak_handler, self);
210
211         return TRUE;
212 }
213
214 static void   
215 modest_account_protocol_finalize   (GObject *obj)
216 {
217         ModestAccountProtocol *protocol = MODEST_ACCOUNT_PROTOCOL (obj);
218         ModestAccountProtocolPrivate *priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (protocol);
219
220         if (priv->account_dialogs) {
221                 g_hash_table_foreach_remove (priv->account_dialogs, (GHRFunc) dialogs_remove, obj);
222                 g_hash_table_destroy (priv->account_dialogs);
223         }
224
225         if (priv->account_options)
226                 g_object_unref (priv->account_options);
227         priv->account_options = NULL;
228
229         if (priv->custom_auth_mechs)
230                 g_hash_table_destroy (priv->custom_auth_mechs);
231         priv->custom_auth_mechs = NULL;
232
233         G_OBJECT_CLASS (parent_class)->finalize (obj);
234 }
235
236 static void   
237 modest_account_protocol_get_property (GObject *obj,
238                                       guint property_id,
239                                       GValue *value,
240                                       GParamSpec *pspec)
241 {
242         ModestAccountProtocol *protocol = MODEST_ACCOUNT_PROTOCOL (obj);
243         ModestAccountProtocolPrivate *priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (protocol);
244
245         switch (property_id) {
246         case PROP_PORT:
247                 g_value_set_uint (value, priv->port);
248                 break;
249         case PROP_ALTERNATE_PORT:
250                 g_value_set_uint (value, priv->alternate_port);
251                 break;
252         case PROP_ACCOUNT_G_TYPE:
253                 g_value_set_gtype (value, priv->account_g_type);
254                 break;
255         default:
256                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
257         }
258
259 }
260
261 static void   
262 modest_account_protocol_set_property (GObject *obj,
263                                       guint property_id,
264                                       const GValue *value,
265                                       GParamSpec *pspec)
266 {
267         ModestAccountProtocol *protocol = MODEST_ACCOUNT_PROTOCOL (obj);
268
269         switch (property_id) {
270         case PROP_PORT:
271                 modest_account_protocol_set_port (protocol, g_value_get_uint (value));
272                 break;
273         case PROP_ALTERNATE_PORT:
274                 modest_account_protocol_set_alternate_port (protocol, g_value_get_uint (value));
275                 break;
276         case PROP_ACCOUNT_G_TYPE:
277                 modest_account_protocol_set_account_g_type (protocol, g_value_get_gtype (value));
278                 break;
279         default:
280                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
281         }
282
283 }
284
285
286 ModestProtocol*
287 modest_account_protocol_new (const gchar *name, const gchar *display_name,
288                              guint port, guint alternate_port,
289                              GType account_g_type)
290 {
291         return g_object_new (MODEST_TYPE_ACCOUNT_PROTOCOL, 
292                              "display-name", display_name, "name", name, 
293                              "port", port, "alternate-port", alternate_port,
294                              "account-g-type", account_g_type,
295                              NULL);
296 }
297
298 guint
299 modest_account_protocol_get_port (ModestAccountProtocol *self)
300 {
301         ModestAccountProtocolPrivate *priv;
302
303         g_return_val_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self), 0);
304
305         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);      
306         return priv->port;
307 }
308
309 void         
310 modest_account_protocol_set_port (ModestAccountProtocol *self,
311                                   guint port)
312 {
313         ModestAccountProtocolPrivate *priv;
314
315         g_return_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self));
316
317         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);
318         priv->port = port;
319 }
320
321
322 guint
323 modest_account_protocol_get_alternate_port (ModestAccountProtocol *self)
324 {
325         ModestAccountProtocolPrivate *priv;
326
327         g_return_val_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self), 0);
328
329         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);      
330         return priv->alternate_port;
331 }
332
333 void         
334 modest_account_protocol_set_alternate_port (ModestAccountProtocol *self,
335                                             guint alternate_port)
336 {
337         ModestAccountProtocolPrivate *priv;
338
339         g_return_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self));
340
341         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);
342         priv->alternate_port = alternate_port;
343 }
344
345 GType
346 modest_account_protocol_get_account_g_type (ModestAccountProtocol *self)
347 {
348         ModestAccountProtocolPrivate *priv;
349
350         g_return_val_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self), 0);
351
352         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);      
353         return priv->account_g_type;
354 }
355
356 TnyList *
357 modest_account_protocol_get_account_options (ModestAccountProtocol *self)
358 {
359         TnyList *result;
360         ModestAccountProtocolPrivate *priv;
361
362         g_return_val_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self), NULL);
363         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);      
364
365         result = tny_list_copy (priv->account_options);
366
367         return result;
368 }
369
370 void
371 modest_account_protocol_set_account_options (ModestAccountProtocol *self,
372                                              TnyList *list)
373 {
374         ModestAccountProtocolPrivate *priv;
375
376         g_return_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self));
377         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);      
378
379         if (priv->account_options) {
380                 g_object_unref (priv->account_options);
381                 priv->account_options = NULL;
382         }
383         priv->account_options = tny_list_copy (list);
384 }
385
386 gboolean
387 modest_account_protocol_has_custom_secure_auth_mech (ModestAccountProtocol *self, 
388                                                      ModestProtocolType auth_protocol_type)
389 {
390         ModestAccountProtocolPrivate *priv;
391
392         g_return_val_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self), FALSE);
393         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);      
394
395         return g_hash_table_lookup_extended (priv->custom_auth_mechs, GINT_TO_POINTER (auth_protocol_type), NULL, NULL);
396 }
397
398 const gchar *
399 modest_account_protocol_get_custom_secure_auth_mech (ModestAccountProtocol *self, 
400                                                      ModestProtocolType auth_protocol_type)
401 {
402         ModestAccountProtocolPrivate *priv;
403
404         g_return_val_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self), NULL);
405         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);      
406
407         return (const gchar *) g_hash_table_lookup (priv->custom_auth_mechs, GINT_TO_POINTER (auth_protocol_type));
408 }
409
410 void
411 modest_account_protocol_set_custom_secure_auth_mech (ModestAccountProtocol *self, ModestProtocolType auth_protocol_type, const gchar *secure_auth_mech)
412 {
413         ModestAccountProtocolPrivate *priv;
414
415         g_return_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self));
416         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);      
417
418         g_hash_table_replace (priv->custom_auth_mechs, GINT_TO_POINTER (auth_protocol_type), g_strdup (secure_auth_mech));
419 }
420
421 void
422 modest_account_protocol_unset_custom_secure_auth_mech (ModestAccountProtocol *self, ModestProtocolType auth_protocol_type)
423 {
424         ModestAccountProtocolPrivate *priv;
425
426         g_return_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self));
427         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);      
428
429         g_hash_table_remove (priv->custom_auth_mechs, GINT_TO_POINTER (auth_protocol_type));
430 }
431
432
433 void         
434 modest_account_protocol_set_account_g_type (ModestAccountProtocol *self,
435                                             GType account_g_type)
436 {
437         ModestAccountProtocolPrivate *priv;
438
439         g_return_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self));
440
441         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);
442         priv->account_g_type = account_g_type;
443 }
444
445 static TnyAccount *
446 modest_account_protocol_create_account_default (ModestAccountProtocol *self)
447 {
448         ModestAccountProtocolPrivate *priv;
449
450         g_return_val_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self), NULL);
451
452         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);
453         if (priv->account_g_type > 0) {
454                 return g_object_new (priv->account_g_type, NULL);
455         } else {
456                 return NULL;
457         }
458 }
459
460 TnyAccount *
461 modest_account_protocol_create_account (ModestAccountProtocol *self)
462 {
463         g_return_val_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self), NULL);
464
465         return MODEST_ACCOUNT_PROTOCOL_GET_CLASS (self)->create_account (self); 
466 }
467
468 /* This is a template method for getting the account settings
469    dialog. It calls create_account_settings that must be implemented
470    by subclasses and then perform several common operations with the
471    dialog */
472 ModestAccountSettingsDialog *
473 modest_account_protocol_get_account_settings_dialog (ModestAccountProtocol *self,
474                                                      const gchar *account_name)
475 {
476         ModestAccountSettingsDialog *dialog;
477         ModestAccountSettings *settings;
478         ModestAccountProtocolPrivate *priv;
479
480         priv = MODEST_ACCOUNT_PROTOCOL_GET_PRIVATE (self);
481         dialog = g_hash_table_lookup (priv->account_dialogs, account_name);
482
483         if (dialog == NULL) {
484
485                 dialog = MODEST_ACCOUNT_PROTOCOL_GET_CLASS (self)->create_account_settings_dialog (self);
486         
487                 /* Load settings */
488                 settings = modest_account_mgr_load_account_settings (modest_runtime_get_account_mgr (), 
489                                                                      account_name);
490                 modest_account_settings_dialog_load_settings (dialog, settings);
491         
492                 /* Close dialog on response */
493                 g_signal_connect_swapped (dialog,
494                                           "response",
495                                           G_CALLBACK (gtk_widget_destroy),
496                                           dialog);
497
498                 g_hash_table_insert (priv->account_dialogs, g_strdup (account_name), dialog);
499                 g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) account_dialog_weak_handler, self);
500         }
501
502         return dialog;
503 }
504
505 ModestPairList*
506 modest_account_protocol_get_easysetupwizard_tabs (ModestAccountProtocol *self)
507 {
508         return MODEST_ACCOUNT_PROTOCOL_GET_CLASS (self)->get_easysetupwizard_tabs (self);
509 }
510
511
512 void 
513 modest_account_protocol_save_settings (ModestAccountProtocol *self, 
514                                        ModestAccountSettingsDialog *dialog,
515                                        ModestAccountSettings *settings)
516 {
517         return MODEST_ACCOUNT_PROTOCOL_GET_CLASS (self)->save_settings (self, dialog, settings);
518 }
519
520 void 
521 modest_account_protocol_save_wizard_settings (ModestAccountProtocol *self, 
522                                               GList *wizard_pages,
523                                               ModestAccountSettings *settings)
524 {
525         return MODEST_ACCOUNT_PROTOCOL_GET_CLASS (self)->save_wizard_settings (self, wizard_pages, settings);
526 }
527
528 /* Default implementations */
529 static ModestAccountSettingsDialog *
530 modest_account_protocol_create_account_settings_dialog_default (ModestAccountProtocol *self)
531 {
532         return modest_default_account_settings_dialog_new ();
533 }
534
535 static ModestPairList*
536 modest_account_protocol_get_easysetupwizard_tabs_default (ModestAccountProtocol *self)
537 {
538         g_warning ("You must implement get_easysetupwizard_tabs");
539         return NULL;
540 }
541
542 static void 
543 modest_account_protocol_save_settings_default (ModestAccountProtocol *self, 
544                                                ModestAccountSettingsDialog *dialog,
545                                                ModestAccountSettings *settings)
546 {
547         g_return_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self));
548         g_return_if_fail (MODEST_IS_ACCOUNT_SETTINGS_DIALOG (dialog));
549         g_return_if_fail (MODEST_IS_ACCOUNT_SETTINGS (settings));
550
551         g_warning ("You must implement save_settings");
552 }
553
554 static void 
555 modest_account_protocol_save_wizard_settings_default (ModestAccountProtocol *self, 
556                                                       GList *wizard_pages,
557                                                       ModestAccountSettings *settings)
558 {
559         g_return_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self));
560         g_return_if_fail (wizard_pages);
561         g_return_if_fail (MODEST_IS_ACCOUNT_SETTINGS (settings));
562
563         g_warning ("You must implement save_wizard_settings");
564 }
565
566 static ModestWizardDialogResponseOverrideFunc
567 modest_account_protocol_get_wizard_response_override_default (ModestAccountProtocol *self)
568 {
569         g_return_val_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self), NULL);
570
571         return NULL;
572 }
573
574 ModestWizardDialogResponseOverrideFunc
575 modest_account_protocol_get_wizard_response_override (ModestAccountProtocol *self)
576 {
577         g_return_val_if_fail (MODEST_IS_ACCOUNT_PROTOCOL (self), NULL);
578
579         return MODEST_ACCOUNT_PROTOCOL_GET_CLASS (self)->get_wizard_response_override (self);   
580 }
581
582 static gboolean
583 modest_account_protocol_is_supported_default (ModestAccountProtocol *self)
584 {
585         return TRUE;
586 }
587
588 gboolean
589 modest_account_protocol_is_supported (ModestAccountProtocol *self)
590 {
591         return MODEST_ACCOUNT_PROTOCOL_GET_CLASS (self)->is_supported (self);
592 }