~elementary-os/elementaryos/os-patch-indicator-session-trusty

« back to all changes in this revision

Viewing changes to src/backend-dbus/guest.c

  • Committer: Cody Garver
  • Date: 2014-04-03 17:08:08 UTC
  • Revision ID: cody@elementaryos.org-20140403170808-z56s93rorb1dzvmk
Initial import, version 12.10.5+14.04.20140324-0ubuntu1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2013 Canonical Ltd.
 
3
 *
 
4
 * Authors:
 
5
 *   Charles Kerr <charles.kerr@canonical.com>
 
6
 *
 
7
 * This program is free software: you can redistribute it and/or modify it
 
8
 * under the terms of the GNU General Public License version 3, as published
 
9
 * by the Free Software Foundation.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranties of
 
13
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
14
 * PURPOSE.  See the GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License along
 
17
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <glib.h>
 
21
 
 
22
#include "guest.h"
 
23
 
 
24
struct _IndicatorSessionGuestDbusPriv
 
25
{
 
26
  GCancellable * cancellable;
 
27
 
 
28
  Login1Manager * login1_manager;
 
29
  Login1Seat * login1_seat;
 
30
  DisplayManagerSeat * dm_seat;
 
31
 
 
32
  gboolean guest_is_active;
 
33
  gboolean guest_is_logged_in;
 
34
  gboolean guest_is_allowed;
 
35
};
 
36
 
 
37
typedef IndicatorSessionGuestDbusPriv priv_t;
 
38
 
 
39
G_DEFINE_TYPE (IndicatorSessionGuestDbus,
 
40
               indicator_session_guest_dbus,
 
41
               INDICATOR_TYPE_SESSION_GUEST)
 
42
 
 
43
/***
 
44
****
 
45
***/
 
46
 
 
47
static void
 
48
set_guest_is_allowed_flag (IndicatorSessionGuestDbus * self, gboolean b)
 
49
{
 
50
  priv_t * p = self->priv;
 
51
 
 
52
  if (p->guest_is_allowed != b)
 
53
    {
 
54
      p->guest_is_allowed = b;
 
55
 
 
56
      indicator_session_guest_notify_allowed (INDICATOR_SESSION_GUEST (self));
 
57
    }
 
58
}
 
59
 
 
60
static void
 
61
set_guest_is_logged_in_flag (IndicatorSessionGuestDbus * self, gboolean b)
 
62
{
 
63
  priv_t * p = self->priv;
 
64
 
 
65
  if (p->guest_is_logged_in != b)
 
66
    {
 
67
      p->guest_is_logged_in = b;
 
68
 
 
69
      indicator_session_guest_notify_logged_in (INDICATOR_SESSION_GUEST (self));
 
70
    }
 
71
}
 
72
 
 
73
static void
 
74
set_guest_is_active_flag (IndicatorSessionGuestDbus * self, gboolean b)
 
75
{
 
76
  priv_t * p = self->priv;
 
77
 
 
78
  if (p->guest_is_active != b)
 
79
    {
 
80
      p->guest_is_active = b;
 
81
 
 
82
      indicator_session_guest_notify_active (INDICATOR_SESSION_GUEST(self));
 
83
    }
 
84
}
 
85
 
 
86
/***
 
87
****
 
88
***/
 
89
 
 
90
/* walk the sessions to see if guest is logged in or active */
 
91
static void
 
92
on_login1_manager_session_list_ready (GObject      * o,
 
93
                                      GAsyncResult * res,
 
94
                                      gpointer       gself)
 
