Merge lp:~mterry/lightdm/no-dmrc into lp:lightdm

Proposed by Michael Terry
Status: Merged
Merged at revision: 1065
Proposed branch: lp:~mterry/lightdm/no-dmrc
Merge into: lp:lightdm
Diff against target: 443 lines (+292/-15)
4 files modified
liblightdm-gobject/user.c (+74/-3)
src/display.c (+4/-10)
src/user.c (+208/-1)
src/user.h (+6/-1)
To merge this branch: bzr merge lp:~mterry/lightdm/no-dmrc
Reviewer Review Type Date Requested Status
Robert Ancell Approve
Review via email: mp+71939@code.launchpad.net

Description of the change

This uses the org.freedesktop.Accounts service instead of dmrc for saving default xsession information.

I could not find where LightDM was loading per-user default xsession information? Seems like it isn't.

If true, we should add that to the liblightdm libraries as a call like get_default_session_hint_for_user and have the lightdm daemon ask accountsservice.

To post a comment you must log in.
Revision history for this message
Robert Ancell (robert-ancell) wrote :

I think we need to continue to support .dmrc for systems that don't have accounts service:
http://lists.freedesktop.org/archives/lightdm/2011-August/000051.html

What we should do is merge user.c into the new accounts.c so that internally LightDM uses the accounts service interface but the backend can fallback to passwd and .dmrc.

Also since it doesn't make sense to have multiple accounts instances inside LightDM I'd make it a singleton and just access through functions for simplicity.

In terms of Unity/GNOME, I definitely think we should be using accounts service.

review: Needs Fixing
Revision history for this message
Michael Terry (mterry) wrote :

Each Accounts object is per-user, not global. So a singleton doesn't make as much sense. Unless you want a global Accounts object that hides the per-user stuff and keeps an internal cache of proxies. But that seems like forcing it.

lp:~mterry/lightdm/no-dmrc updated
1057. By Michael Terry

add back dmrc support as a fallback for accounts service

1058. By Michael Terry

move Accounts class into User class

Revision history for this message
Michael Terry (mterry) wrote :

OK, I've updated the branch. Now we write to .dmrc as well as the Accounts service. And we fallback to .dmrc when trying to read from the Accounts service.

Additionally, I've moved the code into the User class.

Could you review again, please?

