diff options
Diffstat (limited to '')
-rw-r--r-- | src/hotplug-sniffer/hotplug-sniffer.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/src/hotplug-sniffer/hotplug-sniffer.c b/src/hotplug-sniffer/hotplug-sniffer.c new file mode 100644 index 0000000..fd087fd --- /dev/null +++ b/src/hotplug-sniffer/hotplug-sniffer.c @@ -0,0 +1,298 @@ +/* -*- 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 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, see <http://www.gnu.org/licenses/>. + * + * Authors: David Zeuthen <davidz@redhat.com> + * Cosimo Cecchi <cosimoc@redhat.com> + * + */ + +#include "shell-mime-sniffer.h" +#include "hotplug-mimetypes.h" + +/* Set the environment variable HOTPLUG_SNIFFER_DEBUG to show debug */ +static void print_debug (const gchar *str, ...); + +#define BUS_NAME "org.gnome.Shell.HotplugSniffer" +#define AUTOQUIT_TIMEOUT 5 + +static const gchar introspection_xml[] = + "<node>" + " <interface name='org.gnome.Shell.HotplugSniffer'>" + " <method name='SniffURI'>" + " <arg type='s' name='uri' direction='in'/>" + " <arg type='as' name='content_types' direction='out'/>" + " </method>" + " </interface>" + "</node>"; + +static GDBusNodeInfo *introspection_data = NULL; +static GMainLoop *loop = NULL; +static guint autoquit_id = 0; + +static gboolean +autoquit_timeout_cb (gpointer _unused) +{ + print_debug ("Timeout reached, quitting..."); + + autoquit_id = 0; + g_main_loop_quit (loop); + + return FALSE; +} + +static void +ensure_autoquit_off (void) +{ + if (g_getenv ("HOTPLUG_SNIFFER_PERSIST") != NULL) + return; + + g_clear_handle_id (&autoquit_id, g_source_remove); +} + +static void +ensure_autoquit_on (void) +{ + if (g_getenv ("HOTPLUG_SNIFFER_PERSIST") != NULL) + return; + + autoquit_id = + g_timeout_add_seconds (AUTOQUIT_TIMEOUT, + autoquit_timeout_cb, NULL); + g_source_set_name_by_id (autoquit_id, "[gnome-shell] autoquit_timeout_cb"); +} + +typedef struct { + GVariant *parameters; + GDBusMethodInvocation *invocation; +} InvocationData; + +static InvocationData * +invocation_data_new (GVariant *params, + GDBusMethodInvocation *invocation) +{ + InvocationData *ret; + + ret = g_slice_new0 (InvocationData); + ret->parameters = g_variant_ref (params); + ret->invocation = g_object_ref (invocation); + + return ret; +} + +static void +invocation_data_free (InvocationData *data) +{ + g_variant_unref (data->parameters); + g_clear_object (&data->invocation); + + g_slice_free (InvocationData, data); +} + +static void +sniff_async_ready_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + InvocationData *data = user_data; + gchar **types; + GError *error = NULL; + + types = shell_mime_sniffer_sniff_finish (SHELL_MIME_SNIFFER (source), + res, &error); + + if (error != NULL) + { + g_dbus_method_invocation_return_gerror (data->invocation, error); + g_error_free (error); + goto out; + } + + g_dbus_method_invocation_return_value (data->invocation, + g_variant_new ("(^as)", types)); + g_strfreev (types); + + out: + invocation_data_free (data); + ensure_autoquit_on (); +} + +static void +handle_sniff_uri (InvocationData *data) +{ + ShellMimeSniffer *sniffer; + const gchar *uri; + GFile *file; + + ensure_autoquit_off (); + + g_variant_get (data->parameters, + "(&s)", &uri, + NULL); + file = g_file_new_for_uri (uri); + + print_debug ("Initiating sniff for uri %s", uri); + + sniffer = shell_mime_sniffer_new (file); + shell_mime_sniffer_sniff_async (sniffer, + sniff_async_ready_cb, + data); + + g_object_unref (sniffer); + g_object_unref (file); +} + +static void +handle_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + InvocationData *data; + + data = invocation_data_new (parameters, invocation); + + if (g_strcmp0 (method_name, "SniffURI") == 0) + handle_sniff_uri (data); + else + g_assert_not_reached (); +} + +static const GDBusInterfaceVTable interface_vtable = +{ + handle_method_call, + NULL, /* get_property */ + NULL, /* set_property */ +}; + +static void +on_bus_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + GError *error = NULL; + + print_debug ("Connected to the session bus: %s", name); + + g_dbus_connection_register_object (connection, + "/org/gnome/Shell/HotplugSniffer", + introspection_data->interfaces[0], + &interface_vtable, + NULL, + NULL, + &error); + + if (error != NULL) + { + g_printerr ("Error exporting object on the session bus: %s", + error->message); + g_error_free (error); + + _exit(1); + } + + print_debug ("Object exported on the session bus"); +} + +static void +on_name_lost (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + print_debug ("Lost bus name: %s, exiting", name); + + g_main_loop_quit (loop); +} + +static void +on_name_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + print_debug ("Acquired bus name: %s", name); +} + +int +main (int argc, + char **argv) +{ + guint name_owner_id; + + introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); + g_assert (introspection_data != NULL); + + ensure_autoquit_on (); + loop = g_main_loop_new (NULL, FALSE); + + name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + BUS_NAME, 0, + on_bus_acquired, + on_name_acquired, + on_name_lost, + NULL, + NULL); + + g_main_loop_run (loop); + + if (name_owner_id != 0) + g_bus_unown_name (name_owner_id); + + if (loop != NULL) + g_main_loop_unref (loop); + + return 0; +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void __attribute__((format(printf, 1, 0))) +print_debug (const gchar *format, ...) +{ + g_autofree char *s = NULL; + g_autofree char *timestamp = NULL; + va_list ap; + g_autoptr (GDateTime) now = NULL; + static volatile gsize once_init_value = 0; + static gboolean show_debug = FALSE; + static guint pid = 0; + + if (g_once_init_enter (&once_init_value)) + { + show_debug = (g_getenv ("HOTPLUG_SNIFFER_DEBUG") != NULL); + pid = getpid (); + g_once_init_leave (&once_init_value, 1); + } + + if (!show_debug) + goto out; + + now = g_date_time_new_now_local (); + timestamp = g_date_time_format (now, "%H:%M:%S"); + + va_start (ap, format); + s = g_strdup_vprintf (format, ap); + va_end (ap); + + g_print ("gnome-shell-hotplug-sniffer[%d]: %s.%03d: %s\n", + pid, timestamp, g_date_time_get_microsecond (now), s); + out: + ; +} + |