1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
// This file was generated by gir (https://github.com/gtk-rs/gir)
// from gir-files (https://github.com/gtk-rs/gir-files)
// DO NOT EDIT
use crate::{Cancellable, DBusConnection, DBusMethodInvocation, DebugController, Initable};
use glib::{
prelude::*,
signal::{connect_raw, SignalHandlerId},
translate::*,
};
use std::{boxed::Box as Box_, fmt, mem::transmute, ptr};
glib::wrapper! {
/// [`DebugControllerDBus`][crate::DebugControllerDBus] is an implementation of [`DebugController`][crate::DebugController] which exposes
/// debug settings as a D-Bus object.
///
/// It is a [`Initable`][crate::Initable] object, and will register an object at
/// `/org/gtk/Debugging` on the bus given as
/// [`connection`][struct@crate::DebugControllerDBus#connection] once it’s initialized. The object will be
/// unregistered when the last reference to the [`DebugControllerDBus`][crate::DebugControllerDBus] is dropped.
///
/// This D-Bus object can be used by remote processes to enable or disable debug
/// output in this process. Remote processes calling
/// `org.gtk.Debugging.SetDebugEnabled()` will affect the value of
/// [`debug-enabled`][struct@crate::DebugController#debug-enabled] and, by default, `g_log_get_debug_enabled()`.
/// default.
///
/// By default, no processes are allowed to call `SetDebugEnabled()` unless a
/// [`authorize`][struct@crate::DebugControllerDBus#authorize] signal handler is installed. This is because
/// the process may be privileged, or might expose sensitive information in its
/// debug output. You may want to restrict the ability to enable debug output to
/// privileged users or processes.
///
/// One option is to install a D-Bus security policy which restricts access to
/// `SetDebugEnabled()`, installing something like the following in
/// `$datadir/dbus-1/system.d/`:
///
///
/// **⚠️ The following code is in XML ⚠️**
///
/// ```XML
/// <?xml version="1.0"?> <!--*-nxml-*-->
/// <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
/// "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
/// <busconfig>
/// <policy user="root">
/// <allow send_destination="com.example.MyService" send_interface="org.gtk.Debugging"/>
/// </policy>
/// <policy context="default">
/// <deny send_destination="com.example.MyService" send_interface="org.gtk.Debugging"/>
/// </policy>
/// </busconfig>
/// ```
///
/// This will prevent the `SetDebugEnabled()` method from being called by all
/// except root. It will not prevent the `DebugEnabled` property from being read,
/// as it’s accessed through the `org.freedesktop.DBus.Properties` interface.
///
/// Another option is to use polkit to allow or deny requests on a case-by-case
/// basis, allowing for the possibility of dynamic authorisation. To do this,
/// connect to the [`authorize`][struct@crate::DebugControllerDBus#authorize] signal and query polkit in
/// it:
///
///
/// **⚠️ The following code is in C ⚠️**
///
/// ```C
/// g_autoptr(GError) child_error = NULL;
/// g_autoptr(GDBusConnection) connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
/// gulong debug_controller_authorize_id = 0;
///
/// // Set up the debug controller.
/// debug_controller = G_DEBUG_CONTROLLER (g_debug_controller_dbus_new (priv->connection, NULL, &child_error));
/// if (debug_controller == NULL)
/// {
/// g_error ("Could not register debug controller on bus: %s"),
/// child_error->message);
/// }
///
/// debug_controller_authorize_id = g_signal_connect (debug_controller,
/// "authorize",
/// G_CALLBACK (debug_controller_authorize_cb),
/// self);
///
/// static gboolean
/// debug_controller_authorize_cb (GDebugControllerDBus *debug_controller,
/// GDBusMethodInvocation *invocation,
/// gpointer user_data)
/// {
/// g_autoptr(PolkitAuthority) authority = NULL;
/// g_autoptr(PolkitSubject) subject = NULL;
/// g_autoptr(PolkitAuthorizationResult) auth_result = NULL;
/// g_autoptr(GError) local_error = NULL;
/// GDBusMessage *message;
/// GDBusMessageFlags message_flags;
/// PolkitCheckAuthorizationFlags flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
///
/// message = g_dbus_method_invocation_get_message (invocation);
/// message_flags = g_dbus_message_get_flags (message);
///
/// authority = polkit_authority_get_sync (NULL, &local_error);
/// if (authority == NULL)
/// {
/// g_warning ("Failed to get polkit authority: %s", local_error->message);
/// return FALSE;
/// }
///
/// if (message_flags & G_DBUS_MESSAGE_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION)
/// flags |= POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
///
/// subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (invocation));
///
/// auth_result = polkit_authority_check_authorization_sync (authority,
/// subject,
/// "com.example.MyService.set-debug-enabled",
/// NULL,
/// flags,
/// NULL,
/// &local_error);
/// if (auth_result == NULL)
/// {
/// g_warning ("Failed to get check polkit authorization: %s", local_error->message);
/// return FALSE;
/// }
///
/// return polkit_authorization_result_get_is_authorized (auth_result);
/// }
/// ```
///
/// ## Properties
///
///
/// #### `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.
///
/// Readable | Writeable | Construct Only
/// <details><summary><h4>DebugController</h4></summary>
///
///
/// #### `debug-enabled`
/// [`true`] if debug output should be exposed (for example by forwarding it to
/// the journal), [`false`] otherwise.
///
/// Readable | Writeable
/// </details>
///
/// ## Signals
///
///
/// #### `authorize`
/// 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`].
///
///
///
/// # Implements
///
/// [`DebugControllerDBusExt`][trait@crate::prelude::DebugControllerDBusExt], [`trait@glib::ObjectExt`], [`DebugControllerExt`][trait@crate::prelude::DebugControllerExt], [`InitableExt`][trait@crate::prelude::InitableExt], [`DebugControllerDBusExtManual`][trait@crate::prelude::DebugControllerDBusExtManual]
#[doc(alias = "GDebugControllerDBus")]
pub struct DebugControllerDBus(Object<ffi::GDebugControllerDBus, ffi::GDebugControllerDBusClass>) @implements DebugController, Initable;
match fn {
type_ => || ffi::g_debug_controller_dbus_get_type(),
}
}
impl DebugControllerDBus {
pub const NONE: Option<&'static DebugControllerDBus> = None;
/// Create a new [`DebugControllerDBus`][crate::DebugControllerDBus] 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
/// [`DebugControllerDBus`][crate::DebugControllerDBus] is dropped.
///
/// Initialization may fail if registering the object on `connection` fails.
/// ## `connection`
/// a [`DBusConnection`][crate::DBusConnection] to register the debug object on
/// ## `cancellable`
/// a [`Cancellable`][crate::Cancellable], or [`None`]
///
/// # Returns
///
/// a new [`DebugControllerDBus`][crate::DebugControllerDBus], or [`None`]
/// on failure
#[doc(alias = "g_debug_controller_dbus_new")]
pub fn new(
connection: &DBusConnection,
cancellable: Option<&impl IsA<Cancellable>>,
) -> Result<Option<DebugControllerDBus>, glib::Error> {
unsafe {
let mut error = ptr::null_mut();
let ret = ffi::g_debug_controller_dbus_new(
connection.to_glib_none().0,
cancellable.map(|p| p.as_ref()).to_glib_none().0,
&mut error,
);
if error.is_null() {
Ok(from_glib_full(ret))
} else {
Err(from_glib_full(error))
}
}
}
}
mod sealed {
pub trait Sealed {}
impl<T: super::IsA<super::DebugControllerDBus>> Sealed for T {}
}
/// Trait containing all [`struct@DebugControllerDBus`] methods.
///
/// # Implementors
///
/// [`DebugControllerDBus`][struct@crate::DebugControllerDBus]
pub trait DebugControllerDBusExt: IsA<DebugControllerDBus> + sealed::Sealed + 'static {
/// Stop the debug controller, unregistering its object from the bus.
///
/// Any pending method calls to the object will complete successfully, but new
/// ones will return an error. This method will block until all pending
/// [`authorize`][struct@crate::DebugControllerDBus#authorize] signals have been handled. This is expected
/// to not take long, as it will just be waiting for threads to join. If any
/// [`authorize`][struct@crate::DebugControllerDBus#authorize] signal handlers are still executing in other
/// threads, this will block until after they have returned.
///
/// This method will be called automatically when the final reference to the
/// [`DebugControllerDBus`][crate::DebugControllerDBus] is dropped. You may want to call it explicitly to know
/// when the controller has been fully removed from the bus, or to break
/// reference count cycles.
///
/// Calling this method from within a [`authorize`][struct@crate::DebugControllerDBus#authorize] signal
/// handler will cause a deadlock and must not be done.
#[doc(alias = "g_debug_controller_dbus_stop")]
fn stop(&self) {
unsafe {
ffi::g_debug_controller_dbus_stop(self.as_ref().to_glib_none().0);
}
}
/// 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`].
/// ## `invocation`
/// A [`DBusMethodInvocation`][crate::DBusMethodInvocation].
///
/// # Returns
///
/// [`true`] if the call is authorized, [`false`] otherwise.
#[cfg(feature = "v2_72")]
#[cfg_attr(docsrs, doc(cfg(feature = "v2_72")))]
#[doc(alias = "authorize")]
fn connect_authorize<F: Fn(&Self, &DBusMethodInvocation) -> bool + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn authorize_trampoline<
P: IsA<DebugControllerDBus>,
F: Fn(&P, &DBusMethodInvocation) -> bool + 'static,
>(
this: *mut ffi::GDebugControllerDBus,
invocation: *mut ffi::GDBusMethodInvocation,
f: glib::ffi::gpointer,
) -> glib::ffi::gboolean {
let f: &F = &*(f as *const F);
f(
DebugControllerDBus::from_glib_borrow(this).unsafe_cast_ref(),
&from_glib_borrow(invocation),
)
.into_glib()
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
b"authorize\0".as_ptr() as *const _,
Some(transmute::<_, unsafe extern "C" fn()>(
authorize_trampoline::<Self, F> as *const (),
)),
Box_::into_raw(f),
)
}
}
}
impl<O: IsA<DebugControllerDBus>> DebugControllerDBusExt for O {}
impl fmt::Display for DebugControllerDBus {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("DebugControllerDBus")
}
}