From 29e0296b961af7320e9c71d288750009595dade2 Mon Sep 17 00:00:00 2001 From: William Hua Date: Fri, 26 Jul 2013 10:10:11 -0400 Subject: [PATCH] Store input sources in user objects. --- data/org.freedesktop.Accounts.User.xml | 45 +++++++++++++++ src/libaccountsservice/act-user.c | 83 +++++++++++++++++++++++++++ src/libaccountsservice/act-user.h | 3 + src/user.c | 100 +++++++++++++++++++++++++++++++++ 4 files changed, 231 insertions(+) diff --git a/data/org.freedesktop.Accounts.User.xml b/data/org.freedesktop.Accounts.User.xml index 88198d8..d080be6 100644 --- a/data/org.freedesktop.Accounts.User.xml +++ b/data/org.freedesktop.Accounts.User.xml @@ -150,6 +150,41 @@ + + + + + + A list of input sources. An input source is defined by (type, name), where name is a keyboard layout if type is 'xkb' or an input method engine if type is 'ibus'. + + + + + + + Sets the user's input sources. + + + + The caller needs one of the following PolicyKit authorizations: + + + org.freedesktop.accounts.change-own-user-data + To change his own input sources + + + org.freedesktop.accounts.user-administration + To change the input sources of another user + + + + + if the caller lacks the appropriate PolicyKit authorization + if the operation failed + + + + @@ -623,6 +658,16 @@ + + + + + The user's input sources. + + + + + diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c index 9de689e..aadd7dc 100644 --- a/src/libaccountsservice/act-user.c +++ b/src/libaccountsservice/act-user.c @@ -93,6 +93,7 @@ enum { PROP_LOGIN_HISTORY, PROP_ICON_FILE, PROP_LANGUAGE, + PROP_INPUT_SOURCES, PROP_X_SESSION, PROP_IS_LOADED }; @@ -122,6 +123,7 @@ struct _ActUser { char *location; char *icon_file; char *language; + GVariant *input_sources; char *x_session; GList *our_sessions; GList *other_sessions; @@ -308,6 +310,9 @@ act_user_get_property (GObject *object, case PROP_LANGUAGE: g_value_set_string (value, user->language); break; + case PROP_INPUT_SOURCES: + g_value_set_variant (value, user->input_sources); + break; case PROP_X_SESSION: g_value_set_string (value, user->x_session); break; @@ -464,6 +469,14 @@ act_user_class_init (ActUserClass *class) NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, + PROP_INPUT_SOURCES, + g_param_spec_variant ("input-sources", + "Input sources", + "User's input sources.", + G_VARIANT_TYPE ("a(ss)"), + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, PROP_X_SESSION, g_param_spec_string ("x-session", "X session", @@ -581,6 +594,8 @@ act_user_finalize (GObject *object) g_free (user->shell); g_free (user->email); g_free (user->location); + if (user->input_sources) + g_variant_unref (user->input_sources); if (user->login_history) g_variant_unref (user->login_history); @@ -1052,6 +1067,22 @@ act_user_get_language (ActUser *user) } /** + * act_user_get_input_sources: + * @user: a #ActUser + * + * Returns the input sources of @user. + * + * Returns: (transfer none): a list of input sources + */ +GVariant * +act_user_get_input_sources (ActUser *user) +{ + g_return_val_if_fail (ACT_IS_USER (user), NULL); + + return user->input_sources; +} + +/** * act_user_get_x_session: * @user: a #ActUser * @@ -1279,6 +1310,23 @@ collect_props (const gchar *key, user->language = g_strdup (new_language); g_object_notify (G_OBJECT (user), "language"); } + } else if (strcmp (key, "InputSources") == 0) { + GVariant *sources; + + g_variant_get (value, "@a(ss)", &sources); + if (sources != user->input_sources && + (!sources || !user->input_sources || + !g_variant_equal (sources, user->input_sources))) { + if (user->input_sources) + g_variant_unref (user->input_sources); + user->input_sources = sources; + if (user->input_sources) + g_variant_ref (user->input_sources); + g_object_notify (G_OBJECT (user), "input-sources"); + } + + if (sources) + g_variant_unref (sources); } else if (strcmp (key, "XSession") == 0) { const char *new_x_session; @@ -1535,6 +1583,13 @@ _act_user_load_from_user (ActUser *user, user->language = g_strdup (user_to_copy->language); g_object_notify (G_OBJECT (user), "language"); + if (user->input_sources) + g_variant_unref (user->input_sources); + user->input_sources = user_to_copy->input_sources; + if (user->input_sources) + g_variant_ref (user->input_sources); + g_object_notify (G_OBJECT (user), "input-sources"); + g_free (user->x_session); user->x_session = g_strdup (user_to_copy->x_session); g_object_notify (G_OBJECT (user), "x-session"); @@ -1635,6 +1690,34 @@ act_user_set_language (ActUser *user, } /** + * act_user_set_input_sources: + * @user: the user object to alter. + * @sources: a list of input sources + * + * Assigns new input sources for @user. + * + * Note this function is synchronous and ignores errors. + **/ +void +act_user_set_input_sources (ActUser *user, + GVariant *sources) +{ + GError *error = NULL; + + g_return_if_fail (ACT_IS_USER (user)); + g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy)); + + if (!accounts_user_call_set_input_sources_sync (user->accounts_proxy, + sources, + NULL, + &error)) { + g_warning ("SetInputSources call failed: %s", error->message); + g_error_free (error); + return; + } +} + +/** * act_user_set_x_session: * @user: the user object to alter. * @x_session: an x session (e.g. gnome) diff --git a/src/libaccountsservice/act-user.h b/src/libaccountsservice/act-user.h index d188db4..66cf4c4 100644 --- a/src/libaccountsservice/act-user.h +++ b/src/libaccountsservice/act-user.h @@ -77,6 +77,7 @@ gboolean act_user_is_local_account (ActUser *user); gboolean act_user_is_nonexistent (ActUser *user); const char *act_user_get_icon_file (ActUser *user); const char *act_user_get_language (ActUser *user); +GVariant *act_user_get_input_sources (ActUser *user); const char *act_user_get_x_session (ActUser *user); const char *act_user_get_primary_session_id (ActUser *user); @@ -88,6 +89,8 @@ void act_user_set_email (ActUser *user, const char *email); void act_user_set_language (ActUser *user, const char *language); +void act_user_set_input_sources (ActUser *user, + GVariant *sources); void act_user_set_x_session (ActUser *user, const char *x_session); void act_user_set_location (ActUser *user, diff --git a/src/user.c b/src/user.c index 85203f0..3a63d85 100644 --- a/src/user.c +++ b/src/user.c @@ -57,6 +57,7 @@ enum { PROP_SHELL, PROP_EMAIL, PROP_LANGUAGE, + PROP_INPUT_SOURCES, PROP_X_SESSION, PROP_LOCATION, PROP_LOGIN_FREQUENCY, @@ -92,6 +93,7 @@ struct User { gchar *shell; gchar *email; gchar *language; + GVariant *input_sources; gchar *x_session; gchar *location; guint64 login_frequency; @@ -321,6 +323,16 @@ user_update_from_keyfile (User *user, g_object_notify (G_OBJECT (user), "language"); } + s = g_key_file_get_string (keyfile, "User", "InputSources", NULL); + if (s != NULL) { + if (user->input_sources != NULL) + g_variant_unref (user->input_sources); + + user->input_sources = g_variant_parse (G_VARIANT_TYPE ("a(ss)"), s, NULL, NULL, NULL); + g_object_notify (G_OBJECT (user), "input-sources"); + g_free (s); + } + s = g_key_file_get_string (keyfile, "User", "XSession", NULL); if (s != NULL) { g_free (user->x_session); @@ -404,6 +416,12 @@ user_save_to_keyfile (User *user, if (user->language) g_key_file_set_string (keyfile, "User", "Language", user->language); + if (user->input_sources) { + gchar *s = g_variant_print (user->input_sources, TRUE); + g_key_file_set_string (keyfile, "User", "InputSources", s); + g_free (s); + } + if (user->x_session) g_key_file_set_string (keyfile, "User", "XSession", user->x_session); @@ -1105,6 +1123,67 @@ user_set_language (AccountsUser *auser, } static void +user_change_input_sources_authorized_cb (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data) + +{ + GVariant *sources = data; + + if (sources != user->input_sources && + (!sources || !user->input_sources || + !g_variant_equal (sources, user->input_sources))) { + if (user->input_sources) + g_variant_unref (user->input_sources); + + user->input_sources = sources; + + if (user->input_sources) + g_variant_ref (user->input_sources); + + save_extra_data (user); + + accounts_user_emit_changed (ACCOUNTS_USER (user)); + + g_object_notify (G_OBJECT (user), "input-sources"); + } + + accounts_user_complete_set_input_sources (ACCOUNTS_USER (user), context); +} + +static gboolean +user_set_input_sources (AccountsUser *auser, + GDBusMethodInvocation *context, + GVariant *sources) +{ + User *user = (User*)auser; + int uid; + const gchar *action_id; + + if (!get_caller_uid (context, &uid)) { + throw_error (context, ERROR_FAILED, "identifying caller failed"); + return FALSE; + } + + if (user->uid == (uid_t) uid) + action_id = "org.freedesktop.accounts.change-own-user-data"; + else + action_id = "org.freedesktop.accounts.user-administration"; + + daemon_local_check_auth (user->daemon, + user, + action_id, + TRUE, + user_change_input_sources_authorized_cb, + context, + sources ? g_variant_ref (sources) : NULL, + sources ? (GDestroyNotify) g_variant_unref : NULL); + + return TRUE; +} + +static void user_change_x_session_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, @@ -2018,6 +2097,12 @@ user_real_get_language (AccountsUser *user) return USER (user)->language; } +static GVariant * +user_real_get_input_sources (AccountsUser *user) +{ + return USER (user)->input_sources; +} + static const gchar * user_real_get_xsession (AccountsUser *user) { @@ -2109,6 +2194,8 @@ user_finalize (GObject *object) g_free (user->location); g_free (user->password_hint); + if (user->input_sources) + g_variant_unref (user->input_sources); if (user->login_history) g_variant_unref (user->login_history); @@ -2131,6 +2218,13 @@ user_set_property (GObject *object, case PROP_LANGUAGE: user->language = g_value_dup_string (value); break; + case PROP_INPUT_SOURCES: + user->input_sources = g_value_get_variant (value); + + if (user->input_sources) + g_variant_ref (user->input_sources); + + break; case PROP_X_SESSION: user->x_session = g_value_dup_string (value); break; @@ -2197,6 +2291,9 @@ user_get_property (GObject *object, case PROP_LANGUAGE: g_value_set_string (value, user->language); break; + case PROP_INPUT_SOURCES: + g_value_set_variant (value, user->input_sources); + break; case PROP_X_SESSION: g_value_set_string (value, user->x_session); break; @@ -2263,6 +2360,7 @@ user_accounts_user_iface_init (AccountsUserIface *iface) iface->handle_set_home_directory = user_set_home_directory; iface->handle_set_icon_file = user_set_icon_file; iface->handle_set_language = user_set_language; + iface->handle_set_input_sources = user_set_input_sources; iface->handle_set_location = user_set_location; iface->handle_set_locked = user_set_locked; iface->handle_set_password = user_set_password; @@ -2279,6 +2377,7 @@ user_accounts_user_iface_init (AccountsUserIface *iface) iface->get_shell = user_real_get_shell; iface->get_email = user_real_get_email; iface->get_language = user_real_get_language; + iface->get_input_sources = user_real_get_input_sources; iface->get_xsession = user_real_get_xsession; iface->get_location = user_real_get_location; iface->get_login_frequency = user_real_get_login_frequency; @@ -2306,6 +2405,7 @@ user_init (User *user) user->default_icon_file = NULL; user->email = NULL; user->language = NULL; + user->input_sources = NULL; user->x_session = NULL; user->location = NULL; user->password_mode = PASSWORD_MODE_REGULAR; -- 1.8.3.2