about summary refs log tree commit diff
path: root/libnm-glib/nm-remote-settings-system.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2010-11-29 00:47:11 +0100
committerMichael Biebl <biebl@debian.org>2010-11-29 00:47:11 +0100
commit9fae01fa351805b2903e535736e06971bc0b925e (patch)
treec19bccf84c9f894e50fae678ba6ee2b2044e2d30 /libnm-glib/nm-remote-settings-system.c
Imported Upstream version 0.8.1 upstream/0.8.1
Diffstat (limited to 'libnm-glib/nm-remote-settings-system.c')
-rw-r--r--libnm-glib/nm-remote-settings-system.c375
1 files changed, 375 insertions, 0 deletions
diff --git a/libnm-glib/nm-remote-settings-system.c b/libnm-glib/nm-remote-settings-system.c
new file mode 100644
index 00000000..95098c7e
--- /dev/null
+++ b/libnm-glib/nm-remote-settings-system.c
@@ -0,0 +1,375 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * libnm_glib -- Access network status & information from glib applications
+ *
+ * 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 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ * Copyright (C) 2009 - 2010 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <NetworkManager.h>
+#include <nm-connection.h>
+
+#include "nm-marshal.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-remote-settings-system.h"
+#include "nm-settings-system-bindings.h"
+#include "nm-settings-system-interface.h"
+
+static void settings_system_interface_init (NMSettingsSystemInterface *klass);
+
+G_DEFINE_TYPE_EXTENDED (NMRemoteSettingsSystem, nm_remote_settings_system, NM_TYPE_REMOTE_SETTINGS, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_SYSTEM_INTERFACE, settings_system_interface_init))
+
+#define NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystemPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+	DBusGProxy *props_proxy;
+
+	char *hostname;
+	gboolean can_modify;
+
+	NMSettingsSystemPermissions permissions;
+	gboolean have_permissions;
+
+	gboolean disposed;
+} NMRemoteSettingsSystemPrivate;
+
+static void
+properties_changed_cb (DBusGProxy *proxy,
+                       GHashTable *properties,
+                       gpointer user_data)
+{
+	NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data);
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
+	GHashTableIter iter;
+	gpointer key, tmp;
+
+	g_hash_table_iter_init (&iter, properties);
+	while (g_hash_table_iter_next (&iter, &key, &tmp)) {
+		GValue *value = tmp;
+
+		if (!strcmp ((const char *) key, "Hostname")) {
+			g_free (priv->hostname);
+			priv->hostname = g_value_dup_string (value);
+			g_object_notify (G_OBJECT (self), NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME);
+		}
+
+		if (!strcmp ((const char *) key, "CanModify")) {
+			priv->can_modify = g_value_get_boolean (value);
+			g_object_notify (G_OBJECT (self), NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY);
+		}
+	}
+}
+
+static void
+get_all_cb  (DBusGProxy *proxy,
+             DBusGProxyCall *call,
+             gpointer user_data)
+{
+	NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data);
+	GHashTable *props = NULL;
+	GError *error = NULL;
+
+	if (!dbus_g_proxy_end_call (proxy, call, &error,
+	                            DBUS_TYPE_G_MAP_OF_VARIANT, &props,
+	                            G_TYPE_INVALID)) {
+		/* Don't warn when the call times out because the settings service can't
+		 * be activated or whatever.
+		 */
+		if (!(error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NO_REPLY)) {
+			g_warning ("%s: couldn't retrieve system settings properties: (%d) %s.",
+			           __func__,
+			           error ? error->code : -1,
+			           (error && error->message) ? error->message : "(unknown)");
+		}
+		g_clear_error (&error);
+		return;
+	}
+
+	properties_changed_cb (NULL, props, self);
+	g_hash_table_destroy (props);
+}
+
+typedef struct {
+	NMSettingsSystemInterface *settings;
+	NMSettingsSystemSaveHostnameFunc callback;
+	gpointer callback_data;
+} SaveHostnameInfo;
+
+static void
+save_hostname_cb (DBusGProxy *proxy,
+                  DBusGProxyCall *call,
+                  gpointer user_data)
+{
+	SaveHostnameInfo *info = user_data;
+	GError *error = NULL;
+
+	dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID);
+	info->callback (info->settings, error, info->callback_data);
+	g_clear_error (&error);
+}
+
+static gboolean
+save_hostname (NMSettingsSystemInterface *settings,
+	           const char *hostname,
+	           NMSettingsSystemSaveHostnameFunc callback,
+	           gpointer user_data)
+{
+	NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (settings);
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
+	SaveHostnameInfo *info;
+
+	info = g_malloc0 (sizeof (SaveHostnameInfo));
+	info->settings = settings;
+	info->callback = callback;
+	info->callback_data = user_data;
+
+	dbus_g_proxy_begin_call (priv->proxy, "SaveHostname",
+	                         save_hostname_cb,
+	                         info,
+	                         g_free,
+	                         G_TYPE_STRING, hostname ? hostname : "",
+	                         G_TYPE_INVALID);
+	return TRUE;
+}
+
+typedef struct {
+	NMSettingsSystemInterface *settings;
+	NMSettingsSystemGetPermissionsFunc callback;
+	gpointer callback_data;
+} GetPermissionsInfo;
+
+static void
+get_permissions_cb  (DBusGProxy *proxy,
+                     DBusGProxyCall *call,
+                     gpointer user_data)
+{
+	GetPermissionsInfo *info = user_data;
+	NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (info->settings);
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
+	NMSettingsSystemPermissions permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE;
+	GError *error = NULL;
+
+	dbus_g_proxy_end_call (proxy, call, &error,
+	                       G_TYPE_UINT, &permissions,
+	                       G_TYPE_INVALID);
+	priv->permissions = permissions;
+	priv->have_permissions = !error;
+	info->callback (info->settings, permissions, error, info->callback_data);
+	g_clear_error (&error);
+}
+
+static gboolean
+get_permissions (NMSettingsSystemInterface *settings,
+                 NMSettingsSystemGetPermissionsFunc callback,
+                 gpointer user_data)
+{
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (settings);
+	GetPermissionsInfo *info;
+
+	/* Skip D-Bus if we already have permissions */
+	if (priv->have_permissions) {
+		callback (settings, priv->permissions, NULL, user_data);
+		return TRUE;
+	}
+
+	/* Otherwise fetch them from NM */
+	info = g_malloc0 (sizeof (GetPermissionsInfo));
+	info->settings = settings;
+	info->callback = callback;
+	info->callback_data = user_data;
+
+	dbus_g_proxy_begin_call (priv->proxy, "GetPermissions",
+	                         get_permissions_cb,
+	                         info,
+	                         g_free,
+	                         G_TYPE_INVALID);
+	return TRUE;
+}
+
+static void
+check_permissions_cb (DBusGProxy *proxy, gpointer user_data)
+{
+	NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data);
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
+
+	/* Permissions need to be re-fetched */
+	priv->have_permissions = FALSE;
+	g_signal_emit_by_name (self, NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS);
+}
+
+/****************************************************************/
+
+static void
+settings_system_interface_init (NMSettingsSystemInterface *klass)
+{
+	/* interface implementation */
+	klass->save_hostname = save_hostname;
+	klass->get_permissions = get_permissions;
+}
+
+/**
+ * nm_remote_settings_system_new:
+ * @bus: a valid and connected D-Bus connection
+ *
+ * Creates a new object representing the remote system settings service.
+ *
+ * Returns: the new remote system settings object on success, or %NULL on failure
+ **/
+NMRemoteSettingsSystem *
+nm_remote_settings_system_new (DBusGConnection *bus)
+{
+	g_return_val_if_fail (bus != NULL, NULL);
+
+	return (NMRemoteSettingsSystem *) g_object_new (NM_TYPE_REMOTE_SETTINGS_SYSTEM,
+	                                                NM_REMOTE_SETTINGS_BUS, bus,
+	                                                NM_REMOTE_SETTINGS_SCOPE, NM_CONNECTION_SCOPE_SYSTEM,
+	                                                NULL);
+}
+
+static void
+nm_remote_settings_system_init (NMRemoteSettingsSystem *self)
+{
+}
+
+static GObject *
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMRemoteSettingsSystemPrivate *priv;
+	DBusGConnection *bus = NULL;
+
+	object = G_OBJECT_CLASS (nm_remote_settings_system_parent_class)->constructor (type, n_construct_params, construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object);
+
+	g_object_get (G_OBJECT (object), NM_REMOTE_SETTINGS_BUS, &bus, NULL);
+	g_assert (bus);
+
+	/* D-Bus properties proxy */
+	priv->props_proxy = dbus_g_proxy_new_for_name (bus,
+	                                               NM_DBUS_SERVICE_SYSTEM_SETTINGS,
+	                                               NM_DBUS_PATH_SETTINGS,
+	                                               "org.freedesktop.DBus.Properties");
+	g_assert (priv->props_proxy);
+
+	/* System settings proxy */
+	priv->proxy = dbus_g_proxy_new_for_name (bus,
+	                                         NM_DBUS_SERVICE_SYSTEM_SETTINGS,
+	                                         NM_DBUS_PATH_SETTINGS,
+	                                         NM_DBUS_IFACE_SETTINGS_SYSTEM);
+	g_assert (priv->proxy);
+	dbus_g_proxy_set_default_timeout (priv->proxy, G_MAXINT);
+
+	dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED,
+	                                   G_TYPE_NONE,
+	                                   DBUS_TYPE_G_MAP_OF_VARIANT,
+	                                   G_TYPE_INVALID);
+	dbus_g_proxy_add_signal (priv->proxy, "PropertiesChanged",
+	                         DBUS_TYPE_G_MAP_OF_VARIANT,
+	                         G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "PropertiesChanged",
+	                             G_CALLBACK (properties_changed_cb),
+	                             object,
+	                             NULL);
+
+	/* Monitor for permissions changes */
+	dbus_g_proxy_add_signal (priv->proxy, "CheckPermissions", G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "CheckPermissions",
+	                             G_CALLBACK (check_permissions_cb),
+	                             object,
+	                             NULL);
+
+	/* Get properties */
+	dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
+	                         get_all_cb,
+	                         object,
+	                         NULL,
+	                         G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS_SYSTEM,
+	                         G_TYPE_INVALID);
+
+	dbus_g_connection_unref (bus);
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object);
+
+	if (priv->disposed)
+		return;
+
+	priv->disposed = TRUE;
+
+	g_free (priv->hostname);
+
+	g_object_unref (priv->props_proxy);
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_remote_settings_system_parent_class)->dispose (object);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME:
+		g_value_set_string (value, priv->hostname);
+		break;
+	case NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY:
+		g_value_set_boolean (value, priv->can_modify);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_remote_settings_system_class_init (NMRemoteSettingsSystemClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (NMRemoteSettingsSystemPrivate));
+
+	/* Virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+
+	/* Properties */
+	g_object_class_override_property (object_class,
+									  NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME,
+									  NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME);
+
+	g_object_class_override_property (object_class,
+									  NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY,
+									  NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY);
+}
+