/src/glib/gio/gapplicationimpl-dbus.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * Copyright © 2010 Codethink Limited  | 
3  |  |  *  | 
4  |  |  * SPDX-License-Identifier: LGPL-2.1-or-later  | 
5  |  |  *  | 
6  |  |  * This library is free software; you can redistribute it and/or  | 
7  |  |  * modify it under the terms of the GNU Lesser General Public  | 
8  |  |  * License as published by the Free Software Foundation; either  | 
9  |  |  * version 2.1 of the License, or (at your option) any later version.  | 
10  |  |  *  | 
11  |  |  * This library is distributed in the hope that it will be useful,  | 
12  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of  | 
13  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  | 
14  |  |  * Lesser General Public License for more details.  | 
15  |  |  *  | 
16  |  |  * You should have received a copy of the GNU Lesser General  | 
17  |  |  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.  | 
18  |  |  *  | 
19  |  |  * Authors: Ryan Lortie <desrt@desrt.ca>  | 
20  |  |  */  | 
21  |  |  | 
22  |  | #include "config.h"  | 
23  |  |  | 
24  |  | #include "gapplicationimpl.h"  | 
25  |  |  | 
26  |  | #include "gactiongroup.h"  | 
27  |  | #include "gactiongroupexporter.h"  | 
28  |  | #include "gremoteactiongroup.h"  | 
29  |  | #include "gdbusactiongroup-private.h"  | 
30  |  | #include "gapplication.h"  | 
31  |  | #include "gfile.h"  | 
32  |  | #include "gdbusconnection.h"  | 
33  |  | #include "gdbusintrospection.h"  | 
34  |  | #include "gdbuserror.h"  | 
35  |  | #include "glib/gstdio.h"  | 
36  |  |  | 
37  |  | #include <string.h>  | 
38  |  | #include <stdio.h>  | 
39  |  |  | 
40  |  | #include "gapplicationcommandline.h"  | 
41  |  | #include "gdbusmethodinvocation.h"  | 
42  |  |  | 
43  |  | #ifdef G_OS_UNIX  | 
44  |  | #include "gunixinputstream.h"  | 
45  |  | #include "gunixfdlist.h"  | 
46  |  | #endif  | 
47  |  |  | 
48  |  | /* D-Bus Interface definition {{{1 */ | 
49  |  |  | 
50  |  | /* For documentation of these interfaces, see  | 
51  |  |  * https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI  | 
52  |  |  */  | 
53  |  | static const gchar org_gtk_Application_xml[] =  | 
54  |  |   "<node>"  | 
55  |  |     "<interface name='org.gtk.Application'>"  | 
56  |  |       "<method name='Activate'>"  | 
57  |  |         "<arg type='a{sv}' name='platform-data' direction='in'/>" | 
58  |  |       "</method>"  | 
59  |  |       "<method name='Open'>"  | 
60  |  |         "<arg type='as' name='uris' direction='in'/>"  | 
61  |  |         "<arg type='s' name='hint' direction='in'/>"  | 
62  |  |         "<arg type='a{sv}' name='platform-data' direction='in'/>" | 
63  |  |       "</method>"  | 
64  |  |       "<method name='CommandLine'>"  | 
65  |  |         "<arg type='o' name='path' direction='in'/>"  | 
66  |  |         "<arg type='aay' name='arguments' direction='in'/>"  | 
67  |  |         "<arg type='a{sv}' name='platform-data' direction='in'/>" | 
68  |  |         "<arg type='i' name='exit-status' direction='out'/>"  | 
69  |  |       "</method>"  | 
70  |  |     "<property name='Busy' type='b' access='read'/>"  | 
71  |  |     "</interface>"  | 
72  |  |   "</node>";  | 
73  |  |  | 
74  |  | static GDBusInterfaceInfo *org_gtk_Application;  | 
75  |  |  | 
76  |  | static const gchar org_freedesktop_Application_xml[] =  | 
77  |  |   "<node>"  | 
78  |  |     "<interface name='org.freedesktop.Application'>"  | 
79  |  |       "<method name='Activate'>"  | 
80  |  |         "<arg type='a{sv}' name='platform-data' direction='in'/>" | 
81  |  |       "</method>"  | 
82  |  |       "<method name='Open'>"  | 
83  |  |         "<arg type='as' name='uris' direction='in'/>"  | 
84  |  |         "<arg type='a{sv}' name='platform-data' direction='in'/>" | 
85  |  |       "</method>"  | 
86  |  |       "<method name='ActivateAction'>"  | 
87  |  |         "<arg type='s' name='action-name' direction='in'/>"  | 
88  |  |         "<arg type='av' name='parameter' direction='in'/>"  | 
89  |  |         "<arg type='a{sv}' name='platform-data' direction='in'/>" | 
90  |  |       "</method>"  | 
91  |  |     "</interface>"  | 
92  |  |   "</node>";  | 
93  |  |  | 
94  |  | static GDBusInterfaceInfo *org_freedesktop_Application;  | 
95  |  |  | 
96  |  | static const gchar org_gtk_private_CommandLine_xml[] =  | 
97  |  |   "<node>"  | 
98  |  |     "<interface name='org.gtk.private.CommandLine'>"  | 
99  |  |       "<method name='Print'>"  | 
100  |  |         "<arg type='s' name='message' direction='in'/>"  | 
101  |  |       "</method>"  | 
102  |  |       "<method name='PrintError'>"  | 
103  |  |         "<arg type='s' name='message' direction='in'/>"  | 
104  |  |       "</method>"  | 
105  |  |     "</interface>"  | 
106  |  |   "</node>";  | 
107  |  |  | 
108  |  | static GDBusInterfaceInfo *org_gtk_private_CommandLine;  | 
109  |  |  | 
110  |  | /* GApplication implementation {{{1 */ | 
111  |  | struct _GApplicationImpl  | 
112  |  | { | 
113  |  |   GDBusConnection *session_bus;  | 
114  |  |   GActionGroup    *exported_actions;  | 
115  |  |   const gchar     *bus_name;  | 
116  |  |   guint            name_lost_signal;  | 
117  |  |  | 
118  |  |   gchar           *object_path;  | 
119  |  |   guint            object_id;  | 
120  |  |   guint            fdo_object_id;  | 
121  |  |   guint            actions_id;  | 
122  |  |  | 
123  |  |   gboolean         properties_live;  | 
124  |  |   gboolean         primary;  | 
125  |  |   gboolean         busy;  | 
126  |  |   gboolean         registered;  | 
127  |  |   GApplication    *app;  | 
128  |  | };  | 
129  |  |  | 
130  |  |  | 
131  |  | static GApplicationCommandLine *  | 
132  |  | g_dbus_command_line_new (GDBusMethodInvocation *invocation);  | 
133  |  |  | 
134  |  | static GVariant *  | 
135  |  | g_application_impl_get_property (GDBusConnection *connection,  | 
136  |  |                                  const gchar  *sender,  | 
137  |  |                                  const gchar  *object_path,  | 
138  |  |                                  const gchar  *interface_name,  | 
139  |  |                                  const gchar  *property_name,  | 
140  |  |                                  GError      **error,  | 
141  |  |                                  gpointer      user_data)  | 
142  | 0  | { | 
143  | 0  |   GApplicationImpl *impl = user_data;  | 
144  |  | 
  | 
145  | 0  |   if (strcmp (property_name, "Busy") == 0)  | 
146  | 0  |     return g_variant_new_boolean (impl->busy);  | 
147  |  |  | 
148  | 0  |   g_assert_not_reached ();  | 
149  |  |  | 
150  | 0  |   return NULL;  | 
151  | 0  | }  | 
152  |  |  | 
153  |  | static void  | 
154  |  | send_property_change (GApplicationImpl *impl)  | 
155  | 0  | { | 
156  | 0  |   GVariantBuilder builder;  | 
157  |  | 
  | 
158  | 0  |   g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);  | 
159  | 0  |   g_variant_builder_add (&builder,  | 
160  | 0  |                          "{sv}", | 
161  | 0  |                          "Busy", g_variant_new_boolean (impl->busy));  | 
162  |  | 
  | 
