[network-manager-netbook] Add gnome-bluetooth plugin



commit 37433bc6b912fe0d69aa4941a0dc5072fea5da58
Author: Tambet Ingo <tambet gmail com>
Date:   Wed Dec 9 15:38:45 2009 +0200

    Add gnome-bluetooth plugin
    
    Copied from network-manager-applet and modified to handle system connections,
    not re-read everything from GConf, not leak GConf settings etc. This should
    be changed in nm-applet as well.

 Makefile.am                              |    2 +-
 configure.in                             |   10 +
 gnome-bluetooth/Makefile.am              |   15 ++
 gnome-bluetooth/network-manager-applet.c |  344 ++++++++++++++++++++++++++++++
 libnm-gtk/nm-gconf-settings.c            |   81 ++++++-
 po/POTFILES.in                           |    1 +
 src/nmn-panel-client.c                   |    1 +
 7 files changed, 441 insertions(+), 13 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 1d7321d..3755ab9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = icons marshallers libnm-gtk src po
+SUBDIRS = icons marshallers libnm-gtk src gnome-bluetooth po
 
 autostartdir = $(sysconfdir)/xdg/autostart
 autostart_in_files = network-manager-netbook.desktop.in
diff --git a/configure.in b/configure.in
index c9087a5..9cee737 100644
--- a/configure.in
+++ b/configure.in
@@ -28,11 +28,21 @@ PKG_CHECK_MODULES(LIBNM_GTK, gtk+-2.0 gconf-2.0 gnome-keyring-1 libnm-util >= $N
 
 PKG_CHECK_MODULES(NMN, dbus-glib-1 >= 0.75 gtk+-2.0 gconf-2.0 gnome-keyring-1 libnotify libnm-util >= $NM_REQUIRED libnm-glib >= $NM_REQUIRED mobile-broadband-provider-info moblin-panel nbtk-gtk-1.2)
 
+dnl Check for gnome-bluetooth
+PKG_CHECK_MODULES(GNOME_BLUETOOTH,
+		  gconf-2.0
+		  gnome-bluetooth-1.0 >= 2.27.6
+		  libnm-util
+		  libnm-glib,
+		  have_gbt=yes, have_gbt=no)
+AM_CONDITIONAL(HAVE_GBT, test x"$have_gbt" = "xyes")
+
 GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0`
 AC_SUBST(GLIB_GENMARSHAL)
 
 AC_CONFIG_FILES([
 Makefile
+gnome-bluetooth/Makefile
 icons/Makefile
 icons/22/Makefile
 icons/32/Makefile
diff --git a/gnome-bluetooth/Makefile.am b/gnome-bluetooth/Makefile.am
new file mode 100644
index 0000000..6406ab7
--- /dev/null
+++ b/gnome-bluetooth/Makefile.am
@@ -0,0 +1,15 @@
+plugindir = $(libdir)/gnome-bluetooth/plugins
+
+if HAVE_GBT
+plugin_LTLIBRARIES = libnma.la
+
+libnma_la_CPPFLAGS = \
+	-I${top_srcdir}/libnm-gtk \
+	$(GNOME_BLUETOOTH_CFLAGS)
+
+libnma_la_SOURCES = network-manager-applet.c
+libnma_la_LDFLAGS = -module -avoid-version
+libnma_la_LIBADD = $(top_builddir)/libnm-gtk/libnm-gtk.la $(GNOME_BLUETOOTH_LIBS)
+endif
+
+EXTRA_DIST = network-manager-applet.c
diff --git a/gnome-bluetooth/network-manager-applet.c b/gnome-bluetooth/network-manager-applet.c
new file mode 100644
index 0000000..e9a8117
--- /dev/null
+++ b/gnome-bluetooth/network-manager-applet.c
@@ -0,0 +1,344 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009  Bastien Nocera <hadess hadess net>
+ *
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <net/ethernet.h>
+#include <netinet/ether.h>
+#include <glib/gi18n-lib.h>
+
+#include <gtk/gtk.h>
+#include <bluetooth-plugin.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-bluetooth.h>
+#include <nm-setting-ip4-config.h>
+#include <nm-utils.h>
+#include <nm-settings-interface.h>
+#include <nm-remote-settings.h>
+#include <nm-remote-settings-system.h>
+#include <gconf-helpers.h>
+
+static gboolean
+has_config_widget (const char *bdaddr, const char **uuids)
+{
+	guint i;
+
+	for (i = 0; uuids && uuids[i] != NULL; i++) {
+		if (g_str_equal (uuids[i], "NAP"))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static GByteArray *
+get_array_from_bdaddr (const char *str)
+{
+	struct ether_addr *addr;
+	GByteArray *array;
+
+	addr = ether_aton (str);
+	if (addr) {
+		array = g_byte_array_sized_new (ETH_ALEN);
+		g_byte_array_append (array, (const guint8 *) addr->ether_addr_octet, ETH_ALEN);
+		return array;
+	}
+
+	return NULL;
+}
+
+typedef struct {
+	GSList *settings;
+	GMainLoop *loop;
+	guint counter;
+} GetSettingsSyncInfo;
+
+static void
+connection_added (NMSettingsInterface *settings,
+				  NMSettingsConnectionInterface *connection,
+				  gpointer user_data)
+{
+	GetSettingsSyncInfo *info = user_data;
+
+	info->settings = g_slist_prepend (info->settings, g_object_ref (connection));
+}
+
+static void
+connections_read (NMSettingsInterface *settings,
+				  gpointer user_data)
+{
+	GetSettingsSyncInfo *info = user_data;
+
+	info->counter--;
+	if (info->counter < 1)
+		g_main_loop_quit (info->loop);
+}
+
+static gboolean
+get_settings_timed_out (gpointer user_data)
+{
+	GetSettingsSyncInfo *info = user_data;
+
+	g_warning ("Getting settings timed out");
+	g_main_loop_quit (info->loop);
+
+	return FALSE;
+}
+
+static GSList *
+get_settings_sync ()
+{
+	DBusGConnection *bus;
+	NMSettingsInterface *user_settings;
+	NMSettingsInterface *system_settings;
+	GetSettingsSyncInfo info;
+	GError *err = NULL;
+	gboolean running;
+
+	bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
+	if (!bus) {
+		g_warning ("Couldn't connect to system bus: %s", err->message);
+		g_error_free (err);
+		return NULL;
+	}
+
+	info.settings = NULL;
+	info.loop = g_main_loop_new (NULL, FALSE);
+	info.counter = 0;
+
+	user_settings = NM_SETTINGS_INTERFACE (nm_remote_settings_new (bus, NM_CONNECTION_SCOPE_USER));
+	g_object_get (user_settings, NM_REMOTE_SETTINGS_SERVICE_RUNNING, &running, NULL);
+	if (running) {
+		g_signal_connect (user_settings, "new-connection", G_CALLBACK (connection_added), &info);
+		g_signal_connect (user_settings, "connections-read", G_CALLBACK (connections_read), &info);
+		info.counter++;
+	}
+
+	system_settings = NM_SETTINGS_INTERFACE (nm_remote_settings_system_new (bus));
+	g_object_get (system_settings, NM_REMOTE_SETTINGS_SERVICE_RUNNING, &running, NULL);
+	if (running) {
+		g_signal_connect (system_settings, "new-connection", G_CALLBACK (connection_added), &info);
+		g_signal_connect (system_settings, "connections-read", G_CALLBACK (connections_read), &info);
+		info.counter++;
+	}
+
+	dbus_g_connection_unref (bus);
+
+	if (info.counter > 0) {
+		/* Add a timer so that we don't wait here forever in case we never
+		   get signaled that services are read */
+		g_timeout_add_seconds (5, get_settings_timed_out, &info);
+		g_main_loop_run (info.loop);
+	}
+
+	g_main_loop_unref (info.loop);
+	g_object_unref (user_settings);
+	g_object_unref (system_settings);
+
+	return info.settings;
+}
+
+static NMSettingsConnectionInterface *
+get_connection_for_bdaddr (const char *bdaddr)
+{
+	NMSettingsConnectionInterface *found = NULL;
+	GSList *list, *l;
+	GByteArray *array;
+
+	array = get_array_from_bdaddr (bdaddr);
+	if (array == NULL)
+		return NULL;
+
+	list = get_settings_sync ();
+	for (l = list; l != NULL; l = l->next) {
+		NMSettingsConnectionInterface *candidate = l->data;
+		NMSetting *setting;
+		const char *type;
+		const GByteArray *addr;
+
+		setting = nm_connection_get_setting_by_name (NM_CONNECTION (candidate), NM_SETTING_BLUETOOTH_SETTING_NAME);
+		if (setting == NULL)
+			continue;
+		type = nm_setting_bluetooth_get_connection_type (NM_SETTING_BLUETOOTH (setting));
+		if (g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_PANU) != 0)
+			continue;
+		addr = nm_setting_bluetooth_get_bdaddr (NM_SETTING_BLUETOOTH (setting));
+		if (addr == NULL || memcmp (addr->data, array->data, addr->len) != 0)
+			continue;
+		found = g_object_ref (candidate);
+		break;
+	}
+
+	g_slist_foreach (list, (GFunc) g_object_unref, NULL);
+	g_slist_free (list);
+
+	return found;
+}
+
+static NMConnection *
+create_connection (const char *bdaddr)
+{
+	NMConnection *connection;
+	NMSetting *setting;
+	GByteArray *mac;
+	char *id, *uuid;
+
+	mac = get_array_from_bdaddr (bdaddr);
+	if (mac == NULL)
+		return NULL;
+
+	/* The connection */
+	connection = nm_connection_new ();
+
+	/* The connection settings */
+	setting = nm_setting_connection_new ();
+	id = g_strdup_printf ("%s %s", bdaddr, "PANU");
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (G_OBJECT (setting),
+	              NM_SETTING_CONNECTION_ID, id,
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_SETTING_NAME,
+	              NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+	              NULL);
+	g_free (id);
+	g_free (uuid);
+	nm_connection_add_setting (connection, setting);
+
+	/* The Bluetooth settings */
+	setting = nm_setting_bluetooth_new ();
+	g_object_set (G_OBJECT (setting),
+	              NM_SETTING_BLUETOOTH_BDADDR, mac,
+	              NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
+	              NULL);
+	g_byte_array_free (mac, TRUE);
+	nm_connection_add_setting (connection, setting);
+
+	/* The IPv4 settings */
+	setting = nm_setting_ip4_config_new ();
+	g_object_set (G_OBJECT (setting),
+	              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+	              NULL);
+	nm_connection_add_setting (connection, setting);
+
+	nm_gconf_write_connection (connection, NULL, NULL);
+
+	return connection;
+}
+
+static void
+delete_cb (NMSettingsConnectionInterface *connection,
+           GError *error,
+           gpointer user_data)
+{
+	if (error)
+		g_warning ("Error deleting connection: (%d) %s", error->code, error->message);
+	if (user_data)
+		g_object_set_data (G_OBJECT (user_data), "conn", NULL);
+}
+
+static void
+delete_connection (GObject *button, NMConnection *connection)
+{
+	NMSettingsConnectionInterface *ci;
+
+	if (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection))
+		ci = NM_SETTINGS_CONNECTION_INTERFACE (connection);
+	else {
+		const char *bdaddr;
+
+		bdaddr = g_object_get_data (button, "bdaddr");
+		g_assert (bdaddr);
+		ci = get_connection_for_bdaddr (bdaddr);
+	}
+
+	if (ci)
+		nm_settings_connection_interface_delete (ci, delete_cb, button);
+}
+
+static void
+button_toggled (GtkToggleButton *button, gpointer user_data)
+{
+	NMConnection *connection;
+
+	if (gtk_toggle_button_get_active (button) == FALSE) {
+		connection = g_object_get_data (G_OBJECT (button), "conn");
+		delete_connection (G_OBJECT (button), connection);
+	} else {
+		const char *bdaddr;
+
+		bdaddr = g_object_get_data (G_OBJECT (button), "bdaddr");
+		g_assert (bdaddr);
+
+		connection = create_connection (bdaddr);
+		if (connection)
+			g_object_set_data_full (G_OBJECT (button), "conn", connection, g_object_unref);
+	}
+}
+
+static GtkWidget *
+get_config_widgets (const char *bdaddr, const char **uuids)
+{
+	GtkWidget *button;
+	NMSettingsConnectionInterface *connection;
+
+	button = gtk_check_button_new_with_label (_("Access the Internet using your mobile phone"));
+	g_object_set_data_full (G_OBJECT (button),
+	                        "bdaddr", g_strdup (bdaddr),
+	                        (GDestroyNotify) g_free);
+	connection = get_connection_for_bdaddr (bdaddr);
+	if (connection != NULL) {
+		g_object_set_data_full (G_OBJECT (button), "conn", connection, g_object_unref);
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+	}
+	g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (button_toggled), NULL);
+
+	return button;
+}
+
+static void
+device_removed (const char *bdaddr)
+{
+	NMSettingsConnectionInterface *connection;
+
+	g_message ("Device '%s' got removed", bdaddr);
+
+	// FIXME: don't just delete any random PAN conenction for this
+	// bdaddr, actually delete the one this plugin created
+	connection = get_connection_for_bdaddr (bdaddr);
+	if (connection) {
+		nm_settings_connection_interface_delete (connection, delete_cb, NULL);
+		g_object_unref (connection);
+	}
+}
+
+static GbtPluginInfo plugin_info = {
+	"network-manager-applet",
+	has_config_widget,
+	get_config_widgets,
+	device_removed
+};
+
+GBT_INIT_PLUGIN(plugin_info)
+
diff --git a/libnm-gtk/nm-gconf-settings.c b/libnm-gtk/nm-gconf-settings.c
index e9b0b21..062b34f 100644
--- a/libnm-gtk/nm-gconf-settings.c
+++ b/libnm-gtk/nm-gconf-settings.c
@@ -180,6 +180,67 @@ nm_gconf_settings_add_connection (NMGConfSettings *self, NMConnection *connectio
 	return exported;
 }
 
+static gboolean
+is_dbus_request_authorized (DBusGMethodInvocation *context,
+                            GError **error)
+{
+	DBusGConnection *bus = NULL;
+	DBusConnection *connection = NULL;
+	char *sender = NULL;
+	gulong sender_uid = G_MAXULONG;
+	DBusError dbus_error;
+	gboolean success = FALSE;
+
+	sender = dbus_g_method_get_sender (context);
+	if (!sender) {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		             "%s", "Could not determine D-Bus requestor");
+		goto out;
+	}
+
+	bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+	if (!bus) {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		             "%s", "Could not get the system bus");
+		goto out;
+	}
+	connection = dbus_g_connection_get_connection (bus);
+	if (!connection) {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+		             "%s", "Could not get the D-Bus system bus");
+		goto out;
+	}
+
+	dbus_error_init (&dbus_error);
+	sender_uid = dbus_bus_get_unix_user (connection, sender, &dbus_error);
+	if (dbus_error_is_set (&dbus_error)) {
+		dbus_error_free (&dbus_error);
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_PERMISSION_DENIED,
+		             "%s", "Could not determine the Unix user ID of the requestor");
+		goto out;
+	}
+
+	/* And finally, the actual UID check */
+	if (sender_uid == geteuid ())
+		success = TRUE;
+	else {
+		g_set_error (error, NM_SETTINGS_INTERFACE_ERROR,
+		             NM_SETTINGS_INTERFACE_ERROR_PERMISSION_DENIED,
+		             "%s", "Requestor UID does not match the UID of the user settings service");
+	}
+
+ out:
+	if (bus)
+		dbus_g_connection_unref (bus);
+
+	g_free (sender);
+	return success;
+}
+
 static void
 add_connection (NMSettingsService *settings,
                 NMConnection *connection,
@@ -188,21 +249,17 @@ add_connection (NMSettingsService *settings,
                 gpointer user_data)
 {
 	NMGConfSettings *self = NM_GCONF_SETTINGS (settings);
+	GError *error = NULL;
 
-	/* For now, we don't support additions via D-Bus until we figure out
-	 * the security implications.
-	 */
-	if (context) {
-		GError *error;
+	if (context)
+		is_dbus_request_authorized (context, &error);
 
-		error = g_error_new (0, 0, "%s: adding connections via D-Bus is not (yet) supported", __func__);
-		callback (NM_SETTINGS_INTERFACE (settings), error, user_data);
-		g_error_free (error);
-		return;
-	}
+	if (!error)
+		nm_gconf_settings_add_connection (self, connection);
 
-	nm_gconf_settings_add_connection (self, connection);
-	callback (NM_SETTINGS_INTERFACE (settings), NULL, user_data);
+	callback (NM_SETTINGS_INTERFACE (settings), error, user_data);
+	if (error)
+		g_error_free (error);
 }
 
 static NMGConfConnection *
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 934405a..7cc96fd 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,4 +1,5 @@
 network-manager-netbook.desktop.in
+gnome-bluetooth/networm-manager-applet.c
 libnm-gtk/nm-bt-item.c
 libnm-gtk/nm-ethernet-item.c
 libnm-gtk/nm-wifi-item.c
diff --git a/src/nmn-panel-client.c b/src/nmn-panel-client.c
index 138b66f..48e124a 100644
--- a/src/nmn-panel-client.c
+++ b/src/nmn-panel-client.c
@@ -96,6 +96,7 @@ activation_animation (gpointer data)
         priv->animation_step = 1;
 
     image = g_strdup_printf ("progress-%02d", priv->animation_step);
+    g_print ("Requesting button style %s", image);
     mpl_panel_client_request_button_style (MPL_PANEL_CLIENT (self), image);
     g_free (image);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]