diff options
Diffstat (limited to 'src/mcd-account-manager.c')
-rw-r--r-- | src/mcd-account-manager.c | 278 |
1 files changed, 142 insertions, 136 deletions
diff --git a/src/mcd-account-manager.c b/src/mcd-account-manager.c index 81afa31d..5ff7bc9c 100644 --- a/src/mcd-account-manager.c +++ b/src/mcd-account-manager.c @@ -110,6 +110,7 @@ typedef struct gchar *cm_name; gchar *protocol_name; gchar *display_name; + gchar *provider; GHashTable *parameters; GHashTable *properties; McdGetAccountCb callback; @@ -133,8 +134,6 @@ enum PROP_CLIENT_FACTORY }; -static guint write_conf_id = 0; - static void register_dbus_service (McdAccountManager *account_manager); static void release_setup_lock (McdAccountManager *account_manager); static void setup_account_loaded (McdAccount *account, @@ -176,7 +175,7 @@ async_altered_one_manager_cb (McdManager *cm, static void -altered_one_cb (GObject *storage, +altered_one_cb (McpAccountStorage *storage, const gchar *account_name, const gchar *key, gpointer data) @@ -186,6 +185,7 @@ altered_one_cb (GObject *storage, McdAccount *account = NULL; McdManager *cm = NULL; const gchar *cm_name = NULL; + McpAccountStorage *its_plugin; account = mcd_account_manager_lookup_account (am, account_name); @@ -195,6 +195,18 @@ altered_one_cb (GObject *storage, return; } + its_plugin = mcd_account_get_storage_plugin (account); + + if (storage != its_plugin) + { + DEBUG ("Ignoring altered-one from plugin %s because account %s " + "belongs to %s", + mcp_account_storage_name (storage), + account_name, + mcp_account_storage_name (its_plugin)); + return; + } + /* in theory, the CM is already ready by this point, but make sure: */ cm_name = mcd_account_get_manager_name (account); @@ -277,11 +289,12 @@ created_cb (GObject *storage_plugin_obj, McdMaster *master = mcd_master_get_default (); McdManager *cm = NULL; const gchar *cm_name = NULL; + GError *error = NULL; /* actually fetch the data into our cache from the plugin: */ - if (mcd_storage_add_account_from_plugin (storage, plugin, name)) + if (mcd_storage_add_account_from_plugin (storage, plugin, name, &error)) { - account = mcd_account_new (am, name, priv->minotaur); + account = mcd_account_new (am, name, priv->minotaur, plugin); g_assert (MCD_IS_ACCOUNT (account)); lad = g_slice_new (McdLoadAccountsData); @@ -292,7 +305,8 @@ created_cb (GObject *storage_plugin_obj, } else { - /* that function already warned about it */ + WARNING ("%s", error->message); + g_clear_error (&error); goto finish; } @@ -333,6 +347,7 @@ toggled_cb (GObject *plugin, const gchar *name, gboolean on, gpointer data) McdAccountManager *manager = MCD_ACCOUNT_MANAGER (data); McdAccount *account = NULL; GError *error = NULL; + McpAccountStorage *its_plugin; account = mcd_account_manager_lookup_account (manager, name); @@ -346,6 +361,18 @@ toggled_cb (GObject *plugin, const gchar *name, gboolean on, gpointer data) return; } + its_plugin = mcd_account_get_storage_plugin (account); + + if (storage_plugin != its_plugin) + { + DEBUG ("Ignoring toggled signal from plugin %s because account %s " + "belongs to %s", + mcp_account_storage_name (storage_plugin), + name, + mcp_account_storage_name (its_plugin)); + return; + } + _mcd_account_set_enabled (account, on, FALSE, MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE, &error); @@ -381,11 +408,27 @@ reconnect_cb (GObject *plugin, const gchar *name, gpointer data) } static void -_mcd_account_delete_cb (McdAccount *account, const GError *error, gpointer data) +mcd_account_delete_debug_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) { - /* no need to do anything other than release the account ref, which * - * should be the last ref we hold by the time this rolls arouns: */ - g_object_unref (account); + McdAccount *account = MCD_ACCOUNT (source); + GError *error = NULL; + + if (mcd_account_delete_finish (account, res, &error)) + { + DEBUG ("successfully deleted account %s (%s)", + mcd_account_get_unique_name (account), + (const gchar *) user_data); + } + else + { + WARNING ("could not delete account %s (%s): %s #%d: %s", + mcd_account_get_unique_name (account), + (const gchar *) user_data, + g_quark_to_string (error->domain), error->code, error->message); + g_clear_error (&error); + } } /* a backend plugin notified us that an account was vaporised: remove it */ @@ -404,14 +447,28 @@ deleted_cb (GObject *plugin, const gchar *name, gpointer data) if (account != NULL) { const gchar * object_path = mcd_account_get_object_path (account); + McpAccountStorage *its_plugin = mcd_account_get_storage_plugin ( + account); + + if (storage_plugin != its_plugin) + { + DEBUG ("Ignoring deleted signal from plugin %s because account %s " + "belongs to %s", + mcp_account_storage_name (storage_plugin), + name, + mcp_account_storage_name (its_plugin)); + return; + } g_object_ref (account); /* this unhooks the account's signal handlers */ g_hash_table_remove (manager->priv->accounts, name); tp_svc_account_manager_emit_account_removed (manager, object_path); - mcd_account_delete (account, - MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE, - _mcd_account_delete_cb, NULL); + mcd_account_delete_async (account, + MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE, + mcd_account_delete_debug_cb, + "in response to McpAccountStorage::deleted"); + g_object_unref (account); } } @@ -579,7 +636,6 @@ static void on_account_removed (McdAccount *account, McdAccountManager *account_manager) { McdAccountManagerPrivate *priv = account_manager->priv; - McdStorage *storage = priv->storage; const gchar *name, *object_path; object_path = mcd_account_get_object_path (account); @@ -589,10 +645,6 @@ on_account_removed (McdAccount *account, McdAccountManager *account_manager) name = mcd_account_get_unique_name (account); g_hash_table_remove (priv->accounts, name); - - mcd_storage_delete_account (storage, name); - mcd_account_manager_write_conf_async (account_manager, account, NULL, - NULL); } static inline void @@ -672,6 +724,7 @@ mcd_create_account_data_free (McdCreateAccountData *cad) if (cad->destroy != NULL) cad->destroy (cad->user_data); + g_free (cad->provider); g_free (cad->cm_name); g_free (cad->protocol_name); g_free (cad->display_name); @@ -722,13 +775,18 @@ complete_account_creation_finish (McdAccount *account, if (!cad->ok) { - mcd_account_delete (account, MCD_DBUS_PROP_SET_FLAG_NONE, - NULL, NULL); + mcd_account_delete_async (account, + MCD_DBUS_PROP_SET_FLAG_NONE, + mcd_account_delete_debug_cb, + "while recovering from failure to create"); tp_clear_object (&account); } - mcd_account_manager_write_conf_async (account_manager, account, NULL, - NULL); + if (account != NULL) + { + mcd_storage_commit (account_manager->priv->storage, + mcd_account_get_unique_name (account)); + } if (cad->callback != NULL) cad->callback (account_manager, account, cad->error, cad->user_data); @@ -815,10 +873,10 @@ identify_account_cb (GObject *source_object, { McdStorage *storage = MCD_STORAGE (source_object); McdCreateAccountData *cad = user_data; - const gchar *provider; gchar *id; gchar *unique_name; McdAccount *account; + McpAccountStorage *plugin; id = mcp_account_manager_identify_account_finish ( MCP_ACCOUNT_MANAGER (storage), result, &cad->error); @@ -830,12 +888,9 @@ identify_account_cb (GObject *source_object, return; } - provider = tp_asv_get_string (cad->properties, - TP_PROP_ACCOUNT_INTERFACE_STORAGE_STORAGE_PROVIDER); - - unique_name = mcd_storage_create_account (storage, provider, + unique_name = mcd_storage_create_account (storage, cad->provider, cad->cm_name, cad->protocol_name, - id, &cad->error); + id, &plugin, &cad->error); if (unique_name == NULL) { @@ -858,8 +913,10 @@ identify_account_cb (GObject *source_object, cad->display_name); account = mcd_account_new (cad->account_manager, unique_name, - cad->account_manager->priv->minotaur); + cad->account_manager->priv->minotaur, + plugin); g_free (unique_name); + g_object_unref (plugin); if (G_LIKELY (account)) { @@ -902,18 +959,33 @@ _mcd_account_manager_create_account (McdAccountManager *account_manager, return; } - cad = g_slice_new (McdCreateAccountData); + cad = g_slice_new0 (McdCreateAccountData); cad->account_manager = account_manager; cad->cm_name = g_strdup (manager); cad->protocol_name = g_strdup (protocol); cad->display_name = g_strdup (display_name); cad->parameters = g_hash_table_ref (params); - cad->properties = (properties ? g_hash_table_ref (properties) : NULL); cad->callback = callback; cad->user_data = user_data; cad->destroy = destroy; cad->error = NULL; + if (properties != NULL) + { + cad->properties = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) tp_g_value_slice_free); + + tp_g_hash_table_update (cad->properties, properties, + (GBoxedCopyFunc) g_strdup, + (GBoxedCopyFunc) tp_g_value_slice_dup); + + /* special case: "construct-only" */ + cad->provider = g_strdup (tp_asv_get_string (cad->properties, + TP_PROP_ACCOUNT_INTERFACE_STORAGE_STORAGE_PROVIDER)); + g_hash_table_remove (cad->properties, + TP_PROP_ACCOUNT_INTERFACE_STORAGE_STORAGE_PROVIDER); + } + g_value_init (&value, TP_HASH_TYPE_STRING_VARIANT_MAP); g_value_set_static_boxed (&value, params); variant_params = dbus_g_value_build_g_variant (&value); @@ -1061,20 +1133,6 @@ properties_iface_init (TpSvcDBusPropertiesClass *iface, gpointer iface_data) #undef IMPLEMENT } -static gboolean -write_conf (gpointer userdata) -{ - McdStorage *storage = MCD_STORAGE (userdata); - - DEBUG ("called"); - g_source_remove (write_conf_id); - write_conf_id = 0; - - mcd_storage_commit (storage, NULL); - - return TRUE; -} - static void release_setup_lock (McdAccountManager *self) { @@ -1136,15 +1194,6 @@ setup_account_loaded (McdAccount *account, g_object_unref (self); } -static void -uncork_storage_plugins (McdAccountManager *account_manager) -{ - McdAccountManagerPrivate *priv = MCD_ACCOUNT_MANAGER_PRIV (account_manager); - - mcd_account_manager_write_conf_async (account_manager, NULL, NULL, NULL); - mcd_storage_ready (priv->storage); -} - typedef struct { McdAccountManager *self; @@ -1176,12 +1225,13 @@ migrate_ctx_free (MigrateCtx *ctx) static void -migrate_delete_account_cb (McdAccount *account, - const GError *error, - gpointer user_data) +migrate_delete_account_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) { MigrateCtx *ctx = user_data; + mcd_account_delete_debug_cb (source, res, "after migrating it"); migrate_ctx_free (ctx); } @@ -1205,8 +1255,8 @@ migrate_create_account_cb (McdAccountManager *account_manager, DEBUG ("Account %s migrated, removing it", mcd_account_get_unique_name (ctx->account)); - mcd_account_delete (ctx->account, MCD_DBUS_PROP_SET_FLAG_NONE, - migrate_delete_account_cb, ctx); + mcd_account_delete_async (ctx->account, MCD_DBUS_PROP_SET_FLAG_NONE, + migrate_delete_account_cb, ctx); } static void @@ -1233,7 +1283,9 @@ migrate_butterfly_haze_ready (McdManager *manager, /* Parameters; the only mandatory one is 'account' */ if (!mcd_account_get_parameter_of_known_type (ctx->account, - "account", G_TYPE_STRING, + "account", + G_VARIANT_TYPE_STRING, + G_TYPE_STRING, &v, NULL)) { _mcd_account_set_enabled (ctx->account, FALSE, TRUE, @@ -1247,7 +1299,9 @@ migrate_butterfly_haze_ready (McdManager *manager, /* If MC is storing the password, let's copy that too, so Empathy * can migrate it somewhere better. */ if (mcd_account_get_parameter_of_known_type (ctx->account, - "password", G_TYPE_STRING, + "password", + G_VARIANT_TYPE_STRING, + G_TYPE_STRING, &password_v, NULL)) { g_hash_table_insert (parameters, "password", &password_v); @@ -1384,9 +1438,9 @@ _mcd_account_manager_setup (McdAccountManager *account_manager) { McdAccountManagerPrivate *priv = account_manager->priv; McdStorage *storage = priv->storage; - gchar **accounts, **name; + GHashTable *accounts; GHashTableIter iter; - gpointer v; + gpointer k, v; /* for simplicity we don't support re-entrant setup */ g_return_if_fail (priv->setup_lock == 0); @@ -1397,29 +1451,35 @@ _mcd_account_manager_setup (McdAccountManager *account_manager) list_connection_names_cb, NULL, NULL, (GObject *)account_manager); - accounts = mcd_storage_dup_accounts (storage, NULL); + accounts = mcd_storage_get_accounts (storage); + g_hash_table_iter_init (&iter, accounts); - for (name = accounts; *name != NULL; name++) + while (g_hash_table_iter_next (&iter, &k, &v)) { gboolean plausible = FALSE; const gchar *manager = NULL; const gchar *protocol = NULL; + const gchar *account_name = k; + McpAccountStorage *plugin = v; McdAccount *account = mcd_account_manager_lookup_account ( - account_manager, *name); + account_manager, account_name); if (account != NULL) { - /* FIXME: this shouldn't really happen */ - DEBUG ("already have account %p called '%s'; skipping", account, *name); + /* FIXME: can't happen? We shouldn't create any accounts before + * we got here, and there can't be any duplicates in @accounts */ + DEBUG ("already have account %p called '%s'; skipping", + account, account_name); continue; } - account = mcd_account_new (account_manager, *name, priv->minotaur); + account = mcd_account_new (account_manager, account_name, + priv->minotaur, plugin); if (G_UNLIKELY (!account)) { g_warning ("%s: account %s failed to instantiate", G_STRFUNC, - *name); + account_name); continue; } @@ -1434,7 +1494,7 @@ _mcd_account_manager_setup (McdAccountManager *account_manager) const gchar *dbg_protocol = (protocol == NULL) ? "(nil)" : protocol; g_warning ("%s: account %s has implausible manager/protocol: %s/%s", - G_STRFUNC, *name, dbg_manager, dbg_protocol); + G_STRFUNC, account_name, dbg_manager, dbg_protocol); g_object_unref (account); continue; } @@ -1445,9 +1505,18 @@ _mcd_account_manager_setup (McdAccountManager *account_manager) g_object_ref (account_manager)); g_object_unref (account); } - g_strfreev (accounts); - uncork_storage_plugins (account_manager); + /* FIXME: why do we need to commit the accounts at this point? + * It was added to uncork_storage_plugins() in 3d5b5e7a248d + * without explanation */ + g_hash_table_iter_init (&iter, account_manager->priv->accounts); + while (g_hash_table_iter_next (&iter, &k, NULL)) + { + mcd_storage_commit (storage, k); + } + + /* uncork signals from storage plugins */ + mcd_storage_ready (priv->storage); migrate_accounts (account_manager); @@ -1533,12 +1602,6 @@ _mcd_account_manager_finalize (GObject *object) { McdAccountManagerPrivate *priv = MCD_ACCOUNT_MANAGER_PRIV (object); - if (write_conf_id) - { - write_conf (priv->storage); - g_assert (write_conf_id == 0); - } - tp_clear_object (&priv->storage); g_free (priv->account_connections_dir); remove (priv->account_connections_file); @@ -1690,63 +1753,6 @@ mcd_account_manager_get_connectivity_monitor (McdAccountManager *self) return self->priv->minotaur; } -/** - * McdAccountManagerWriteConfCb: - * @account_manager: the #McdAccountManager - * @error: a set #GError on failure or %NULL if there was no error - * @user_data: user data - * - * The callback from mcd_account_manager_write_conf_async(). If the config - * writing was successful, @error will be %NULL, otherwise it will be set - * with the appropriate error. - */ - -/** - * mcd_account_manager_write_conf_async: - * @account_manager: the #McdAccountManager - * @account: the account to be written, or %NULL to flush all accounts - * @callback: a callback to be called on write success or failure - * @user_data: data to be passed to @callback - * - * Write the account manager configuration to disk. - */ -void -mcd_account_manager_write_conf_async (McdAccountManager *account_manager, - McdAccount *account, - McdAccountManagerWriteConfCb callback, - gpointer user_data) -{ - McdStorage *storage = NULL; - const gchar *account_name = NULL; - - g_return_if_fail (MCD_IS_ACCOUNT_MANAGER (account_manager)); - - storage = account_manager->priv->storage; - - if (account != NULL) - { - account_name = mcd_account_get_unique_name (account); - - DEBUG ("updating %s", account_name); - mcd_storage_commit (storage, account_name); - } - else - { - GStrv groups; - gsize n_accounts = 0; - - groups = mcd_storage_dup_accounts (storage, &n_accounts); - DEBUG ("updating all %" G_GSIZE_FORMAT " accounts", n_accounts); - - mcd_storage_commit (storage, NULL); - - g_strfreev (groups); - } - - if (callback != NULL) - callback (account_manager, NULL, user_data); -} - GHashTable * _mcd_account_manager_get_accounts (McdAccountManager *account_manager) { |