gnome-shell-3.6.3.1/src/hotplug-sniffer/hotplug-sniffer.c

No issues found

  1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2 /*
  3  * Copyright (C) 2011 Red Hat, Inc.
  4  *
  5  * This program is free software; you can redistribute it and/or
  6  * modify it under the terms of the GNU General Public License as
  7  * published by the Free Software Foundation; either version 2 of the
  8  * License, or (at your option) any later version.
  9  *
 10  * This program is distributed in the hope that it will be useful, but
 11  * WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  * General Public License for more details.
 14  *
 15  * You should have received a copy of the GNU General Public License
 16  * along with this program; if not, write to the Free Software
 17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 18  * 02111-1307, USA.
 19  *
 20  * Authors: David Zeuthen <davidz@redhat.com>
 21  *          Cosimo Cecchi <cosimoc@redhat.com>
 22  *
 23  */
 24 
 25 #include "shell-mime-sniffer.h"
 26 #include "hotplug-mimetypes.h"
 27 
 28 /* Set the environment variable HOTPLUG_SNIFFER_DEBUG to show debug */
 29 static void print_debug (const gchar *str, ...);
 30 
 31 #define BUS_NAME "org.gnome.Shell.HotplugSniffer"
 32 #define AUTOQUIT_TIMEOUT 5
 33 
 34 static const gchar introspection_xml[] =
 35   "<node>"
 36   "  <interface name='org.gnome.Shell.HotplugSniffer'>"
 37   "    <method name='SniffURI'>"
 38   "      <arg type='s' name='uri' direction='in'/>"
 39   "      <arg type='as' name='content_types' direction='out'/>"
 40   "    </method>"
 41   "  </interface>"
 42   "</node>";
 43 
 44 static GDBusNodeInfo *introspection_data = NULL;
 45 static GMainLoop     *loop = NULL;
 46 static guint          autoquit_id = 0;
 47 
 48 static gboolean
 49 autoquit_timeout_cb (gpointer _unused)
 50 {
 51   print_debug ("Timeout reached, quitting...");
 52 
 53   autoquit_id = 0;
 54   g_main_loop_quit (loop);
 55 
 56   return FALSE;
 57 }
 58 
 59 static void
 60 ensure_autoquit_off (void)
 61 {
 62   if (g_getenv ("HOTPLUG_SNIFFER_PERSIST") != NULL)
 63     return;
 64 
 65   if (autoquit_id != 0)
 66     {
 67       g_source_remove (autoquit_id);
 68       autoquit_id = 0;
 69     }
 70 }
 71 
 72 static void
 73 ensure_autoquit_on (void)
 74 {
 75   if (g_getenv ("HOTPLUG_SNIFFER_PERSIST") != NULL)
 76     return;
 77 
 78   autoquit_id = 
 79     g_timeout_add_seconds (AUTOQUIT_TIMEOUT,
 80                            autoquit_timeout_cb, NULL);
 81 }
 82 
 83 typedef struct {
 84   GVariant *parameters;
 85   GDBusMethodInvocation *invocation;
 86 } InvocationData;
 87 
 88 static InvocationData *
 89 invocation_data_new (GVariant *params,
 90                      GDBusMethodInvocation *invocation)
 91 {
 92   InvocationData *ret;
 93 
 94   ret = g_slice_new0 (InvocationData);
 95   ret->parameters = g_variant_ref (params);
 96   ret->invocation = g_object_ref (invocation);
 97 
 98   return ret;
 99 }
