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