[gnome-session] gsm: Add a new system to get information and frob Shell Extensions
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-session] gsm: Add a new system to get information and frob Shell Extensions
- Date: Fri, 26 Aug 2011 23:01:23 +0000 (UTC)
commit aadad2377c841570b90a409c0a9ae51429cfff6c
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Wed Aug 17 01:13:52 2011 -0400
gsm: Add a new system to get information and frob Shell Extensions
This functionality will be used to allow the user to enable and disable GNOME
Shell Extensions in the fail whale dialog after a crash.
https://bugzilla.gnome.org/show_bug.cgi?id=656747
configure.ac | 2 +
gnome-session/Makefile.am | 2 +
gnome-session/gsm-shell-extensions.c | 375 ++++++++++++++++++++++++++++++++++
gnome-session/gsm-shell-extensions.h | 84 ++++++++
4 files changed, 463 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index b1833d5..1af6c3a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -36,6 +36,7 @@ GLIB_REQUIRED=2.28.0
GTK3_REQUIRED=2.90.7
DBUS_GLIB_REQUIRED=0.76
UPOWER_REQUIRED=0.9.0
+JSON_GLIB_REQUIRED=0.10
dnl ====================================================================
dnl Dependency Checks
@@ -51,6 +52,7 @@ PKG_CHECK_MODULES(GNOME_SESSION,
gtk+-3.0 >= $GTK3_REQUIRED
dbus-glib-1 >= $DBUS_GLIB_REQUIRED
upower-glib >= $UPOWER_REQUIRED
+ json-glib-1.0 >= $JSON_GLIB_REQUIRED
)
PKG_CHECK_MODULES(SESSION_PROPERTIES,
diff --git a/gnome-session/Makefile.am b/gnome-session/Makefile.am
index e86c06a..2c5a36c 100644
--- a/gnome-session/Makefile.am
+++ b/gnome-session/Makefile.am
@@ -58,6 +58,8 @@ gnome_session_SOURCES = \
gsm-session-fill.h \
gsm-session-save.c \
gsm-session-save.h \
+ gsm-shell-extensions.c \
+ gsm-shell-extensions.h \
gsm-shell.c \
gsm-shell.h \
gsm-xsmp-server.c \
diff --git a/gnome-session/gsm-shell-extensions.c b/gnome-session/gsm-shell-extensions.c
new file mode 100644
index 0000000..60eaf2f
--- /dev/null
+++ b/gnome-session/gsm-shell-extensions.c
@@ -0,0 +1,375 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2011 Red Hat, Inc
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors:
+ * Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <json-glib/json-glib.h>
+
+#include "gsm-shell-extensions.h"
+
+
+struct _GsmShellExtension
+{
+ gchar *uuid;
+
+ gchar *name;
+ gchar *description;
+ gboolean enabled;
+};
+
+static void
+gsm_shell_extension_free (gpointer data)
+{
+ GsmShellExtension *extension = (GsmShellExtension *)data;
+
+ g_free (extension->uuid);
+ g_free (extension->name);
+ g_free (extension->description);
+}
+
+gchar *
+gsm_shell_extension_get_uuid (GsmShellExtension *extension)
+{
+ return extension->uuid;
+}
+
+gchar *
+gsm_shell_extension_get_name (GsmShellExtension *extension)
+{
+ return extension->name;
+}
+
+gchar *
+gsm_shell_extension_get_description (GsmShellExtension *extension)
+{
+ return extension->description;
+}
+
+gboolean
+gsm_shell_extension_get_is_enabled (GsmShellExtension *extension)
+{
+ return extension->enabled;
+}
+
+#define SHELL_SCHEMA "org.gnome.shell"
+#define ENABLED_EXTENSIONS_KEY "enabled-extensions"
+
+#define SHELL_EXTENSIONS_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_SHELL_EXTENSIONS, GsmShellExtensionsPrivate))
+
+struct _GsmShellExtensionsPrivate
+{
+ GSettings *settings;
+
+ /* uuid => GsmShellExtension */
+ GHashTable *uuid_to_extension;
+};
+
+G_DEFINE_TYPE (GsmShellExtensions, gsm_shell_extensions, G_TYPE_OBJECT);
+
+/**
+ * gsm_shell_extensions_finalize:
+ * @object: (in): A #GsmShellExtensions.
+ *
+ * Finalizer for a #GsmShellExtensions instance. Frees any resources held by
+ * the instance.
+ */
+static void
+gsm_shell_extensions_finalize (GObject *object)
+{
+ GsmShellExtensions *extensions = GSM_SHELL_EXTENSIONS (object);
+ GsmShellExtensionsPrivate *priv = extensions->priv;
+
+ if (priv->settings != NULL)
+ {
+ g_object_unref (priv->settings);
+ priv->settings = NULL;
+ }
+
+ if (priv->uuid_to_extension != NULL)
+ {
+ g_hash_table_unref (priv->uuid_to_extension);
+ priv->uuid_to_extension = NULL;
+ }
+
+ G_OBJECT_CLASS (gsm_shell_extensions_parent_class)->finalize (object);
+}
+
+/**
+ * gsm_shell_extensions_class_init:
+ * @klass: (in): A #GsmShellExtensionsClass.
+ *
+ * Initializes the #GsmShellExtensionsClass and prepares the vtable.
+ */
+static void
+gsm_shell_extensions_class_init (GsmShellExtensionsClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gsm_shell_extensions_finalize;
+ g_type_class_add_private (object_class, sizeof (GsmShellExtensionsPrivate));
+}
+
+static void
+gsm_shell_extensions_fetch_enabled (GsmShellExtensions *self)
+{
+ gchar **enabled_uuids;
+ gchar **uuids;
+
+ enabled_uuids = g_settings_get_strv (self->priv->settings, ENABLED_EXTENSIONS_KEY);
+
+ uuids = enabled_uuids;
+ while (*uuids != '\0')
+ {
+ GsmShellExtension *extension;
+ extension = g_hash_table_lookup (self->priv->uuid_to_extension, *uuids);
+ if (extension != NULL)
+ extension->enabled = TRUE;
+
+ uuids ++;
+ }
+
+ g_strfreev (enabled_uuids);
+}
+
+static void
+gsm_shell_extensions_scan_dir (GsmShellExtensions *self,
+ GFile *dir)
+{
+ GFileEnumerator *enumerator;
+ GFileInfo *info;
+ JsonParser *metadata_parser;
+
+ metadata_parser = json_parser_new ();
+
+ enumerator = g_file_enumerate_children (dir,
+ "standard::*",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+
+ if (enumerator == NULL)
+ return;
+
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL)
+ {
+ GsmShellExtension *extension = g_slice_new (GsmShellExtension);
+ gchar *metadata_filename;
+ gchar *metadata_uuid;
+ JsonObject *metadata_root;
+
+ extension->uuid = (char *) g_file_info_get_name (info);
+
+ metadata_filename = g_build_filename (g_file_get_path (dir),
+ extension->uuid,
+ "metadata.json",
+ NULL);
+
+ if (!json_parser_load_from_file (metadata_parser, metadata_filename, NULL))
+ continue;
+
+ g_free (metadata_filename);
+
+ metadata_root = json_node_get_object (json_parser_get_root (metadata_parser));
+
+ metadata_uuid = g_strdup (json_object_get_string_member (metadata_root, "uuid"));
+ if (!g_str_equal (metadata_uuid, extension->uuid))
+ {
+ g_warning ("Extension with dirname '%s' does not match metadata's UUID of '%s'. Skipping.",
+ extension->uuid,
+ metadata_uuid);
+ continue;
+ }
+
+ extension->enabled = FALSE;
+ extension->name = g_strdup (json_object_get_string_member (metadata_root, "name"));
+ extension->description = g_strdup (json_object_get_string_member (metadata_root, "description"));
+
+ g_hash_table_insert (self->priv->uuid_to_extension,
+ g_strdup (extension->uuid), extension);
+ }
+}
+
+static void
+gsm_shell_extensions_scan (GsmShellExtensions *self)
+{
+ gchar *dirname;
+ GFile *dir;
+ const gchar * const * system_data_dirs;
+
+ /* User data dir first. */
+ dirname = g_build_filename (g_get_user_data_dir (), "gnome-shell", "extensions", NULL);
+ dir = g_file_new_for_path (dirname);
+ g_free (dirname);
+
+ gsm_shell_extensions_scan_dir (self, dir);
+ g_object_unref (dir);
+
+ system_data_dirs = g_get_system_data_dirs ();
+ while ((*system_data_dirs) != '\0')
+ {
+ dirname = g_build_filename (*system_data_dirs, "gnome-shell", "extensions", NULL);
+ dir = g_file_new_for_path (dirname);
+ g_free (dirname);
+
+ gsm_shell_extensions_scan_dir (self, dir);
+ g_object_unref (dir);
+ system_data_dirs ++;
+ }
+}
+
+/**
+ * gsm_shell_extensions_init:
+ * @self: (in): A #GsmShellExtensions.
+ *
+ * Initializes the newly created #GsmShellExtensions instance.
+ */
+static void
+gsm_shell_extensions_init (GsmShellExtensions *self)
+{
+ gchar * const * schemas;
+
+ self->priv = SHELL_EXTENSIONS_PRIVATE (self);
+
+ /* Unfortunately, gsettings does not have a way to test
+ * for the existance of a schema, so hack around it. */
+ schemas = g_settings_list_schemas ();
+ while (schemas != '\0')
+ {
+ if (g_str_equal (*schemas, SHELL_SCHEMA))
+ {
+ self->priv->settings = g_settings_new (SHELL_SCHEMA);
+ break;
+ }
+
+ schemas ++;
+ }
+
+ if (self->priv->settings)
+ {
+ self->priv->uuid_to_extension = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ gsm_shell_extension_free);
+ gsm_shell_extensions_scan (self);
+ gsm_shell_extensions_fetch_enabled (self);
+ }
+}
+
+gboolean
+gsm_shell_extensions_set_enabled (GsmShellExtensions *self,
+ gchar *uuid,
+ gboolean enabled)
+{
+ gsize i, length;
+ gchar **uuids;
+ const gchar **new_uuids;
+ GsmShellExtension *extension;
+
+ if (self->priv->settings == NULL)
+ return FALSE;
+
+ extension = g_hash_table_lookup (self->priv->uuid_to_extension,
+ uuid);
+
+ if (extension == NULL)
+ return FALSE;
+
+ if (extension->enabled == enabled)
+ return TRUE;
+
+ uuids = g_settings_get_strv (self->priv->settings, ENABLED_EXTENSIONS_KEY);
+ length = g_strv_length (uuids);
+
+ if (enabled)
+ {
+ new_uuids = g_new (const gchar *, length + 2); /* New key, NULL */
+ for (i = 0; i < length; i ++)
+ new_uuids[i] = g_strdup (uuids[i]);
+
+ new_uuids[i++] = g_strdup (uuid);
+ new_uuids[i] = NULL;
+ }
+ else
+ {
+ gsize j = 0;
+ new_uuids = g_new (const gchar *, length);
+ for (i = 0; i < length; i ++)
+ {
+ if (g_str_equal (uuids[i], uuid))
+ continue;
+
+ new_uuids[j] = g_strdup (uuids[i]);
+ j ++;
+ }
+
+ new_uuids[j] = NULL;
+ }
+
+ g_strfreev (uuids);
+
+ if (g_settings_set_strv (self->priv->settings,
+ ENABLED_EXTENSIONS_KEY,
+ new_uuids))
+ {
+ extension->enabled = enabled;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+gsm_shell_extensions_foreach (GsmShellExtensions *self,
+ GsmShellExtensionFunc func,
+ gpointer user_data)
+{
+ GHashTableIter iter;
+ GsmShellExtension *extension;
+
+ if (self->priv->settings == NULL)
+ return;
+
+ g_hash_table_iter_init (&iter, self->priv->uuid_to_extension);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &extension))
+ (*func) (self, extension, user_data);
+}
+
+GsmShellExtension *
+gsm_shell_extensions_get_for_uuid (GsmShellExtensions *self,
+ gchar *uuid)
+{
+ if (self->priv->settings == NULL)
+ return NULL;
+
+ return g_hash_table_lookup (self->priv->uuid_to_extension, uuid);
+}
+
+guint
+gsm_shell_extensions_n_extensions (GsmShellExtensions *self)
+{
+ if (self->priv->settings == NULL)
+ return 0;
+
+ return g_hash_table_size (self->priv->uuid_to_extension);
+}
diff --git a/gnome-session/gsm-shell-extensions.h b/gnome-session/gsm-shell-extensions.h
new file mode 100644
index 0000000..94a8423
--- /dev/null
+++ b/gnome-session/gsm-shell-extensions.h
@@ -0,0 +1,84 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2011 Red Hat, Inc
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors:
+ * Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#ifndef __GSM_SHELL_EXTENSIONS_H
+#define __GSM_SHELL_EXTENSIONS_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* Opaque struct to represent one shell extension. */
+typedef struct _GsmShellExtension GsmShellExtension;
+
+gchar * gsm_shell_extension_get_uuid (GsmShellExtension *extension);
+gchar * gsm_shell_extension_get_name (GsmShellExtension *extension);
+gchar * gsm_shell_extension_get_description (GsmShellExtension *extension);
+gboolean gsm_shell_extension_get_is_enabled (GsmShellExtension *extension);
+
+#define GSM_TYPE_SHELL_EXTENSIONS (gsm_shell_extensions_get_type ())
+#define GSM_SHELL_EXTENSIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_SHELL_EXTENSIONS, GsmShellExtensions))
+#define GSM_SHELL_EXTENSIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_SHELL_EXTENSIONS, GsmShellExtensionsClass))
+#define GSM_IS_SHELL_EXTENSIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_SHELL_EXTENSIONS))
+#define GSM_IS_SHELL_EXTENSIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_SHELL_EXTENSIONS))
+#define GSM_SHELL_EXTENSIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_SHELL_EXTENSIONS, GsmShellExtensionsClass))
+
+typedef struct _GsmShellExtensions GsmShellExtensions;
+typedef struct _GsmShellExtensionsClass GsmShellExtensionsClass;
+typedef struct _GsmShellExtensionsPrivate GsmShellExtensionsPrivate;
+
+typedef void (* GsmShellExtensionFunc) (GsmShellExtensions *extensions,
+ GsmShellExtension *extension,
+ gpointer user_data);
+
+struct _GsmShellExtensions
+{
+ GObject parent;
+
+ /*< private >*/
+ GsmShellExtensionsPrivate *priv;
+};
+
+struct _GsmShellExtensionsClass
+{
+ GObjectClass parent_class;
+};
+
+GType gsm_shell_extensions_get_type (void) G_GNUC_CONST;
+
+gboolean gsm_shell_extensions_set_enabled (GsmShellExtensions *self,
+ gchar *uuid,
+ gboolean value);
+
+void gsm_shell_extensions_foreach (GsmShellExtensions *self,
+ GsmShellExtensionFunc func,
+ gpointer user_data);
+
+guint gsm_shell_extensions_n_extensions (GsmShellExtensions *self);
+
+GsmShellExtension * gsm_shell_extensions_get_for_uuid (GsmShellExtensions *self,
+ gchar *uuid);
+
+G_END_DECLS
+
+#endif /* __GSM_SHELL_EXTENSIONS_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]