163  | 0  |   g_dbus_connection_emit_signal (impl->session_bus,  | 
164  | 0  |                                  NULL,  | 
165  | 0  |                                  impl->object_path,  | 
166  | 0  |                                  "org.freedesktop.DBus.Properties",  | 
167  | 0  |                                  "PropertiesChanged",  | 
168  | 0  |                                  g_variant_new ("(sa{sv}as)", | 
169  | 0  |                                                 "org.gtk.Application",  | 
170  | 0  |                                                 &builder,  | 
171  | 0  |                                                 NULL),  | 
172  | 0  |                                  NULL);  | 
173  | 0  | }  | 
174  |  |  | 
175  |  | static void  | 
176  |  | g_application_impl_method_call (GDBusConnection       *connection,  | 
177  |  |                                 const gchar           *sender,  | 
178  |  |                                 const gchar           *object_path,  | 
179  |  |                                 const gchar           *interface_name,  | 
180  |  |                                 const gchar           *method_name,  | 
181  |  |                                 GVariant              *parameters,  | 
182  |  |                                 GDBusMethodInvocation *invocation,  | 
183  |  |                                 gpointer               user_data)  | 
184  | 0  | { | 
185  | 0  |   GApplicationImpl *impl = user_data;  | 
186  | 0  |   GApplicationClass *class;  | 
187  |  | 
  | 
188  | 0  |   class = G_APPLICATION_GET_CLASS (impl->app);  | 
189  |  | 
  | 
190  | 0  |   if (strcmp (method_name, "Activate") == 0)  | 
191  | 0  |     { | 
192  | 0  |       GVariant *platform_data;  | 
193  |  |  | 
194  |  |       /* Completely the same for both freedesktop and gtk interfaces */  | 
195  |  | 
  | 
196  | 0  |       g_variant_get (parameters, "(@a{sv})", &platform_data); | 
197  |  | 
  | 
198  | 0  |       class->before_emit (impl->app, platform_data);  | 
199  | 0  |       g_signal_emit_by_name (impl->app, "activate");  | 
200  | 0  |       class->after_emit (impl->app, platform_data);  | 
201  | 0  |       g_variant_unref (platform_data);  | 
202  |  | 
  | 
203  | 0  |       g_dbus_method_invocation_return_value (invocation, NULL);  | 
204  | 0  |     }  | 
205  |  |  | 
206  | 0  |   else if (strcmp (method_name, "Open") == 0)  | 
207  | 0  |     { | 
208  | 0  |       GApplicationFlags flags;  | 
209  | 0  |       GVariant *platform_data;  | 
210  | 0  |       const gchar *hint;  | 
211  | 0  |       GVariant *array;  | 
212  | 0  |       GFile **files;  | 
213  | 0  |       gint n, i;  | 
214  |  | 
  | 
215  | 0  |       flags = g_application_get_flags (impl->app);  | 
216  | 0  |       if ((flags & G_APPLICATION_HANDLES_OPEN) == 0)  | 
217  | 0  |         { | 
218  | 0  |           g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "Application does not open files");  | 
219  | 0  |           return;  | 
220  | 0  |         }  | 
221  |  |  | 
222  |  |       /* freedesktop interface has no hint parameter */  | 
223  | 0  |       if (g_str_equal (interface_name, "org.freedesktop.Application"))  | 
224  | 0  |         { | 
225  | 0  |           g_variant_get (parameters, "(@as@a{sv})", &array, &platform_data); | 
226  | 0  |           hint = "";  | 
227  | 0  |         }  | 
228  | 0  |       else  | 
229  | 0  |         g_variant_get (parameters, "(@as&s@a{sv})", &array, &hint, &platform_data); | 
230  |  | 
  | 
231  | 0  |       n = g_variant_n_children (array);  | 
232  | 0  |       files = g_new (GFile *, n + 1);  | 
233  |  | 
  | 
234  | 0  |       for (i = 0; i < n; i++)  | 
235  | 0  |         { | 
236  | 0  |           const gchar *uri;  | 
237  |  | 
  | 
238  | 0  |           g_variant_get_child (array, i, "&s", &uri);  | 
239  | 0  |           files[i] = g_file_new_for_uri (uri);  | 
240  | 0  |         }  | 
241  | 0  |       g_variant_unref (array);  | 
242  | 0  |       files[n] = NULL;  | 
243  |  | 
  | 
244  | 0  |       class->before_emit (impl->app, platform_data);  | 
245  | 0  |       g_signal_emit_by_name (impl->app, "open", files, n, hint);  | 
246  | 0  |       class->after_emit (impl->app, platform_data);  | 
247  |  | 
  | 
248  | 0  |       g_variant_unref (platform_data);  | 
249  |  | 
  | 
250  | 0  |       for (i = 0; i < n; i++)  | 
251  | 0  |         g_object_unref (files[i]);  | 
252  | 0  |       g_free (files);  | 
253  |  | 
  | 
254  | 0  |       g_dbus_method_invocation_return_value (invocation, NULL);  | 
255  | 0  |     }  | 
256  |  |  | 
257  | 0  |   else if (strcmp (method_name, "CommandLine") == 0)  | 
258  | 0  |     { | 
259  | 0  |       GApplicationFlags flags;  | 
260  | 0  |       GApplicationCommandLine *cmdline;  | 
261  | 0  |       GVariant *platform_data;  | 
262  | 0  |       int status;  | 
263  |  | 
  | 
264  | 0  |       flags = g_application_get_flags (impl->app);  | 
265  | 0  |       if ((flags & G_APPLICATION_HANDLES_COMMAND_LINE) == 0)  | 
266  | 0  |         { | 
267  | 0  |           g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED,  | 
268  | 0  |                                                  "Application does not handle command line arguments");  | 
269  | 0  |           return;  | 
270  | 0  |         }  | 
271  |  |  | 
272  |  |       /* Only on the GtkApplication interface */  | 
273  |  |  | 
274  | 0  |       cmdline = g_dbus_command_line_new (invocation);  | 
275  | 0  |       platform_data = g_variant_get_child_value (parameters, 2);  | 
276  | 0  |       class->before_emit (impl->app, platform_data);  | 
277  | 0  |       g_signal_emit_by_name (impl->app, "command-line", cmdline, &status);  | 
278  | 0  |       g_application_command_line_set_exit_status (cmdline, status);  | 
279  | 0  |       class->after_emit (impl->app, platform_data);  | 
280  | 0  |       g_variant_unref (platform_data);  | 
281  | 0  |       g_object_unref (cmdline);  | 
282  | 0  |     }  | 
283  | 0  |   else if (g_str_equal (method_name, "ActivateAction"))  | 
284  | 0  |     { | 
285  | 0  |       GVariant *parameter = NULL;  | 
286  | 0  |       GVariant *platform_data;  | 
287  | 0  |       GVariantIter *iter;  | 
288  | 0  |       const gchar *name;  | 
289  | 0  |       const GVariantType *parameter_type = NULL;  | 
290  |  |  | 
291  |  |       /* Only on the freedesktop interface */  | 
292  |  | 
  | 
293  | 0  |       g_variant_get (parameters, "(&sav@a{sv})", &name, &iter, &platform_data); | 
294  | 0  |       g_variant_iter_next (iter, "v", ¶meter);  | 
295  | 0  |       g_variant_iter_free (iter);  | 
296  |  |  | 
297  |  |       /* Check the action exists and the parameter type matches. */  | 
298  | 0  |       if (!g_action_group_query_action (impl->exported_actions,  | 
299  | 0  |                                         name, NULL, ¶meter_type,  | 
300  | 0  |                                         NULL, NULL, NULL))  | 
301  | 0  |         { | 
302  | 0  |           g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,  | 
303  | 0  |                                                  "Unknown action ‘%s’", name);  | 
304  | 0  |           g_clear_pointer (¶meter, g_variant_unref);  | 
305  | 0  |           g_variant_unref (platform_data);  | 
306  | 0  |           return;  | 
307  | 0  |         }  | 
308  |  |  | 
309  | 0  |       if (!((parameter_type == NULL && parameter == NULL) ||  | 
310  | 0  |             (parameter_type != NULL && parameter != NULL && g_variant_is_of_type (parameter, parameter_type))))  | 
311  | 0  |         { | 
312  | 0  |           g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,  | 
313  | 0  |                                                  "Invalid parameter for action ‘%s’: expected type %s but got type %s",  | 
314  | 0  |                                                  name,  | 
315  | 0  |                                                  (parameter_type != NULL) ? (const gchar *) parameter_type : "()",  | 
316  | 0  |                                                  (parameter != NULL) ? g_variant_get_type_string (parameter) : "()");  | 
317  | 0  |           g_clear_pointer (¶meter, g_variant_unref);  | 
318  | 0  |           g_variant_unref (platform_data);  | 
319  | 0  |           return;  | 
320  | 0  |         }  | 
321  |  |  | 
322  | 0  |       class->before_emit (impl->app, platform_data);  | 
323  | 0  |       g_action_group_activate_action (impl->exported_actions, name, parameter);  | 
324  | 0  |       class->after_emit (impl->app, platform_data);  | 
325  |  | 
  | 
