diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml index 2986f9d64..76057e897 100644 --- a/docs/reference/gio/gio-docs.xml +++ b/docs/reference/gio/gio-docs.xml @@ -232,6 +232,8 @@ + + diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt index 137737260..73dd24892 100644 --- a/docs/reference/gio/gio-sections-common.txt +++ b/docs/reference/gio/gio-sections-common.txt @@ -4205,6 +4205,36 @@ G_DBUS_OBJECT_MANAGER_SERVER_GET_CLASS GDBusObjectManagerServerPrivate +
+gdebugcontroller +GDebugController +GDebugController +GDebugControllerInterface +G_DEBUG_CONTROLLER_EXTENSION_POINT_NAME +g_debug_controller_dup_default +g_debug_controller_get_debug_enabled +g_debug_controller_set_debug_enabled + +g_debug_controller_get_type +G_TYPE_DEBUG_CONTROLLER +G_DEBUG_CONTROLLER +G_IS_DEBUG_CONTROLLER +G_DEBUG_CONTROLLER_GET_INTERFACE +
+ +
+gdebugcontrollerdbus +GDebugControllerDBus +GDebugControllerDBus +g_debug_controller_dbus_new + +g_debug_controller_dbus_get_type +G_TYPE_DEBUG_CONTROLLER_DBUS +G_DEBUG_CONTROLLER_DBUS +G_IS_DEBUG_CONTROLLER_DBUS +G_DEBUG_CONTROLLER_DBUS_GET_CLASS +
+
gmemorymonitor GMemoryMonitor diff --git a/gio/gdebugcontroller.c b/gio/gdebugcontroller.c new file mode 100644 index 000000000..155c30445 --- /dev/null +++ b/gio/gdebugcontroller.c @@ -0,0 +1,132 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright © 2021 Endless OS Foundation, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "config.h" +#include "glib.h" +#include "glibintl.h" + +#include "gdebugcontroller.h" +#include "ginitable.h" +#include "giomodule-priv.h" + +/** + * SECTION:gdebugcontroller + * @title: GDebugController + * @short_description: Debugging controller + * @include: gio/gio.h + * + * #GDebugController is an interface to expose control of debugging features and + * debug output. + * + * It is implemented on Linux using #GDebugControllerDBus, which exposes a D-Bus + * interface to allow authenticated peers to control debug features in this + * process. + * + * Whether debug output is enabled is exposed as + * #GDebugController:debug-enabled. This controls g_log_set_debug_enabled() by + * default. Application code may connect to the #GObject::notify signal for it + * to control other parts of its debug infrastructure as necessary. + * + * Since: 2.72 + */ + +G_DEFINE_INTERFACE_WITH_CODE (GDebugController, g_debug_controller, G_TYPE_OBJECT, + g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_INITABLE)) + +/** + * g_debug_controller_dup_default: + * + * Gets a reference to the default #GDebugController for the system. + * + * Returns: (not nullable) (transfer full): a new reference to the default #GDebugController + * + * Since: 2.72 + */ +GDebugController * +g_debug_controller_dup_default (void) +{ + return g_object_ref (_g_io_module_get_default (G_DEBUG_CONTROLLER_EXTENSION_POINT_NAME, + "GIO_USE_DEBUG_CONTROLLER", + NULL)); +} + +static void +g_debug_controller_default_init (GDebugControllerInterface *iface) +{ + /** + * GDebugController:debug-enabled: + * + * %TRUE if debug output should be exposed (for example by forwarding it to + * the journal), %FALSE otherwise. + * + * Since: 2.72 + */ + g_object_interface_install_property (iface, + g_param_spec_boolean ("debug-enabled", + "Debug Enabled", + "Whether to expose debug output", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY)); +} + +/** + * g_debug_controller_get_debug_enabled: + * @self: a #GDebugController + * + * Get the value of #GDebugController:debug-enabled. + * + * Returns: %TRUE if debug output should be exposed, %FALSE otherwise + * Since: 2.72 + */ +gboolean +g_debug_controller_get_debug_enabled (GDebugController *self) +{ + gboolean enabled; + + g_return_val_if_fail (G_IS_DEBUG_CONTROLLER (self), FALSE); + + g_object_get (G_OBJECT (self), + "debug-enabled", &enabled, + NULL); + + return enabled; +} + +/** + * g_debug_controller_set_debug_enabled: + * @self: a #GDebugController + * @debug_enabled: %TRUE if debug output should be exposed, %FALSE otherwise + * + * Set the value of #GDebugController:debug-enabled. + * + * Since: 2.72 + */ +void +g_debug_controller_set_debug_enabled (GDebugController *self, + gboolean debug_enabled) +{ + g_return_if_fail (G_IS_DEBUG_CONTROLLER (self)); + + g_object_set (G_OBJECT (self), + "debug-enabled", debug_enabled, + NULL); +} diff --git a/gio/gdebugcontroller.h b/gio/gdebugcontroller.h new file mode 100644 index 000000000..59b1ede2b --- /dev/null +++ b/gio/gdebugcontroller.h @@ -0,0 +1,82 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright © 2021 Endless OS Foundation, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef __G_DEBUG_CONTROLLER_H__ +#define __G_DEBUG_CONTROLLER_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +/** + * G_DEBUG_CONTROLLER_EXTENSION_POINT_NAME: + * + * Extension point for debug control functionality. + * See [Extending GIO][extending-gio]. + * + * Since: 2.72 + */ +#define G_DEBUG_CONTROLLER_EXTENSION_POINT_NAME "gio-debug-controller" + +/** + * GDebugController: + * + * #GDebugController is an interface to expose control of debugging features and + * debug output. + * + * Since: 2.72 + */ +#define G_TYPE_DEBUG_CONTROLLER (g_debug_controller_get_type ()) +GLIB_AVAILABLE_IN_2_72 +G_DECLARE_INTERFACE(GDebugController, g_debug_controller, g, debug_controller, GObject) + +#define G_DEBUG_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DEBUG_CONTROLLER, GDebugController)) +#define G_IS_DEBUG_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DEBUG_CONTROLLER)) +#define G_DEBUG_CONTROLLER_GET_INTERFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_DEBUG_CONTROLLER, GDebugControllerInterface)) + +/** + * GDebugControllerInterface: + * @g_iface: The parent interface. + * + * The virtual function table for #GDebugController. + * + * Since: 2.72 + */ +struct _GDebugControllerInterface { + /*< private >*/ + GTypeInterface g_iface; +}; + +GLIB_AVAILABLE_IN_2_72 +GDebugController *g_debug_controller_dup_default (void); + +GLIB_AVAILABLE_IN_2_72 +gboolean g_debug_controller_get_debug_enabled (GDebugController *self); +GLIB_AVAILABLE_IN_2_72 +void g_debug_controller_set_debug_enabled (GDebugController *self, + gboolean debug_enabled); + +G_END_DECLS + +#endif /* __G_DEBUG_CONTROLLER_H__ */ diff --git a/gio/gdebugcontrollerdbus.c b/gio/gdebugcontrollerdbus.c new file mode 100644 index 000000000..9085620b4 --- /dev/null +++ b/gio/gdebugcontrollerdbus.c @@ -0,0 +1,490 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright © 2021 Endless OS Foundation, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "config.h" + +#include +#include "gdebugcontroller.h" +#include "gdebugcontrollerdbus.h" +#include "giomodule-priv.h" +#include "gi18n.h" +#include "gio/gdbusprivate.h" +#include "gio/gmarshal-internal.h" + +/** + * SECTION:gdebugcontrollerdbus + * @title: GDebugControllerDBus + * @short_description: Debugging controller D-Bus implementation + * @include: gio/gio.h + * + * #GDebugControllerDBus is an implementation of #GDebugController which exposes + * debug settings as a D-Bus object. + * + * It is a #GInitable object, and will register an object at + * `/org/gtk/Debugging` on the bus given as + * #GDebugControllerDBus:connection once it’s initialized. The object will be + * unregistered when the last reference to the #GDebugControllerDBus is dropped. + * + * Since: 2.72 + */ + +static const gchar org_gtk_Debugging_xml[] = + "" + "" + "" + "" + "" + "" + "" + ""; + +static GDBusInterfaceInfo *org_gtk_Debugging; + +#define G_DEBUG_CONTROLLER_DBUS_GET_INITABLE_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_INITABLE, GInitable)) + +static void g_debug_controller_dbus_iface_init (GDebugControllerInterface *iface); +static void g_debug_controller_dbus_initable_iface_init (GInitableIface *iface); +static gboolean g_debug_controller_dbus_authorize_default (GDebugControllerDBus *self, + GDBusMethodInvocation *invocation); + +typedef enum +{ + PROP_CONNECTION = 1, + /* Overrides: */ + PROP_DEBUG_ENABLED, +} GDebugControllerDBusProperty; + +static GParamSpec *props[PROP_CONNECTION + 1] = { NULL, }; + +typedef enum +{ + SIGNAL_AUTHORIZE, +} GDebugControllerDBusSignal; + +static guint signals[SIGNAL_AUTHORIZE + 1] = {0}; + +typedef struct +{ + GObject parent_instance; + + GDBusConnection *connection; /* (owned) */ + guint object_id; + + gboolean debug_enabled; +} GDebugControllerDBusPrivate; + +G_DEFINE_TYPE_WITH_CODE (GDebugControllerDBus, g_debug_controller_dbus, G_TYPE_OBJECT, + G_ADD_PRIVATE (GDebugControllerDBus) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + g_debug_controller_dbus_initable_iface_init) + G_IMPLEMENT_INTERFACE (G_TYPE_DEBUG_CONTROLLER, + g_debug_controller_dbus_iface_init) + _g_io_modules_ensure_extension_points_registered (); + g_io_extension_point_implement (G_DEBUG_CONTROLLER_EXTENSION_POINT_NAME, + g_define_type_id, + "dbus", + 30)) + +static void +g_debug_controller_dbus_init (GDebugControllerDBus *dbus) +{ +} + +static void +set_debug_enabled (GDebugControllerDBus *self, + gboolean debug_enabled) +{ + GDebugControllerDBusPrivate *priv = g_debug_controller_dbus_get_instance_private (self); + + if (debug_enabled != priv->debug_enabled) + { + GVariantBuilder builder; + + priv->debug_enabled = debug_enabled; + + /* Change the default log writer’s behaviour in GLib. */ + g_log_set_debug_enabled (debug_enabled); + + /* Notify internally and externally of the property change. */ + g_object_notify (G_OBJECT (self), "debug-enabled"); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&builder, "{sv}", "DebugEnabled", g_variant_new_boolean (priv->debug_enabled)); + + g_dbus_connection_emit_signal (priv->connection, + NULL, + "/org/gtk/Debugging", + "org.gtk.DBus.Properties", + "PropertiesChanged", + g_variant_new ("(sa{sv}as)", + "org.gtk.Debugging", + &builder, + NULL), + NULL); + + g_debug ("Debug output %s", debug_enabled ? "enabled" : "disabled"); + } +} + +/* Called in the #GMainContext which was default when the #GDebugControllerDBus + * was initialised. */ +static GVariant * +dbus_get_property (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + GDebugControllerDBus *self = user_data; + GDebugControllerDBusPrivate *priv = g_debug_controller_dbus_get_instance_private (self); + + if (g_str_equal (property_name, "DebugEnabled")) + return g_variant_new_boolean (priv->debug_enabled); + + g_assert_not_reached (); + + return NULL; +} + +/* Called in a worker thread. */ +static void +authorize_task_cb (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + GDebugControllerDBus *self = G_DEBUG_CONTROLLER_DBUS (source_object); + GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (task_data); + gboolean authorized = TRUE; + + g_signal_emit (self, signals[SIGNAL_AUTHORIZE], 0, invocation, &authorized); + + g_task_return_boolean (task, authorized); +} + +/* Called in the #GMainContext which was default when the #GDebugControllerDBus + * was initialised. */ +static void +authorize_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GDebugControllerDBus *self = G_DEBUG_CONTROLLER_DBUS (object); + GTask *task = G_TASK (result); + GDBusMethodInvocation *invocation = g_task_get_task_data (task); + GVariant *parameters = g_dbus_method_invocation_get_parameters (invocation); + gboolean enabled = FALSE; + gboolean authorized; + + authorized = g_task_propagate_boolean (task, NULL); + + if (!authorized) + { + GError *local_error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, + _("Not authorized to change debug settings")); + g_dbus_method_invocation_take_error (invocation, g_steal_pointer (&local_error)); + return; + } + + /* Update the property value. */ + g_variant_get (parameters, "(b)", &enabled); + set_debug_enabled (self, enabled); + + g_dbus_method_invocation_return_value (invocation, NULL); +} + +/* Called in the #GMainContext which was default when the #GDebugControllerDBus + * was initialised. */ +static void +dbus_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + GDebugControllerDBus *self = user_data; + GDebugControllerDBusClass *klass = G_DEBUG_CONTROLLER_DBUS_GET_CLASS (self); + + /* Only on the org.gtk.Debugging interface */ + if (g_str_equal (method_name, "SetDebugEnabled")) + { + GTask *task = NULL; + + task = g_task_new (self, NULL, authorize_cb, NULL); + g_task_set_source_tag (task, dbus_method_call); + g_task_set_task_data (task, g_object_ref (invocation), (GDestroyNotify) g_object_unref); + + /* Check the calling peer is authorised to change the debug mode. So that + * the signal handler can block on checking polkit authorisation (which + * definitely involves D-Bus calls, and might involve user interaction), + * emit the #GDebugControllerDBus::authorize signal in a worker thread, so + * that handlers can synchronously block it. This is similar to how + * #GDBusInterfaceSkeleton::g-authorize-method works. + * + * If no signal handlers are connected, don’t bother running the worker + * thread, and just return a default value of %FALSE. Fail closed. */ + if (g_signal_has_handler_pending (self, signals[SIGNAL_AUTHORIZE], 0, FALSE) || + klass->authorize != g_debug_controller_dbus_authorize_default) + g_task_run_in_thread (task, authorize_task_cb); + else + g_task_return_boolean (task, FALSE); + + g_clear_object (&task); + } + else + g_assert_not_reached (); +} + +static gboolean +g_debug_controller_dbus_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + GDebugControllerDBus *self = G_DEBUG_CONTROLLER_DBUS (initable); + GDebugControllerDBusPrivate *priv = g_debug_controller_dbus_get_instance_private (self); + static const GDBusInterfaceVTable vtable = { + dbus_method_call, + dbus_get_property, + NULL /* set_property */, + { 0 } + }; + + if (org_gtk_Debugging == NULL) + { + GError *local_error = NULL; + GDBusNodeInfo *info; + + info = g_dbus_node_info_new_for_xml (org_gtk_Debugging_xml, &local_error); + if G_UNLIKELY (info == NULL) + g_error ("%s", local_error->message); + org_gtk_Debugging = g_dbus_node_info_lookup_interface (info, "org.gtk.Debugging"); + g_assert (org_gtk_Debugging != NULL); + g_dbus_interface_info_ref (org_gtk_Debugging); + g_dbus_node_info_unref (info); + } + + priv->object_id = g_dbus_connection_register_object (priv->connection, + "/org/gtk/Debugging", + org_gtk_Debugging, + &vtable, self, NULL, error); + if (priv->object_id == 0) + return FALSE; + + return TRUE; +} + +static void +g_debug_controller_dbus_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GDebugControllerDBus *self = G_DEBUG_CONTROLLER_DBUS (object); + GDebugControllerDBusPrivate *priv = g_debug_controller_dbus_get_instance_private (self); + + switch ((GDebugControllerDBusProperty) prop_id) + { + case PROP_CONNECTION: + g_value_set_object (value, priv->connection); + break; + case PROP_DEBUG_ENABLED: + g_value_set_boolean (value, priv->debug_enabled); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_debug_controller_dbus_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GDebugControllerDBus *self = G_DEBUG_CONTROLLER_DBUS (object); + GDebugControllerDBusPrivate *priv = g_debug_controller_dbus_get_instance_private (self); + + switch ((GDebugControllerDBusProperty) prop_id) + { + case PROP_CONNECTION: + /* Construct only */ + g_assert (priv->connection == NULL); + priv->connection = g_value_dup_object (value); + break; + case PROP_DEBUG_ENABLED: + set_debug_enabled (self, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_debug_controller_dbus_dispose (GObject *object) +{ + GDebugControllerDBus *self = G_DEBUG_CONTROLLER_DBUS (object); + GDebugControllerDBusPrivate *priv = g_debug_controller_dbus_get_instance_private (self); + + if (priv->object_id != 0) + { + g_dbus_connection_unregister_object (priv->connection, priv->object_id); + priv->object_id = 0; + } + + g_clear_object (&priv->connection); + + G_OBJECT_CLASS (g_debug_controller_dbus_parent_class)->dispose (object); +} + +static gboolean +g_debug_controller_dbus_authorize_default (GDebugControllerDBus *self, + GDBusMethodInvocation *invocation) +{ + return TRUE; +} + +static void +g_debug_controller_dbus_class_init (GDebugControllerDBusClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = g_debug_controller_dbus_get_property; + gobject_class->set_property = g_debug_controller_dbus_set_property; + gobject_class->dispose = g_debug_controller_dbus_dispose; + + klass->authorize = g_debug_controller_dbus_authorize_default; + + /** + * GDebugControllerDBus:connection: + * + * The D-Bus connection to expose the debugging interface on. + * + * Typically this will be the same connection (to the system or session bus) + * which the rest of the application or service’s D-Bus objects are registered + * on. + * + * Since: 2.72 + */ + props[PROP_CONNECTION] = + g_param_spec_object ("connection", "D-Bus Connection", + "The D-Bus connection to expose the debugging interface on.", + G_TYPE_DBUS_CONNECTION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, G_N_ELEMENTS (props), props); + + g_object_class_override_property (gobject_class, PROP_DEBUG_ENABLED, "debug-enabled"); + + /** + * GDebugControllerDBus::authorize: + * @controller: The #GDebugControllerDBus emitting the signal. + * @invocation: A #GDBusMethodInvocation. + * + * Emitted when a D-Bus peer is trying to change the debug settings and used + * to determine if that is authorized. + * + * This signal is emitted in a dedicated worker thread, so handlers are + * allowed to perform blocking I/O. This means that, for example, it is + * appropriate to call `polkit_authority_check_authorization_sync()` to check + * authorization using polkit. + * + * If %FALSE is returned then no further handlers are run and the request to + * change the debug settings is rejected. + * + * Otherwise, if %TRUE is returned, signal emission continues. If no handlers + * return %FALSE, then the debug settings are allowed to be changed. + * + * Signal handlers must not modify @invocation, or cause it to return a value. + * + * The default class handler just returns %TRUE. + * + * Returns: %TRUE if the call is authorized, %FALSE otherwise. + * + * Since: 2.72 + */ + signals[SIGNAL_AUTHORIZE] = + g_signal_new ("authorize", + G_TYPE_DEBUG_CONTROLLER_DBUS, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GDebugControllerDBusClass, authorize), + _g_signal_accumulator_false_handled, + NULL, + _g_cclosure_marshal_BOOLEAN__OBJECT, + G_TYPE_BOOLEAN, + 1, + G_TYPE_DBUS_METHOD_INVOCATION); + g_signal_set_va_marshaller (signals[SIGNAL_AUTHORIZE], + G_TYPE_FROM_CLASS (klass), + _g_cclosure_marshal_BOOLEAN__OBJECTv); +} + +static void +g_debug_controller_dbus_iface_init (GDebugControllerInterface *iface) +{ +} + +static void +g_debug_controller_dbus_initable_iface_init (GInitableIface *iface) +{ + iface->init = g_debug_controller_dbus_initable_init; +} + +/** + * g_debug_controller_dbus_new: + * @connection: a #GDBusConnection to register the debug object on + * @cancellable: (nullable): a #GCancellable, or %NULL + * @error: return location for a #GError, or %NULL + * + * Create a new #GDebugControllerDBus and synchronously initialize it. + * + * Initializing the object will export the debug object on @connection. The + * object will remain registered until the last reference to the + * #GDebugControllerDBus is dropped. + * + * Initialization may fail if registering the object on @connection fails. + * + * Returns: (nullable) (transfer full): a new #GDebugControllerDBus, or %NULL + * on failure + * Since: 2.72 + */ +GDebugControllerDBus * +g_debug_controller_dbus_new (GDBusConnection *connection, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); + g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + return g_initable_new (G_TYPE_DEBUG_CONTROLLER_DBUS, + cancellable, + error, + "connection", connection, + NULL); +} diff --git a/gio/gdebugcontrollerdbus.h b/gio/gdebugcontrollerdbus.h new file mode 100644 index 000000000..2d41c25cf --- /dev/null +++ b/gio/gdebugcontrollerdbus.h @@ -0,0 +1,66 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright © 2021 Endless OS Foundation, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef __G_DEBUG_CONTROLLER_DBUS_H__ +#define __G_DEBUG_CONTROLLER_DBUS_H__ + +#include +#include + +G_BEGIN_DECLS + +/** + * GDebugControllerDBus: + * + * #GDebugControllerDBus is an implementation of #GDebugController over D-Bus. + * + * Since: 2.72 + */ +#define G_TYPE_DEBUG_CONTROLLER_DBUS (g_debug_controller_dbus_get_type ()) +GLIB_AVAILABLE_IN_2_72 +G_DECLARE_DERIVABLE_TYPE (GDebugControllerDBus, g_debug_controller_dbus, G, DEBUG_CONTROLLER_DBUS, GObject) + +/** + * GDebugControllerDBusClass: + * @parent_class: The parent class. + * @authorize: Default handler for the #GDebugControllerDBus::authorize signal. + * + * The virtual function table for #GDebugControllerDBus. + * + * Since: 2.72 + */ +struct _GDebugControllerDBusClass +{ + GObjectClass parent_class; + + gboolean (*authorize) (GDebugControllerDBus *controller, + GDBusMethodInvocation *invocation); + + gpointer padding[12]; +}; + +GLIB_AVAILABLE_IN_2_72 +GDebugControllerDBus *g_debug_controller_dbus_new (GDBusConnection *connection, + GCancellable *cancellable, + GError **error); + +G_END_DECLS + +#endif /* __G_DEBUG_CONTROLLER_DBUS_H__ */ diff --git a/gio/gio.h b/gio/gio.h index e9afab666..2d0a9c274 100644 --- a/gio/gio.h +++ b/gio/gio.h @@ -69,6 +69,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/gio/giomodule.c b/gio/giomodule.c index d34037a45..3b80b9029 100644 --- a/gio/giomodule.c +++ b/gio/giomodule.c @@ -45,6 +45,8 @@ #include "gnotificationbackend.h" #include "ginitable.h" #include "gnetworkmonitor.h" +#include "gdebugcontroller.h" +#include "gdebugcontrollerdbus.h" #include "gmemorymonitor.h" #include "gmemorymonitorportal.h" #include "gmemorymonitordbus.h" @@ -1078,6 +1080,7 @@ extern GType _g_network_monitor_netlink_get_type (void); extern GType _g_network_monitor_nm_get_type (void); #endif +extern GType g_debug_controller_dbus_get_type (void); extern GType g_memory_monitor_dbus_get_type (void); extern GType g_memory_monitor_portal_get_type (void); extern GType g_power_profile_monitor_dbus_get_type (void); @@ -1189,6 +1192,9 @@ _g_io_modules_ensure_extension_points_registered (void) ep = g_io_extension_point_register (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME); g_io_extension_point_set_required_type (ep, G_TYPE_NOTIFICATION_BACKEND); + ep = g_io_extension_point_register (G_DEBUG_CONTROLLER_EXTENSION_POINT_NAME); + g_io_extension_point_set_required_type (ep, G_TYPE_DEBUG_CONTROLLER); + ep = g_io_extension_point_register (G_MEMORY_MONITOR_EXTENSION_POINT_NAME); g_io_extension_point_set_required_type (ep, G_TYPE_MEMORY_MONITOR); diff --git a/gio/meson.build b/gio/meson.build index 29473d26b..3a55b6f55 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -477,6 +477,8 @@ gio_sources = files( 'gdatagrambased.c', 'gdatainputstream.c', 'gdataoutputstream.c', + 'gdebugcontroller.c', + 'gdebugcontrollerdbus.c', 'gdrive.c', 'gdummyfile.c', 'gdummyproxyresolver.c', @@ -624,6 +626,8 @@ gio_headers = files( 'gdatagrambased.h', 'gdatainputstream.h', 'gdataoutputstream.h', + 'gdebugcontroller.h', + 'gdebugcontrollerdbus.h', 'gdrive.h', 'gemblem.h', 'gemblemedicon.h', diff --git a/po/POTFILES.in b/po/POTFILES.in index c31517dcf..24daa0813 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -39,6 +39,7 @@ gio/gdbusprivate.c gio/gdbusproxy.c gio/gdbusserver.c gio/gdbus-tool.c +gio/gdebugcontrollerdbus.c gio/gdesktopappinfo.c gio/gdrive.c gio/gdtlsclientconnection.c