diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2012-02-20 18:40:53 +0000 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2012-02-20 18:40:53 +0000 |
commit | 8618ecef8930ad39a8bfe8b37a9c854945b9dcb8 (patch) | |
tree | c27e32c60d7c681ba2d6dfc928266196c2762f7c | |
parent | 572d39fb51e5d1aecdbaa2329686f5b818ce9897 (diff) | |
parent | c0dba4b307cbc965bec3a325373e11a706dda7fe (diff) | |
download | telepathy-mission-control-8618ecef8930ad39a8bfe8b37a9c854945b9dcb8.tar.gz |
Merge branch 'butterfly-migration-42814'
-rw-r--r-- | src/mcd-account-config.h | 1 | ||||
-rw-r--r-- | src/mcd-account-manager.c | 220 | ||||
-rw-r--r-- | src/mcd-account-priv.h | 1 | ||||
-rw-r--r-- | src/mcd-account.c | 97 | ||||
-rw-r--r-- | src/mcd-account.h | 10 | ||||
-rw-r--r-- | src/plugin-account.c | 45 | ||||
-rw-r--r-- | tests/twisted/account-manager/account-basics.py | 21 | ||||
-rw-r--r-- | tests/twisted/account-manager/create-with-properties.py | 15 | ||||
-rw-r--r-- | tests/twisted/constants.py | 3 |
9 files changed, 402 insertions, 11 deletions
diff --git a/src/mcd-account-config.h b/src/mcd-account-config.h index fc5fcb04..2d6d053f 100644 --- a/src/mcd-account-config.h +++ b/src/mcd-account-config.h @@ -51,6 +51,7 @@ #define MC_ACCOUNTS_KEY_SECONDARY_VCARD_FIELDS "secondary_vcard_fields" #define MC_ACCOUNTS_KEY_HIDDEN "Hidden" #define MC_ACCOUNTS_KEY_ALWAYS_DISPATCH "always_dispatch" +#define MC_ACCOUNTS_KEY_SUPERSEDES "Supersedes" #define PRESETS_GROUP "Presets" #define PRESETS_GROUP_DEFAULTS "Defaults" diff --git a/src/mcd-account-manager.c b/src/mcd-account-manager.c index 84ea0f26..4d93220b 100644 --- a/src/mcd-account-manager.c +++ b/src/mcd-account-manager.c @@ -4,7 +4,7 @@ * This file is part of mission-control * * Copyright © 2007-2011 Nokia Corporation. - * Copyright © 2009-2011 Collabora Ltd. + * Copyright © 2009-2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -1028,6 +1028,7 @@ get_supported_account_properties (TpSvcDBusProperties *svc, TP_IFACE_ACCOUNT ".Nickname", TP_IFACE_ACCOUNT ".ConnectAutomatically", TP_IFACE_ACCOUNT ".RequestedPresence", + TP_IFACE_ACCOUNT ".Supersedes", TP_IFACE_ACCOUNT_INTERFACE_AVATAR ".Avatar", MC_IFACE_ACCOUNT_INTERFACE_COMPAT ".SecondaryVCardFields", MC_IFACE_ACCOUNT_INTERFACE_CONDITIONS ".Condition", @@ -1135,6 +1136,221 @@ uncork_storage_plugins (McdAccountManager *account_manager) _mcd_plugin_account_manager_ready (priv->plugin_manager); } +typedef struct +{ + McdAccountManager *self; + McdAccount *account; + McdLoadAccountsData *lad; +} MigrateCtx; + +static MigrateCtx * +migrate_ctx_new (McdAccountManager *self, + McdAccount *account, + McdLoadAccountsData *lad) +{ + MigrateCtx *ctx = g_slice_new (MigrateCtx); + + ctx->self = g_object_ref (self); + ctx->account = g_object_ref (account); + ctx->lad = lad; + + /* Lock attempting to migrate the account */ + lad->account_lock++; + return ctx; +} + +static void +migrate_ctx_free (MigrateCtx *ctx) +{ + g_object_unref (ctx->self); + g_object_unref (ctx->account); + release_load_accounts_lock (ctx->lad); + g_slice_free (MigrateCtx, ctx); +} + + +static void +migrate_delete_account_cb (McdAccount *account, + const GError *error, + gpointer user_data) +{ + MigrateCtx *ctx = user_data; + + migrate_ctx_free (ctx); +} + +static void +migrate_create_account_cb (McdAccountManager *account_manager, + McdAccount *account, + const GError *error, + gpointer user_data) +{ + MigrateCtx *ctx = user_data; + + if (error != NULL) + { + DEBUG ("Failed to create account: %s", error->message); + _mcd_account_set_enabled (ctx->account, FALSE, TRUE, NULL); + migrate_ctx_free (ctx); + return; + } + + DEBUG ("Account %s migrated, removing it", + mcd_account_get_unique_name (ctx->account)); + + mcd_account_delete (ctx->account, migrate_delete_account_cb, ctx); +} + +static void +migrate_butterfly_haze_ready (McdManager *manager, + const GError *error, + gpointer user_data) +{ + MigrateCtx *ctx = user_data; + gchar *display_name; + GValue v = {0,}; + GHashTable *parameters, *properties; + gchar *str; + GPtrArray *supersedes; + GPtrArray *old_supersedes; + + if (error != NULL) + { + DEBUG ("Can't find Haze: %s", error->message); + _mcd_account_set_enabled (ctx->account, FALSE, TRUE, NULL); + goto error; + } + + /* Parameters; we just care about 'account' */ + if (!mcd_account_get_parameter (ctx->account, "account", &v, NULL)) + { + _mcd_account_set_enabled (ctx->account, FALSE, TRUE, NULL); + goto error; + } + + parameters = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (parameters, "account", &v); + + display_name = mcd_account_dup_display_name (ctx->account); + + /* Properties */ + properties = tp_asv_new (NULL, NULL); + + str = mcd_account_dup_icon (ctx->account); + if (str != NULL) + tp_asv_take_string (properties, TP_PROP_ACCOUNT_ICON, str); + + tp_asv_set_boolean (properties, TP_PROP_ACCOUNT_ENABLED, + mcd_account_is_enabled (ctx->account)); + + str = mcd_account_dup_nickname (ctx->account); + if (str != NULL) + tp_asv_take_string (properties, TP_PROP_ACCOUNT_NICKNAME, str); + + supersedes = g_ptr_array_new (); + old_supersedes = _mcd_account_get_supersedes (ctx->account); + + if (old_supersedes != NULL) + { + guint i; + + for (i = 0; i < old_supersedes->len; i++) + g_ptr_array_add (supersedes, + g_strdup (g_ptr_array_index (old_supersedes, i))); + } + + g_ptr_array_add (supersedes, + g_strdup (mcd_account_get_object_path (ctx->account))); + tp_asv_take_boxed (properties, TP_PROP_ACCOUNT_SUPERSEDES, + TP_ARRAY_TYPE_OBJECT_PATH_LIST, supersedes); + + /* Set the service while we're on it */ + tp_asv_set_string (properties, TP_PROP_ACCOUNT_SERVICE, "windows-live"); + + _mcd_account_manager_create_account (ctx->self, + "haze", "msn", display_name, + parameters, properties, + migrate_create_account_cb, ctx, NULL); + + g_value_unset (&v); + g_free (display_name); + g_hash_table_unref (parameters); + g_hash_table_unref (properties); + return; + +error: + migrate_ctx_free (ctx); +} + +static void +butterfly_account_loaded (McdAccount *account, + const GError *error, + gpointer user_data) +{ + MigrateCtx *ctx = user_data; + McdMaster *master = mcd_master_get_default (); + McdManager *manager; + + if (error != NULL) + goto error; + + DEBUG ("Try migrating butterfly account %s", + mcd_account_get_unique_name (account)); + + /* Check if Haze is installed */ + manager = _mcd_master_lookup_manager (master, "haze"); + if (manager == NULL) + { + DEBUG ("Can't find Haze"); + _mcd_account_set_enabled (account, FALSE, TRUE, NULL); + goto error; + } + + mcd_manager_call_when_ready (manager, migrate_butterfly_haze_ready, ctx); + return; + +error: + migrate_ctx_free (ctx); +} + +static void +migrate_butterfly_account (McdAccountManager *self, + McdAccount *account, + McdLoadAccountsData *lad) +{ + MigrateCtx *ctx; + + ctx = migrate_ctx_new (self, account, lad); + + _mcd_account_load (account, butterfly_account_loaded, ctx); +} + +/* Migrate some specific type of account. If something went wrong during the + * migration we disable it. */ +static void +migrate_accounts (McdAccountManager *self, + McdLoadAccountsData *lad) +{ + McdAccountManagerPrivate *priv = self->priv; + GHashTableIter iter; + gpointer v; + + g_hash_table_iter_init (&iter, priv->accounts); + while (g_hash_table_iter_next (&iter, NULL, &v)) + { + McdAccount *account = v; + TpConnectionManager *cm; + + cm = mcd_account_get_cm (account); + + if (cm == NULL) + continue; + + if (!tp_strdiff (cm->name, "butterfly")) + migrate_butterfly_account (self, account, lad); + } +} + /** * _mcd_account_manager_setup: * @account_manager: the #McdAccountManager. @@ -1210,6 +1426,8 @@ _mcd_account_manager_setup (McdAccountManager *account_manager) uncork_storage_plugins (account_manager); + migrate_accounts (account_manager, lad); + release_load_accounts_lock (lad); } diff --git a/src/mcd-account-priv.h b/src/mcd-account-priv.h index 9097ed5c..624227a6 100644 --- a/src/mcd-account-priv.h +++ b/src/mcd-account-priv.h @@ -87,6 +87,7 @@ G_GNUC_INTERNAL void _mcd_account_set_alias (McdAccount *account, const gchar *alias); G_GNUC_INTERNAL gchar *_mcd_account_get_avatar_filename (McdAccount *account); +G_GNUC_INTERNAL GPtrArray *_mcd_account_get_supersedes (McdAccount *self); G_GNUC_INTERNAL void _mcd_account_tp_connection_changed (McdAccount *account, TpConnection *tp_conn); diff --git a/src/mcd-account.c b/src/mcd-account.c index 36a86ce8..eb02c8aa 100644 --- a/src/mcd-account.c +++ b/src/mcd-account.c @@ -4,7 +4,7 @@ * This file is part of mission-control * * Copyright © 2008–2010 Nokia Corporation. - * Copyright © 2009–2011 Collabora Ltd. + * Copyright © 2009–2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -140,6 +140,7 @@ struct _McdAccountPrivate McdAccountConnectionContext *connection_context; GKeyFile *keyfile; /* configuration file */ McpAccountStorage *storage_plugin; + GPtrArray *supersedes; /* connection status */ TpConnectionStatus conn_status; @@ -422,7 +423,7 @@ static GType mc_param_type (const TpConnectionManagerParam *param); * * Returns: %TRUE if the parameter could be retrieved; %FALSE otherwise */ -static gboolean +gboolean mcd_account_get_parameter (McdAccount *account, const gchar *name, GValue *parameter, GError **error) @@ -1780,6 +1781,49 @@ get_normalized_name (TpSvcDBusProperties *self, mcd_account_get_string_val (account, name, value); } +static gboolean +set_supersedes (TpSvcDBusProperties *svc, + const gchar *name, + const GValue *value, + GError **error) +{ + McdAccount *self = MCD_ACCOUNT (svc); + + if (!G_VALUE_HOLDS (value, TP_ARRAY_TYPE_OBJECT_PATH_LIST)) + { + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "Unexpected type for Supersedes: wanted 'ao', got %s", + G_VALUE_TYPE_NAME (value)); + return FALSE; + } + + if (self->priv->supersedes != NULL) + g_ptr_array_unref (self->priv->supersedes); + + self->priv->supersedes = g_value_dup_boxed (value); + mcd_account_changed_property (self, name, value); + + mcd_storage_set_value (self->priv->storage, self->priv->unique_name, + MC_ACCOUNTS_KEY_SUPERSEDES, value, FALSE); + mcd_storage_commit (self->priv->storage, self->priv->unique_name); + + return TRUE; +} + +static void +get_supersedes (TpSvcDBusProperties *svc, + const gchar *name, + GValue *value) +{ + McdAccount *self = MCD_ACCOUNT (svc); + + if (self->priv->supersedes == NULL) + self->priv->supersedes = g_ptr_array_new (); + + g_value_init (value, TP_ARRAY_TYPE_OBJECT_PATH_LIST); + g_value_set_boxed (value, self->priv->supersedes); +} + static McpAccountStorage * get_storage_plugin (McdAccount *account) { @@ -1898,6 +1942,7 @@ static const McdDBusProp account_properties[] = { { "ChangingPresence", NULL, get_changing_presence }, { "NormalizedName", NULL, get_normalized_name }, { "HasBeenOnline", NULL, get_has_been_online }, + { "Supersedes", set_supersedes, get_supersedes }, { 0 }, }; @@ -2730,6 +2775,7 @@ mcd_account_setup (McdAccount *account) McdAccountPrivate *priv = account->priv; McdStorage *storage = priv->storage; const gchar *name = mcd_account_get_unique_name (account); + GValue *value; priv->manager_name = mcd_storage_dup_string (storage, name, MC_ACCOUNTS_KEY_MANAGER); @@ -2796,6 +2842,23 @@ mcd_account_setup (McdAccount *account) mcd_storage_dup_string (storage, name, MC_ACCOUNTS_KEY_AUTO_PRESENCE_MESSAGE); + value = mcd_storage_dup_value (storage, name, + MC_ACCOUNTS_KEY_SUPERSEDES, + TP_ARRAY_TYPE_OBJECT_PATH_LIST, NULL); + + if (priv->supersedes != NULL) + g_ptr_array_unref (priv->supersedes); + + if (value == NULL) + { + priv->supersedes = g_ptr_array_new (); + } + else + { + priv->supersedes = g_value_dup_boxed (value); + tp_g_value_slice_free (value); + } + /* check the manager */ if (!priv->manager && !load_manager (account)) { @@ -3667,6 +3730,12 @@ _mcd_account_get_avatar (McdAccount *account, GArray **avatar, g_free (filename); } +GPtrArray * +_mcd_account_get_supersedes (McdAccount *self) +{ + return self->priv->supersedes; +} + static void mcd_account_connection_self_nickname_changed_cb (McdAccount *account, const gchar *alias, @@ -4441,3 +4510,27 @@ _mcd_account_set_changing_presence (McdAccount *self, gboolean value) g_value_unset (&changing_presence); } + +gchar * +mcd_account_dup_display_name (McdAccount *self) +{ + const gchar *name = mcd_account_get_unique_name (self); + + return mcd_storage_dup_string (self->priv->storage, name, "DisplayName"); +} + +gchar * +mcd_account_dup_icon (McdAccount *self) +{ + const gchar *name = mcd_account_get_unique_name (self); + + return mcd_storage_dup_string (self->priv->storage, name, "Icon"); +} + +gchar * +mcd_account_dup_nickname (McdAccount *self) +{ + const gchar *name = mcd_account_get_unique_name (self); + + return mcd_storage_dup_string (self->priv->storage, name, "Nickname"); +} diff --git a/src/mcd-account.h b/src/mcd-account.h index 2480440e..6b0dd605 100644 --- a/src/mcd-account.h +++ b/src/mcd-account.h @@ -142,6 +142,16 @@ gboolean mcd_account_parameter_is_secret (McdAccount *self, void mcd_account_property_changed (McdAccount *account, const gchar *name); +gchar * mcd_account_dup_display_name (McdAccount *self); + +gboolean mcd_account_get_parameter (McdAccount *account, const gchar *name, + GValue *parameter, + GError **error); + +gchar * mcd_account_dup_icon (McdAccount *self); + +gchar * mcd_account_dup_nickname (McdAccount *self); + G_END_DECLS #endif diff --git a/src/plugin-account.c b/src/plugin-account.c index 99b16810..14b4e443 100644 --- a/src/plugin-account.c +++ b/src/plugin-account.c @@ -2,7 +2,7 @@ * deliberately a "smaller" API than McdAccountManager. * * Copyright © 2010 Nokia Corporation - * Copyright © 2010 Collabora Ltd. + * Copyright © 2010-2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,9 +27,9 @@ #include <string.h> -#include "mission-control-plugins/implementation.h" +#include <telepathy-glib/telepathy-glib.h> -#include <telepathy-glib/util.h> +#include "mission-control-plugins/implementation.h" /* these pseudo-plugins take care of the actual account storage/retrieval */ #include "mcd-account-manager-default.h" @@ -554,6 +554,38 @@ _storage_dup_value (McdStorage *storage, value = tp_g_value_slice_new_take_object_path (v_string); } } + else if (type == TP_ARRAY_TYPE_OBJECT_PATH_LIST) + { + gchar **v = + g_key_file_get_string_list (keyfile, account, key, NULL, error); + gchar **iter; + GPtrArray *arr = g_ptr_array_new (); + + for (iter = v; iter != NULL && *iter != NULL; iter++) + { + if (!g_variant_is_object_path (*iter)) + { + g_set_error (error, MCD_ACCOUNT_ERROR, + MCD_ACCOUNT_ERROR_GET_PARAMETER, + "Invalid object path %s stored in account", *iter); + g_strfreev (v); + v = NULL; + break; + } + } + + for (iter = v; iter != NULL && *iter != NULL; iter++) + { + /* transfer ownership from v to arr */ + g_ptr_array_add (arr, *iter); + } + + /* not g_strfreev - the strings' ownership has been transferred */ + g_free (v); + + value = tp_g_value_slice_new_take_boxed ( + TP_ARRAY_TYPE_OBJECT_PATH_LIST, arr); + } else { gchar *message = @@ -745,6 +777,13 @@ _storage_set_value (McdStorage *storage, g_key_file_set_string (self->keyfile, name, key, g_value_get_boxed (value)); } + else if (G_VALUE_HOLDS (value, TP_ARRAY_TYPE_OBJECT_PATH_LIST)) + { + GPtrArray *arr = g_value_get_boxed (value); + + g_key_file_set_string_list (self->keyfile, name, key, + (const gchar * const *) arr->pdata, arr->len); + } else { g_warning ("Unexpected param type %s", diff --git a/tests/twisted/account-manager/account-basics.py b/tests/twisted/account-manager/account-basics.py index 1a8e86eb..aceb7aed 100644 --- a/tests/twisted/account-manager/account-basics.py +++ b/tests/twisted/account-manager/account-basics.py @@ -1,5 +1,5 @@ # Copyright (C) 2009 Nokia Corporation -# Copyright (C) 2009 Collabora Ltd. +# Copyright (C) 2009-2012 Collabora Ltd. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -20,7 +20,7 @@ import dbus import dbus.service from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \ - call_async + call_async, assertEquals from mctest import exec_test, create_fakecm_account, get_account_manager import constants as cs @@ -162,6 +162,23 @@ def test(q, bus, mc): assert account_props.Get(cs.ACCOUNT_IFACE_NOKIA_CONDITIONS, 'Condition') == {':foo': 'bar'} + assertEquals(dbus.Array(signature='o'), + account_props.Get(cs.ACCOUNT, 'Supersedes')) + call_async(q, account_props, 'Set', cs.ACCOUNT, 'Supersedes', + dbus.Array([cs.ACCOUNT_PATH_PREFIX + 'x/y/z'], + signature='o')) + q.expect_many( + EventPattern('dbus-signal', + path=account_path, + signal='AccountPropertyChanged', + interface=cs.ACCOUNT, + args=[{'Supersedes': [cs.ACCOUNT_PATH_PREFIX + 'x/y/z']}]), + EventPattern('dbus-return', method='Set'), + ) + assertEquals(dbus.Array([cs.ACCOUNT_PATH_PREFIX + 'x/y/z'], + signature='o'), + account_props.Get(cs.ACCOUNT, 'Supersedes')) + # Set some properties to invalidly typed values - this currently succeeds # but is a no-op, although in future it should change to raising an # exception diff --git a/tests/twisted/account-manager/create-with-properties.py b/tests/twisted/account-manager/create-with-properties.py index d5e9685e..ca3b50d2 100644 --- a/tests/twisted/account-manager/create-with-properties.py +++ b/tests/twisted/account-manager/create-with-properties.py @@ -1,5 +1,5 @@ # Copyright (C) 2009 Nokia Corporation -# Copyright (C) 2009 Collabora Ltd. +# Copyright (C) 2009-2012 Collabora Ltd. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ import dbus import dbus.service from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \ - call_async + call_async, assertEquals from mctest import exec_test, create_fakecm_account, AccountManager import constants as cs @@ -52,6 +52,7 @@ def test(q, bus, mc): assert (cs.ACCOUNT_IFACE_NOKIA_CONDITIONS + '.Condition') in supported assert (cs.ACCOUNT + '.RequestedPresence') in supported + assert (cs.ACCOUNT + '.Supersedes') in supported params = dbus.Dictionary({"account": "anarki@example.com", "password": "secrecy"}, signature='sv') @@ -76,6 +77,10 @@ def test(q, bus, mc): dbus.Array(['x-ioquake3', 'x-quake3'], signature='s'), cs.ACCOUNT_IFACE_NOKIA_CONDITIONS + '.Condition': dbus.Dictionary({ 'has-quad-damage': ':y' }, signature='ss'), + cs.ACCOUNT + '.Supersedes': dbus.Array([ + cs.ACCOUNT_PATH_PREFIX + 'q1/q1/Ranger', + cs.ACCOUNT_PATH_PREFIX + 'q2/q2/Grunt', + ], signature='o'), }, signature='sv') call_async(q, account_manager, 'CreateAccount', @@ -122,6 +127,12 @@ def test(q, bus, mc): properties.get('Icon') assert properties.get('Nickname') == 'AnArKi', \ properties.get('Nickname') + assertEquals( + dbus.Array([ + cs.ACCOUNT_PATH_PREFIX + 'q1/q1/Ranger', + cs.ACCOUNT_PATH_PREFIX + 'q2/q2/Grunt', + ], signature='o'), + properties.get('Supersedes')) properties = account_props.GetAll(cs.ACCOUNT_IFACE_AVATAR) assert properties.get('Avatar') == ([ord('f'), ord('o'), ord('o')], diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py index 4ba24ef7..11587ad2 100644 --- a/tests/twisted/constants.py +++ b/tests/twisted/constants.py @@ -1,5 +1,5 @@ # Copyright (C) 2009 Nokia Corporation -# Copyright (C) 2009 Collabora Ltd. +# Copyright (C) 2009-2012 Collabora Ltd. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -173,6 +173,7 @@ ACCOUNT_IFACE_ADDRESSING = ACCOUNT + '.Interface.Addressing' ACCOUNT_IFACE_HIDDEN = ACCOUNT + '.Interface.Hidden.DRAFT1' ACCOUNT_IFACE_NOKIA_COMPAT = 'com.nokia.Account.Interface.Compat' ACCOUNT_IFACE_NOKIA_CONDITIONS = 'com.nokia.Account.Interface.Conditions' +ACCOUNT_PATH_PREFIX = tp_path_prefix + '/Account/' AM = tp_name_prefix + '.AccountManager' AM_IFACE_HIDDEN = AM + '.Interface.Hidden.DRAFT1' |