Fixed headers in galician translation file
[platform/upstream/glib.git] / gio / gdbusapplication.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright © 2010 Red Hat, Inc
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Authors: Colin Walters <walters@verbum.org>
21  */
22
23 #define G_APPLICATION_IFACE "org.gtk.Application"
24
25 static void
26 application_dbus_method_call (GDBusConnection       *connection,
27                               const gchar           *sender,
28                               const gchar           *object_path,
29                               const gchar           *interface_name,
30                               const gchar           *method_name,
31                               GVariant              *parameters,
32                               GDBusMethodInvocation *invocation,
33                               gpointer               user_data)
34 {
35   GApplication *app = G_APPLICATION (user_data);
36
37   if (method_name == NULL && *method_name == '\0')
38     return;
39
40   if (strcmp (method_name, "Quit") == 0)
41     {
42       GVariant *platform_data;
43
44       g_variant_get (parameters, "(@a{sv})", &platform_data);
45
46       g_dbus_method_invocation_return_value (invocation, NULL);
47
48       g_application_quit_with_data (app, platform_data);
49
50       g_variant_unref (platform_data);
51     }
52   else if (strcmp (method_name, "ListActions") == 0)
53     {
54       GHashTableIter iter;
55       GApplicationAction *value;
56       GVariantBuilder builder;
57
58       g_variant_builder_init (&builder, G_VARIANT_TYPE ("(a{s(sb)})"));
59       g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{s(sb)}"));
60       g_hash_table_iter_init (&iter, app->priv->actions);
61       while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&value))
62         g_variant_builder_add (&builder, "{s(sb)}",
63                                value->name,
64                                value->description ? value->description : "",
65                                value->enabled);
66       g_variant_builder_close (&builder);
67
68       g_dbus_method_invocation_return_value (invocation,
69                                              g_variant_builder_end (&builder));
70     }
71   else if (strcmp (method_name, "InvokeAction") == 0)
72     {
73       const char *action_name;
74       GVariant *platform_data;
75       GApplicationAction *action;
76
77       g_variant_get (parameters, "(&s@a{sv})", &action_name, &platform_data);
78
79       action = g_hash_table_lookup (app->priv->actions, action_name);
80
81       if (!action)
82         {
83           char *errmsg  = g_strdup_printf ("Invalid action: %s", action_name);
84           g_dbus_method_invocation_return_dbus_error (invocation, G_APPLICATION_IFACE ".InvalidAction", errmsg);
85           g_free (errmsg);
86           g_variant_unref (platform_data);
87           return;
88         }
89
90       g_signal_emit (app, application_signals[ACTION_WITH_DATA],
91                      g_quark_from_string (action_name), action_name, platform_data);
92
93       g_dbus_method_invocation_return_value (invocation, NULL);
94       g_variant_unref (platform_data);
95     }
96   else if (strcmp (method_name, "Activate") == 0)
97     {
98       GVariant *args;
99       GVariant *platform_data;
100
101       g_variant_get (parameters, "(@aay@a{sv})", &args, &platform_data);
102
103       g_signal_emit (app, application_signals[PREPARE_ACTIVATION], 0, args, platform_data);
104
105       g_variant_unref (args);
106       g_variant_unref (platform_data);
107
108       g_dbus_method_invocation_return_value (invocation, NULL);
109     }
110 }
111
112 static const GDBusArgInfo application_quit_in_args[] =
113 {
114   {
115     -1,
116     "platform_data",
117     "a{sv}",
118     NULL
119   }
120 };
121
122 static const GDBusArgInfo * const application_quit_in_args_p[] = {
123   &application_quit_in_args[0],
124   NULL
125 };
126
127 static const GDBusArgInfo application_list_actions_out_args[] =
128 {
129   {
130     -1,
131     "actions",
132     "a{s(sb)}",
133     NULL
134   }
135 };
136
137 static const GDBusArgInfo * const application_list_actions_out_args_p[] = {
138   &application_list_actions_out_args[0],
139   NULL
140 };
141
142 static const GDBusArgInfo application_invoke_action_in_args[] =
143 {
144   {
145     -1,
146     "action",
147     "s",
148     NULL
149   },
150   {
151     -1,
152     "platform_data",
153     "a{sv}",
154     NULL
155   }
156 };
157
158 static const GDBusArgInfo * const application_invoke_action_in_args_p[] = {
159   &application_invoke_action_in_args[0],
160   &application_invoke_action_in_args[1],
161   NULL
162 };
163
164 static const GDBusMethodInfo application_quit_method_info =
165 {
166   -1,
167   "Quit",
168   (GDBusArgInfo **) &application_quit_in_args_p,
169   NULL,
170   NULL
171 };
172
173 static const GDBusMethodInfo application_list_actions_method_info =
174 {
175   -1,
176   "ListActions",
177   NULL,
178   (GDBusArgInfo **) &application_list_actions_out_args_p,
179   NULL
180 };
181
182 static const GDBusMethodInfo application_invoke_action_method_info =
183 {
184   -1,
185   "InvokeAction",
186   (GDBusArgInfo **) &application_invoke_action_in_args_p,
187   NULL,
188   NULL
189 };
190
191 static const GDBusArgInfo application_activate_in_args[] =
192 {
193   {
194     -1,
195     "arguments",
196     "aay",
197     NULL
198   },
199   {
200     -1,
201     "data",
202     "a{sv}",
203     NULL
204   }
205 };
206
207 static const GDBusArgInfo * const application_activate_in_args_p[] = {
208   &application_activate_in_args[0],
209   &application_activate_in_args[1],
210   NULL
211 };
212
213 static const GDBusMethodInfo application_activate_method_info =
214 {
215   -1,
216   "Activate",
217   (GDBusArgInfo **) &application_activate_in_args_p,
218   NULL,
219   NULL
220 };
221
222 static const GDBusMethodInfo * const application_dbus_method_info_p[] =
223 {
224   &application_quit_method_info,
225   &application_list_actions_method_info,
226   &application_invoke_action_method_info,
227   &application_activate_method_info,
228   NULL
229 };
230
231 static const GDBusSignalInfo application_dbus_signal_info[] =
232 {
233   {
234     -1,
235     "ActionsChanged",
236     NULL,
237     NULL
238   }
239 };
240
241 static const GDBusSignalInfo * const application_dbus_signal_info_p[] = {
242   &application_dbus_signal_info[0],
243   NULL
244 };
245
246 static const GDBusInterfaceInfo application_dbus_interface_info =
247 {
248   -1,
249   G_APPLICATION_IFACE,
250   (GDBusMethodInfo **) application_dbus_method_info_p,
251   (GDBusSignalInfo **) application_dbus_signal_info_p,
252   NULL,
253 };
254
255 static GDBusInterfaceVTable application_dbus_vtable =
256 {
257   application_dbus_method_call,
258   NULL,
259   NULL
260 };
261
262 static gchar *
263 application_path_from_appid (const gchar *appid)
264 {
265   gchar *appid_path, *iter;
266
267
268   appid_path = g_strconcat ("/", appid, NULL);
269   for (iter = appid_path; *iter; iter++)
270     {
271       if (*iter == '.')
272         *iter = '/';
273     }
274
275   return appid_path;
276 }
277
278 static gboolean
279 _g_application_platform_init (GApplication  *app,
280                               GCancellable  *cancellable,
281                               GError       **error)
282 {
283   if (app->priv->session_bus == NULL)
284     app->priv->session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, error);
285   if (!app->priv->session_bus)
286     return FALSE;
287
288   if (!app->priv->dbus_path)
289     app->priv->dbus_path = application_path_from_appid (app->priv->appid);
290   return TRUE;
291 }
292
293 static gboolean
294 _g_application_platform_register (GApplication  *app,
295                                   gboolean      *unique,
296                                   GCancellable  *cancellable,
297                                   GError       **error)
298 {
299   GVariant *request_result;
300   guint32 request_status;
301   gboolean result;
302   guint registration_id;
303
304   /* Callers should have verified this */
305   g_assert (app->priv->registration_tried == FALSE);
306   app->priv->registration_tried = TRUE;
307
308   registration_id = g_dbus_connection_register_object (app->priv->session_bus,
309                                                        app->priv->dbus_path,
310                                                        &application_dbus_interface_info,
311                                                        &application_dbus_vtable,
312                                                        app,
313                                                        NULL,
314                                                        error);
315   if (registration_id == 0)
316     return FALSE;
317
318   request_result = g_dbus_connection_call_sync (app->priv->session_bus,
319                                                 "org.freedesktop.DBus",
320                                                 "/org/freedesktop/DBus",
321                                                 "org.freedesktop.DBus",
322                                                 "RequestName",
323                                                 g_variant_new ("(su)", app->priv->appid, 0x4),
324                                                 NULL, 0, -1, cancellable, error);
325
326   if (request_result == NULL)
327     {
328       result = FALSE;
329       goto done;
330     }
331
332   if (g_variant_is_of_type (request_result, G_VARIANT_TYPE ("(u)")))
333     g_variant_get (request_result, "(u)", &request_status);
334   else
335     request_status = 0;
336
337   g_variant_unref (request_result);
338
339   *unique = (request_status == 1 || request_status == 4);
340   result = TRUE;
341
342   if (*unique)
343     {
344       app->priv->is_remote = FALSE;
345     }
346   else
347     {
348       GVariantBuilder builder;
349       GVariant *message;
350       GVariant *result;
351
352       g_variant_builder_init (&builder, G_VARIANT_TYPE ("(aaya{sv})"));
353       g_variant_builder_add_value (&builder, app->priv->argv);
354       g_variant_builder_add_value (&builder, app->priv->platform_data);
355       message = g_variant_builder_end (&builder);
356
357       result = g_dbus_connection_call_sync (app->priv->session_bus,
358                                             app->priv->appid,
359                                             app->priv->dbus_path,
360                                             G_APPLICATION_IFACE,
361                                             "Activate",
362                                             message,
363                                             NULL, 0, -1, NULL, NULL);
364
365       if (result)
366         g_variant_unref (result);
367
368       if (app->priv->default_quit)
369         exit (0);
370     }
371
372 done:
373   if (!result)
374     g_dbus_connection_unregister_object (app->priv->session_bus, registration_id);
375
376   return result;
377 }
378
379 static void
380 _g_application_platform_on_actions_changed (GApplication *app)
381 {
382   g_dbus_connection_emit_signal (app->priv->session_bus, NULL,
383                                  app->priv->dbus_path,
384                                  G_APPLICATION_IFACE,
385                                  "ActionsChanged", NULL, NULL);
386 }
387
388 static void
389 _g_application_platform_remote_invoke_action (GApplication  *app,
390                                               const gchar   *action,
391                                               GVariant      *platform_data)
392 {
393   GVariant *result;
394
395   result = g_dbus_connection_call_sync (app->priv->session_bus,
396                                         app->priv->appid,
397                                         app->priv->dbus_path,
398                                         G_APPLICATION_IFACE,
399                                         "InvokeAction",
400                                         g_variant_new ("(s@a{sv})",
401                                                        action,
402                                                        platform_data),
403                                         NULL, 0, -1, NULL, NULL);
404   if (result)
405     g_variant_unref (result);
406 }
407
408 static void
409 _g_application_platform_remote_quit (GApplication *app,
410                                      GVariant     *platform_data)
411 {
412   GVariant *result;
413
414   result = g_dbus_connection_call_sync (app->priv->session_bus,
415                                         app->priv->appid,
416                                         app->priv->dbus_path,
417                                         G_APPLICATION_IFACE,
418                                         "Quit",
419                                         g_variant_new ("(@a{sv})",
420                                                        platform_data),
421                                         NULL, 0, -1, NULL, NULL);
422   if (result)
423     g_variant_unref (result);
424 }