326  | 0  |       if (parameter)  | 
327  | 0  |         g_variant_unref (parameter);  | 
328  |  | 
  | 
329  | 0  |       g_variant_unref (platform_data);  | 
330  |  | 
  | 
331  | 0  |       g_dbus_method_invocation_return_value (invocation, NULL);  | 
332  | 0  |     }  | 
333  | 0  |   else  | 
334  | 0  |     g_assert_not_reached ();  | 
335  | 0  | }  | 
336  |  |  | 
337  |  | static gchar *  | 
338  |  | application_path_from_appid (const gchar *appid)  | 
339  | 0  | { | 
340  | 0  |   gchar *appid_path, *iter;  | 
341  |  | 
  | 
342  | 0  |   if (appid == NULL)  | 
343  |  |     /* this is a private implementation detail */  | 
344  | 0  |     return g_strdup ("/org/gtk/Application/anonymous"); | 
345  |  |  | 
346  | 0  |   appid_path = g_strconcat ("/", appid, NULL); | 
347  | 0  |   for (iter = appid_path; *iter; iter++)  | 
348  | 0  |     { | 
349  | 0  |       if (*iter == '.')  | 
350  | 0  |         *iter = '/';  | 
351  |  | 
  | 
352  | 0  |       if (*iter == '-')  | 
353  | 0  |         *iter = '_';  | 
354  | 0  |     }  | 
355  |  | 
  | 
356  | 0  |   return appid_path;  | 
357  | 0  | }  | 
358  |  |  | 
359  |  | static void g_application_impl_stop_primary (GApplicationImpl *impl);  | 
360  |  |  | 
361  |  | static void  | 
362  |  | name_lost (GDBusConnection *bus,  | 
363  |  |            const char      *sender_name,  | 
364  |  |            const char      *object_path,  | 
365  |  |            const char      *interface_name,  | 
366  |  |            const char      *signal_name,  | 
367  |  |            GVariant        *parameters,  | 
368  |  |            gpointer         user_data)  | 
369  | 0  | { | 
370  | 0  |   GApplicationImpl *impl = user_data;  | 
371  | 0  |   gboolean handled;  | 
372  |  | 
  | 
373  | 0  |   impl->primary = FALSE;  | 
374  | 0  |   g_application_impl_stop_primary (impl);  | 
375  | 0  |   g_signal_emit_by_name (impl->app, "name-lost", &handled);  | 
376  | 0  | }  | 
377  |  |  | 
378  |  | /* Attempt to become the primary instance.  | 
379  |  |  *  | 
380  |  |  * Returns %TRUE if everything went OK, regardless of if we became the  | 
381  |  |  * primary instance or not.  %FALSE is reserved for when something went  | 
382  |  |  * seriously wrong (and @error will be set too, in that case).  | 
383  |  |  *  | 
384  |  |  * After a %TRUE return, impl->primary will be TRUE if we were  | 
385  |  |  * successful.  | 
386  |  |  */  | 
387  |  | static gboolean  | 
388  |  | g_application_impl_attempt_primary (GApplicationImpl  *impl,  | 
389  |  |                                     GCancellable      *cancellable,  | 
390  |  |                                     GError           **error)  | 
391  | 0  | { | 
392  | 0  |   static const GDBusInterfaceVTable vtable = { | 
393  | 0  |     g_application_impl_method_call,  | 
394  | 0  |     g_application_impl_get_property,  | 
395  | 0  |     NULL, /* set_property */  | 
396  | 0  |     { 0 } | 
397  | 0  |   };  | 
398  | 0  |   GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app);  | 
399  | 0  |   GBusNameOwnerFlags name_owner_flags;  | 
400  | 0  |   GApplicationFlags app_flags;  | 
401  | 0  |   GVariant *reply;  | 
402  | 0  |   guint32 rval;  | 
403  | 0  |   GError *local_error = NULL;  | 
404  |  | 
  | 