(Again, this branch writes correctly to Accounts/dmrc, but still doesn't solve the problem that we never load per-user values from them.)

lp:~mterry/lightdm/no-dmrc updated
1059. By Michael Terry

liblightdm-gobject: look at Accounts object when checking per-user session and language values

Revision history for this message
Michael Terry (mterry) wrote :

Sorry, I was wrong about never loading per-user values from them. I missed the glue in liblightdm-gobject/user.c that did that.

So I've now updated this branch to modify that file to also look at the Accounts service for session info. This fixes bug 818201.

Revision history for this message
Robert Ancell (robert-ancell) wrote :

Pushed with some minor changes:
- Missing 'return TRUE' at the end of load_accounts_service ()
- Replace '//' comments with '/*' ones
- Add NEWS entry

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'liblightdm-gobject/user.c'
--- liblightdm-gobject/user.c 2011-08-17 00:26:17 +0000
+++ liblightdm-gobject/user.c 2011-08-22 20:39:30 +0000
@@ -1095,11 +1095,82 @@
10951095
1096 // FIXME: Watch for changes1096 // FIXME: Watch for changes
10971097
1098 if (priv->language)
1099 g_free (priv->language);
1100 if (priv->layout)
1101 g_free (priv->layout);
1102 if (priv->session)
1103 g_free (priv->session);
1104
1098 priv->language = g_key_file_get_string (priv->dmrc_file, "Desktop", "Language", NULL);1105 priv->language = g_key_file_get_string (priv->dmrc_file, "Desktop", "Language", NULL);
1099 priv->layout = g_key_file_get_string (priv->dmrc_file, "Desktop", "Layout", NULL);1106 priv->layout = g_key_file_get_string (priv->dmrc_file, "Desktop", "Layout", NULL);
1100 priv->session = g_key_file_get_string (priv->dmrc_file, "Desktop", "Session", NULL);1107 priv->session = g_key_file_get_string (priv->dmrc_file, "Desktop", "Session", NULL);
1101}1108}
11021109
1110static gchar *
1111get_string_property (GDBusProxy *proxy, const gchar *property)
1112{
1113 GVariant *answer;
1114 gchar *rv;
1115
1116 if (!proxy)
1117 return NULL;
1118
1119 answer = g_dbus_proxy_get_cached_property (proxy, property);
1120
1121 if (!answer) {
1122 g_warning ("Could not get accounts property %s", property);
1123 return NULL;
1124 }
1125
1126 if (!g_variant_is_of_type (answer, G_VARIANT_TYPE ("s"))) {
1127 g_warning ("Unexpected accounts property type for %s: %s",
1128 property, g_variant_get_type_string (answer));
1129 g_variant_unref (answer);
1130 return NULL;
1131 }
1132
1133 g_variant_get (answer, "s", &rv);
1134
1135 g_variant_unref (answer);
1136 return rv;
1137}
1138
1139static gboolean
1140load_accounts_service (LightDMUser *user)
1141{
1142 // First, find AccountObject proxy
1143 LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
1144 LightDMUserListPrivate *list_priv = GET_LIST_PRIVATE (priv->user_list);
1145
1146 UserAccountObject *account = NULL;
1147 GList *iter;
1148 for (iter = list_priv->user_account_objects; iter; iter = iter->next) {
1149 if (((UserAccountObject *)iter->data)->user == user) {
1150 account = (UserAccountObject *)iter->data;
1151 break;
1152 }
1153 }
1154 if (!account)
1155 return FALSE;
1156
1157 // We have proxy, let's grab some properties
1158 if (priv->language)
1159 g_free (priv->language);
1160 if (priv->session)
1161 g_free (priv->session);
1162 priv->language = get_string_property (account->proxy, "Language");
1163 priv->session = get_string_property (account->proxy, "XSession");
1164}
1165
1166/* Loads language/layout/session info for user */
1167static void
1168load_user_values (LightDMUser *user)
1169{
1170 load_dmrc (user);
1171 load_accounts_service (user); // overrides dmrc values
1172}
1173
1103/**1174/**
1104 * lightdm_user_get_language1175 * lightdm_user_get_language
1105 * @user: A #LightDMUser1176 * @user: A #LightDMUser
@@ -1112,7 +1183,7 @@
1112lightdm_user_get_language (LightDMUser *user)1183lightdm_user_get_language (LightDMUser *user)
1113{1184{
1114 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);1185 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
1115 load_dmrc (user);1186 load_user_values (user);
1116 return GET_USER_PRIVATE (user)->language;1187 return GET_USER_PRIVATE (user)->language;
1117}1188}
11181189
@@ -1128,7 +1199,7 @@
1128lightdm_user_get_layout (LightDMUser *user)1199lightdm_user_get_layout (LightDMUser *user)
1129{1200{
1130 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);1201 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
1131 load_dmrc (user);1202 load_user_values (user);
1132 return GET_USER_PRIVATE (user)->layout;1203 return GET_USER_PRIVATE (user)->layout;
1133}1204}
11341205
@@ -1144,7 +1215,7 @@
1144lightdm_user_get_session (LightDMUser *user)1215lightdm_user_get_session (LightDMUser *user)
1145{1216{
1146 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);1217 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
1147 load_dmrc (user);1218 load_user_values (user);
1148 return GET_USER_PRIVATE (user)->session; 1219 return GET_USER_PRIVATE (user)->session;
1149}1220}
11501221
11511222
=== modified file 'src/display.c'
--- src/display.c 2011-08-18 00:11:39 +0000
+++ src/display.c 2011-08-22 20:39:30 +0000
@@ -1,4 +1,5 @@
1/*1/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*-
2 *
2 * Copyright (C) 2010-2011 Robert Ancell.3 * Copyright (C) 2010-2011 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>4 * Author: Robert Ancell <robert.ancell@canonical.com>
4 *5 *
@@ -18,7 +19,6 @@
18#include "configuration.h"19#include "configuration.h"
19#include "user.h"20#include "user.h"
20#include "pam-session.h"21#include "pam-session.h"
21#include "dmrc.h"
22#include "ldm-marshal.h"22#include "ldm-marshal.h"
23#include "greeter.h"23#include "greeter.h"
24#include "xserver-local.h" // FIXME: Shouldn't know if it's an xserver24#include "xserver-local.h" // FIXME: Shouldn't know if it's an xserver
@@ -771,7 +771,6 @@
771start_user_session (Display *display, PAMSession *authentication)771start_user_session (Display *display, PAMSession *authentication)
772{772{
773 User *user;773 User *user;
774 GKeyFile *dmrc_file;
775 gchar *log_filename;774 gchar *log_filename;
776 gboolean result = FALSE;775 gboolean result = FALSE;
777776
@@ -779,13 +778,8 @@
779778
780 user = pam_session_get_user (authentication);779 user = pam_session_get_user (authentication);
781780
782 /* Load the users login settings (~/.dmrc) */781 /* Update user's xsession setting */
783 dmrc_file = dmrc_load (user_get_name (user));782 user_set_session (user, display->priv->user_session);
784
785 /* Update the .dmrc with changed settings */
786 g_key_file_set_string (dmrc_file, "Desktop", "Session", display->priv->user_session);
787 dmrc_save (dmrc_file, user_get_name (user));
788 g_key_file_free (dmrc_file);
789783
790 // FIXME: Copy old error file784 // FIXME: Copy old error file
791 log_filename = g_build_filename (user_get_home_directory (user), ".xsession-errors", NULL);785 log_filename = g_build_filename (user_get_home_directory (user), ".xsession-errors", NULL);
792786
=== modified file 'src/user.c'
--- src/user.c 2011-08-06 15:00:26 +0000
+++ src/user.c 2011-08-22 20:39:30 +0000
@@ -1,4 +1,5 @@
1/*1/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*-
2 *
2 * Copyright (C) 2010-2011 Robert Ancell.3 * Copyright (C) 2010-2011 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>4 * Author: Robert Ancell <robert.ancell@canonical.com>
4 * 5 *
@@ -15,12 +16,16 @@
15#include <string.h>16#include <string.h>
1617
17#include "user.h"18#include "user.h"
19#include "dmrc.h"
1820
19struct UserPrivate21struct UserPrivate
20{22{
21 /* Name of user */23 /* Name of user */
22 gchar *name;24 gchar *name;
2325
26 /* Accounts interface proxy */
27 GDBusProxy *proxy;
28
24 /* User ID */29 /* User ID */
25 uid_t uid;30 uid_t uid;
2631
@@ -41,6 +46,157 @@
4146
42static gchar *passwd_file = NULL;47static gchar *passwd_file = NULL;
4348
49static gboolean
50call_method (GDBusProxy *proxy, const gchar *method, GVariant *args,
51 const gchar *expected, GVariant **result)
52{
53 GVariant *answer;
54 GError *error = NULL;
55
56 if (!proxy)
57 return FALSE;
58
59 answer = g_dbus_proxy_call_sync (proxy,
60 method,
61 args,
62 G_DBUS_CALL_FLAGS_NONE,
63 -1,
64 NULL,
65 &error);
66
67 if (!answer) {
68 g_warning ("Could not call %s: %s", method, error->message);
69 g_error_free (error);
70 return FALSE;
71 }
72
73 if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected))) {
74 g_warning ("Unexpected response from %s: %s",
75 method, g_variant_get_type_string (answer));
76 g_variant_unref (answer);
77 return FALSE;
78 }
79
80 if (result)
81 *result = answer;
82 else
83 g_variant_unref (answer);
84 return TRUE;
85}
86
87static gboolean
88get_property (GDBusProxy *proxy, const gchar *property,
89 const gchar *expected, GVariant **result)
90{
91 GVariant *answer;
92
93 if (!proxy)
94 return FALSE;
95
96 answer = g_dbus_proxy_get_cached_property (proxy, property);
97
98 if (!answer) {
99 g_warning ("Could not get accounts property %s", property);
100 return FALSE;
101 }
102
103 if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected))) {
104 g_warning ("Unexpected accounts property type for %s: %s",
105 property, g_variant_get_type_string (answer));
106 g_variant_unref (answer);
107 return FALSE;
108 }
109
110 if (result)
111 *result = answer;
112 else
113 g_variant_unref (answer);
114 return TRUE;
115}
116
117static void
118save_string_to_dmrc (const gchar *username, const gchar *group,
119 const gchar *key, const gchar *value)
120{
121 GKeyFile *dmrc;
122
123 dmrc = dmrc_load (username);
124 g_key_file_set_string (dmrc, group, key, value);
125 dmrc_save (dmrc, username);
126
127 g_key_file_free (dmrc);
128}
129
130static gchar *
131get_string_from_dmrc (const gchar *username, const gchar *group,
132 const gchar *key)
133{
134 GKeyFile *dmrc;
135 gchar *value;
136
137 dmrc = dmrc_load (username);
138 value = g_key_file_get_string (dmrc, group, key, NULL);
139
140 g_key_file_free (dmrc);
141 return value;
142}
143
144static GDBusProxy *
145get_accounts_proxy_for_user (const gchar *user)
146{
147 g_return_val_if_fail (user != NULL, NULL);
148
149 GDBusProxy *proxy;
150 GError *error = NULL;
151 GVariant *result;
152 gboolean success;
153 gchar *user_path = NULL;
154
155 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
156 G_DBUS_PROXY_FLAGS_NONE,
157 NULL,
158 "org.freedesktop.Accounts",
159 "/org/freedesktop/Accounts",
160 "org.freedesktop.Accounts",
161 NULL, &error);
162
163 if (!proxy) {
164 g_warning ("Could not get accounts proxy: %s", error->message);
165 g_error_free (error);
166 return NULL;
167 }
168
169 success = call_method (proxy, "FindUserByName", g_variant_new ("(s)", user),
170 "(o)", &result);
171 g_object_unref (proxy);
172
173 if (!success)
174 return NULL;
175
176 g_variant_get (result, "(o)", &user_path);
177 g_variant_unref (result);
178
179 if (!user_path)
180 return NULL;
181
182 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
183 G_DBUS_PROXY_FLAGS_NONE,
184 NULL,
185 "org.freedesktop.Accounts",
186 user_path,
187 "org.freedesktop.Accounts.User",
188 NULL, &error);
189 g_free (user_path);
190
191 if (!proxy) {
192 g_warning ("Could not get accounts user proxy: %s", error->message);
193 g_error_free (error);
194 return NULL;
195 }
196
197 return proxy;
198}
199
44static User *200static User *
45user_from_passwd (struct passwd *user_info)201user_from_passwd (struct passwd *user_info)
46{202{
@@ -53,6 +209,7 @@
53 user->priv->gecos = g_strdup (user_info->pw_gecos);209 user->priv->gecos = g_strdup (user_info->pw_gecos);
54 user->priv->home_directory = g_strdup (user_info->pw_dir);210 user->priv->home_directory = g_strdup (user_info->pw_dir);
55 user->priv->shell = g_strdup (user_info->pw_shell);211 user->priv->shell = g_strdup (user_info->pw_shell);
212 user->priv->proxy = get_accounts_proxy_for_user (user->priv->name);
56213
57 return user;214 return user;
58}215}
@@ -236,6 +393,40 @@
236 return user->priv->shell;393 return user->priv->shell;
237}394}
238395
396void
397user_set_session (User *user, const gchar *session)
398{
399 g_return_if_fail (user != NULL);
400
401 call_method (user->priv->proxy, "SetXSession",
402 g_variant_new ("(s)", session), "()", NULL);
403
404 save_string_to_dmrc (user->priv->name, "Desktop", "Session", session);
405}
406
407gchar *
408user_get_session (User *user)
409{
410 g_return_val_if_fail (user != NULL, NULL);
411
412 GVariant *result;
413 gchar *session;
414
415 if (!get_property (user->priv->proxy, "XSession",
416 "s", &result))
417 return get_string_from_dmrc (user->priv->name, "Desktop", "Session");
418
419 g_variant_get (result, "s", &session);
420 g_variant_unref (result);
421
422 if (g_strcmp0 (session, "") == 0) {
423 g_free (session);
424 return NULL;
425 }
426
427 return session;
428}
429
239static void430static void
240user_init (User *user)431user_init (User *user)
241{432{
@@ -243,6 +434,21 @@
243}434}
244435
245static void436static void
437user_dispose (GObject *object)
438{
439 User *self;
440
441 self = USER (object);
442
443 if (self->priv->proxy) {
444 g_object_unref (self->priv->proxy);
445 self->priv->proxy = NULL;
446 }
447
448 G_OBJECT_CLASS (user_parent_class)->dispose (object);
449}
450
451static void
246user_finalize (GObject *object)452user_finalize (GObject *object)
247{453{
248 User *self;454 User *self;
@@ -262,6 +468,7 @@
262{468{
263 GObjectClass *object_class = G_OBJECT_CLASS (klass);469 GObjectClass *object_class = G_OBJECT_CLASS (klass);
264470
471 object_class->dispose = user_dispose;
265 object_class->finalize = user_finalize; 472 object_class->finalize = user_finalize;
266473
267 g_type_class_add_private (klass, sizeof (UserPrivate));474 g_type_class_add_private (klass, sizeof (UserPrivate));
268475
=== modified file 'src/user.h'
--- src/user.h 2011-06-27 11:17:39 +0000
+++ src/user.h 2011-08-22 20:39:30 +0000
@@ -1,4 +1,5 @@
1/*1/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*-
2 *
2 * Copyright (C) 2010-2011 Robert Ancell.3 * Copyright (C) 2010-2011 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>4 * Author: Robert Ancell <robert.ancell@canonical.com>
4 * 5 *
@@ -57,6 +58,10 @@
5758
58const gchar *user_get_shell (User *user);59const gchar *user_get_shell (User *user);
5960
61gchar *user_get_session (User *user);
62
63void user_set_session (User *user, const gchar *session);
64
60G_END_DECLS65G_END_DECLS
6166
62#endif /* _USER_H_ */67#endif /* _USER_H_ */

Subscribers

People subscribed via source and target branches