Blob Blame History Raw
From 04b92f38a2ebce2479670580857f722e9b3b3be4 Mon Sep 17 00:00:00 2001
From: Dan Williams <dcbw@redhat.com>
Date: Tue, 25 Nov 2014 17:45:05 -0600
Subject: [PATCH 1/2] Revert "applet: don't check for gnome shell (bgo
 #707953)"

This reverts commit 4473e6a48fcfda1d87d4a4bc9f5c0589235dcfe0.
---
 src/applet.c        |  47 +++++++++-
 src/applet.h        |   4 +
 src/shell-watcher.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/shell-watcher.h |  56 ++++++++++++
 4 files changed, 347 insertions(+), 1 deletion(-)
 create mode 100644 src/shell-watcher.c
 create mode 100644 src/shell-watcher.h

diff --git a/src/applet.c b/src/applet.c
index f0536f8..f3f4344 100644
--- a/src/applet.c
+++ b/src/applet.c
@@ -87,6 +87,7 @@
 #include "nm-wifi-dialog.h"
 #include "applet-vpn-request.h"
 #include "utils.h"
+#include "shell-watcher.h"
 #include "nm-ui-utils.h"
 #include "nm-glib-compat.h"
 
@@ -3542,6 +3543,39 @@ register_agent (NMApplet *applet)
 	                  G_CALLBACK (applet_agent_cancel_secrets_cb), applet);
 }
 
+static void
+shell_version_changed_cb (NMShellWatcher *watcher, GParamSpec *pspec, gpointer user_data)
+{
+	NMApplet *applet = user_data;
+
+	if (nm_shell_watcher_version_at_least (watcher, 3, 0)) {
+		g_debug ("gnome-shell is running");
+
+		if (applet->agent) {
+			g_debug ("destroying secret agent");
+
+			g_signal_handlers_disconnect_by_func (applet->agent,
+			                                      G_CALLBACK (applet_agent_get_secrets_cb),
+			                                      applet);
+			g_signal_handlers_disconnect_by_func (applet->agent,
+			                                      G_CALLBACK (applet_agent_cancel_secrets_cb),
+			                                      applet);
+			nm_secret_agent_unregister (NM_SECRET_AGENT (applet->agent));
+			g_clear_object (&applet->agent);
+		}
+
+		/* We don't need the watcher any more */
+		g_signal_handlers_disconnect_by_func (applet->shell_watcher,
+		                                      G_CALLBACK (shell_version_changed_cb),
+		                                      applet);
+		g_clear_object (&applet->shell_watcher);
+	} else if (!applet->agent) {
+		/* No shell */
+		g_debug ("gnome-shell is not running, registering secret agent");
+		register_agent (applet);
+	}
+}
+
 static gboolean
 dbus_setup (NMApplet *applet, GError **error)
 {
@@ -3694,7 +3728,15 @@ initable_init (GInitable *initable, GCancellable *cancellable, GError **error)
 	                  G_CALLBACK (applet_embedded_cb), NULL);
 	applet_embedded_cb (G_OBJECT (applet->status_icon), NULL, NULL);
 
-	register_agent (applet);
+	/* Watch GNOME Shell so we can unregister our applet agent if it appears */
+	if (!shell_debug) {
+		applet->shell_watcher = nm_shell_watcher_new ();
+		g_signal_connect (applet->shell_watcher,
+			              "notify::shell-version",
+			              G_CALLBACK (shell_version_changed_cb),
+			              applet);
+	} else
+		register_agent (applet);
 
 	return TRUE;
 }
@@ -3764,6 +3806,9 @@ static void finalize (GObject *object)
 	if (applet->session_bus)
 		dbus_g_connection_unref (applet->session_bus);
 
+	if (applet->shell_watcher)
+		g_object_unref (applet->shell_watcher);
+
 	G_OBJECT_CLASS (nma_parent_class)->finalize (object);
 }
 
diff --git a/src/applet.h b/src/applet.h
index 23632f7..cd5ac97 100644
--- a/src/applet.h
+++ b/src/applet.h
@@ -44,6 +44,7 @@
 #include <nm-active-connection.h>
 #include <nm-remote-settings.h>
 #include "applet-agent.h"
+#include "shell-watcher.h"
 
 #if WITH_MODEM_MANAGER_1
 #include <libmm-glib.h>
@@ -86,6 +87,9 @@ typedef struct
 	GMainLoop *loop;
 	DBusGConnection *session_bus;
 
+	NMShellWatcher *shell_watcher;
+	guint agent_start_id;
+
 	NMClient *nm_client;
 	NMRemoteSettings *settings;
 	AppletAgent *agent;