405  | 0  |   if (org_gtk_Application == NULL)  | 
406  | 0  |     { | 
407  | 0  |       GError *my_error = NULL;  | 
408  | 0  |       GDBusNodeInfo *info;  | 
409  |  | 
  | 
410  | 0  |       info = g_dbus_node_info_new_for_xml (org_gtk_Application_xml, &my_error);  | 
411  | 0  |       if G_UNLIKELY (info == NULL)  | 
412  | 0  |         g_error ("%s", my_error->message); | 
413  | 0  |       org_gtk_Application = g_dbus_node_info_lookup_interface (info, "org.gtk.Application");  | 
414  | 0  |       g_assert (org_gtk_Application != NULL);  | 
415  | 0  |       g_dbus_interface_info_ref (org_gtk_Application);  | 
416  | 0  |       g_dbus_node_info_unref (info);  | 
417  |  | 
  | 
418  | 0  |       info = g_dbus_node_info_new_for_xml (org_freedesktop_Application_xml, &my_error);  | 
419  | 0  |       if G_UNLIKELY (info == NULL)  | 
420  | 0  |         g_error ("%s", my_error->message); | 
421  | 0  |       org_freedesktop_Application = g_dbus_node_info_lookup_interface (info, "org.freedesktop.Application");  | 
422  | 0  |       g_assert (org_freedesktop_Application != NULL);  | 
423  | 0  |       g_dbus_interface_info_ref (org_freedesktop_Application);  | 
424  | 0  |       g_dbus_node_info_unref (info);  | 
425  | 0  |     }  | 
426  |  |  | 
427  |  |   /* We could possibly have been D-Bus activated as a result of incoming  | 
428  |  |    * requests on either the application or actiongroup interfaces.  | 
429  |  |    * Because of how GDBus dispatches messages, we need to ensure that  | 
430  |  |    * both of those things are registered before we attempt to request  | 
431  |  |    * our name.  | 
432  |  |    *  | 
433  |  |    * The action group need not be populated yet, as long as it happens  | 
434  |  |    * before we return to the mainloop.  The reason for that is because  | 
435  |  |    * GDBus does the check to make sure the object exists from the worker  | 
436  |  |    * thread but doesn't actually dispatch the action invocation until we  | 
437  |  |    * hit the mainloop in this thread.  There is also no danger of  | 
438  |  |    * receiving 'activate' or 'open' signals until after 'startup' runs,  | 
439  |  |    * for the same reason.  | 
440  |  |    */  | 
441  | 0  |   impl->object_id = g_dbus_connection_register_object (impl->session_bus, impl->object_path,  | 
442  | 0  |                                                        org_gtk_Application, &vtable, impl, NULL, error);  | 
443  |  | 
  | 
444  | 0  |   if (impl->object_id == 0)  | 
445  | 0  |     return FALSE;  | 
446  |  |  | 
447  | 0  |   impl->fdo_object_id = g_dbus_connection_register_object (impl->session_bus, impl->object_path,  | 
448  | 0  |                                                            org_freedesktop_Application, &vtable, impl, NULL, error);  | 
449  |  | 
  | 
450  | 0  |   if (impl->fdo_object_id == 0)  | 
451  | 0  |     return FALSE;  | 
452  |  |  | 
453  | 0  |   impl->actions_id = g_dbus_connection_export_action_group (impl->session_bus, impl->object_path,  | 
454  | 0  |                                                             impl->exported_actions, error);  | 
455  |  | 
  | 
456  | 0  |   if (impl->actions_id == 0)  | 
457  | 0  |     return FALSE;  | 
458  |  |  | 
459  | 0  |   impl->registered = TRUE;  | 
460  | 0  |   if (!app_class->dbus_register (impl->app,  | 
461  | 0  |                                  impl->session_bus,  | 
462  | 0  |                                  impl->object_path,  | 
463  | 0  |                                  &local_error))  | 
464  | 0  |     { | 
465  | 0  |       g_return_val_if_fail (local_error != NULL, FALSE);  | 
466  | 0  |       g_propagate_error (error, g_steal_pointer (&local_error));  | 
467  | 0  |       return FALSE;  | 
468  | 0  |     }  | 
469  |  |  | 
470  | 0  |   g_return_val_if_fail (local_error == NULL, FALSE);  | 
471  |  |  | 
472  | 0  |   if (impl->bus_name == NULL)  | 
473  | 0  |     { | 
474  |  |       /* If this is a non-unique application then it is sufficient to  | 
475  |  |        * have our object paths registered. We can return now.  | 
476  |  |        *  | 
477  |  |        * Note: non-unique applications always act as primary-instance.  | 
478  |  |        */  | 
479  | 0  |       impl->primary = TRUE;  | 
480  | 0  |       return TRUE;  | 
481  | 0  |     }  | 
482  |  |  | 
483  |  |   /* If this is a unique application then we need to attempt to own  | 
484  |  |    * the well-known name and fall back to remote mode (!is_primary)  | 
485  |  |    * in the case that we can't do that.  | 
486  |  |    */  | 
487  | 0  |   name_owner_flags = G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE;  | 
488  | 0  |   app_flags = g_application_get_flags (impl->app);  | 
489  |  | 
  | 
490  | 0  |   if (app_flags & G_APPLICATION_ALLOW_REPLACEMENT)  | 
491  | 0  |     { | 
492  | 0  |       impl->name_lost_signal = g_dbus_connection_signal_subscribe (impl->session_bus,  | 
493  | 0  |                                                                    "org.freedesktop.DBus",  | 
494  | 0  |                                                                    "org.freedesktop.DBus",  | 
495  | 0  |                                                                    "NameLost",  | 
496  | 0  |                                                                    "/org/freedesktop/DBus",  | 
497  | 0  |                                                                    impl->bus_name,  | 
498  | 0  |                                                                    G_DBUS_SIGNAL_FLAGS_NONE,  | 
499  | 0  |                                                                    name_lost,  | 
500  | 0  |                                                                    impl,  | 
501  | 0  |                                                                    NULL);  | 
502  |  | 
  | 
503  | 0  |       name_owner_flags |= G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT;  | 
504  | 0  |     }  | 
505  | 0  |   if (app_flags & G_APPLICATION_REPLACE)  | 
506  | 0  |     name_owner_flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE;  | 
507  |  | 
  | 
508  | 0  |   reply = g_dbus_connection_call_sync (impl->session_bus,  | 
509  | 0  |                                        "org.freedesktop.DBus",  | 
510  | 0  |                                        "/org/freedesktop/DBus",  | 
511  | 0  |                                        "org.freedesktop.DBus",  | 
512  | 0  |                                        "RequestName",  | 
513  | 0  |                                        g_variant_new ("(su)", impl->bus_name, name_owner_flags), | 
514  | 0  |                                        G_VARIANT_TYPE ("(u)"), | 
515  | 0  |                                        0, -1, cancellable, error);  | 
516  |  | 
  | 
