/* -*- 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 .
*
* Authors:
* Jasper St. Pierre
*/
#include
#include
#include
#include
#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;
}