2
* A pseudo-plugin that stores/fetches accounts in/from the SSO via libaccounts
4
* Copyright © 2010 Nokia Corporation
5
* Copyright © 2010 Collabora Ltd.
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
#include "mcd-account-manager-sso.h"
24
#include "mcd-debug.h"
29
/* IMPORTANT IMPLEMENTATION NOTE:
31
* Note for implementors: save_param is for saving account parameters (in MC
32
* terms) - anything that ends up stored as "param-" in the standard gkeyfile
33
* save_value is for everything else.
35
* Whether such a value is stored in the global section of an SSO account or
36
* in the IM specific section is orthogonal to the above, and in the mapping
37
* is not necessarily from MC "name" to SSO "name", or from MC "param-name"
38
* to SSO "parameters/name" - so be careful when making such decisions.
40
* The existing mappings have been arrived at empirically.
43
#define PLUGIN_PRIORITY (MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_KEYRING + 10)
44
#define PLUGIN_NAME "maemo-libaccounts"
45
#define PLUGIN_DESCRIPTION \
46
"Account storage in the Maemo SSO store via libaccounts-glib API"
48
#define PARAM_PREFIX_MC "param-"
49
#define PARAM_PREFIX "parameters/"
50
#define LIBACCT_ID_KEY "libacct-uid"
52
#define AG_LABEL_KEY "name"
53
#define MC_LABEL_KEY "DisplayName"
55
#define AG_ACCOUNT_KEY "username"
56
#define MC_ACCOUNT_KEY "account"
57
#define PASSWORD_KEY "password"
59
#define MC_CMANAGER_KEY "manager"
60
#define MC_PROTOCOL_KEY "protocol"
61
#define MC_IDENTITY_KEY "tmc-uid"
70
AgAccountId account_id;
73
static gboolean _sso_account_enabled (AgAccount *account,
76
static void account_storage_iface_init (McpAccountStorageIface *,
80
_ag_accountid_to_mc_key (const McdAccountManagerSso *sso,
84
static gchar * get_mc_param_key (const gchar *key);
87
save_value (AgAccount *account,
91
static void _ag_account_stored_cb (AgAccount *acct,
95
G_DEFINE_TYPE_WITH_CODE (McdAccountManagerSso, mcd_account_manager_sso,
97
G_IMPLEMENT_INTERFACE (MCP_TYPE_ACCOUNT_STORAGE,
98
account_storage_iface_init));
101
_gvalue_to_string (const GValue *val)
103
switch (G_VALUE_TYPE (val))
106
return g_value_dup_string (val);
108
return g_strdup (g_value_get_boolean (val) ? "true" : "false");
110
return g_strdup_printf ("%c", g_value_get_uchar (val));
112
return g_strdup_printf ("%c", g_value_get_char (val));
114
return g_strdup_printf ("%i", g_value_get_int (val));
116
return g_strdup_printf ("%u", g_value_get_uint (val));
118
return g_strdup_printf ("%ld", g_value_get_long (val));
120
return g_strdup_printf ("%lu", g_value_get_ulong (val));
122
return g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (val));
124
return g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (val));
126
return g_strdup_printf ("%d" , g_value_get_enum (val));
128
return g_strdup_printf ("%u", g_value_get_flags (val));
130
return g_strdup_printf ("%f", g_value_get_float (val));
132
return g_strdup_printf ("%g", g_value_get_double (val));
134
DEBUG ("Unsupported type %s", G_VALUE_TYPE_NAME (val));
139
/* Is an AG key corresponding to an MC _parameter_ global? */
140
static gboolean _ag_key_is_global (const gchar *key)
143
g_str_equal (key, AG_ACCOUNT_KEY) ||
144
g_str_equal (key, PASSWORD_KEY) ||
145
g_str_equal (key, AG_LABEL_KEY);
148
/* Is an AG key corresponding to an MC non-parameter service specific? */
149
static gboolean _ag_value_is_local (const gchar *key)
151
return g_str_equal (key, MC_IDENTITY_KEY);
155
_ag_account_select_default_im_service (AgAccount *account)
157
gboolean have_im_service = FALSE;
158
GList *first = ag_account_list_services_by_type (account, "IM");
160
if (first != NULL && first->data != NULL)
162
have_im_service = TRUE;
163
DEBUG ("default IM service %s", ag_service_get_name (first->data));
164
ag_account_select_service (account, first->data);
167
ag_service_list_free (first);
169
return have_im_service;
172
static AgSettingSource
173
_ag_account_global_value (AgAccount *account,
177
AgSettingSource src = AG_SETTING_SOURCE_NONE;
178
AgService *service = ag_account_get_selected_service (account);
182
ag_account_select_service (account, NULL);
183
src = ag_account_get_value (account, key, value);
184
ag_account_select_service (account, service);
188
src = ag_account_get_value (account, key, value);
194
static AgSettingSource
195
_ag_account_local_value (AgAccount *account,
199
AgSettingSource src = AG_SETTING_SOURCE_NONE;
200
AgService *service = ag_account_get_selected_service (account);
204
src = ag_account_get_value (account, key, value);
208
_ag_account_select_default_im_service (account);
209
src = ag_account_get_value (account, key, value);
210
ag_account_select_service (account, NULL);
216
static void _sso_toggled (GObject *object,
217
const gchar *service_name,
221
AgAccount *account = AG_ACCOUNT (object);
222
AgAccountId id = account->id;
223
McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (data);
224
McpAccountStorage *mcpa = MCP_ACCOUNT_STORAGE (sso);
226
const gchar *name = NULL;
227
AgService *service = NULL;
228
AgManager *manager = NULL;
230
/* If the account manager isn't ready, account state changes are of no *
231
* interest to us: it will pick up the then-current state of the account *
232
* when it does become ready, and anything that happens between now and *
233
* then is not important: */
237
manager = ag_account_get_manager (account);
238
service = ag_manager_get_service (manager, service_name);
240
/* non IM services are of no interest to us, we don't handle them */
243
const gchar *service_type = ag_service_get_service_type (service);
245
if (!g_str_equal (service_type, "IM"))
249
on = _sso_account_enabled (account, service);
250
name = g_hash_table_lookup (sso->id_name_map, GUINT_TO_POINTER (id));
254
const gchar *value = on ? "true" : "false";
255
McpAccountManager *am = sso->manager_interface;
257
mcp_account_manager_set_value (am, name, "Enabled", value);
258
g_signal_emit_by_name (mcpa, "toggled", name, on);
262
DEBUG ("received enabled=%u signal for unknown SSO account %u", on, id);
266
static void _sso_deleted (GObject *object,
270
McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (data);
275
g_hash_table_lookup (sso->id_name_map, GUINT_TO_POINTER (id));
277
/* if the account was in our cache, then this was a 3rd party delete *
278
* op that someone did behind our back: fire the signal and clean up */
281
McpAccountStorage *mcpa = MCP_ACCOUNT_STORAGE (sso);
282
gchar *signalled_name = g_strdup (name);
284
/* forget id->name map first, so the signal can't start a loop */
285
g_hash_table_remove (sso->id_name_map, GUINT_TO_POINTER (id));
286
g_hash_table_remove (sso->accounts, signalled_name);
287
g_signal_emit_by_name (mcpa, "deleted", signalled_name);
289
g_free (signalled_name);
294
DelayedSignalData *sig_data = g_slice_new0 (DelayedSignalData);
296
sig_data->signal = DELAYED_DELETE;
297
sig_data->account_id = id;
298
g_queue_push_tail (sso->pending_signals, sig_data);
302
static void _sso_account_enable (AgAccount *account,
306
AgService *original = ag_account_get_selected_service (account);
308
/* turn the local enabled flag on/off as required */
310
ag_account_select_service (account, service);
312
_ag_account_select_default_im_service (account);
314
ag_account_set_enabled (account, on);
316
/* if we are turning the account on, the global flag must also be set *
317
* NOTE: this isn't needed when turning the account off */
320
ag_account_select_service (account, NULL);
321
ag_account_set_enabled (account, on);
324
ag_account_select_service (account, original);
327
static gboolean _sso_account_enabled (AgAccount *account,
330
gboolean local = FALSE;
331
gboolean global = FALSE;
332
AgService *original = ag_account_get_selected_service (account);
336
_ag_account_select_default_im_service (account);
337
local = ag_account_get_enabled (account);
341
if (original != service)
342
ag_account_select_service (account, service);
344
local = ag_account_get_enabled (account);
347
ag_account_select_service (account, NULL);
348
global = ag_account_get_enabled (account);
350
ag_account_select_service (account, original);
352
DEBUG ("_sso_account_enabled: global:%d && local:%d", global, local);
354
return local && global;
357
static void _sso_created (GObject *object,
361
AgManager *ag_manager = AG_MANAGER (object);
362
McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (data);
364
g_hash_table_lookup (sso->id_name_map, GUINT_TO_POINTER (id));
368
/* if we already know the account's name, we shouldn't fire the new *
369
* account signal as it is one we (and our superiors) already have */
372
McpAccountStorage *mcpa = MCP_ACCOUNT_STORAGE (sso);
373
AgAccount *account = ag_manager_get_account (ag_manager, id);
377
/* this will be owned by the ag account hash, do not free it */
378
name = _ag_accountid_to_mc_key (sso, id, TRUE);
382
g_hash_table_insert (sso->accounts, name, account);
383
g_hash_table_insert (sso->id_name_map, GUINT_TO_POINTER (id),
386
save_value (account, MC_IDENTITY_KEY, name);
388
ag_account_store (account, _ag_account_stored_cb, NULL);
390
g_signal_emit_by_name (mcpa, "created", name);
392
g_signal_connect (account, "enabled",
393
G_CALLBACK (_sso_toggled), data);
395
/* this doesn't seem to fire when we expect it to, but this *
396
* is the right place to hook it up: */
397
/* ag_account_watch_dir (account, "", _sso_updated, sso); */
401
DEBUG ("SSO account #%u is unnameable, ignoring it", id);
408
DelayedSignalData *sig_data = g_slice_new0 (DelayedSignalData);
410
sig_data->signal = DELAYED_CREATE;
411
sig_data->account_id = id;
412
g_queue_push_tail (sso->pending_signals, sig_data);
417
mcd_account_manager_sso_init (McdAccountManagerSso *self)
419
DEBUG ("mcd_account_manager_sso_init");
420
self->ag_manager = ag_manager_new ();
422
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
424
g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
426
self->pending_signals = g_queue_new ();
428
self->services = ag_manager_list_services (self->ag_manager);
430
g_signal_connect(self->ag_manager, "account-deleted",
431
G_CALLBACK (_sso_deleted), self);
432
g_signal_connect(self->ag_manager, "account-created",
433
G_CALLBACK (_sso_created), self);
437
mcd_account_manager_sso_class_init (McdAccountManagerSsoClass *cls)
439
DEBUG ("mcd_account_manager_sso_class_init");
443
_ag_account_stored_cb (AgAccount *acct, const GError *err, gpointer ignore)
446
const gchar *name = NULL;
447
AgSettingSource src = AG_SETTING_SOURCE_NONE;
449
g_value_init (&uid, G_TYPE_STRING);
451
src = _ag_account_local_value (acct, MC_IDENTITY_KEY, &uid);
453
if (src != AG_SETTING_SOURCE_NONE && G_VALUE_HOLDS_STRING (&uid))
455
name = g_value_get_string (&uid);
456
DEBUG ("%p:%s stored: %s", acct, name, err ? err->message : "-");
457
g_value_unset (&uid);
461
DEBUG ("%p:%s not stored? %s", acct,
462
ag_account_get_display_name (acct), err ? err->message : "-");
467
_ag_accountid_to_mc_key (const McdAccountManagerSso *sso,
471
AgAccount *acct = ag_manager_get_account (sso->ag_manager, id);
472
AgSettingSource src = AG_SETTING_SOURCE_NONE;
473
GValue value = { 0 };
475
DEBUG ("AG Account ID: %u", id);
477
g_value_init (&value, G_TYPE_STRING);
479
/* first look for the stored TMC uid */
480
src = _ag_account_local_value (acct, MC_IDENTITY_KEY, &value);
482
/* if we found something, our work here is done: */
483
if (src != AG_SETTING_SOURCE_NONE)
485
gchar *uid = g_value_dup_string (&value);
486
g_value_unset (&value);
493
DEBUG ("no " MC_IDENTITY_KEY " found, synthesising one:\n");
495
src = _ag_account_global_value (acct, AG_ACCOUNT_KEY, &value);
497
DEBUG (AG_ACCOUNT_KEY ": %s; type: %s",
498
src ? "exists" : "missing",
499
src ? (G_VALUE_TYPE_NAME (&value)) : "n/a" );
501
if (src != AG_SETTING_SOURCE_NONE && G_VALUE_HOLDS_STRING (&value))
503
AgAccountSettingIter setting;
506
GValue cmanager = { 0 };
507
GValue protocol = { 0 };
508
const gchar *cman, *proto;
509
McpAccountManager *am = sso->manager_interface;
510
AgService *service = ag_account_get_selected_service (acct);
511
GHashTable *params = g_hash_table_new_full (g_str_hash, g_str_equal,
515
g_value_init (&cmanager, G_TYPE_STRING);
516
g_value_init (&protocol, G_TYPE_STRING);
518
/* if we weren't on a service when got here, pick the most likely one: */
520
_ag_account_select_default_im_service (acct);
522
ag_account_get_value (acct, MC_CMANAGER_KEY, &cmanager);
523
cman = g_value_get_string (&cmanager);
528
ag_account_get_value (acct, MC_PROTOCOL_KEY, &protocol);
529
proto = g_value_get_string (&protocol);
534
g_hash_table_insert (params, g_strdup (MC_ACCOUNT_KEY), &value);
536
/* prepare the hash of MC param keys -> GValue */
537
/* NOTE: some AG bare settings map to MC parameters, *
538
* so we must iterate over all AG settings, parameters *
539
* and bare settings included */
541
/* first any matching global values: */
542
ag_account_select_service (acct, NULL);
543
ag_account_settings_iter_init (acct, &setting, NULL);
545
while (ag_account_settings_iter_next (&setting, &k, &v))
547
gchar *mc_key = get_mc_param_key (k);
549
if (mc_key != NULL && g_str_has_prefix (mc_key, PARAM_PREFIX_MC))
551
gchar *param_key = g_strdup (mc_key + strlen (PARAM_PREFIX_MC));
553
g_hash_table_insert (params, param_key, (gpointer) v);
559
/* then any service specific settings */
561
ag_account_select_service (acct, service);
563
_ag_account_select_default_im_service (acct);
565
ag_account_settings_iter_init (acct, &setting, NULL);
566
while (ag_account_settings_iter_next (&setting, &k, &v))
568
gchar *mc_key = get_mc_param_key (k);
570
if (mc_key != NULL && g_str_has_prefix (mc_key, PARAM_PREFIX_MC))
572
gchar *param_key = g_strdup (mc_key + strlen (PARAM_PREFIX_MC));
574
g_hash_table_insert (params, param_key, (gpointer) v);
580
name = mcp_account_manager_get_unique_name (am, cman, proto, params);
583
ag_account_select_service (acct, service);
584
g_hash_table_unref (params);
585
g_value_unset (&value);
586
g_value_unset (&cmanager);
587
g_value_unset (&protocol);
589
DEBUG (MC_IDENTITY_KEY " value %p:%s synthesised", name, name);
593
DEBUG (MC_IDENTITY_KEY "not synthesised, returning NULL");
598
get_ag_account (const McdAccountManagerSso *sso,
599
const McpAccountManager *am,
605
g_return_val_if_fail (id != NULL, NULL);
607
/* we have a cached account, just return that */
608
account = g_hash_table_lookup (sso->accounts, name);
621
save_param (AgAccount *account,
625
const gchar *pkey = key + strlen (PARAM_PREFIX_MC);
626
gchar *param_key = NULL;
627
gboolean global = FALSE;
628
AgService *service = ag_account_get_selected_service (account);
630
/* username and password are parameters in MC but not in AG: *
631
* also it's 'username' in AG but 'account' in MC */
632
if (g_str_equal (pkey, MC_ACCOUNT_KEY))
633
param_key = g_strdup (AG_ACCOUNT_KEY);
634
else if (g_str_equal (pkey, PASSWORD_KEY))
635
param_key = g_strdup (PASSWORD_KEY);
637
param_key = g_strdup_printf (PARAM_PREFIX "%s", pkey);
639
global = _ag_key_is_global (param_key);
642
ag_account_select_service (account, NULL);
643
else if (service == NULL)
644
_ag_account_select_default_im_service (account);
648
GValue value = { 0 };
650
g_value_init (&value, G_TYPE_STRING);
651
g_value_set_string (&value, val);
652
ag_account_set_value (account, param_key, &value);
653
g_value_unset (&value);
657
ag_account_set_value (account, param_key, NULL);
660
/* leave the selected service as we found it: */
661
ag_account_select_service (account, service);
667
save_value (AgAccount *account,
671
AgService *service = NULL;
672
gboolean local = FALSE;
674
/* special cases, never saved */
675
if (g_str_equal (key, MC_CMANAGER_KEY) || g_str_equal (key, MC_PROTOCOL_KEY))
678
/* values, unlike parameters, are _mostly_ global - not service specific */
679
service = ag_account_get_selected_service (account);
680
local = _ag_value_is_local (key);
682
/* Enabled is both a global and a local value, for extra fun: */
683
if (g_str_equal (key, "Enabled"))
685
gboolean on = g_str_equal (val, "true");
687
DEBUG ("setting enabled flag: '%d'", on);
688
_sso_account_enable (account, NULL, on);
693
/* pick the right service/global section of SSO, and switch if necessary */
694
if (local && service == NULL)
695
_ag_account_select_default_im_service (account);
696
else if (!local && service != NULL)
697
ag_account_select_service (account, NULL);
699
/* yet another special case mapping */
700
if (g_str_equal (key, MC_LABEL_KEY))
705
ag_account_set_value (account, key, NULL);
709
GValue value = { 0 };
710
g_value_init (&value, G_TYPE_STRING);
711
g_value_set_string (&value, val);
712
ag_account_set_value (account, key, &value);
713
g_value_unset (&value);
717
/* leave the slected service as we found it */
718
ag_account_select_service (account, service);
722
_set (const McpAccountStorage *self,
723
const McpAccountManager *am,
729
McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
730
AgAccount *account = get_ag_account (sso, am, acct, &id);
732
/* we no longer create accounts in libaccount: either an account exists *
733
* in libaccount as a result of some 3rd party intervention, or it is *
734
* not an account that this plugin should ever concern itself with */
735
g_return_val_if_fail (key != NULL, FALSE);
739
if (g_str_equal (key, "sso-services"))
742
if (g_str_has_prefix (key, PARAM_PREFIX_MC))
743
save_param (account, key, val);
745
save_value (account, key, val);
751
/* no account and we couldn't/wouldn't create one */
755
/* get the MC parameter key corresponding to an SSO key *
756
* note that not all MC parameters correspond to SSO parameters, *
757
* some correspond to values instead */
758
/* NOTE: value keys are passed through unchanged */
759
/* NOTE: except for "name", which maps to "DisplayName" */
761
get_mc_param_key (const gchar *key)
763
/* these two are parameters in MC but not in AG */
764
if (g_str_equal (key, AG_ACCOUNT_KEY))
765
return g_strdup (PARAM_PREFIX_MC MC_ACCOUNT_KEY);
767
if (g_str_equal (key, PASSWORD_KEY))
768
return g_strdup (PARAM_PREFIX_MC PASSWORD_KEY);
770
/* yet another special case */
771
if (g_str_equal (key, AG_LABEL_KEY))
772
return g_strdup (MC_LABEL_KEY);
774
/* now check for regular params */
775
if (g_str_has_prefix (key, PARAM_PREFIX))
776
return g_strdup_printf (PARAM_PREFIX_MC "%s", key + strlen (PARAM_PREFIX));
778
return g_strdup (key);
781
/* get the SSO key corresponding to an MC parameter */
782
/* NOTE: value keys are passed through unchanged */
784
get_ag_param_key (const gchar *key)
786
if (g_str_equal (key, PARAM_PREFIX_MC MC_ACCOUNT_KEY))
787
return g_strdup (AG_ACCOUNT_KEY);
789
if (g_str_equal (key, PARAM_PREFIX_MC PASSWORD_KEY))
790
return g_strdup (PASSWORD_KEY);
792
if (g_str_has_prefix (key, PARAM_PREFIX_MC))
793
return g_strdup_printf (PARAM_PREFIX "%s", key + strlen (PARAM_PREFIX_MC));
795
return g_strdup (key);
799
_get (const McpAccountStorage *self,
800
const McpAccountManager *am,
805
McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
806
AgAccount *account = get_ag_account (sso, am, acct, &id);
807
AgService *service = ag_account_get_selected_service (account);
814
if (g_str_equal (key, "Enabled"))
816
const gchar *v = NULL;
818
v = _sso_account_enabled (account, service) ? "true" : "false";
819
mcp_account_manager_set_value (am, acct, key, v);
821
else if (g_str_equal (key, "sso-services"))
823
GString *result = g_string_new ("");
824
AgManager * agm = ag_account_get_manager (account);
825
GList *services = ag_manager_list_services (agm);
828
for (item = services; item != NULL; item = g_list_next (item))
830
const gchar *name = ag_service_get_name (item->data);
832
g_string_append_printf (result, "%s;", name);
835
mcp_account_manager_set_value (am, acct, key, result->str);
837
ag_service_list_free (services);
838
g_string_free (result, TRUE);
842
gchar *k = get_ag_param_key (key);
844
AgSettingSource src = AG_SETTING_SOURCE_NONE;
846
g_value_init (&v, G_TYPE_STRING);
848
if (_ag_key_is_global (k))
850
src = _ag_account_global_value (account, k, &v);
854
src = _ag_account_local_value (account, k, &v);
857
if (src != AG_SETTING_SOURCE_NONE)
859
gchar *val = _gvalue_to_string (&v);
861
mcp_account_manager_set_value (am, acct, key, val);
872
AgAccountSettingIter setting;
875
const gchar *on = NULL;
877
/* pick the IM service if we haven't got one set */
879
_ag_account_select_default_im_service (account);
881
ag_account_settings_iter_init (account, &setting, NULL);
882
while (ag_account_settings_iter_next (&setting, &k, &v))
884
if (!_ag_key_is_global (k))
886
gchar *mc_key = get_mc_param_key (k);
887
gchar *value = _gvalue_to_string (v);
889
mcp_account_manager_set_value (am, acct, mc_key, value);
896
/* deselect any service we may have to get global settings */
897
ag_account_select_service (account, NULL);
898
ag_account_settings_iter_init (account, &setting, NULL);
900
while (ag_account_settings_iter_next (&setting, &k, &v))
902
if (_ag_key_is_global (k))
904
gchar *mc_key = get_mc_param_key (k);
905
gchar *value = _gvalue_to_string (v);
907
mcp_account_manager_set_value (am, acct, mc_key, value);
914
/* special case, actually two separate but related flags in SSO */
915
on = _sso_account_enabled (account, NULL) ? "true" : "false";
916
mcp_account_manager_set_value (am, acct, "Enabled", on);
919
/* leave the selected service as we found it */
920
ag_account_select_service (account, service);
925
_delete (const McpAccountStorage *self,
926
const McpAccountManager *am,
931
McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
932
AgAccount *account = get_ag_account (sso, am, acct, &id);
934
/* have no values for this account, nothing to do here: */
940
ag_account_delete (account);
941
g_hash_table_remove (sso->accounts, acct);
942
g_hash_table_remove (sso->id_name_map, GUINT_TO_POINTER (id));
946
if (g_str_has_prefix (key, PARAM_PREFIX_MC))
947
save_param (account, key, NULL);
949
save_value (account, key, NULL);
956
_commit (const McpAccountStorage *self,
957
const McpAccountManager *am)
960
McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
967
/* FIXME: implement commit_one(), and use account_name if it's non-NULL */
969
g_hash_table_iter_init (&iter, sso->accounts);
971
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &account))
973
/* this value ties MC accounts to SSO accounts */
974
save_value (account, MC_IDENTITY_KEY, key);
975
ag_account_store (account, _ag_account_stored_cb, NULL);
978
/* any pending changes should now have been pushed, clear the save-me flag */
985
_load_from_libaccounts (McdAccountManagerSso *sso,
986
const McpAccountManager *am)
989
GList *ag_ids = ag_manager_list_by_service_type (sso->ag_manager, "IM");
991
for (ag_id = ag_ids; ag_id != NULL; ag_id = g_list_next (ag_id))
995
AgAccountSettingIter iter;
996
AgAccountId id = GPOINTER_TO_UINT (ag_id->data);
997
AgAccount *account = ag_manager_get_account (sso->ag_manager, id);
998
const gchar *enabled = NULL;
1000
if (account != NULL)
1002
AgService *service = ag_account_get_selected_service (account);
1003
gchar *name = _ag_accountid_to_mc_key (sso, id, FALSE);
1007
gchar *ident = g_strdup_printf ("%u", id);
1008
GStrv mc_id = g_strsplit (name, "/", 3);
1010
/* cache the account object, and the ID->name maping: the *
1011
* latter is required because we might receive an async *
1012
* delete signal with the ID after libaccounts-glib has *
1013
* purged all its account data, so we couldn't rely on the *
1014
* MC_IDENTITY_KEY setting. */
1015
g_hash_table_insert (sso->accounts, name, account);
1016
g_hash_table_insert (sso->id_name_map, GUINT_TO_POINTER (id),
1019
if (service == NULL)
1020
_ag_account_select_default_im_service (account);
1022
ag_account_settings_iter_init (account, &iter, NULL);
1024
while (ag_account_settings_iter_next (&iter, &key, &val))
1026
if (!_ag_key_is_global (key))
1028
gchar *mc_key = get_mc_param_key (key);
1029
gchar *value = _gvalue_to_string (val);
1031
mcp_account_manager_set_value (am, name, mc_key, value);
1037
ag_account_select_service (account, NULL);
1038
ag_account_settings_iter_init (account, &iter, NULL);
1040
while (ag_account_settings_iter_next (&iter, &key, &val))
1042
if (_ag_key_is_global (key))
1044
gchar *mc_key = get_mc_param_key (key);
1045
gchar *value = _gvalue_to_string (val);
1047
mcp_account_manager_set_value (am, name, mc_key, value);
1053
/* special case, actually two separate but related flags in SSO */
1054
enabled = _sso_account_enabled (account, NULL) ? "true": "false";
1056
mcp_account_manager_set_value (am, name, "Enabled", enabled);
1057
mcp_account_manager_set_value (am, name, LIBACCT_ID_KEY, ident);
1058
mcp_account_manager_set_value (am, name, MC_CMANAGER_KEY, mc_id[0]);
1059
mcp_account_manager_set_value (am, name, MC_PROTOCOL_KEY, mc_id[1]);
1060
mcp_account_manager_set_value (am, name, MC_IDENTITY_KEY, name);
1062
ag_account_select_service (account, service);
1064
g_signal_connect (account, "enabled",
1065
G_CALLBACK (_sso_toggled), sso);
1067
/* this doesn't seem to fire when we expect it to, but this *
1068
* is the right place to hook it up: */
1069
/* ag_account_watch_dir (account, "", _sso_updated, sso); */
1077
DelayedSignalData *data = g_slice_new0 (DelayedSignalData);
1079
data->account_id = id;
1080
g_queue_push_tail (sso->pending_signals, data);
1085
ag_manager_list_free (ag_ids);
1089
_list (const McpAccountStorage *self,
1090
const McpAccountManager *am)
1093
McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
1094
GList *ag_ids = NULL;
1098
_load_from_libaccounts (sso, am);
1100
ag_ids = ag_manager_list_by_service_type (sso->ag_manager, "IM");
1102
for (ag_id = ag_ids; ag_id != NULL; ag_id = g_list_next (ag_id))
1104
AgAccountId id = GPOINTER_TO_UINT (ag_id->data);
1107
name = _ag_accountid_to_mc_key (sso, id, FALSE);
1111
DEBUG ("\naccount %s listed", name);
1112
rval = g_list_prepend (rval, name);
1116
DelayedSignalData *data = g_slice_new0 (DelayedSignalData);
1118
DEBUG ("\naccount %u delayed", id);
1119
data->signal = DELAYED_CREATE;
1120
data->account_id = id;
1121
g_queue_push_tail (sso->pending_signals, data);
1125
ag_manager_list_free (ag_ids);
1131
_ready (const McpAccountStorage *self,
1132
const McpAccountManager *am)
1134
McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
1139
g_assert (sso->manager_interface == NULL);
1140
sso->manager_interface = g_object_ref (G_OBJECT (am));
1143
while (g_queue_get_length (sso->pending_signals) > 0)
1145
DelayedSignalData *data = g_queue_pop_head (sso->pending_signals);
1146
GObject *signal_source = G_OBJECT (sso->ag_manager);
1148
switch (data->signal)
1150
case DELAYED_CREATE:
1151
_sso_created (signal_source, data->account_id, sso);
1153
case DELAYED_DELETE:
1154
_sso_deleted (signal_source, data->account_id, sso);
1157
g_assert_not_reached ();
1160
g_slice_free (DelayedSignalData, data);
1163
g_queue_free (sso->pending_signals);
1164
sso->pending_signals = NULL;
1168
account_storage_iface_init (McpAccountStorageIface *iface,
1169
gpointer unused G_GNUC_UNUSED)
1171
mcp_account_storage_iface_set_name (iface, PLUGIN_NAME);
1172
mcp_account_storage_iface_set_desc (iface, PLUGIN_DESCRIPTION);
1173
mcp_account_storage_iface_set_priority (iface, PLUGIN_PRIORITY);
1175
mcp_account_storage_iface_implement_get (iface, _get);
1176
mcp_account_storage_iface_implement_set (iface, _set);
1177
mcp_account_storage_iface_implement_delete (iface, _delete);
1178
mcp_account_storage_iface_implement_commit (iface, _commit);
1179
mcp_account_storage_iface_implement_list (iface, _list);
1180
mcp_account_storage_iface_implement_ready (iface, _ready);
1183
McdAccountManagerSso *
1184
mcd_account_manager_sso_new (void)
1186
return g_object_new (MCD_TYPE_ACCOUNT_MANAGER_SSO, NULL);