517  | 0  |   if (reply == NULL)  | 
518  | 0  |     return FALSE;  | 
519  |  |  | 
520  | 0  |   g_variant_get (reply, "(u)", &rval);  | 
521  | 0  |   g_variant_unref (reply);  | 
522  |  |  | 
523  |  |   /* DBUS_REQUEST_NAME_REPLY_EXISTS: 3 */  | 
524  | 0  |   impl->primary = (rval != 3);  | 
525  |  | 
  | 
526  | 0  |   if (!impl->primary && impl->name_lost_signal)  | 
527  | 0  |     { | 
528  | 0  |       g_dbus_connection_signal_unsubscribe (impl->session_bus, impl->name_lost_signal);  | 
529  | 0  |       impl->name_lost_signal = 0;  | 
530  | 0  |     }  | 
531  |  | 
  | 
532  | 0  |   return TRUE;  | 
533  | 0  | }  | 
534  |  |  | 
535  |  | /* Stop doing the things that the primary instance does.  | 
536  |  |  *  | 
537  |  |  * This should be called if attempting to become the primary instance  | 
538  |  |  * failed (in order to clean up any partial success) and should also  | 
539  |  |  * be called when freeing the GApplication.  | 
540  |  |  *  | 
541  |  |  * It is safe to call this multiple times.  | 
542  |  |  */  | 
543  |  | static void  | 
544  |  | g_application_impl_stop_primary (GApplicationImpl *impl)  | 
545  | 0  | { | 
546  | 0  |   GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app);  | 
547  |  | 
  | 
548  | 0  |   if (impl->registered)  | 
549  | 0  |     { | 
550  | 0  |       app_class->dbus_unregister (impl->app,  | 
551  | 0  |                                   impl->session_bus,  | 
552  | 0  |                                   impl->object_path);  | 
553  | 0  |       impl->registered = FALSE;  | 
554  | 0  |     }  | 
555  |  | 
  | 
556  | 0  |   if (impl->object_id)  | 
557  | 0  |     { | 
558  | 0  |       g_dbus_connection_unregister_object (impl->session_bus, impl->object_id);  | 
559  | 0  |       impl->object_id = 0;  | 
560  | 0  |     }  | 
561  |  | 
  | 
562  | 0  |   if (impl->fdo_object_id)  | 
563  | 0  |     { | 
564  | 0  |       g_dbus_connection_unregister_object (impl->session_bus, impl->fdo_object_id);  | 
565  | 0  |       impl->fdo_object_id = 0;  | 
566  | 0  |     }  | 
567  |  | 
  | 
568  | 0  |   if (impl->actions_id)  | 
569  | 0  |     { | 
570  | 0  |       g_dbus_connection_unexport_action_group (impl->session_bus, impl->actions_id);  | 
571  | 0  |       impl->actions_id = 0;  | 
572  | 0  |     }  | 
573  |  | 
  | 
574  | 0  |   if (impl->name_lost_signal)  | 
575  | 0  |     { | 
576  | 0  |       g_dbus_connection_signal_unsubscribe (impl->session_bus, impl->name_lost_signal);  | 
577  | 0  |       impl->name_lost_signal = 0;  | 
578  | 0  |     }  | 
579  |  | 
  | 
580  | 0  |   if (impl->primary && impl->bus_name)  | 
581  | 0  |     { | 
582  | 0  |       g_dbus_connection_call (impl->session_bus, "org.freedesktop.DBus",  | 
583  | 0  |                               "/org/freedesktop/DBus", "org.freedesktop.DBus",  | 
584  | 0  |                               "ReleaseName", g_variant_new ("(s)", impl->bus_name), | 
585  | 0  |                               NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);  | 
586  | 0  |       impl->primary = FALSE;  | 
587  | 0  |     }  | 
588  | 0  | }  | 
589  |  |  | 
590  |  | void  | 
591  |  | g_application_impl_set_busy_state (GApplicationImpl *impl,  | 
592  |  |                                    gboolean          busy)  | 
593  | 0  | { | 
594  | 0  |   if (impl->busy != busy)  | 
595  | 0  |     { | 
596  | 0  |       impl->busy = busy;  | 
597  | 0  |       send_property_change (impl);  | 
598  | 0  |     }  | 
599  | 0  | }  | 
600  |  |  | 
601  |  | void  | 
602  |  | g_application_impl_destroy (GApplicationImpl *impl)  | 
603  | 0  | { | 
604  | 0  |   g_application_impl_stop_primary (impl);  | 
605  |  | 
  | 
606  | 0  |   if (impl->session_bus)  | 
607  | 0  |     g_object_unref (impl->session_bus);  | 
608  |  | 
  | 
609  | 0  |   g_free (impl->object_path);  | 
610  |  | 
  | 
611  | 0  |   g_slice_free (GApplicationImpl, impl);  | 
612  | 0  | }  | 
613  |  |  | 
614  |  | GApplicationImpl *  | 
615  |  | g_application_impl_register (GApplication        *application,  | 
616  |  |                              const gchar         *appid,  | 
617  |  |                              GApplicationFlags    flags,  | 
618  |  |                              GActionGroup        *exported_actions,  | 
619  |  |                              GRemoteActionGroup **remote_actions,  | 
620  |  |                              GCancellable        *cancellable,  | 
621  |  |                              GError             **error)  | 
622  | 0  | { | 
623  | 0  |   GDBusActionGroup *actions;  | 
624  | 0  |   GApplicationImpl *impl;  | 
625  |  | 
  | 
626  | 0  |   g_assert ((flags & G_APPLICATION_NON_UNIQUE) || appid != NULL);  | 
627  |  |  | 
628  | 0  |   impl = g_slice_new0 (GApplicationImpl);  | 
629  |  | 
  | 
630  | 0  |   impl->app = application;  | 
631  | 0  |   impl->exported_actions = exported_actions;  | 
632  |  |  | 
633  |  |   /* non-unique applications do not attempt to acquire a bus name */  | 
634  | 0  |   if (~flags & G_APPLICATION_NON_UNIQUE)  | 
635  | 0  |     impl->bus_name = appid;  | 
636  |  | 
  | 
637  | 0  |   impl->session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, NULL);  | 
638  |  | 
  | 