diff --git a/src/shell-watcher.c b/src/shell-watcher.c
new file mode 100644
index 0000000..da62121
--- /dev/null
+++ b/src/shell-watcher.c
@@ -0,0 +1,241 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "shell-watcher.h"
+
+G_DEFINE_TYPE (NMShellWatcher, nm_shell_watcher, G_TYPE_OBJECT)
+
+struct NMShellWatcherPrivate {
+	GDBusProxy *shell_proxy;
+	guint signal_id;
+
+	guint retry_timeout;
+	guint retries;
+
+	guint shell_version;
+	gboolean shell_version_set;
+};
+
+enum {
+	PROP_0,
+	PROP_SHELL_VERSION,
+	LAST_PROP
+};
+
+static void create_gnome_shell_proxy (NMShellWatcher *watcher);
+
+static gboolean
+retry_create_shell_proxy (gpointer user_data)
+{
+	NMShellWatcher *watcher = user_data;
+	NMShellWatcherPrivate *priv = watcher->priv;
+
+	priv->retry_timeout = 0;
+	create_gnome_shell_proxy (watcher);
+	return FALSE;
+}
+
+static void
+try_update_version (NMShellWatcher *watcher)
+{
+	NMShellWatcherPrivate *priv = watcher->priv;
+	GVariant *v;
+	char *version, *p;
+
+	v = g_dbus_proxy_get_cached_property (priv->shell_proxy, "ShellVersion");
+	if (!v) {
+		/* The shell has claimed the name, but not yet registered its interfaces...
+		 * (https://bugzilla.gnome.org/show_bug.cgi?id=673182). There's no way
+		 * to make GDBusProxy re-read the properties at this point, so we
+		 * have to destroy this proxy and try again.
+		 */
+		if (priv->signal_id) {
+			g_signal_handler_disconnect (priv->shell_proxy, priv->signal_id);
+			priv->signal_id = 0;
+		}
+		g_object_unref (priv->shell_proxy);
+		priv->shell_proxy = NULL;
+
+		priv->retry_timeout = g_timeout_add_seconds (2, retry_create_shell_proxy, watcher); 
+		return;
+	}
+
+	g_warn_if_fail (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING));
+	version = g_variant_dup_string (v, NULL);
+	if (version) {
+		guint major, minor;
+
+		major = strtoul (version, &p, 10);
+		if (*p == '.')
+			minor = strtoul (p + 1, NULL, 10);
+		else
+			minor = 0;
+
+		g_warn_if_fail (major < 256);
+		g_warn_if_fail (minor < 256);
+
+		priv->shell_version = (major << 8) | minor;
+		priv->shell_version_set = TRUE;
+		g_object_notify (G_OBJECT (watcher), "shell-version");
+	}
+
+	g_variant_unref (v);
+}
+
+static void
+name_owner_changed_cb (GDBusProxy *proxy, GParamSpec *pspec, gpointer user_data)
+{
+	NMShellWatcher *watcher = user_data;
+	NMShellWatcherPrivate *priv = watcher->priv;
+	char *owner;
+
+	owner = g_dbus_proxy_get_name_owner (proxy);
+	if (owner) {
+		try_update_version (watcher);
+		g_free (owner);
+	} else if (priv->shell_version || !priv->shell_version_set) {
+		priv->shell_version = 0;
+		priv->shell_version_set = TRUE;
+		g_object_notify (G_OBJECT (watcher), "shell-version");
+	}
+}
+
+static void
+got_shell_proxy (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	NMShellWatcher *watcher = user_data;
+	NMShellWatcherPrivate *priv = watcher->priv;
+	GError *error = NULL;
+
+	priv->shell_proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
+	if (!priv->shell_proxy) {
+		g_warning ("Could not create GDBusProxy for org.gnome.Shell: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	priv->signal_id = g_signal_connect (priv->shell_proxy,
+	                                    "notify::g-name-owner",
+	                                    G_CALLBACK (name_owner_changed_cb),
+	                                    watcher);
+
+	name_owner_changed_cb (priv->shell_proxy, NULL, watcher);
+	g_object_unref (watcher);
+}
+
+static void
+create_gnome_shell_proxy (NMShellWatcher *watcher)
+{
+	NMShellWatcherPrivate *priv = watcher->priv;
+
+	if (priv->retries++ == 5) {
+		g_warning ("Could not find ShellVersion property on org.gnome.Shell after 5 tries");
+		return;
+	}
+
+	g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+	                          G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+	                          NULL,
+	                          "org.gnome.Shell",
+	                          "/org/gnome/Shell",
+	                          "org.gnome.Shell",
+	                          NULL,
+	                          got_shell_proxy,
+	                          g_object_ref (watcher));
+}
+
+static void
+nm_shell_watcher_init (NMShellWatcher *watcher)
+{
+	watcher->priv = G_TYPE_INSTANCE_GET_PRIVATE (watcher, NM_TYPE_SHELL_WATCHER,
+	                                             NMShellWatcherPrivate);
+	create_gnome_shell_proxy (watcher);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	NMShellWatcher *watcher = NM_SHELL_WATCHER (object);
+
+	switch (prop_id) {
+	case PROP_SHELL_VERSION:
+		g_value_set_uint (value, watcher->priv->shell_version);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+finalize (GObject *object)
+{
+	NMShellWatcher *watcher = NM_SHELL_WATCHER (object);
+	NMShellWatcherPrivate *priv = watcher->priv;
+
+	if (priv->retry_timeout)
+		g_source_remove (priv->retry_timeout);
+	if (priv->signal_id)
+		g_signal_handler_disconnect (priv->shell_proxy, priv->signal_id);
+	if (priv->shell_proxy)
+		g_object_unref (priv->shell_proxy);
+
+	G_OBJECT_CLASS (nm_shell_watcher_parent_class)->finalize (object);
+}
+
+static void
+nm_shell_watcher_class_init (NMShellWatcherClass *klass)
+{
+	GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (NMShellWatcherPrivate));
+
+	oclass->get_property = get_property;
+	oclass->finalize = finalize;
+
+	g_object_class_install_property (oclass, PROP_SHELL_VERSION,
+	                                 g_param_spec_uint ("shell-version",
+	                                                    "Shell version",
+	                                                    "Running GNOME Shell version, eg, 0x0304",
+	                                                    0, 0xFFFF, 0,
+	                                                    G_PARAM_READABLE |
+	                                                    G_PARAM_STATIC_STRINGS));
+}
+
+NMShellWatcher *
+nm_shell_watcher_new (void)
+{
+	return g_object_new (NM_TYPE_SHELL_WATCHER, NULL);
+}
+
+gboolean
+nm_shell_watcher_version_at_least (NMShellWatcher *watcher, guint major, guint minor)
+{
+	guint version = (major << 8) | minor;
+
+	return watcher->priv->shell_version >= version;
+}
diff --git a/src/shell-watcher.h b/src/shell-watcher.h
new file mode 100644
index 0000000..a6065f8
--- /dev/null
+++ b/src/shell-watcher.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ */
+
+#ifndef SHELL_WATCHER_H
+#define SHELL_WATCHER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gio/gio.h>
+
+#define NM_TYPE_SHELL_WATCHER			(nm_shell_watcher_get_type())
+#define NM_SHELL_WATCHER(object)		(G_TYPE_CHECK_INSTANCE_CAST((object), NM_TYPE_SHELL_WATCHER, NMShellWatcher))
+#define NM_SHELL_WATCHER_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SHELL_WATCHER, NMShellWatcherClass))
+#define NM_IS_SHELL_WATCHER(object)		(G_TYPE_CHECK_INSTANCE_TYPE((object), NM_TYPE_SHELL_WATCHER))
+#define NM_IS_SHELL_WATCHER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SHELL_WATCHER))
+#define NM_SHELL_WATCHER_GET_CLASS(object)	(G_TYPE_INSTANCE_GET_CLASS((object), NM_TYPE_SHELL_WATCHER, NMShellWatcherClass))
+
+typedef struct NMShellWatcherPrivate NMShellWatcherPrivate;
+
+typedef struct {
+	GObject parent_instance;
+
+	NMShellWatcherPrivate *priv;
+} NMShellWatcher;
+
+typedef struct {
+	GObjectClass parent_class;
+} NMShellWatcherClass;
+
+GType nm_shell_watcher_get_type (void);
+
+NMShellWatcher *nm_shell_watcher_new (void);
+
+gboolean nm_shell_watcher_version_at_least (NMShellWatcher *watcher,
+                                            guint major, guint minor);
+
+#endif
-- 
1.9.3

From bfc24e17555126bb1a9783c2d3c2771bb886ed58 Mon Sep 17 00:00:00 2001
From: Dan Williams <dcbw@redhat.com>
Date: Tue, 25 Nov 2014 17:45:11 -0600
Subject: [PATCH 2/2] Revert "build: fix build after "applet: don't check for
 gnome shell (bgo #707953)""

This reverts commit 2014927869cb92be2c9e360f1a6a4b118b866403.
---
 src/Makefile.am | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 0e85dd5..d8c1238 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -69,7 +69,9 @@ nm_applet_SOURCES = \
 	applet-device-bridge.c \
 	applet-device-infiniband.h \
 	applet-device-infiniband.c \
-	fallback-icon.h
+	fallback-icon.h \
+	shell-watcher.h \
+	shell-watcher.c
 
 nm_applet_LDADD = \
 	-lm \
-- 
1.9.3