From 1e2385077256bd5156d4269becc3a9e0a2d29c58 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 3 Oct 2017 13:48:52 -0400 Subject: [PATCH 11/13] lib: simplify code dramatically ActUser is a wrapper over the accountsservice daemon's managed user objects. There's a nearly 1-to-1 correspondence between properties on the proxy to the daemon and properties on the ActUser object. This commit dramatically reduces the code, by leveraging the proxies properties directly, rather than duplicating the values on the ActUser object. At the same time, it drops manual GetAll() calls for synchronizing the proxies properties, since it's completely redundant with the work the proxy is doing under the hood anyway. --- src/libaccountsservice/act-user.c | 676 ++++++++------------------------------ 1 file changed, 143 insertions(+), 533 deletions(-) diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c index 17acacb..94884a1 100644 --- a/src/libaccountsservice/act-user.c +++ b/src/libaccountsservice/act-user.c @@ -81,94 +81,66 @@ enum { PROP_PASSWORD_HINT, PROP_HOME_DIR, PROP_SHELL, PROP_EMAIL, PROP_LOCATION, PROP_LOCKED, PROP_AUTOMATIC_LOGIN, PROP_SYSTEM_ACCOUNT, PROP_NONEXISTENT, PROP_LOCAL_ACCOUNT, PROP_LOGIN_FREQUENCY, PROP_LOGIN_TIME, PROP_LOGIN_HISTORY, PROP_ICON_FILE, PROP_LANGUAGE, PROP_X_SESSION, PROP_IS_LOADED }; enum { CHANGED, SESSIONS_CHANGED, LAST_SIGNAL }; struct _ActUser { GObject parent; GDBusConnection *connection; AccountsUser *accounts_proxy; - GDBusProxy *object_proxy; - GCancellable *get_all_cancellable; - char *object_path; - - uid_t uid; - char *user_name; - char *real_name; - char *password_hint; - char *home_dir; - char *shell; - char *email; - char *location; - char *icon_file; - char *language; - char *x_session; + GList *our_sessions; GList *other_sessions; - int login_frequency; - gint64 login_time; - GVariant *login_history; - - ActUserAccountType account_type; - ActUserPasswordMode password_mode; - - guint uid_set : 1; guint is_loaded : 1; - guint locked : 1; - guint automatic_login : 1; - guint system_account : 1; - guint local_account : 1; guint nonexistent : 1; - - guint update_info_timeout_id; }; struct _ActUserClass { GObjectClass parent_class; }; static void act_user_finalize (GObject *object); static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (ActUser, act_user, G_TYPE_OBJECT) static int session_compare (const char *a, const char *b) { if (a == NULL) { return 1; } else if (b == NULL) { return -1; } return strcmp (a, b); } void _act_user_add_session (ActUser *user, const char *ssid, gboolean is_ours) @@ -238,128 +210,75 @@ act_user_get_num_sessions (ActUser *user) /** * act_user_get_num_sessions_anywhere: * @user: a user * * Get the number of sessions for a user on any seat of any type. * See also act_user_get_num_sessions(). * * (Currently, this function is only implemented for systemd-logind. * For ConsoleKit, it is equivalent to act_user_get_num_sessions.) * * Returns: the number of sessions */ guint act_user_get_num_sessions_anywhere (ActUser *user) { return (g_list_length (user->our_sessions) + g_list_length (user->other_sessions)); } static void act_user_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec) { ActUser *user; user = ACT_USER (object); switch (param_id) { - case PROP_UID: - g_value_set_int (value, user->uid); - break; - case PROP_USER_NAME: - g_value_set_string (value, user->user_name); - break; - case PROP_REAL_NAME: - g_value_set_string (value, user->real_name); - break; - case PROP_ACCOUNT_TYPE: - g_value_set_int (value, user->account_type); - break; - case PROP_PASSWORD_MODE: - g_value_set_int (value, user->password_mode); - break; - case PROP_PASSWORD_HINT: - g_value_set_string (value, user->password_hint); - break; - case PROP_HOME_DIR: - g_value_set_string (value, user->home_dir); - break; - case PROP_LOGIN_FREQUENCY: - g_value_set_int (value, user->login_frequency); - break; - case PROP_LOGIN_TIME: - g_value_set_int64 (value, user->login_time); - break; - case PROP_LOGIN_HISTORY: - g_value_set_variant (value, user->login_history); - break; - case PROP_SHELL: - g_value_set_string (value, user->shell); - break; - case PROP_EMAIL: - g_value_set_string (value, user->email); - break; - case PROP_LOCATION: - g_value_set_string (value, user->location); - break; - case PROP_ICON_FILE: - g_value_set_string (value, user->icon_file); - break; - case PROP_LANGUAGE: - g_value_set_string (value, user->language); - break; - case PROP_X_SESSION: - g_value_set_string (value, user->x_session); - break; - case PROP_LOCKED: - g_value_set_boolean (value, user->locked); - break; - case PROP_AUTOMATIC_LOGIN: - g_value_set_boolean (value, user->automatic_login); - break; - case PROP_SYSTEM_ACCOUNT: - g_value_set_boolean (value, user->system_account); - break; - case PROP_LOCAL_ACCOUNT: - g_value_set_boolean (value, user->local_account); - break; case PROP_NONEXISTENT: g_value_set_boolean (value, user->nonexistent); break; case PROP_IS_LOADED: g_value_set_boolean (value, user->is_loaded); break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + if (user->accounts_proxy != NULL) { + const char *property_name; + + property_name = g_param_spec_get_name (pspec); + + g_object_get_property (G_OBJECT (user->accounts_proxy), property_name, value); + + } break; } } static void act_user_class_init (ActUserClass *class) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (class); gobject_class->finalize = act_user_finalize; gobject_class->get_property = act_user_get_property; g_object_class_install_property (gobject_class, PROP_REAL_NAME, g_param_spec_string ("real-name", "Real Name", "The real name to display for this user.", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_ACCOUNT_TYPE, g_param_spec_int ("account-type", "Account Type", "The account type for this user.", ACT_USER_ACCOUNT_TYPE_STANDARD, ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR, @@ -525,1082 +444,773 @@ act_user_class_init (ActUserClass *class) * Emitted when the user accounts changes in some way. */ signals [CHANGED] = g_signal_new ("changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * ActUser::sessions-changed: * * Emitted when the list of sessions for this user changes. */ signals [SESSIONS_CHANGED] = g_signal_new ("sessions-changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void act_user_init (ActUser *user) { GError *error = NULL; - user->local_account = TRUE; - user->user_name = NULL; - user->real_name = NULL; user->our_sessions = NULL; user->other_sessions = NULL; - user->login_history = NULL; user->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (user->connection == NULL) { g_warning ("Couldn't connect to system bus: %s", error->message); g_error_free (error); } } static void act_user_finalize (GObject *object) { ActUser *user; user = ACT_USER (object); - g_free (user->user_name); - g_free (user->real_name); - g_free (user->icon_file); - g_free (user->language); - g_free (user->object_path); - g_free (user->password_hint); - g_free (user->home_dir); - g_free (user->shell); - g_free (user->email); - g_free (user->location); - if (user->login_history) - g_variant_unref (user->login_history); - if (user->accounts_proxy != NULL) { g_object_unref (user->accounts_proxy); } - if (user->object_proxy != NULL) { - g_object_unref (user->object_proxy); - } - - if (user->get_all_cancellable != NULL) { - g_object_unref (user->get_all_cancellable); - } - if (user->connection != NULL) { g_object_unref (user->connection); } - if (user->update_info_timeout_id != 0) { - g_source_remove (user->update_info_timeout_id); - } - if (G_OBJECT_CLASS (act_user_parent_class)->finalize) (*G_OBJECT_CLASS (act_user_parent_class)->finalize) (object); } static void set_is_loaded (ActUser *user, gboolean is_loaded) { if (user->is_loaded != is_loaded) { user->is_loaded = is_loaded; g_object_notify (G_OBJECT (user), "is-loaded"); } } /** * act_user_get_uid: * @user: the user object to examine. * * Retrieves the ID of @user. * * Returns: (transfer none): a pointer to an array of characters which must not be modified or * freed, or %NULL. **/ uid_t act_user_get_uid (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), -1); - return user->uid; + if (user->accounts_proxy == NULL) + return -1; + + return accounts_user_get_uid (user->accounts_proxy); } /** * act_user_get_real_name: * @user: the user object to examine. * * Retrieves the display name of @user. * * Returns: (transfer none): a pointer to an array of characters which must not be modified or * freed, or %NULL. **/ const char * act_user_get_real_name (ActUser *user) { + const char *real_name = NULL; + g_return_val_if_fail (ACT_IS_USER (user), NULL); - if (user->real_name == NULL || - user->real_name[0] == '\0') { - return user->user_name; + real_name = accounts_user_get_real_name (user->accounts_proxy); + + if (real_name == NULL || real_name[0] == '\0') { + real_name = accounts_user_get_user_name (user->accounts_proxy); } - return user->real_name; + return real_name; } /** * act_user_get_account_type: * @user: the user object to examine. * * Retrieves the account type of @user. * * Returns: a #ActUserAccountType **/ ActUserAccountType act_user_get_account_type (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), ACT_USER_ACCOUNT_TYPE_STANDARD); - return user->account_type; + if (user->accounts_proxy == NULL) + return ACT_USER_ACCOUNT_TYPE_STANDARD; + + return accounts_user_get_account_type (user->accounts_proxy); } /** * act_user_get_password_mode: * @user: the user object to examine. * * Retrieves the password mode of @user. * * Returns: a #ActUserPasswordMode **/ ActUserPasswordMode act_user_get_password_mode (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), ACT_USER_PASSWORD_MODE_REGULAR); - return user->password_mode; + if (user->accounts_proxy == NULL) + return ACT_USER_PASSWORD_MODE_REGULAR; + + return accounts_user_get_password_mode (user->accounts_proxy); } /** * act_user_get_password_hint: * @user: the user object to examine. * * Retrieves the password hint set by @user. * * Returns: (transfer none): a pointer to an array of characters which must not be modified or * freed, or %NULL. **/ const char * act_user_get_password_hint (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->password_hint; + if (user->accounts_proxy == NULL) + return NULL; + + return accounts_user_get_password_hint (user->accounts_proxy); } /** * act_user_get_home_dir: * @user: the user object to examine. * * Retrieves the home directory for @user. * * Returns: (transfer none): a pointer to an array of characters which must not be modified or * freed, or %NULL. **/ const char * act_user_get_home_dir (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->home_dir; + if (user->accounts_proxy == NULL) + return NULL; + + return accounts_user_get_home_directory (user->accounts_proxy); } /** * act_user_get_shell: * @user: the user object to examine. * * Retrieves the shell assigned to @user. * * Returns: (transfer none): a pointer to an array of characters which must not be modified or * freed, or %NULL. **/ const char * act_user_get_shell (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->shell; + if (user->accounts_proxy == NULL) + return NULL; + + return accounts_user_get_shell (user->accounts_proxy); } /** * act_user_get_email: * @user: the user object to examine. * * Retrieves the email address set by @user. * * Returns: (transfer none): a pointer to an array of characters which must not be modified or * freed, or %NULL. **/ const char * act_user_get_email (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->email; + if (user->accounts_proxy == NULL) + return NULL; + + return accounts_user_get_email (user->accounts_proxy); } /** * act_user_get_location: * @user: the user object to examine. * * Retrieves the location set by @user. * * Returns: (transfer none): a pointer to an array of characters which must not be modified or * freed, or %NULL. **/ const char * act_user_get_location (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->location; + if (user->accounts_proxy == NULL) + return NULL; + + return accounts_user_get_location (user->accounts_proxy); } /** * act_user_get_user_name: * @user: the user object to examine. * * Retrieves the login name of @user. * * Returns: (transfer none): a pointer to an array of characters which must not be modified or * freed, or %NULL. **/ const char * act_user_get_user_name (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->user_name; + if (user->accounts_proxy == NULL) + return NULL; + + return accounts_user_get_user_name (user->accounts_proxy); } /** * act_user_get_login_frequency: * @user: a #ActUser * * Returns the number of times @user has logged in. * * Returns: the login frequency */ int act_user_get_login_frequency (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), 0); - return user->login_frequency; + if (user->accounts_proxy == NULL) + return 0; + + return accounts_user_get_login_frequency (user->accounts_proxy); } /** * act_user_get_login_time: * @user: a #ActUser * * Returns the last login time for @user. * * Returns: (transfer none): the login time */ gint64 -act_user_get_login_time (ActUser *user) { +act_user_get_login_time (ActUser *user) +{ g_return_val_if_fail (ACT_IS_USER (user), 0); - return user->login_time; + if (user->accounts_proxy == NULL) + return 0; + + return accounts_user_get_login_time (user->accounts_proxy); } /** * act_user_get_login_history: * @user: a #ActUser * * Returns the login history for @user. * * Returns: (transfer none): a pointer to GVariant of type "a(xxa{sv})" * which must not be modified or freed, or %NULL. */ const GVariant * -act_user_get_login_history (ActUser *user) { +act_user_get_login_history (ActUser *user) +{ g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->login_history; + if (user->accounts_proxy == NULL) + return NULL; + + return accounts_user_get_login_history (user->accounts_proxy); } /** * act_user_collate: * @user1: a user * @user2: a user * * Organize the user by login frequency and names. * * Returns: negative if @user1 is before @user2, zero if equal * or positive if @user1 is after @user2 */ int act_user_collate (ActUser *user1, ActUser *user2) { const char *str1; const char *str2; int num1; int num2; guint len1; guint len2; g_return_val_if_fail (ACT_IS_USER (user1), 0); g_return_val_if_fail (ACT_IS_USER (user2), 0); - num1 = user1->login_frequency; - num2 = user2->login_frequency; + num1 = act_user_get_login_frequency (user1); + num2 = act_user_get_login_frequency (user2); if (num1 > num2) { return -1; } if (num1 < num2) { return 1; } len1 = g_list_length (user1->our_sessions); len2 = g_list_length (user2->our_sessions); if (len1 > len2) { return -1; } if (len1 < len2) { return 1; } /* if login frequency is equal try names */ - if (user1->real_name != NULL) { - str1 = user1->real_name; - } else { - str1 = user1->user_name; - } - - if (user2->real_name != NULL) { - str2 = user2->real_name; - } else { - str2 = user2->user_name; - } + str1 = act_user_get_real_name (user1); + str2 = act_user_get_real_name (user2); if (str1 == NULL && str2 != NULL) { return -1; } if (str1 != NULL && str2 == NULL) { return 1; } if (str1 == NULL && str2 == NULL) { return 0; } return g_utf8_collate (str1, str2); } /** * act_user_is_logged_in: * @user: a #ActUser * * Returns whether or not #ActUser is currently graphically logged in * on the same seat as the seat of the session of the calling process. * * Returns: %TRUE or %FALSE */ gboolean act_user_is_logged_in (ActUser *user) { return user->our_sessions != NULL; } /** * act_user_is_logged_in_anywhere: * @user: a #ActUser * * Returns whether or not #ActUser is currently logged in in any way * whatsoever. See also act_user_is_logged_in(). * * (Currently, this function is only implemented for systemd-logind. * For ConsoleKit, it is equivalent to act_user_is_logged_in.) * * Returns: %TRUE or %FALSE */ gboolean act_user_is_logged_in_anywhere (ActUser *user) { return user->our_sessions != NULL || user->other_sessions != NULL; } /** * act_user_get_locked: * @user: a #ActUser * * Returns whether or not the #ActUser account is locked. * * Returns: %TRUE or %FALSE */ gboolean act_user_get_locked (ActUser *user) { - return user->locked;; + return accounts_user_get_locked (user->accounts_proxy); } /** * act_user_get_automatic_login: * @user: a #ActUser * * Returns whether or not #ActUser is automatically logged in at boot time. * * Returns: %TRUE or %FALSE */ gboolean act_user_get_automatic_login (ActUser *user) { - return user->automatic_login; + g_return_val_if_fail (ACT_IS_USER (user), FALSE); + + if (user->accounts_proxy == NULL) + return FALSE; + + return accounts_user_get_automatic_login (user->accounts_proxy); } /** * act_user_is_system_account: * @user: a #ActUser * * Returns whether or not #ActUser represents a 'system account' like * 'root' or 'nobody'. * * Returns: %TRUE or %FALSE */ gboolean act_user_is_system_account (ActUser *user) { - return user->system_account; + g_return_val_if_fail (ACT_IS_USER (user), TRUE); + + if (user->accounts_proxy == NULL) + return TRUE; + + return accounts_user_get_system_account (user->accounts_proxy); } /** * act_user_is_local_account: * @user: the user object to examine. * * Retrieves whether the user is a local account or not. * * Returns: (transfer none): %TRUE if the user is local **/ gboolean act_user_is_local_account (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), FALSE); - return user->local_account; + if (user->accounts_proxy == NULL) + return FALSE; + + return accounts_user_get_local_account (user->accounts_proxy); } /** * act_user_is_nonexistent: * @user: the user object to examine. * * Retrieves whether the user is nonexistent or not. * * Returns: (transfer none): %TRUE if the user is nonexistent **/ gboolean act_user_is_nonexistent (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), FALSE); return user->nonexistent; } /** * act_user_get_icon_file: * @user: a #ActUser * * Returns the path to the account icon belonging to @user. * * Returns: (transfer none): a path to an icon */ const char * act_user_get_icon_file (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->icon_file; + if (user->accounts_proxy == NULL) + return NULL; + + return accounts_user_get_icon_file (user->accounts_proxy); } /** * act_user_get_language: * @user: a #ActUser * * Returns the path to the configured locale of @user. * * Returns: (transfer none): a path to an icon */ const char * act_user_get_language (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->language; + if (user->accounts_proxy == NULL) + return NULL; + + return accounts_user_get_language (user->accounts_proxy); } /** * act_user_get_x_session: * @user: a #ActUser * * Returns the path to the configured X session for @user. * * Returns: (transfer none): a path to an icon */ const char * act_user_get_x_session (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->x_session; + if (user->accounts_proxy == NULL) + return NULL; + + return accounts_user_get_xsession (user->accounts_proxy); } /** * act_user_get_object_path: * @user: a #ActUser * * Returns the user accounts service object path of @user, * or %NULL if @user doesn't have an object path associated * with it. * * Returns: (transfer none): the object path of the user */ const char * act_user_get_object_path (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), NULL); - return user->object_path; + if (user->accounts_proxy == NULL) + return NULL; + + return g_dbus_proxy_get_object_path (G_DBUS_PROXY (user->accounts_proxy)); } /** * act_user_get_primary_session_id: * @user: a #ActUser * * Returns the id of the primary session of @user, or %NULL if @user * has no primary session. The primary session will always be * graphical and will be chosen from the sessions on the same seat as * the seat of the session of the calling process. * * Returns: (transfer none): the id of the primary session of the user */ const char * act_user_get_primary_session_id (ActUser *user) { if (user->our_sessions == NULL) { g_debug ("User %s is not logged in here, so has no primary session", act_user_get_user_name (user)); return NULL; } /* FIXME: better way to choose? */ return user->our_sessions->data; } -static void -collect_props (const gchar *key, - GVariant *value, - ActUser *user) -{ - gboolean handled = TRUE; - - if (strcmp (key, "Uid") == 0) { - guint64 new_uid; - - new_uid = g_variant_get_uint64 (value); - if (!user->uid_set || (guint64) user->uid != new_uid) { - user->uid = (uid_t) new_uid; - user->uid_set = TRUE; - g_object_notify (G_OBJECT (user), "uid"); - } - } else if (strcmp (key, "UserName") == 0) { - const char *new_user_name; - - new_user_name = g_variant_get_string (value, NULL); - if (g_strcmp0 (user->user_name, new_user_name) != 0) { - g_free (user->user_name); - user->user_name = g_strdup (new_user_name); - g_object_notify (G_OBJECT (user), "user-name"); - } - } else if (strcmp (key, "RealName") == 0) { - const char *new_real_name; - - new_real_name = g_variant_get_string (value, NULL); - if (g_strcmp0 (user->real_name, new_real_name) != 0) { - g_free (user->real_name); - user->real_name = g_strdup (new_real_name); - g_object_notify (G_OBJECT (user), "real-name"); - } - } else if (strcmp (key, "AccountType") == 0) { - int new_account_type; - - new_account_type = g_variant_get_int32 (value); - if ((int) user->account_type != new_account_type) { - user->account_type = (ActUserAccountType) new_account_type; - g_object_notify (G_OBJECT (user), "account-type"); - } - } else if (strcmp (key, "PasswordMode") == 0) { - int new_password_mode; - - new_password_mode = g_variant_get_int32 (value); - if ((int) user->password_mode != new_password_mode) { - user->password_mode = (ActUserPasswordMode) new_password_mode; - g_object_notify (G_OBJECT (user), "password-mode"); - } - } else if (strcmp (key, "PasswordHint") == 0) { - const char *new_password_hint; - - new_password_hint = g_variant_get_string (value, NULL); - if (g_strcmp0 (user->password_hint, new_password_hint) != 0) { - g_free (user->password_hint); - user->password_hint = g_strdup (new_password_hint); - g_object_notify (G_OBJECT (user), "password-hint"); - } - } else if (strcmp (key, "HomeDirectory") == 0) { - const char *new_home_dir; - - new_home_dir = g_variant_get_string (value, NULL); - if (g_strcmp0 (user->home_dir, new_home_dir) != 0) { - g_free (user->home_dir); - user->home_dir = g_strdup (new_home_dir); - g_object_notify (G_OBJECT (user), "home-directory"); - } - } else if (strcmp (key, "Shell") == 0) { - const char *new_shell; - - new_shell = g_variant_get_string (value, NULL); - if (g_strcmp0 (user->shell, new_shell) != 0) { - g_free (user->shell); - user->shell = g_strdup (new_shell); - g_object_notify (G_OBJECT (user), "shell"); - } - } else if (strcmp (key, "Email") == 0) { - const char *new_email; - - new_email = g_variant_get_string (value, NULL); - if (g_strcmp0 (user->email, new_email) != 0) { - g_free (user->email); - user->email = g_strdup (new_email); - g_object_notify (G_OBJECT (user), "email"); - } - } else if (strcmp (key, "Location") == 0) { - const char *new_location; - - new_location = g_variant_get_string (value, NULL); - if (g_strcmp0 (user->location, new_location) != 0) { - g_free (user->location); - user->location = g_strdup (new_location); - g_object_notify (G_OBJECT (user), "location"); - } - } else if (strcmp (key, "Locked") == 0) { - gboolean new_locked_state; - - new_locked_state = g_variant_get_boolean (value); - if (new_locked_state != user->locked) { - user->locked = new_locked_state; - g_object_notify (G_OBJECT (user), "locked"); - } - } else if (strcmp (key, "AutomaticLogin") == 0) { - gboolean new_automatic_login_state; - - new_automatic_login_state = g_variant_get_boolean (value); - if (new_automatic_login_state != user->automatic_login) { - user->automatic_login = new_automatic_login_state; - g_object_notify (G_OBJECT (user), "automatic-login"); - } - } else if (strcmp (key, "SystemAccount") == 0) { - gboolean new_system_account_state; - - new_system_account_state = g_variant_get_boolean (value); - if (new_system_account_state != user->system_account) { - user->system_account = new_system_account_state; - g_object_notify (G_OBJECT (user), "system-account"); - } - } else if (strcmp (key, "LocalAccount") == 0) { - gboolean new_local; - - new_local = g_variant_get_boolean (value); - if (user->local_account != new_local) { - user->local_account = new_local; - g_object_notify (G_OBJECT (user), "local-account"); - } - } else if (strcmp (key, "LoginFrequency") == 0) { - int new_login_frequency; - - new_login_frequency = (int) g_variant_get_uint64 (value); - if ((int) user->login_frequency != (int) new_login_frequency) { - user->login_frequency = new_login_frequency; - g_object_notify (G_OBJECT (user), "login-frequency"); - } - } else if (strcmp (key, "LoginTime") == 0) { - gint64 new_login_time = g_variant_get_int64 (value); - - if (user->login_time != new_login_time) { - user->login_time = new_login_time; - g_object_notify (G_OBJECT (user), "login-time"); - } - } else if (strcmp (key, "LoginHistory") == 0) { - GVariant *new_login_history = value; - - if (user->login_history == NULL || - !g_variant_equal (user->login_history, new_login_history)) { - if (user->login_history) - g_variant_unref (user->login_history); - user->login_history = g_variant_ref (new_login_history); - g_object_notify (G_OBJECT (user), "login-history"); - } - } else if (strcmp (key, "IconFile") == 0) { - const char *new_icon_file; - - new_icon_file = g_variant_get_string (value, NULL); - if (g_strcmp0 (user->icon_file, new_icon_file) != 0) { - g_free (user->icon_file); - user->icon_file = g_strdup (new_icon_file); - g_object_notify (G_OBJECT (user), "icon-file"); - } - } else if (strcmp (key, "Language") == 0) { - const char *new_language; - - new_language = g_variant_get_string (value, NULL); - if (g_strcmp0 (user->language, new_language) != 0) { - g_free (user->language); - user->language = g_strdup (new_language); - g_object_notify (G_OBJECT (user), "language"); - } - } else if (strcmp (key, "XSession") == 0) { - const char *new_x_session; - - new_x_session = g_variant_get_string (value, NULL); - if (g_strcmp0 (user->x_session, new_x_session) != 0) { - g_free (user->x_session); - user->x_session = g_strdup (new_x_session); - g_object_notify (G_OBJECT (user), "x-session"); - } - } else { - handled = FALSE; - } - - if (!handled) { - g_debug ("unhandled property %s", key); - } -} - -static void -on_get_all_finished (GObject *object, - GAsyncResult *result, - gpointer data) -{ - GDBusProxy *proxy = G_DBUS_PROXY (object); - ActUser *user = data; - GError *error; - GVariant *res; - GVariantIter *iter; - gchar *key; - GVariant *value; - - g_assert (G_IS_DBUS_PROXY (user->object_proxy)); - g_assert (user->object_proxy == proxy); - - error = NULL; - res = g_dbus_proxy_call_finish (proxy, result, &error); - - g_clear_object (&user->get_all_cancellable); - - if (! res) { - g_debug ("Error calling GetAll() when retrieving properties for %s: %s", - user->object_path, error->message); - g_error_free (error); - - if (!user->is_loaded) { - set_is_loaded (user, TRUE); - } - return; - } - - g_variant_get (res, "(a{sv})", &iter); - while (g_variant_iter_next (iter, "{sv}", &key, &value)) { - collect_props (key, value, user); - g_free (key); - g_variant_unref (value); - } - g_variant_iter_free (iter); - g_variant_unref (res); - - if (!user->is_loaded) { - set_is_loaded (user, TRUE); - } - - g_signal_emit (user, signals[CHANGED], 0); -} - -static void -update_info (ActUser *user) -{ - g_assert (G_IS_DBUS_PROXY (user->object_proxy)); - - if (user->get_all_cancellable != NULL) { - g_cancellable_cancel (user->get_all_cancellable); - g_clear_object (&user->get_all_cancellable); - } - - user->get_all_cancellable = g_cancellable_new (); - g_dbus_proxy_call (user->object_proxy, - "GetAll", - g_variant_new ("(s)", ACCOUNTS_USER_INTERFACE), - G_DBUS_CALL_FLAGS_NONE, - -1, - user->get_all_cancellable, - on_get_all_finished, - user); -} - -static gboolean -on_timeout_update_info (ActUser *user) -{ - update_info (user); - user->update_info_timeout_id = 0; - - return G_SOURCE_REMOVE; -} - -static void -changed_handler (AccountsUser *object, - gpointer *data) -{ - ActUser *user = ACT_USER (data); - - if (user->update_info_timeout_id != 0) - return; - - user->update_info_timeout_id = g_timeout_add (250, (GSourceFunc) on_timeout_update_info, user); -} - /** * _act_user_update_as_nonexistent: * @user: the user object to update. * * Set's the 'non-existent' property of @user to #TRUE * Can only be called before the user is loaded. **/ void _act_user_update_as_nonexistent (ActUser *user) { g_return_if_fail (ACT_IS_USER (user)); g_return_if_fail (!act_user_is_loaded (user)); - g_return_if_fail (user->object_path == NULL); + g_return_if_fail (act_user_get_object_path (user) == NULL); user->nonexistent = TRUE; g_object_notify (G_OBJECT (user), "nonexistent"); set_is_loaded (user, TRUE); } +static void +on_accounts_proxy_changed (ActUser *user) +{ + g_signal_emit (user, signals[CHANGED], 0); +} + /** * _act_user_update_from_object_path: * @user: the user object to update. * @object_path: the object path of the user to use. * * Updates the properties of @user from the accounts service via * the object path in @object_path. **/ void _act_user_update_from_object_path (ActUser *user, const char *object_path) { - GError *error = NULL; + AccountsUser *accounts_proxy; + GError *error = NULL; g_return_if_fail (ACT_IS_USER (user)); g_return_if_fail (object_path != NULL); - g_return_if_fail (user->object_path == NULL); - - user->object_path = g_strdup (object_path); - - user->accounts_proxy = accounts_user_proxy_new_sync (user->connection, - G_DBUS_PROXY_FLAGS_NONE, - ACCOUNTS_NAME, - user->object_path, - NULL, - &error); - if (!user->accounts_proxy) { + g_return_if_fail (act_user_get_object_path (user) == NULL); + + accounts_proxy = accounts_user_proxy_new_sync (user->connection, + G_DBUS_PROXY_FLAGS_NONE, + ACCOUNTS_NAME, + object_path, + NULL, + &error); + if (!accounts_proxy) { g_warning ("Couldn't create accounts proxy: %s", error->message); g_error_free (error); return; } - g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (user->accounts_proxy), INT_MAX); - g_signal_connect (user->accounts_proxy, "changed", G_CALLBACK (changed_handler), user); + user->accounts_proxy = accounts_proxy; - user->object_proxy = g_dbus_proxy_new_sync (user->connection, - G_DBUS_PROXY_FLAGS_NONE, - 0, - ACCOUNTS_NAME, - user->object_path, - "org.freedesktop.DBus.Properties", - NULL, - &error); - if (!user->object_proxy) { - g_warning ("Couldn't create accounts property proxy: %s", error->message); - g_error_free (error); - return; - } + g_signal_connect_object (user->accounts_proxy, + "changed", + G_CALLBACK (on_accounts_proxy_changed), + user, + G_CONNECT_SWAPPED); - update_info (user); + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (user->accounts_proxy), INT_MAX); + + set_is_loaded (user, TRUE); } void _act_user_update_login_frequency (ActUser *user, int login_frequency) { - if (user->login_frequency != login_frequency) { - user->login_frequency = login_frequency; - g_object_notify (G_OBJECT (user), "login-frequency"); + if (act_user_get_login_frequency (user) == login_frequency) { + return; } + + accounts_user_set_login_frequency (user->accounts_proxy, + login_frequency); } static void copy_sessions_lists (ActUser *user, ActUser *user_to_copy) { GList *node; for (node = g_list_last (user_to_copy->our_sessions); node != NULL; node = node->prev) { user->our_sessions = g_list_prepend (user->our_sessions, g_strdup (node->data)); } for (node = g_list_last (user_to_copy->other_sessions); node != NULL; node = node->prev) { user->other_sessions = g_list_prepend (user->other_sessions, g_strdup (node->data)); } } void _act_user_load_from_user (ActUser *user, ActUser *user_to_copy) { if (!user_to_copy->is_loaded) { return; } - /* loading users may already have a uid, user name, or session list - * from creation, so only update them if necessary - */ - if (!user->uid_set) { - user->uid = user_to_copy->uid; - g_object_notify (G_OBJECT (user), "uid"); - } + user->accounts_proxy = g_object_ref (user_to_copy->accounts_proxy); - if (user->user_name == NULL) { - user->user_name = g_strdup (user_to_copy->user_name); - g_object_notify (G_OBJECT (user), "user-name"); - } + g_signal_connect_object (user->accounts_proxy, + "changed", + G_CALLBACK (on_accounts_proxy_changed), + user, + G_CONNECT_SWAPPED); if (user->our_sessions == NULL && user->other_sessions == NULL) { copy_sessions_lists (user, user_to_copy); g_signal_emit (user, signals[SESSIONS_CHANGED], 0); } - g_free (user->real_name); - user->real_name = g_strdup (user_to_copy->real_name); - g_object_notify (G_OBJECT (user), "real-name"); - - g_free (user->password_hint); - user->password_hint = g_strdup (user_to_copy->password_hint); - g_object_notify (G_OBJECT (user), "password-hint"); - - g_free (user->home_dir); - user->home_dir = g_strdup (user_to_copy->home_dir); - g_object_notify (G_OBJECT (user), "home-directory"); - - g_free (user->shell); - user->shell = g_strdup (user_to_copy->shell); - g_object_notify (G_OBJECT (user), "shell"); - - g_free (user->email); - user->email = g_strdup (user_to_copy->email); - g_object_notify (G_OBJECT (user), "email"); - - g_free (user->location); - user->location = g_strdup (user_to_copy->location); - g_object_notify (G_OBJECT (user), "location"); - - g_free (user->icon_file); - user->icon_file = g_strdup (user_to_copy->icon_file); - g_object_notify (G_OBJECT (user), "icon-file"); - - g_free (user->language); - user->language = g_strdup (user_to_copy->language); - g_object_notify (G_OBJECT (user), "language"); - - g_free (user->x_session); - user->x_session = g_strdup (user_to_copy->x_session); - g_object_notify (G_OBJECT (user), "x-session"); - - user->login_frequency = user_to_copy->login_frequency; - g_object_notify (G_OBJECT (user), "login-frequency"); - - user->login_time = user_to_copy->login_time; - g_object_notify (G_OBJECT (user), "login-time"); - - user->login_history = user_to_copy->login_history ? g_variant_ref (user_to_copy->login_history) : NULL; - g_object_notify (G_OBJECT (user), "login-history"); - - user->account_type = user_to_copy->account_type; - g_object_notify (G_OBJECT (user), "account-type"); - - user->password_mode = user_to_copy->password_mode; - g_object_notify (G_OBJECT (user), "password-mode"); - - user->nonexistent = user_to_copy->nonexistent; - g_object_notify (G_OBJECT (user), "nonexistent"); - set_is_loaded (user, TRUE); } /** * act_user_is_loaded: * @user: a #ActUser * * Determines whether or not the user object is loaded and ready to read from. * #ActUserManager:is-loaded property must be %TRUE before calling * act_user_manager_list_users() * * Returns: %TRUE or %FALSE */ gboolean act_user_is_loaded (ActUser *user) { return user->is_loaded; } /** * act_user_get_login_history: * @user: the user object to query. * @expiration_time: time users passwor expires * @last_change_time, * @min_days_between_changes, * @max_days_between_changes, * @days_to_warn, * @days_after_expiration_until_lock) * * Assigns a new email to @user. -- 2.14.1