639  | 0  |   if (impl->session_bus == NULL)  | 
640  | 0  |     { | 
641  |  |       /* If we can't connect to the session bus, proceed as a normal  | 
642  |  |        * non-unique application.  | 
643  |  |        */  | 
644  | 0  |       *remote_actions = NULL;  | 
645  | 0  |       return impl;  | 
646  | 0  |     }  | 
647  |  |  | 
648  | 0  |   impl->object_path = application_path_from_appid (appid);  | 
649  |  |  | 
650  |  |   /* Only try to be the primary instance if  | 
651  |  |    * G_APPLICATION_IS_LAUNCHER was not specified.  | 
652  |  |    */  | 
653  | 0  |   if (~flags & G_APPLICATION_IS_LAUNCHER)  | 
654  | 0  |     { | 
655  | 0  |       if (!g_application_impl_attempt_primary (impl, cancellable, error))  | 
656  | 0  |         { | 
657  | 0  |           g_application_impl_destroy (impl);  | 
658  | 0  |           return NULL;  | 
659  | 0  |         }  | 
660  |  |  | 
661  | 0  |       if (impl->primary)  | 
662  | 0  |         return impl;  | 
663  |  |  | 
664  |  |       /* We didn't make it.  Drop our service-side stuff. */  | 
665  | 0  |       g_application_impl_stop_primary (impl);  | 
666  |  | 
  | 
667  | 0  |       if (flags & G_APPLICATION_IS_SERVICE)  | 
668  | 0  |         { | 
669  | 0  |           g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,  | 
670  | 0  |                        "Unable to acquire bus name '%s'", appid);  | 
671  | 0  |           g_application_impl_destroy (impl);  | 
672  |  | 
  | 
673  | 0  |           return NULL;  | 
674  | 0  |         }  | 
675  | 0  |     }  | 
676  |  |  | 
677  |  |   /* We are non-primary.  Try to get the primary's list of actions.  | 
678  |  |    * This also serves as a mechanism to ensure that the primary exists  | 
679  |  |    * (ie: D-Bus service files installed correctly, etc).  | 
680  |  |    */  | 
681  | 0  |   actions = g_dbus_action_group_get (impl->session_bus, impl->bus_name, impl->object_path);  | 
682  | 0  |   if (!g_dbus_action_group_sync (actions, cancellable, error))  | 
683  | 0  |     { | 
684  |  |       /* The primary appears not to exist.  Fail the registration. */  | 
685  | 0  |       g_application_impl_destroy (impl);  | 
686  | 0  |       g_object_unref (actions);  | 
687  |  | 
  | 
688  | 0  |       return NULL;  | 
689  | 0  |     }  | 
690  |  |  | 
691  | 0  |   *remote_actions = G_REMOTE_ACTION_GROUP (actions);  | 
692  |  | 
  | 
693  | 0  |   return impl;  | 
694  | 0  | }  | 
695  |  |  | 
696  |  | void  | 
697  |  | g_application_impl_activate (GApplicationImpl *impl,  | 
698  |  |                              GVariant         *platform_data)  | 
699  | 0  | { | 
700  | 0  |   g_dbus_connection_call (impl->session_bus,  | 
701  | 0  |                           impl->bus_name,  | 
702  | 0  |                           impl->object_path,  | 
703  | 0  |                           "org.gtk.Application",  | 
704  | 0  |                           "Activate",  | 
705  | 0  |                           g_variant_new ("(@a{sv})", platform_data), | 
706  | 0  |                           NULL, 0, -1, NULL, NULL, NULL);  | 
707  | 0  | }  | 
708  |  |  | 
709  |  | void  | 
710  |  | g_application_impl_open (GApplicationImpl  *impl,  | 
711  |  |                          GFile            **files,  | 
712  |  |                          gint               n_files,  | 
713  |  |                          const gchar       *hint,  | 
714  |  |                          GVariant          *platform_data)  | 
715  | 0  | { | 
716  | 0  |   GVariantBuilder builder;  | 
717  | 0  |   gint i;  | 
718  |  | 
  | 
719  | 0  |   g_variant_builder_init (&builder, G_VARIANT_TYPE ("(assa{sv})")); | 
720  | 0  |   g_variant_builder_open (&builder, G_VARIANT_TYPE_STRING_ARRAY);  | 
721  | 0  |   for (i = 0; i < n_files; i++)  | 
722  | 0  |     { | 
723  | 0  |       gchar *uri = g_file_get_uri (files[i]);  | 
724  | 0  |       g_variant_builder_add (&builder, "s", uri);  | 
725  | 0  |       g_free (uri);  | 
726  | 0  |     }  | 
727  | 0  |   g_variant_builder_close (&builder);  | 
728  | 0  |   g_variant_builder_add (&builder, "s", hint);  | 
729  | 0  |   g_variant_builder_add_value (&builder, platform_data);  | 
730  |  | 
  | 
731  | 0  |   g_dbus_connection_call (impl->session_bus,  | 
732  | 0  |                           impl->bus_name,  | 
733  | 0  |                           impl->object_path,  | 
734  | 0  |                           "org.gtk.Application",  | 
735  | 0  |                           "Open",  | 
736  | 0  |                           g_variant_builder_end (&builder),  | 
737  | 0  |                           NULL, 0, -1, NULL, NULL, NULL);  | 
738  | 0  | }  | 
739  |  |  | 
740  |  | static void  | 
741  |  | g_application_impl_cmdline_method_call (GDBusConnection       *connection,  | 
742  |  |                                         const gchar           *sender,  | 
743  |  |                                         const gchar           *object_path,  | 
744  |  |                                         const gchar           *interface_name,  | 
745  |  |                                         const gchar           *method_name,  | 
746  |  |                                         GVariant              *parameters,  | 
747  |  |                                         GDBusMethodInvocation *invocation,  | 
748  |  |                                         gpointer               user_data)  | 
749  | 0  | { | 
750  | 0  |   const gchar *message;  | 
751  |  | 
  | 
752  | 0  |   g_variant_get_child (parameters, 0, "&s", &message);  | 
753  |  | 
  | 
754  | 0  |   if (strcmp (method_name, "Print") == 0)  | 
755  | 0  |     g_print ("%s", message); | 
756  | 0  |   else if (strcmp (method_name, "PrintError") == 0)  | 
757  | 0  |     g_printerr ("%s", message); | 
758  | 0  |   else  | 
759  | 0  |     g_assert_not_reached ();  | 
760  |  |  | 
761  | 0  |   g_dbus_method_invocation_return_value (invocation, NULL);  | 
762  | 0  | }  | 
763  |  |  | 
764  |  | typedef struct  | 
765  |  | { | 
766  |  |   GMainLoop *loop;  | 
767  |  |   int status;  | 
768  |  | } CommandLineData;  | 
769  |  |  | 
770  |  | static void  | 
771  |  | g_application_impl_cmdline_done (GObject      *source,  | 
772  |  |                                  GAsyncResult *result,  | 
773  |  |                                  gpointer      user_data)  | 
774  | 0  | { | 
775  | 0  |   CommandLineData *data = user_data;  | 
776  | 0  |   GError *error = NULL;  | 
777  | 0  |   GVariant *reply;  | 
778  |  | 
  | 
779  | 0  | #ifdef G_OS_UNIX  | 
780  | 0  |   reply = g_dbus_connection_call_with_unix_fd_list_finish (G_DBUS_CONNECTION (source), NULL, result, &error);  | 
781  |  | #else  | 
782  |  |   reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);  | 
783  |  | #endif  | 
784  |  |  | 
785  |  | 
  | 
