summaryrefslogtreecommitdiffstats
path: root/gnome-session/gsm-shell-extensions.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gnome-session/gsm-shell-extensions.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/gnome-session/gsm-shell-extensions.c b/gnome-session/gsm-shell-extensions.c
new file mode 100644
index 0000000..73d898f
--- /dev/null
+++ b/gnome-session/gsm-shell-extensions.c
@@ -0,0 +1,199 @@
+/* -*- 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <json-glib/json-glib.h>
+
+#include "gsm-shell-extensions.h"
+
+#define SHELL_SCHEMA "org.gnome.shell"
+#define DISABLE_EXTENSIONS_KEY "disable-user-extensions"
+
+#define SHELL_EXTENSIONS_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_SHELL_EXTENSIONS, GsmShellExtensionsPrivate))
+
+struct _GsmShellExtensionsPrivate
+{
+ GSettings *settings;
+ guint num_extensions;
+};
+
+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;
+
+ g_clear_object (&priv->settings);
+
+ 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_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)
+ {
+ gchar *metadata_filename;
+ const gchar *metadata_uuid;
+ gchar *dir_uuid;
+ JsonObject *metadata_root;
+
+ dir_uuid = (char *) g_file_info_get_name (info);
+
+ metadata_filename = g_build_filename (g_file_get_path (dir),
+ dir_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 = json_object_get_string_member (metadata_root, "uuid");
+ if (!g_str_equal (metadata_uuid, dir_uuid))
+ {
+ g_warning ("Extension with dirname '%s' does not match metadata's UUID of '%s'. Skipping.",
+ dir_uuid, metadata_uuid);
+ continue;
+ }
+
+ self->priv->num_extensions++;
+ }
+}
+
+static void
+gsm_shell_extensions_scan (GsmShellExtensions *self)
+{
+ gchar *dirname;
+ GFile *dir;
+ const gchar * const * system_data_dirs;
+ int i;
+
+ /* 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 ();
+ for (i = 0; system_data_dirs[i]; i++)
+ {
+ dirname = g_build_filename (system_data_dirs[i], "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);
+ }
+}
+
+/**
+ * gsm_shell_extensions_init:
+ * @self: (in): A #GsmShellExtensions.
+ *
+ * Initializes the newly created #GsmShellExtensions instance.
+ */
+static void
+gsm_shell_extensions_init (GsmShellExtensions *self)
+{
+ GSettingsSchemaSource *source;
+ GSettingsSchema *schema;
+
+ self->priv = SHELL_EXTENSIONS_PRIVATE (self);
+
+ source = g_settings_schema_source_get_default ();
+ schema = g_settings_schema_source_lookup (source, SHELL_SCHEMA, TRUE);
+
+ if (schema != NULL)
+ {
+ self->priv->settings = g_settings_new_full (schema, NULL, NULL);
+ g_settings_schema_unref (schema);
+ }
+
+ if (self->priv->settings != NULL)
+ gsm_shell_extensions_scan (self);
+}
+
+gboolean
+gsm_shell_extensions_disable_all (GsmShellExtensions *self)
+{
+ return g_settings_set_boolean (self->priv->settings,
+ DISABLE_EXTENSIONS_KEY,
+ TRUE);
+}
+
+guint
+gsm_shell_extensions_n_extensions (GsmShellExtensions *self)
+{
+ if (self->priv->settings == NULL)
+ return 0;
+
+ return self->priv->num_extensions;
+}