95
{
 
96
  GVariant * sessions;
 
97
  GError * err;
 
98
 
 
99
  sessions = NULL;
 
100
  err = NULL;
 
101
  login1_manager_call_list_sessions_finish (LOGIN1_MANAGER(o),
 
102
                                            &sessions,
 
103
                                            res,
 
104
                                            &err);
 
105
  if (err != NULL)
 
106
    {
 
107
      if (!g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 
108
        g_warning ("%s: %s", G_STRFUNC, err->message);
 
109
 
 
110
      g_error_free (err);
 
111
    }
 
112
  else
 
113
    {
 
114
      const gchar * const current_seat_id = g_getenv ("XDG_SEAT");
 
115
      const gchar * const current_session_id = g_getenv ("XDG_SESSION_ID");
 
116
      gboolean is_logged_in = FALSE;
 
117
      gboolean is_active = FALSE;
 
118
      const gchar * session_id = NULL;
 
119
      guint32 uid = 0;
 
120
      const gchar * user_name = NULL;
 
121
      const gchar * seat_id = NULL;
 
122
      GVariantIter iter;
 
123
 
 
124
      g_variant_iter_init (&iter, sessions);
 
125
      while (g_variant_iter_loop (&iter, "(&su&s&so)", &session_id,
 
126
                                                        &uid,
 
127
                                                        &user_name,
 
128
                                                        &seat_id,
 
129
                                                        NULL))
 
130
        {
 
131
          gboolean is_current_session;
 
132
          gboolean is_guest;
 
133
 
 
134
          is_current_session = !g_strcmp0 (current_seat_id, seat_id)
 
135
                            && !g_strcmp0 (current_session_id, session_id);
 
136
 
 
137
          is_guest = g_str_has_prefix (user_name, "guest-")
 
138
                  && (uid < 1000);
 
139
 
 
140
          if (is_guest)
 
141
            {
 
142
              is_logged_in = TRUE;
 
143
 
 
144
              is_active = is_current_session;
 
145
            }
 
146
        }
 
147
 
 
148
      set_guest_is_logged_in_flag (gself, is_logged_in);
 
149
      set_guest_is_active_flag (gself, is_active);
 
150
 
 
151
      g_variant_unref (sessions);
 
152
    }
 
153
}
 
154
 
 
155
static void
 
156
update_session_list (IndicatorSessionGuestDbus * self)
 
157
{
 
158
  priv_t * p = self->priv;
 
159
 
 
160
  if (p->login1_manager != NULL)
 
161
    {
 
162
      login1_manager_call_list_sessions (p->login1_manager,
 
163
                                         p->cancellable,
 
164
                                         on_login1_manager_session_list_ready,
 
165
                                         self);
 
166
    }
 
167
}
 
168
 
 
169
static void
 
170
set_login1_manager (IndicatorSessionGuestDbus * self,
 
171
                    Login1Manager             * login1_manager)
 
172
{
 
173
  priv_t * p = self->priv;
 
174
 
 
175
  if (p->login1_manager != NULL)
 
176
    {
 
177
      g_signal_handlers_disconnect_by_data (p->login1_manager, self);
 
178
 
 
179
      g_clear_object (&p->login1_manager);
 
180
    }
 
181
 
 
182
  if (login1_manager != NULL)
 
183
    {
 
184
      p->login1_manager = g_object_ref (login1_manager);
 
185
 
 
186
      g_signal_connect_swapped (login1_manager, "session-new",
 
187
                                G_CALLBACK(update_session_list), self);
 
188
      g_signal_connect_swapped (login1_manager, "session-removed",
 
189
                                G_CALLBACK(update_session_list), self);
 
190
      update_session_list (self);
 
191
    }
 
192
}
 
193
 
 
194
static void
 
195
set_login1_seat (IndicatorSessionGuestDbus * self,
 
196
                 Login1Seat                * login1_seat)
 
197
{
 
198
  priv_t * p = self->priv;
 
199
 
 
200
  if (p->login1_seat != NULL)
 
201
    {
 
202
      g_signal_handlers_disconnect_by_data (p->login1_seat, self);
 
203
      g_clear_object (&p->login1_seat);
 
204
    }
 
205
 
 
206
  if (login1_seat != NULL)
 
207
    {
 
208
      p->login1_seat = g_object_ref (login1_seat);
 
209
 
 
210
      g_signal_connect_swapped (login1_seat, "notify::active-session",
 
211
                                G_CALLBACK(update_session_list), self);
 
212
      update_session_list (self);
 
213
    }
 
214
}
 
215
 
 
216
/***
 
217
****
 
218
***/
 
219
 
 
220
static void
 
221
on_switch_to_guest_done (GObject      * o,
 
222
                         GAsyncResult * res,
 
223
                         gpointer       unused G_GNUC_UNUSED)
 
224
{
 
225
  GError * err;
 
226
 
 
227
  err = NULL;
 
228
  display_manager_seat_call_switch_to_guest_finish (DISPLAY_MANAGER_SEAT(o),
 
229
                                                    res,
 
230
                                                    &err);
 
231
  if (err != NULL)
 
232
    {
 
233
      if (!g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 
234
        g_warning ("%s %s: %s", G_STRLOC, G_STRFUNC, err->message);
 
235
 
 
236
      g_error_free (err);
 
237
    }
 
238
}
 
239
 
 
240
static void
 
241
my_switch_to_guest (IndicatorSessionGuest * guest)
 
242
{
 
243
  IndicatorSessionGuestDbus * self = INDICATOR_SESSION_GUEST_DBUS(guest);
 
244
 
 
245
  g_return_if_fail (self != NULL);
 
246
  g_return_if_fail (self->priv->dm_seat != NULL);
 
247
 
 
248
  display_manager_seat_call_switch_to_guest (self->priv->dm_seat,
 
249
                                             "",
 
250
                                             self->priv->cancellable,
 
251
                                             on_switch_to_guest_done,
 
252
                                             self);
 
253
}
 
254
 
 
255
static void
 
256
on_notify_has_guest_account (DisplayManagerSeat        * dm_seat,
 
257
                             GParamSpec                * pspec G_GNUC_UNUSED,
 
258
                             IndicatorSessionGuestDbus * self)
 
259
{
 
260
  gboolean guest_exists = display_manager_seat_get_has_guest_account (dm_seat);
 
261
  set_guest_is_allowed_flag (self, guest_exists);
 
262
}
 
263
 
 
264
static void
 
265
set_display_manager_seat (IndicatorSessionGuestDbus * self,
 
266
                          DisplayManagerSeat        * dm_seat)
 
267
{
 
268
  priv_t * p = self->priv;
 
269
 
 
270
  if (p->dm_seat != NULL)
 
271
    {
 
272
      g_signal_handlers_disconnect_by_data (p->dm_seat, self);
 
273
 
 
274
      g_clear_object (&p->dm_seat);
 
275
    }
 
276
 
 
277
  if (dm_seat != NULL)
 
278
    {
 
279
      p->dm_seat = g_object_ref (dm_seat);
 
280
 
 
281
      g_signal_connect (dm_seat, "notify::has-guest-account",
 
282
                        G_CALLBACK(on_notify_has_guest_account), self);
 
283
      on_notify_has_guest_account (dm_seat, NULL, self);
 
284
    }
 
285
}
 
286
 
 
287
/***
 
288
****  IndiatorSessionGuest Virtual Functions
 
289
***/
 
290
 
 
291
static gboolean
 
292
my_is_allowed (IndicatorSessionGuest * self)
 
293
{
 
294
  g_return_val_if_fail (INDICATOR_IS_SESSION_GUEST_DBUS(self), FALSE);
 
295
 
 
296
  return INDICATOR_SESSION_GUEST_DBUS(self)->priv->guest_is_allowed;
 
297
}
 
298
 
 
299
static gboolean
 
300
my_is_logged_in (IndicatorSessionGuest * self)
 
301
{
 
302
  g_return_val_if_fail (INDICATOR_IS_SESSION_GUEST_DBUS(self), FALSE);
 
303
 
 
304
  return INDICATOR_SESSION_GUEST_DBUS(self)->priv->guest_is_logged_in;
 
305
}
 
306
 
 
307
static gboolean
 
308
my_is_active (IndicatorSessionGuest * self)
 
309
{
 
310
  g_return_val_if_fail (INDICATOR_IS_SESSION_GUEST_DBUS(self), FALSE);
 
311
 
 
312
  return INDICATOR_SESSION_GUEST_DBUS(self)->priv->guest_is_active;
 
313
}
 
314
 
 
315
/***
 
316
****  GObject Virtual Functions
 
317
***/
 
318
 
 
319
static void
 
320
my_dispose (GObject * o)
 
321
{
 
322
  IndicatorSessionGuestDbus * self = INDICATOR_SESSION_GUEST_DBUS (o);
 
323
 
 
324
  if (self->priv->cancellable != NULL)
 
325
    {
 
326
      g_cancellable_cancel (self->priv->cancellable);
 
327
      g_clear_object (&self->priv->cancellable);
 
328
    }
 
329
 
 
330
  set_login1_seat (self, NULL);
 
331
  set_login1_manager (self, NULL);
 
332
  set_display_manager_seat (self, NULL);
 
333
 
 
334
  G_OBJECT_CLASS (indicator_session_guest_dbus_parent_class)->dispose (o);
 
335
}
 
336
 
 
337
/***
 
338
****  Instantiation
 
339
***/
 
340
 
 
341
static void
 
342
indicator_session_guest_dbus_class_init (IndicatorSessionGuestDbusClass * klass)
 
343
{
 
344
  GObjectClass * object_class;
 
345
  IndicatorSessionGuestClass * guest_class;
 
346
 
 
347
  object_class = G_OBJECT_CLASS (klass);
 
348
  object_class->dispose = my_dispose;
 
349
 
 
350
  guest_class = INDICATOR_SESSION_GUEST_CLASS (klass);
 
351
  guest_class->is_allowed = my_is_allowed;
 
352
  guest_class->is_logged_in = my_is_logged_in;
 
353
  guest_class->is_active = my_is_active;
 
354
  guest_class->switch_to_guest = my_switch_to_guest;
 
355
 
 
356
  g_type_class_add_private (klass, sizeof (IndicatorSessionGuestDbusPriv));
 
357
}
 
358
 
 
359
static void
 
360
indicator_session_guest_dbus_init (IndicatorSessionGuestDbus * self)
 
361
{
 
362
  priv_t * p;
 
363
 
 
364
  p = G_TYPE_INSTANCE_GET_PRIVATE (self,
 
365
                                   INDICATOR_TYPE_SESSION_GUEST_DBUS,
 
366
                                   IndicatorSessionGuestDbusPriv);
 
367
  p->cancellable = g_cancellable_new ();
 
368
  self->priv = p;
 
369
}
 
370
 
 
371
/***
 
372
****  Public
 
373
***/
 
374
 
 
375
IndicatorSessionGuest *
 
376
indicator_session_guest_dbus_new (void)
 
377
{
 
378
  gpointer o = g_object_new (INDICATOR_TYPE_SESSION_GUEST_DBUS, NULL);
 
379
 
 
380
  return INDICATOR_SESSION_GUEST (o);
 
381
}
 
382
 
 
383
void
 
384
indicator_session_guest_dbus_set_proxies (IndicatorSessionGuestDbus * self,
 
385
                                          Login1Manager             * login1_manager,
 
386
                                          Login1Seat                * login1_seat,
 
387
                                          DisplayManagerSeat        * dm_seat)
 
388
{
 
389
  g_return_if_fail (INDICATOR_IS_SESSION_GUEST_DBUS(self));
 
390
 
 
391
  set_login1_manager (self, login1_manager);
 
392
  set_login1_seat (self, login1_seat);
 
393
  set_display_manager_seat (self, dm_seat);
 
394
}