786  | 0  |   if (reply != NULL)  | 
787  | 0  |     { | 
788  | 0  |       g_variant_get (reply, "(i)", &data->status);  | 
789  | 0  |       g_variant_unref (reply);  | 
790  | 0  |     }  | 
791  |  |  | 
792  | 0  |   else  | 
793  | 0  |     { | 
794  | 0  |       g_printerr ("%s\n", error->message); | 
795  | 0  |       g_error_free (error);  | 
796  | 0  |       data->status = 1;  | 
797  | 0  |     }  | 
798  |  | 
  | 
799  | 0  |   g_main_loop_quit (data->loop);  | 
800  | 0  | }  | 
801  |  |  | 
802  |  | int  | 
803  |  | g_application_impl_command_line (GApplicationImpl    *impl,  | 
804  |  |                                  const gchar * const *arguments,  | 
805  |  |                                  GVariant            *platform_data)  | 
806  | 0  | { | 
807  | 0  |   static const GDBusInterfaceVTable vtable = { | 
808  | 0  |     g_application_impl_cmdline_method_call, NULL, NULL, { 0 } | 
809  | 0  |   };  | 
810  | 0  |   const gchar *object_path = "/org/gtk/Application/CommandLine";  | 
811  | 0  |   GMainContext *context;  | 
812  | 0  |   CommandLineData data;  | 
813  | 0  |   guint object_id G_GNUC_UNUSED  /* when compiling with G_DISABLE_ASSERT */;  | 
814  |  | 
  | 
815  | 0  |   context = g_main_context_new ();  | 
816  | 0  |   data.loop = g_main_loop_new (context, FALSE);  | 
817  | 0  |   g_main_context_push_thread_default (context);  | 
818  |  | 
  | 
819  | 0  |   if (org_gtk_private_CommandLine == NULL)  | 
820  | 0  |     { | 
821  | 0  |       GError *error = NULL;  | 
822  | 0  |       GDBusNodeInfo *info;  | 
823  |  | 
  | 
824  | 0  |       info = g_dbus_node_info_new_for_xml (org_gtk_private_CommandLine_xml, &error);  | 
825  | 0  |       if G_UNLIKELY (info == NULL)  | 
826  | 0  |         g_error ("%s", error->message); | 
827  | 0  |       org_gtk_private_CommandLine = g_dbus_node_info_lookup_interface (info, "org.gtk.private.CommandLine");  | 
828  | 0  |       g_assert (org_gtk_private_CommandLine != NULL);  | 
829  | 0  |       g_dbus_interface_info_ref (org_gtk_private_CommandLine);  | 
830  | 0  |       g_dbus_node_info_unref (info);  | 
831  | 0  |     }  | 
832  |  |  | 
833  | 0  |   object_id = g_dbus_connection_register_object (impl->session_bus, object_path,  | 
834  | 0  |                                                  org_gtk_private_CommandLine,  | 
835  | 0  |                                                  &vtable, &data, NULL, NULL);  | 
836  |  |   /* In theory we should try other paths... */  | 
837  | 0  |   g_assert (object_id != 0);  | 
838  |  |  | 
839  | 0  | #ifdef G_OS_UNIX  | 
840  | 0  |   { | 
841  | 0  |     GError *error = NULL;  | 
842  | 0  |     GUnixFDList *fd_list;  | 
843  |  |  | 
844  |  |     /* send along the stdin in case  | 
845  |  |      * g_application_command_line_get_stdin_data() is called  | 
846  |  |      */  | 
847  | 0  |     fd_list = g_unix_fd_list_new ();  | 
848  | 0  |     g_unix_fd_list_append (fd_list, 0, &error);  | 
849  | 0  |     g_assert_no_error (error);  | 
850  |  | 
  | 
851  | 0  |     g_dbus_connection_call_with_unix_fd_list (impl->session_bus, impl->bus_name, impl->object_path,  | 
852  | 0  |                                               "org.gtk.Application", "CommandLine",  | 
853  | 0  |                                               g_variant_new ("(o^aay@a{sv})", object_path, arguments, platform_data), | 
854  | 0  |                                               G_VARIANT_TYPE ("(i)"), 0, G_MAXINT, fd_list, NULL, | 
855  | 0  |                                               g_application_impl_cmdline_done, &data);  | 
856  | 0  |     g_object_unref (fd_list);  | 
857  | 0  |   }  | 
858  |  | #else  | 
859  |  |   g_dbus_connection_call (impl->session_bus, impl->bus_name, impl->object_path,  | 
860  |  |                           "org.gtk.Application", "CommandLine",  | 
861  |  |                           g_variant_new ("(o^aay@a{sv})", object_path, arguments, platform_data), | 
862  |  |                           G_VARIANT_TYPE ("(i)"), 0, G_MAXINT, NULL, | 
863  |  |                           g_application_impl_cmdline_done, &data);  | 
864  |  | #endif  | 
865  |  | 
  | 
866  | 0  |   g_main_loop_run (data.loop);  | 
867  |  | 
  | 
868  | 0  |   g_main_context_pop_thread_default (context);  | 
869  | 0  |   g_main_context_unref (context);  | 
870  | 0  |   g_main_loop_unref (data.loop);  | 
871  |  | 
  | 
872  | 0  |   return data.status;  | 
873  | 0  | }  | 
874  |  |  | 
875  |  | void  | 
876  |  | g_application_impl_flush (GApplicationImpl *impl)  | 
877  | 0  | { | 
878  | 0  |   if (impl->session_bus)  | 
879  | 0  |     g_dbus_connection_flush_sync (impl->session_bus, NULL, NULL);  | 
880  | 0  | }  | 
881  |  |  | 
882  |  | GDBusConnection *  | 
883  |  | g_application_impl_get_dbus_connection (GApplicationImpl *impl)  | 
884  | 0  | { | 
885  | 0  |   return impl->session_bus;  | 
886  | 0  | }  | 
887  |  |  | 
888  |  | const gchar *  | 
889  |  | g_application_impl_get_dbus_object_path (GApplicationImpl *impl)  | 
890  | 0  | { | 
891  | 0  |   return impl->object_path;  | 
892  | 0  | }  | 
893  |  |  | 
894  |  | /* GDBusCommandLine implementation {{{1 */ | 
895  |  |  | 
896  |  | typedef GApplicationCommandLineClass GDBusCommandLineClass;  | 
897  |  | static GType g_dbus_command_line_get_type (void);  | 
898  |  | typedef struct  | 
899  |  | { | 
900  |  |   GApplicationCommandLine  parent_instance;  | 
901  |  |   GDBusMethodInvocation   *invocation;  | 
902  |  |  | 
903  |  |   GDBusConnection *connection;  | 
904  |  |   const gchar     *bus_name;  | 
905  |  |   const gchar     *object_path;  | 
906  |  | } GDBusCommandLine;  | 
907  |  |  | 
908  |  |  | 
909  |  | G_DEFINE_TYPE (GDBusCommandLine,  | 
910  |  |                g_dbus_command_line,  | 
911  |  |                G_TYPE_APPLICATION_COMMAND_LINE)  | 
912  |  |  | 
913  |  | static void  | 
914  |  | g_dbus_command_line_print_literal (GApplicationCommandLine *cmdline,  | 
915  |  |                                    const gchar             *message)  | 
916  | 0  | { | 
917  | 0  |   GDBusCommandLine *gdbcl = (GDBusCommandLine *) cmdline;  | 
918  |  | 
  | 
919  | 0  |   g_dbus_connection_call (gdbcl->connection,  | 
920  | 0  |                           gdbcl->bus_name,  | 
921  | 0  |                           gdbcl->object_path,  | 
922  | 0  |                           "org.gtk.private.CommandLine", "Print",  | 
923  | 0  |                           g_variant_new ("(s)", message), | 
924  | 0  |                           NULL, 0, -1, NULL, NULL, NULL);  | 
925  | 0  | }  | 
926  |  |  | 
927  |  | static void  | 
928  |  | g_dbus_command_line_printerr_literal (GApplicationCommandLine *cmdline,  | 
929  |  |                                       const gchar             *message)  | 
930  | 0  | { | 
931  | 0  |   GDBusCommandLine *gdbcl = (GDBusCommandLine *) cmdline;  | 
932  |  | 
  | 
933  | 0  |   g_dbus_connection_call (gdbcl->connection,  | 
934  | 0  |                           gdbcl->bus_name,  | 
935  | 0  |                           gdbcl->object_path,  | 
936  | 0  |                           "org.gtk.private.CommandLine", "PrintError",  | 
937  | 0  |                           g_variant_new ("(s)", message), | 
938  | 0  |                           NULL, 0, -1, NULL, NULL, NULL);  | 
939  | 0  | }  | 
940  |  |  | 
941  |  | static GInputStream *  | 
942  |  | g_dbus_command_line_get_stdin (GApplicationCommandLine *cmdline)  | 
943  | 0  | { | 
944  | 0  | #ifdef G_OS_UNIX  | 
945  | 0  |   GDBusCommandLine *gdbcl = (GDBusCommandLine *) cmdline;  | 
946  | 0  |   GInputStream *result = NULL;  | 
947  | 0  |   GDBusMessage *message;  | 
948  | 0  |   GUnixFDList *fd_list;  | 
949  |  | 
  | 
950  | 0  |   message = g_dbus_method_invocation_get_message (gdbcl->invocation);  | 
951  | 0  |   fd_list = g_dbus_message_get_unix_fd_list (message);  | 
952  |  | 
  | 
953  | 0  |   if (fd_list && g_unix_fd_list_get_length (fd_list))  | 
954  | 0  |     { | 
955  | 0  |       gint *fds, n_fds, i;  | 
956  |  | 
  | 
957  | 0  |       fds = g_unix_fd_list_steal_fds (fd_list, &n_fds);  | 
958  | 0  |       result = g_unix_input_stream_new (fds[0], TRUE);  | 
959  | 0  |       for (i = 1; i < n_fds; i++)  | 
960  | 0  |         (void) g_close (fds[i], NULL);  | 
961  | 0  |       g_free (fds);  | 
962  | 0  |     }  | 
963  |  | 
  | 
964  | 0  |   return result;  | 
965  |  | #else  | 
966  |  |   return NULL;  | 
967  |  | #endif  | 
968  | 0  | }  | 
969  |  |  | 
970  |  | static void  | 
971  |  | g_dbus_command_line_finalize (GObject *object)  | 
972  | 0  | { | 
973  | 0  |   GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object);  | 
974  | 0  |   GDBusCommandLine *gdbcl = (GDBusCommandLine *) object;  | 
975  | 0  |   gint status;  | 
976  |  | 
  | 
