1/* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright 2019 Red Hat, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but 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 Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "config.h"
20
21#include "gmemorymonitor.h"
22#include "gmemorymonitordbus.h"
23#include "gioerror.h"
24#include "ginitable.h"
25#include "giomodule-priv.h"
26#include "glibintl.h"
27#include "glib/gstdio.h"
28#include "gdbusproxy.h"
29#include "gdbusnamewatching.h"
30
31#define G_MEMORY_MONITOR_DBUS_GET_INITABLE_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_INITABLE, GInitable))
32
33static void g_memory_monitor_dbus_iface_init (GMemoryMonitorInterface *iface);
34static void g_memory_monitor_dbus_initable_iface_init (GInitableIface *iface);
35
36struct _GMemoryMonitorDBus
37{
38 GObject parent_instance;
39
40 guint watch_id;
41 GDBusProxy *proxy;
42 gulong signal_id;
43};
44
45G_DEFINE_TYPE_WITH_CODE (GMemoryMonitorDBus, g_memory_monitor_dbus, G_TYPE_OBJECT,
46 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
47 g_memory_monitor_dbus_initable_iface_init)
48 G_IMPLEMENT_INTERFACE (G_TYPE_MEMORY_MONITOR,
49 g_memory_monitor_dbus_iface_init)
50 _g_io_modules_ensure_extension_points_registered ();
51 g_io_extension_point_implement (G_MEMORY_MONITOR_EXTENSION_POINT_NAME,
52 g_define_type_id,
53 "dbus",
54 30))
55
56static void
57g_memory_monitor_dbus_init (GMemoryMonitorDBus *dbus)
58{
59}
60
61static void
62proxy_signal_cb (GDBusProxy *proxy,
63 const gchar *sender_name,
64 const gchar *signal_name,
65 GVariant *parameters,
66 GMemoryMonitorDBus *dbus)
67{
68 guint8 level;
69
70 if (g_strcmp0 (str1: signal_name, str2: "LowMemoryWarning") != 0)
71 return;
72 if (parameters == NULL)
73 return;
74
75 g_variant_get (value: parameters, format_string: "(y)", &level);
76 g_signal_emit_by_name (instance: dbus, detailed_signal: "low-memory-warning", level);
77}
78
79static void
80lmm_appeared_cb (GDBusConnection *connection,
81 const gchar *name,
82 const gchar *name_owner,
83 gpointer user_data)
84{
85 GMemoryMonitorDBus *dbus = user_data;
86 GDBusProxy *proxy;
87 GError *error = NULL;
88
89 proxy = g_dbus_proxy_new_for_bus_sync (bus_type: G_BUS_TYPE_SYSTEM,
90 flags: G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
91 NULL,
92 name: "org.freedesktop.LowMemoryMonitor",
93 object_path: "/org/freedesktop/LowMemoryMonitor",
94 interface_name: "org.freedesktop.LowMemoryMonitor",
95 NULL,
96 error: &error);
97
98 if (!proxy)
99 {
100 g_debug ("Failed to create LowMemoryMonitor D-Bus proxy: %s",
101 error->message);
102 g_error_free (error);
103 return;
104 }
105
106 dbus->signal_id = g_signal_connect (G_OBJECT (proxy), "g-signal",
107 G_CALLBACK (proxy_signal_cb), dbus);
108 dbus->proxy = proxy;
109}
110
111static void
112lmm_vanished_cb (GDBusConnection *connection,
113 const gchar *name,
114 gpointer user_data)
115{
116 GMemoryMonitorDBus *dbus = user_data;
117
118 if (dbus->proxy != NULL)
119 g_clear_signal_handler (&dbus->signal_id, dbus->proxy);
120 g_clear_object (&dbus->proxy);
121}
122
123static gboolean
124g_memory_monitor_dbus_initable_init (GInitable *initable,
125 GCancellable *cancellable,
126 GError **error)
127{
128 GMemoryMonitorDBus *dbus = G_MEMORY_MONITOR_DBUS (ptr: initable);
129
130 dbus->watch_id = g_bus_watch_name (bus_type: G_BUS_TYPE_SYSTEM,
131 name: "org.freedesktop.LowMemoryMonitor",
132 flags: G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
133 name_appeared_handler: lmm_appeared_cb,
134 name_vanished_handler: lmm_vanished_cb,
135 user_data: dbus,
136 NULL);
137
138 return TRUE;
139}
140
141static void
142g_memory_monitor_dbus_finalize (GObject *object)
143{
144 GMemoryMonitorDBus *dbus = G_MEMORY_MONITOR_DBUS (ptr: object);
145
146 if (dbus->proxy != NULL)
147 g_clear_signal_handler (&dbus->signal_id, dbus->proxy);
148 g_clear_object (&dbus->proxy);
149 g_clear_handle_id (&dbus->watch_id, g_bus_unwatch_name);
150
151 G_OBJECT_CLASS (g_memory_monitor_dbus_parent_class)->finalize (object);
152}
153
154static void
155g_memory_monitor_dbus_class_init (GMemoryMonitorDBusClass *nl_class)
156{
157 GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class);
158
159 gobject_class->finalize = g_memory_monitor_dbus_finalize;
160}
161
162static void
163g_memory_monitor_dbus_iface_init (GMemoryMonitorInterface *monitor_iface)
164{
165}
166
167static void
168g_memory_monitor_dbus_initable_iface_init (GInitableIface *iface)
169{
170 iface->init = g_memory_monitor_dbus_initable_init;
171}
172

source code of gtk/subprojects/glib/gio/gmemorymonitordbus.c