100 
101 static void
102 invocation_data_free (InvocationData *data)
103 {
104   g_variant_unref (data->parameters);
105   g_clear_object (&data->invocation);
106 
107   g_slice_free (InvocationData, data);
108 }
109 
110 static void
111 sniff_async_ready_cb (GObject *source,
112                       GAsyncResult *res,
113                       gpointer user_data)
114 {
115   InvocationData *data = user_data;
116   gchar **types;
117   GError *error = NULL;
118 
119   types = shell_mime_sniffer_sniff_finish (SHELL_MIME_SNIFFER (source),
120                                            res, &error);
121 
122   if (error != NULL)
123     {
124       g_dbus_method_invocation_return_gerror (data->invocation, error);
125       g_error_free (error);
126       goto out;
127     }
128 
129   g_dbus_method_invocation_return_value (data->invocation,
130                                          g_variant_new ("(^as)", types));
131   g_strfreev (types);
132 
133  out:
134   invocation_data_free (data);
135   ensure_autoquit_on ();
136 }
137 
138 static void
139 handle_sniff_uri (InvocationData *data)
140 {
141   ShellMimeSniffer *sniffer;
142   const gchar *uri;
143   GFile *file;
144 
145   ensure_autoquit_off ();
146 
147   g_variant_get (data->parameters, 
148                  "(&s)", &uri,
149                  NULL);
150   file = g_file_new_for_uri (uri);
151 
152   print_debug ("Initiating sniff for uri %s", uri);
153 
154   sniffer = shell_mime_sniffer_new (file);
155   shell_mime_sniffer_sniff_async (sniffer,
156                                   sniff_async_ready_cb,
157                                   data);
158 
159   g_object_unref (sniffer);
160   g_object_unref (file);
161 }
162 
163 static void
164 handle_method_call (GDBusConnection       *connection,
165                     const gchar           *sender,
166                     const gchar           *object_path,
167                     const gchar           *interface_name,
168                     const gchar           *method_name,
169                     GVariant              *parameters,
170                     GDBusMethodInvocation *invocation,
171                     gpointer               user_data)
172 {
173   InvocationData *data;
174 
175   data = invocation_data_new (parameters, invocation);
176 
177   if (g_strcmp0 (method_name, "SniffURI") == 0)
178     handle_sniff_uri (data);
179   else
180     g_assert_not_reached ();
181 }
182 
183 static const GDBusInterfaceVTable interface_vtable =
184 {
185   handle_method_call,
186   NULL, /* get_property */
187   NULL, /* set_property */
188 };
189 
190 static void
191 on_bus_acquired (GDBusConnection *connection,
192                  const gchar *name,
193                  gpointer user_data)
194 {
195   GError *error = NULL;
196 
197   print_debug ("Connected to the session bus: %s", name);
198 
199   g_dbus_connection_register_object (connection,
200                                      "/org/gnome/Shell/HotplugSniffer",
201                                      introspection_data->interfaces[0],
202                                      &interface_vtable,
203                                      NULL,
204                                      NULL,
205                                      &error);
206 
207   if (error != NULL)
208     {
209       g_printerr ("Error exporting object on the session bus: %s",
210                   error->message);
211       g_error_free (error);
212 
213       _exit(1);
214     }
215 
216   print_debug ("Object exported on the session bus");
217 }
218 
219 static void
220 on_name_lost (GDBusConnection *connection,
221               const gchar *name,
222               gpointer user_data)
223 {
224   print_debug ("Lost bus name: %s, exiting", name);
225 
226   g_main_loop_quit (loop);
227 }
228 
229 static void
230 on_name_acquired (GDBusConnection *connection,
231                   const gchar *name,
232                   gpointer user_data)
233 {
234   print_debug ("Acquired bus name: %s", name);
235 }
236 
237 int
238 main (int    argc,
239       char **argv)
240 {
241   guint name_owner_id;
242 
243   g_type_init ();
244 
245   introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
246   g_assert (introspection_data != NULL);
247 
248   ensure_autoquit_on ();
249   loop = g_main_loop_new (NULL, FALSE);
250 
251   name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
252                                   BUS_NAME, 0,
253                                   on_bus_acquired,
254                                   on_name_acquired,
255                                   on_name_lost,
256                                   NULL,
257                                   NULL);
258 
259   g_main_loop_run (loop);
260 
261   if (name_owner_id != 0)
262     g_bus_unown_name (name_owner_id);
263 
264   if (loop != NULL)
265     g_main_loop_unref (loop);
266 
267   return 0;
268 }
269 
270 /* ---------------------------------------------------------------------------------------------------- */
271 
272 static void
273 print_debug (const gchar *format, ...)
274 {
275   gchar *s;
276   va_list ap;
277   gchar timebuf[64];
278   GTimeVal now;
279   time_t now_t;
280   struct tm broken_down;
281   static volatile gsize once_init_value = 0;
282   static gboolean show_debug = FALSE;
283   static guint pid = 0;
284 
285   if (g_once_init_enter (&once_init_value))
286     {
287       show_debug = (g_getenv ("HOTPLUG_SNIFFER_DEBUG") != NULL);
288       pid = getpid ();
289       g_once_init_leave (&once_init_value, 1);
290     }
291 
292   if (!show_debug)
293     goto out;
294 
295   g_get_current_time (&now);
296   now_t = now.tv_sec;
297   localtime_r (&now_t, &broken_down);
298   strftime (timebuf, sizeof timebuf, "%H:%M:%S", &broken_down);
299 
300   va_start (ap, format);
301   s = g_strdup_vprintf (format, ap);
302   va_end (ap);
303 
304   g_print ("gnome-shell-hotplug-sniffer[%d]: %s.%03d: %s\n", pid, timebuf, (gint) (now.tv_usec / 1000), s);
305   g_free (s);
306  out:
307   ;
308 }