From e0b120cc3c732901f4b9f0a37d5123310bea6e3f Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 20 Jul 2018 18:53:09 -0400 Subject: [PATCH 1/4] Add debug spew to module loading This is useful to verify which modules are loaded, and why. --- gio/giomodule.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/gio/giomodule.c b/gio/giomodule.c index 30731f7c2..36c0cefed 100644 --- a/gio/giomodule.c +++ b/gio/giomodule.c @@ -802,14 +802,29 @@ _g_io_module_get_default_type (const gchar *extension_point, } static gpointer -try_implementation (GIOExtension *extension, +try_implementation (const char *extension_point, + GIOExtension *extension, GIOModuleVerifyFunc verify_func) { GType type = g_io_extension_get_type (extension); gpointer impl; if (g_type_is_a (type, G_TYPE_INITABLE)) - return g_initable_new (type, NULL, NULL, NULL); + { + GError *error = NULL; + + impl = g_initable_new (type, NULL, &error, NULL); + if (impl) + return impl; + + g_debug ("Failed to initialize %s (%s) for %s: %s", + g_io_extension_get_name (extension), + g_type_name (type), + extension_point, + error ? error->message : ""); + g_clear_error (&error); + return NULL; + } else { impl = g_object_new (type, NULL); @@ -895,7 +910,7 @@ _g_io_module_get_default (const gchar *extension_point, preferred = g_io_extension_point_get_extension_by_name (ep, use_this); if (preferred) { - impl = try_implementation (preferred, verify_func); + impl = try_implementation (extension_point, preferred, verify_func); if (impl) goto done; } @@ -911,7 +926,7 @@ _g_io_module_get_default (const gchar *extension_point, if (extension == preferred) continue; - impl = try_implementation (extension, verify_func); + impl = try_implementation (extension_point, extension, verify_func); if (impl) goto done; } From 5ed808d7c497d6861c1588911edb1f1b4ff59d96 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 20 Jul 2018 18:53:57 -0400 Subject: [PATCH 2/4] network monitor: Update portal implementation The network monitor portal interface is changing. Version 2 is no longer using properties, but getters instead (this lets the portal apply access control and avoid sending information to non-networked sandboxes). To support both version 1 and 2 of the interface, we stop using generated code and instead deal with the api differences in our own code, which is not too difficult. Support version 1 as well --- gio/gnetworkmonitorportal.c | 236 +++++++++++++++--- gio/org.freedesktop.portal.NetworkMonitor.xml | 81 +++++- 2 files changed, 278 insertions(+), 39 deletions(-) diff --git a/gio/gnetworkmonitorportal.c b/gio/gnetworkmonitorportal.c index 856f8aa5b..16249ac55 100644 --- a/gio/gnetworkmonitorportal.c +++ b/gio/gnetworkmonitorportal.c @@ -21,7 +21,6 @@ #include "gnetworkmonitorportal.h" #include "ginitable.h" #include "giomodule-priv.h" -#include "gnetworkmonitor.h" #include "xdp-dbus.h" #include "gportalsupport.h" @@ -39,8 +38,13 @@ enum struct _GNetworkMonitorPortalPrivate { - GXdpNetworkMonitor *proxy; - gboolean network_available; + GDBusProxy *proxy; + gboolean has_network; + int version; + + gboolean available; + gboolean metered; + GNetworkConnectivity connectivity; }; G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorPortal, g_network_monitor_portal, G_TYPE_NETWORK_MONITOR_BASE, @@ -72,22 +76,15 @@ g_network_monitor_portal_get_property (GObject *object, switch (prop_id) { case PROP_NETWORK_AVAILABLE: - g_value_set_boolean (value, - nm->priv->network_available && - gxdp_network_monitor_get_available (nm->priv->proxy)); + g_value_set_boolean (value, nm->priv->available); break; case PROP_NETWORK_METERED: - g_value_set_boolean (value, - nm->priv->network_available && - gxdp_network_monitor_get_metered (nm->priv->proxy)); + g_value_set_boolean (value, nm->priv->metered); break; case PROP_CONNECTIVITY: - g_value_set_enum (value, - nm->priv->network_available - ? gxdp_network_monitor_get_connectivity (nm->priv->proxy) - : G_NETWORK_CONNECTIVITY_LOCAL); + g_value_set_enum (value, nm->priv->connectivity); break; default: @@ -97,22 +94,184 @@ g_network_monitor_portal_get_property (GObject *object, } static void -proxy_changed (GXdpNetworkMonitor *proxy, - gboolean available, - GNetworkMonitorPortal *nm) +got_available (GObject *source, + GAsyncResult *res, + gpointer data) { - if (nm->priv->network_available) - g_signal_emit_by_name (nm, "network-changed", available); + GDBusProxy *proxy = G_DBUS_PROXY (source); + GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (data); + GError *error = NULL; + GVariant *ret; + gboolean available; + + ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (ret == NULL) + { + g_warning ("%s", error->message); + g_clear_error (&error); + return; + } + + g_variant_get (ret, "(b)", &available); + g_variant_unref (ret); + + if (nm->priv->available != available) + { + nm->priv->available = available; + g_object_notify (G_OBJECT (nm), "network-available"); + g_signal_emit_by_name (nm, "network-changed", available); + } } +static void +got_metered (GObject *source, + GAsyncResult *res, + gpointer data) +{ + GDBusProxy *proxy = G_DBUS_PROXY (source); + GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (data); + GError *error = NULL; + GVariant *ret; + gboolean metered; + + ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (ret == NULL) + { + g_warning ("%s", error->message); + g_clear_error (&error); + return; + } + + g_variant_get (ret, "(b)", &metered); + g_variant_unref (ret); + + if (nm->priv->metered != metered) + { + nm->priv->metered = metered; + g_object_notify (G_OBJECT (nm), "network-metered"); + } +} + +static void +got_connectivity (GObject *source, + GAsyncResult *res, + gpointer data) +{ + GDBusProxy *proxy = G_DBUS_PROXY (source); + GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (data); + GError *error = NULL; + GVariant *ret; + GNetworkConnectivity connectivity; + + ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (ret == NULL) + { + g_warning ("%s", error->message); + g_clear_error (&error); + return; + } + + g_variant_get (ret, "(u)", &connectivity); + g_variant_unref (ret); + + if (nm->priv->connectivity != connectivity) + { + nm->priv->connectivity = connectivity; + g_object_notify (G_OBJECT (nm), "connectivity"); + } +} + +static void +proxy_signal (GDBusProxy *proxy, + const char *sender, + const char *signal, + GVariant *parameters, + GNetworkMonitorPortal *nm) +{ + if (!nm->priv->has_network) + return; + + if (nm->priv->version == 1) + { + gboolean available; + + g_variant_get (parameters, "(b)", &available); + g_signal_emit_by_name (nm, "network-changed", available); + } + else if (nm->priv->version == 2) + { + g_dbus_proxy_call (proxy, "GetConnectivity", NULL, 0, -1, NULL, got_connectivity, nm); + g_dbus_proxy_call (proxy, "GetMetered", NULL, 0, -1, NULL, got_metered, nm); + g_dbus_proxy_call (proxy, "GetAvailable", NULL, 0, -1, NULL, got_available, nm); + } +} + +static void +proxy_properties_changed (GDBusProxy *proxy, + GVariant *changed, + GVariant *invalidated, + GNetworkMonitorPortal *nm) +{ + if (!nm->priv->has_network) + return; + + if (nm->priv->version == 1) + { + GVariant *ret; + + ret = g_dbus_proxy_get_cached_property (proxy, "connectivity"); + if (ret) + { + GNetworkConnectivity connectivity = g_variant_get_uint32 (ret); + if (nm->priv->connectivity != connectivity) + { + nm->priv->connectivity = connectivity; + g_object_notify (G_OBJECT (nm), "connectivity"); + } + g_variant_unref (ret); + } + + ret = g_dbus_proxy_get_cached_property (proxy, "metered"); + if (ret) + { + gboolean metered = g_variant_get_boolean (ret); + if (nm->priv->metered != metered) + { + nm->priv->metered = metered; + g_object_notify (G_OBJECT (nm), "network-metered"); + } + g_variant_unref (ret); + } + + ret = g_dbus_proxy_get_cached_property (proxy, "available"); + if (ret) + { + gboolean available = g_variant_get_boolean (ret); + if (nm->priv->available != available) + { + nm->priv->available = available; + g_object_notify (G_OBJECT (nm), "network-available"); + g_signal_emit_by_name (nm, "network-changed", available); + } + g_variant_unref (ret); + } + } +} + static gboolean g_network_monitor_portal_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (initable); - GXdpNetworkMonitor *proxy; + GDBusProxy *proxy; gchar *name_owner = NULL; + int version; + GVariant *ret; + + nm->priv->available = FALSE; + nm->priv->metered = FALSE; + nm->priv->connectivity = G_NETWORK_CONNECTIVITY_LOCAL; if (!glib_should_use_portal ()) { @@ -120,17 +279,19 @@ g_network_monitor_portal_initable_init (GInitable *initable, return FALSE; } - proxy = gxdp_network_monitor_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START - | G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, - "org.freedesktop.portal.Desktop", - "/org/freedesktop/portal/desktop", - cancellable, - error); + proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START + | G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, + NULL, + "org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.NetworkMonitor", + cancellable, + error); if (!proxy) return FALSE; - name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy)); + name_owner = g_dbus_proxy_get_name_owner (proxy); if (!name_owner) { @@ -144,9 +305,26 @@ g_network_monitor_portal_initable_init (GInitable *initable, g_free (name_owner); - g_signal_connect (proxy, "changed", G_CALLBACK (proxy_changed), nm); + ret = g_dbus_proxy_get_cached_property (proxy, "version"); + g_variant_get (ret, "u", &version); + g_variant_unref (ret); + + if (version != 1 && version != 2) + { + g_object_unref (proxy); + g_set_error (error, + G_DBUS_ERROR, + G_DBUS_ERROR_NAME_HAS_NO_OWNER, + "NetworkMonitor portal unsupported version: %d", version); + return FALSE; + } + + g_signal_connect (proxy, "g-signal", G_CALLBACK (proxy_signal), nm); + g_signal_connect (proxy, "g-properties-changed", G_CALLBACK (proxy_properties_changed), nm); + nm->priv->proxy = proxy; - nm->priv->network_available = glib_network_available_in_sandbox (); + nm->priv->has_network = glib_network_available_in_sandbox (); + nm->priv->version = version; return initable_parent_iface->init (initable, cancellable, error); } diff --git a/gio/org.freedesktop.portal.NetworkMonitor.xml b/gio/org.freedesktop.portal.NetworkMonitor.xml index 8d3a471d5..fb551d6ed 100644 --- a/gio/org.freedesktop.portal.NetworkMonitor.xml +++ b/gio/org.freedesktop.portal.NetworkMonitor.xml @@ -5,25 +5,86 @@ 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. + version 2 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 . + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . Author: Matthias Clasen --> - + + - - - - - - + + + + + + + + + + + + + + + From 7217fe56e00be80091ec6a5a4a979dd077cb6106 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 21 Jul 2018 08:17:44 -0400 Subject: [PATCH 3/4] Stop generating code for NetworkMonitor The portal implementation no longer uses generated code for org.freedesktop.portal.NetworkMonitor. --- gio/Makefile.am | 1 - gio/meson.build | 1 - gio/org.freedesktop.portal.NetworkMonitor.xml | 90 ------------------- 3 files changed, 92 deletions(-) delete mode 100644 gio/org.freedesktop.portal.NetworkMonitor.xml diff --git a/gio/Makefile.am b/gio/Makefile.am index f06244149..98c808815 100644 --- a/gio/Makefile.am +++ b/gio/Makefile.am @@ -369,7 +369,6 @@ CLEANFILES += $(xdp_dbus_built_sources) portal_interfaces = \ org.freedesktop.portal.Documents.xml \ org.freedesktop.portal.OpenURI.xml \ - org.freedesktop.portal.NetworkMonitor.xml \ org.freedesktop.portal.ProxyResolver.xml \ $(NULL) diff --git a/gio/meson.build b/gio/meson.build index a24a92e3d..a6af822b5 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -234,7 +234,6 @@ subdir('gdbus-2.0/codegen') xdp_dbus_generated = custom_target('xdp-dbus', input : ['org.freedesktop.portal.Documents.xml', 'org.freedesktop.portal.OpenURI.xml', - 'org.freedesktop.portal.NetworkMonitor.xml', 'org.freedesktop.portal.ProxyResolver.xml'], output : ['xdp-dbus.h', 'xdp-dbus.c'], depend_files : gdbus_codegen_built_files, diff --git a/gio/org.freedesktop.portal.NetworkMonitor.xml b/gio/org.freedesktop.portal.NetworkMonitor.xml deleted file mode 100644 index fb551d6ed..000000000 --- a/gio/org.freedesktop.portal.NetworkMonitor.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - From 1db3b6def6a736429ba778e49fce0d3044cfdf79 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 20 Jul 2018 18:55:10 -0400 Subject: [PATCH 4/4] Add a gnet utility This is currently just a wrapper around GNetworkMonitor. --- gio/Makefile.am | 8 +++++ gio/gnet-tool.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 gio/gnet-tool.c diff --git a/gio/Makefile.am b/gio/Makefile.am index 98c808815..ca1422739 100644 --- a/gio/Makefile.am +++ b/gio/Makefile.am @@ -974,6 +974,14 @@ gio_LDADD = libgio-2.0.la \ $(top_builddir)/glib/libglib-2.0.la \ $(NULL) +bin_PROGRAMS += gnet +gnet_SOURCES = \ + gnet-tool.c +gnet_LDADD = libgio-2.0.la \ + $(top_builddir)/gobject/libgobject-2.0.la \ + $(top_builddir)/glib/libglib-2.0.la \ + $(NULL) + dist-hook: $(BUILT_EXTRA_DIST) files='$(BUILT_EXTRA_DIST)'; \ for f in $$files; do \ diff --git a/gio/gnet-tool.c b/gio/gnet-tool.c new file mode 100644 index 000000000..334923654 --- /dev/null +++ b/gio/gnet-tool.c @@ -0,0 +1,77 @@ +/* + * Copyright 2015 Red Hat, Inc. + * + * 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 . + * + * Author: Matthias Clasen + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +static void +network_changed (GNetworkMonitor *nm, + gboolean available, + gpointer data) +{ + g_print ("::network-changed available: %d\n", available); +} + +static void +notify (GObject *object, + GParamSpec *pspec, + gpointer data) +{ + GNetworkMonitor *nm = G_NETWORK_MONITOR (object); + + g_print ("notify::"); + if (strcmp (pspec->name, "network-available") == 0) + g_print ("network-available: %d\n", g_network_monitor_get_network_available (nm)); + else if (strcmp (pspec->name, "network-metered") == 0) + g_print ("network-metered: %d\n", g_network_monitor_get_network_metered (nm)); + else if (strcmp (pspec->name, "connectivity") == 0) + g_print ("connectivity: %d\n", g_network_monitor_get_connectivity (nm)); +} + +int +main (int argc, char **argv) +{ + GNetworkMonitor *nm; + + setlocale (LC_ALL, ""); + textdomain (GETTEXT_PACKAGE); + bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR); + +#ifdef HAVE_BIND_TEXTDOMAIN_CODESET + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif + + nm = g_network_monitor_get_default (); + g_print ("Using %s\n", g_type_name_from_instance (nm)); + + g_signal_connect (nm, "network-changed", G_CALLBACK (network_changed), NULL); + g_signal_connect (nm, "notify", G_CALLBACK (notify), NULL); + + while (TRUE) + g_main_context_iteration (NULL, TRUE); + + return 1; +}