977  | 0  |   status = g_application_command_line_get_exit_status (cmdline);  | 
978  |  | 
  | 
979  | 0  |   g_dbus_method_invocation_return_value (gdbcl->invocation,  | 
980  | 0  |                                          g_variant_new ("(i)", status)); | 
981  | 0  |   g_object_unref (gdbcl->invocation);  | 
982  |  | 
  | 
983  | 0  |   G_OBJECT_CLASS (g_dbus_command_line_parent_class)  | 
984  | 0  |     ->finalize (object);  | 
985  | 0  | }  | 
986  |  |  | 
987  |  | static void  | 
988  |  | g_dbus_command_line_init (GDBusCommandLine *gdbcl)  | 
989  | 0  | { | 
990  | 0  | }  | 
991  |  |  | 
992  |  | static void  | 
993  |  | g_dbus_command_line_class_init (GApplicationCommandLineClass *class)  | 
994  | 0  | { | 
995  | 0  |   GObjectClass *object_class = G_OBJECT_CLASS (class);  | 
996  |  | 
  | 
997  | 0  |   object_class->finalize = g_dbus_command_line_finalize;  | 
998  | 0  |   class->printerr_literal = g_dbus_command_line_printerr_literal;  | 
999  | 0  |   class->print_literal = g_dbus_command_line_print_literal;  | 
1000  | 0  |   class->get_stdin = g_dbus_command_line_get_stdin;  | 
1001  | 0  | }  | 
1002  |  |  | 
1003  |  | static GApplicationCommandLine *  | 
1004  |  | g_dbus_command_line_new (GDBusMethodInvocation *invocation)  | 
1005  | 0  | { | 
1006  | 0  |   GDBusCommandLine *gdbcl;  | 
1007  | 0  |   GVariant *args;  | 
1008  | 0  |   GVariant *arguments, *platform_data;  | 
1009  |  | 
  | 
1010  | 0  |   args = g_dbus_method_invocation_get_parameters (invocation);  | 
1011  |  | 
  | 
1012  | 0  |   arguments = g_variant_get_child_value (args, 1);  | 
1013  | 0  |   platform_data = g_variant_get_child_value (args, 2);  | 
1014  | 0  |   gdbcl = g_object_new (g_dbus_command_line_get_type (),  | 
1015  | 0  |                         "arguments", arguments,  | 
1016  | 0  |                         "platform-data", platform_data,  | 
1017  | 0  |                         NULL);  | 
1018  | 0  |   g_variant_unref (arguments);  | 
1019  | 0  |   g_variant_unref (platform_data);  | 
1020  |  | 
  | 
1021  | 0  |   gdbcl->connection = g_dbus_method_invocation_get_connection (invocation);  | 
1022  | 0  |   gdbcl->bus_name = g_dbus_method_invocation_get_sender (invocation);  | 
1023  | 0  |   g_variant_get_child (args, 0, "&o", &gdbcl->object_path);  | 
1024  | 0  |   gdbcl->invocation = g_object_ref (invocation);  | 
1025  |  | 
  | 
1026  | 0  |   return G_APPLICATION_COMMAND_LINE (gdbcl);  | 
1027  | 0  | }  | 
1028  |  |  | 
1029  |  | /* Epilogue {{{1 */ | 
1030  |  |  | 
1031  |  | /* vim:set foldmethod=marker: */  |