1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2008 Red Hat, Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA
18 * 02110-1335, USA.
19 */
20
21 #include "config.h"
22
23 #include <fcntl.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <unistd.h>
28
29 #include "csm-inhibitor.h"
30 #include "csm-exported-inhibitor.h"
31
32 #include "csm-util.h"
33
34 static guint32 inhibitor_serial = 1;
35
36 #define CSM_INHIBITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSM_TYPE_INHIBITOR, CsmInhibitorPrivate))
37
38 struct CsmInhibitorPrivate
39 {
40 char *id;
41 char *bus_name;
42 char *app_id;
43 char *client_id;
44 char *reason;
45 guint flags;
46 guint toplevel_xid;
47 guint cookie;
48 GDBusConnection *connection;
49 CsmExportedInhibitor *skeleton;
50 };
51
52 enum {
53 PROP_0,
54 PROP_BUS_NAME,
55 PROP_REASON,
56 PROP_APP_ID,
57 PROP_CLIENT_ID,
58 PROP_FLAGS,
59 PROP_TOPLEVEL_XID,
60 PROP_COOKIE
61 };
62
63 G_DEFINE_TYPE (CsmInhibitor, csm_inhibitor, G_TYPE_OBJECT)
64
65 #define CSM_INHIBITOR_DBUS_IFACE "org.gnome.SessionManager.Inhibitor"
66
67 static const GDBusErrorEntry csm_inhibitor_error_entries[] = {
68 { CSM_INHIBITOR_ERROR_GENERAL, CSM_INHIBITOR_DBUS_IFACE ".GeneralError" },
69 { CSM_INHIBITOR_ERROR_NOT_SET, CSM_INHIBITOR_DBUS_IFACE ".NotSet" }
70 };
71
72 GQuark
csm_inhibitor_error_quark(void)73 csm_inhibitor_error_quark (void)
74 {
75 static volatile gsize quark_volatile = 0;
76
77 g_dbus_error_register_error_domain ("csm_inhibitor_error",
78 &quark_volatile,
79 csm_inhibitor_error_entries,
80 G_N_ELEMENTS (csm_inhibitor_error_entries));
81
82 return quark_volatile;
83 }
84
85 static gboolean
csm_inhibitor_get_app_id(CsmExportedInhibitor * skeleton,GDBusMethodInvocation * invocation,CsmInhibitor * inhibitor)86 csm_inhibitor_get_app_id (CsmExportedInhibitor *skeleton,
87 GDBusMethodInvocation *invocation,
88 CsmInhibitor *inhibitor)
89 {
90 const gchar *id;
91
92 if (inhibitor->priv->app_id != NULL) {
93 id = inhibitor->priv->app_id;
94 } else {
95 id = "";
96 }
97
98 csm_exported_inhibitor_complete_get_app_id (skeleton, invocation, id);
99
100 return TRUE;
101 }
102
103 static gboolean
csm_inhibitor_get_client_id(CsmExportedInhibitor * skeleton,GDBusMethodInvocation * invocation,CsmInhibitor * inhibitor)104 csm_inhibitor_get_client_id (CsmExportedInhibitor *skeleton,
105 GDBusMethodInvocation *invocation,
106 CsmInhibitor *inhibitor)
107 {
108 /* object paths are not allowed to be NULL or blank */
109 if (IS_STRING_EMPTY (inhibitor->priv->client_id)) {
110 g_dbus_method_invocation_return_error (invocation,
111 CSM_INHIBITOR_ERROR,
112 CSM_INHIBITOR_ERROR_NOT_SET,
113 "Value is not set");
114
115 return TRUE;
116 }
117
118 csm_exported_inhibitor_complete_get_client_id (skeleton, invocation, inhibitor->priv->client_id);
119
120 g_debug ("CsmInhibitor: getting client-id = '%s'", inhibitor->priv->client_id);
121
122 return TRUE;
123 }
124
125 static gboolean
csm_inhibitor_get_reason(CsmExportedInhibitor * skeleton,GDBusMethodInvocation * invocation,CsmInhibitor * inhibitor)126 csm_inhibitor_get_reason (CsmExportedInhibitor *skeleton,
127 GDBusMethodInvocation *invocation,
128 CsmInhibitor *inhibitor)
129 {
130 const gchar *reason;
131
132 if (inhibitor->priv->reason != NULL) {
133 reason = inhibitor->priv->reason;
134 } else {
135 reason = "";
136 }
137
138 csm_exported_inhibitor_complete_get_reason (skeleton, invocation, reason);
139
140 return TRUE;
141 }
142
143 static gboolean
csm_inhibitor_get_flags(CsmExportedInhibitor * skeleton,GDBusMethodInvocation * invocation,CsmInhibitor * inhibitor)144 csm_inhibitor_get_flags (CsmExportedInhibitor *skeleton,
145 GDBusMethodInvocation *invocation,
146 CsmInhibitor *inhibitor)
147 {
148 csm_exported_inhibitor_complete_get_flags (skeleton, invocation, inhibitor->priv->flags);
149
150 return TRUE;
151 }
152
153 static gboolean
csm_inhibitor_get_toplevel_xid(CsmExportedInhibitor * skeleton,GDBusMethodInvocation * invocation,CsmInhibitor * inhibitor)154 csm_inhibitor_get_toplevel_xid (CsmExportedInhibitor *skeleton,
155 GDBusMethodInvocation *invocation,
156 CsmInhibitor *inhibitor)
157 {
158
159 csm_exported_inhibitor_complete_get_toplevel_xid (skeleton, invocation, inhibitor->priv->toplevel_xid);
160
161 return TRUE;
162 }
163
164 static guint32
get_next_inhibitor_serial(void)165 get_next_inhibitor_serial (void)
166 {
167 guint32 serial;
168
169 serial = inhibitor_serial++;
170
171 if ((gint32)inhibitor_serial < 0) {
172 inhibitor_serial = 1;
173 }
174
175 return serial;
176 }
177
178 static gboolean
register_inhibitor(CsmInhibitor * inhibitor)179 register_inhibitor (CsmInhibitor *inhibitor)
180 {
181 GError *error;
182 CsmExportedInhibitor *skeleton;
183
184 error = NULL;
185 inhibitor->priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
186
187 if (error != NULL) {
188 g_critical ("error getting session bus: %s", error->message);
189 g_error_free (error);
190 return FALSE;
191 }
192
193 skeleton = csm_exported_inhibitor_skeleton_new ();
194 inhibitor->priv->skeleton = skeleton;
195 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
196 inhibitor->priv->connection,
197 inhibitor->priv->id, &error);
198
199 if (error != NULL) {
200 g_critical ("error exporting inhibitor on session bus: %s", error->message);
201 g_error_free (error);
202 return FALSE;
203 }
204
205 g_signal_connect (skeleton, "handle-get-app-id",
206 G_CALLBACK (csm_inhibitor_get_app_id), inhibitor);
207 g_signal_connect (skeleton, "handle-get-client-id",
208 G_CALLBACK (csm_inhibitor_get_client_id), inhibitor);
209 g_signal_connect (skeleton, "handle-get-flags",
210 G_CALLBACK (csm_inhibitor_get_flags), inhibitor);
211 g_signal_connect (skeleton, "handle-get-reason",
212 G_CALLBACK (csm_inhibitor_get_reason), inhibitor);
213 g_signal_connect (skeleton, "handle-get-toplevel-xid",
214 G_CALLBACK (csm_inhibitor_get_toplevel_xid), inhibitor);
215
216 return TRUE;
217 }
218
219 static GObject *
csm_inhibitor_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_properties)220 csm_inhibitor_constructor (GType type,
221 guint n_construct_properties,
222 GObjectConstructParam *construct_properties)
223 {
224 CsmInhibitor *inhibitor;
225 gboolean res;
226
227 inhibitor = CSM_INHIBITOR (G_OBJECT_CLASS (csm_inhibitor_parent_class)->constructor (type,
228 n_construct_properties,
229 construct_properties));
230
231 g_free (inhibitor->priv->id);
232 inhibitor->priv->id = g_strdup_printf ("/org/gnome/SessionManager/Inhibitor%u", get_next_inhibitor_serial ());
233 res = register_inhibitor (inhibitor);
234 if (! res) {
235 g_warning ("Unable to register inhibitor with session bus");
236 }
237
238 return G_OBJECT (inhibitor);
239 }
240
241 static void
csm_inhibitor_init(CsmInhibitor * inhibitor)242 csm_inhibitor_init (CsmInhibitor *inhibitor)
243 {
244 inhibitor->priv = CSM_INHIBITOR_GET_PRIVATE (inhibitor);
245 }
246
247 static void
csm_inhibitor_set_bus_name(CsmInhibitor * inhibitor,const char * bus_name)248 csm_inhibitor_set_bus_name (CsmInhibitor *inhibitor,
249 const char *bus_name)
250 {
251 g_return_if_fail (CSM_IS_INHIBITOR (inhibitor));
252
253 g_free (inhibitor->priv->bus_name);
254
255 if (bus_name != NULL) {
256 inhibitor->priv->bus_name = g_strdup (bus_name);
257 } else {
258 inhibitor->priv->bus_name = g_strdup ("");
259 }
260 g_object_notify (G_OBJECT (inhibitor), "bus-name");
261 }
262
263 static void
csm_inhibitor_set_app_id(CsmInhibitor * inhibitor,const char * app_id)264 csm_inhibitor_set_app_id (CsmInhibitor *inhibitor,
265 const char *app_id)
266 {
267 g_return_if_fail (CSM_IS_INHIBITOR (inhibitor));
268
269 g_free (inhibitor->priv->app_id);
270
271 inhibitor->priv->app_id = g_strdup (app_id);
272 g_object_notify (G_OBJECT (inhibitor), "app-id");
273 }
274
275 static void
csm_inhibitor_set_client_id(CsmInhibitor * inhibitor,const char * client_id)276 csm_inhibitor_set_client_id (CsmInhibitor *inhibitor,
277 const char *client_id)
278 {
279 g_return_if_fail (CSM_IS_INHIBITOR (inhibitor));
280
281 g_free (inhibitor->priv->client_id);
282
283 g_debug ("CsmInhibitor: setting client-id = %s", client_id);
284
285 if (client_id != NULL) {
286 inhibitor->priv->client_id = g_strdup (client_id);
287 } else {
288 inhibitor->priv->client_id = g_strdup ("");
289 }
290 g_object_notify (G_OBJECT (inhibitor), "client-id");
291 }
292
293 static void
csm_inhibitor_set_reason(CsmInhibitor * inhibitor,const char * reason)294 csm_inhibitor_set_reason (CsmInhibitor *inhibitor,
295 const char *reason)
296 {
297 g_return_if_fail (CSM_IS_INHIBITOR (inhibitor));
298
299 g_free (inhibitor->priv->reason);
300
301 if (reason != NULL) {
302 inhibitor->priv->reason = g_strdup (reason);
303 } else {
304 inhibitor->priv->reason = g_strdup ("");
305 }
306 g_object_notify (G_OBJECT (inhibitor), "reason");
307 }
308
309 static void
csm_inhibitor_set_cookie(CsmInhibitor * inhibitor,guint cookie)310 csm_inhibitor_set_cookie (CsmInhibitor *inhibitor,
311 guint cookie)
312 {
313 g_return_if_fail (CSM_IS_INHIBITOR (inhibitor));
314
315 if (inhibitor->priv->cookie != cookie) {
316 inhibitor->priv->cookie = cookie;
317 g_object_notify (G_OBJECT (inhibitor), "cookie");
318 }
319 }
320
321 static void
csm_inhibitor_set_flags(CsmInhibitor * inhibitor,guint flags)322 csm_inhibitor_set_flags (CsmInhibitor *inhibitor,
323 guint flags)
324 {
325 g_return_if_fail (CSM_IS_INHIBITOR (inhibitor));
326
327 if (inhibitor->priv->flags != flags) {
328 inhibitor->priv->flags = flags;
329 g_object_notify (G_OBJECT (inhibitor), "flags");
330 }
331 }
332
333 static void
csm_inhibitor_set_toplevel_xid(CsmInhibitor * inhibitor,guint xid)334 csm_inhibitor_set_toplevel_xid (CsmInhibitor *inhibitor,
335 guint xid)
336 {
337 g_return_if_fail (CSM_IS_INHIBITOR (inhibitor));
338
339 if (inhibitor->priv->toplevel_xid != xid) {
340 inhibitor->priv->toplevel_xid = xid;
341 g_object_notify (G_OBJECT (inhibitor), "toplevel-xid");
342 }
343 }
344
345 const char *
csm_inhibitor_peek_bus_name(CsmInhibitor * inhibitor)346 csm_inhibitor_peek_bus_name (CsmInhibitor *inhibitor)
347 {
348 g_return_val_if_fail (CSM_IS_INHIBITOR (inhibitor), NULL);
349
350 return inhibitor->priv->bus_name;
351 }
352
353 const char *
csm_inhibitor_peek_id(CsmInhibitor * inhibitor)354 csm_inhibitor_peek_id (CsmInhibitor *inhibitor)
355 {
356 g_return_val_if_fail (CSM_IS_INHIBITOR (inhibitor), NULL);
357
358 return inhibitor->priv->id;
359 }
360
361 const char *
csm_inhibitor_peek_app_id(CsmInhibitor * inhibitor)362 csm_inhibitor_peek_app_id (CsmInhibitor *inhibitor)
363 {
364 g_return_val_if_fail (CSM_IS_INHIBITOR (inhibitor), NULL);
365
366 return inhibitor->priv->app_id;
367 }
368
369 const char *
csm_inhibitor_peek_client_id(CsmInhibitor * inhibitor)370 csm_inhibitor_peek_client_id (CsmInhibitor *inhibitor)
371 {
372 g_return_val_if_fail (CSM_IS_INHIBITOR (inhibitor), NULL);
373
374 return inhibitor->priv->client_id;
375 }
376
377 const char *
csm_inhibitor_peek_reason(CsmInhibitor * inhibitor)378 csm_inhibitor_peek_reason (CsmInhibitor *inhibitor)
379 {
380 g_return_val_if_fail (CSM_IS_INHIBITOR (inhibitor), NULL);
381
382 return inhibitor->priv->reason;
383 }
384
385 guint
csm_inhibitor_peek_flags(CsmInhibitor * inhibitor)386 csm_inhibitor_peek_flags (CsmInhibitor *inhibitor)
387 {
388 g_return_val_if_fail (CSM_IS_INHIBITOR (inhibitor), 0);
389
390 return inhibitor->priv->flags;
391 }
392
393 guint
csm_inhibitor_peek_toplevel_xid(CsmInhibitor * inhibitor)394 csm_inhibitor_peek_toplevel_xid (CsmInhibitor *inhibitor)
395 {
396 g_return_val_if_fail (CSM_IS_INHIBITOR (inhibitor), 0);
397
398 return inhibitor->priv->toplevel_xid;
399 }
400
401 guint
csm_inhibitor_peek_cookie(CsmInhibitor * inhibitor)402 csm_inhibitor_peek_cookie (CsmInhibitor *inhibitor)
403 {
404 g_return_val_if_fail (CSM_IS_INHIBITOR (inhibitor), 0);
405
406 return inhibitor->priv->cookie;
407 }
408
409 static void
csm_inhibitor_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)410 csm_inhibitor_set_property (GObject *object,
411 guint prop_id,
412 const GValue *value,
413 GParamSpec *pspec)
414 {
415 CsmInhibitor *self;
416
417 self = CSM_INHIBITOR (object);
418
419 switch (prop_id) {
420 case PROP_BUS_NAME:
421 csm_inhibitor_set_bus_name (self, g_value_get_string (value));
422 break;
423 case PROP_APP_ID:
424 csm_inhibitor_set_app_id (self, g_value_get_string (value));
425 break;
426 case PROP_CLIENT_ID:
427 csm_inhibitor_set_client_id (self, g_value_get_string (value));
428 break;
429 case PROP_REASON:
430 csm_inhibitor_set_reason (self, g_value_get_string (value));
431 break;
432 case PROP_FLAGS:
433 csm_inhibitor_set_flags (self, g_value_get_uint (value));
434 break;
435 case PROP_COOKIE:
436 csm_inhibitor_set_cookie (self, g_value_get_uint (value));
437 break;
438 case PROP_TOPLEVEL_XID:
439 csm_inhibitor_set_toplevel_xid (self, g_value_get_uint (value));
440 break;
441 default:
442 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
443 break;
444 }
445 }
446
447 static void
csm_inhibitor_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)448 csm_inhibitor_get_property (GObject *object,
449 guint prop_id,
450 GValue *value,
451 GParamSpec *pspec)
452 {
453 CsmInhibitor *self;
454
455 self = CSM_INHIBITOR (object);
456
457 switch (prop_id) {
458 case PROP_BUS_NAME:
459 g_value_set_string (value, self->priv->bus_name);
460 break;
461 case PROP_APP_ID:
462 g_value_set_string (value, self->priv->app_id);
463 break;
464 case PROP_CLIENT_ID:
465 g_value_set_string (value, self->priv->client_id);
466 break;
467 case PROP_REASON:
468 g_value_set_string (value, self->priv->reason);
469 break;
470 case PROP_FLAGS:
471 g_value_set_uint (value, self->priv->flags);
472 break;
473 case PROP_COOKIE:
474 g_value_set_uint (value, self->priv->cookie);
475 break;
476 case PROP_TOPLEVEL_XID:
477 g_value_set_uint (value, self->priv->toplevel_xid);
478 break;
479 default:
480 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
481 break;
482 }
483 }
484
485 static void
csm_inhibitor_finalize(GObject * object)486 csm_inhibitor_finalize (GObject *object)
487 {
488 CsmInhibitor *inhibitor = (CsmInhibitor *) object;
489
490 g_free (inhibitor->priv->id);
491 g_free (inhibitor->priv->bus_name);
492 g_free (inhibitor->priv->app_id);
493 g_free (inhibitor->priv->client_id);
494 g_free (inhibitor->priv->reason);
495
496 if (inhibitor->priv->skeleton != NULL) {
497 g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (inhibitor->priv->skeleton),
498 inhibitor->priv->connection);
499 g_clear_object (&inhibitor->priv->skeleton);
500 }
501
502 g_clear_object (&inhibitor->priv->connection);
503
504 G_OBJECT_CLASS (csm_inhibitor_parent_class)->finalize (object);
505 }
506
507 static void
csm_inhibitor_class_init(CsmInhibitorClass * klass)508 csm_inhibitor_class_init (CsmInhibitorClass *klass)
509 {
510 GObjectClass *object_class = G_OBJECT_CLASS (klass);
511
512 object_class->finalize = csm_inhibitor_finalize;
513 object_class->constructor = csm_inhibitor_constructor;
514 object_class->get_property = csm_inhibitor_get_property;
515 object_class->set_property = csm_inhibitor_set_property;
516
517 g_object_class_install_property (object_class,
518 PROP_BUS_NAME,
519 g_param_spec_string ("bus-name",
520 "bus-name",
521 "bus-name",
522 "",
523 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
524 g_object_class_install_property (object_class,
525 PROP_APP_ID,
526 g_param_spec_string ("app-id",
527 "app-id",
528 "app-id",
529 "",
530 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
531 g_object_class_install_property (object_class,
532 PROP_CLIENT_ID,
533 g_param_spec_string ("client-id",
534 "client-id",
535 "client-id",
536 "",
537 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
538 g_object_class_install_property (object_class,
539 PROP_REASON,
540 g_param_spec_string ("reason",
541 "reason",
542 "reason",
543 "",
544 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
545 g_object_class_install_property (object_class,
546 PROP_FLAGS,
547 g_param_spec_uint ("flags",
548 "flags",
549 "flags",
550 0,
551 G_MAXINT,
552 0,
553 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
554 g_object_class_install_property (object_class,
555 PROP_TOPLEVEL_XID,
556 g_param_spec_uint ("toplevel-xid",
557 "toplevel-xid",
558 "toplevel-xid",
559 0,
560 G_MAXINT,
561 0,
562 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
563 g_object_class_install_property (object_class,
564 PROP_COOKIE,
565 g_param_spec_uint ("cookie",
566 "cookie",
567 "cookie",
568 0,
569 G_MAXINT,
570 0,
571 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
572
573 g_type_class_add_private (klass, sizeof (CsmInhibitorPrivate));
574 }
575
576 CsmInhibitor *
csm_inhibitor_new(const char * app_id,guint toplevel_xid,guint flags,const char * reason,const char * bus_name,guint cookie)577 csm_inhibitor_new (const char *app_id,
578 guint toplevel_xid,
579 guint flags,
580 const char *reason,
581 const char *bus_name,
582 guint cookie)
583 {
584 CsmInhibitor *inhibitor;
585
586 inhibitor = g_object_new (CSM_TYPE_INHIBITOR,
587 "app-id", app_id,
588 "reason", reason,
589 "bus-name", bus_name,
590 "flags", flags,
591 "toplevel-xid", toplevel_xid,
592 "cookie", cookie,
593 NULL);
594
595 return inhibitor;
596 }
597
598 CsmInhibitor *
csm_inhibitor_new_for_client(const char * client_id,const char * app_id,guint flags,const char * reason,const char * bus_name,guint cookie)599 csm_inhibitor_new_for_client (const char *client_id,
600 const char *app_id,
601 guint flags,
602 const char *reason,
603 const char *bus_name,
604 guint cookie)
605 {
606 CsmInhibitor *inhibitor;
607
608 inhibitor = g_object_new (CSM_TYPE_INHIBITOR,
609 "client-id", client_id,
610 "app-id", app_id,
611 "reason", reason,
612 "bus-name", bus_name,
613 "flags", flags,
614 "cookie", cookie,
615 NULL);
616
617 return inhibitor;
618 }
619