X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgapplicationimpl-dbus.c;h=4b1b5c915f4ca1e40a7af4ea78cf8b3767ed6699;hb=2a53b4d0e2c98a14aedf31e38f0ad1fb2e8fe26f;hp=b258f026446fdd03bd2b16e598f1aba30c0f2800;hpb=eb5381b8622eda26b6bd86dbac39bd9ed86bf730;p=platform%2Fupstream%2Fglib.git
diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c
index b258f02..4b1b5c9 100644
--- a/gio/gapplicationimpl-dbus.c
+++ b/gio/gapplicationimpl-dbus.c
@@ -12,24 +12,25 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Public License along with this library; if not, see .
*
* Authors: Ryan Lortie
*/
+#include "config.h"
+
#include "gapplicationimpl.h"
#include "gactiongroup.h"
#include "gactiongroupexporter.h"
#include "gremoteactiongroup.h"
-#include "gdbusactiongroup.h"
+#include "gdbusactiongroup-private.h"
#include "gapplication.h"
#include "gfile.h"
#include "gdbusconnection.h"
#include "gdbusintrospection.h"
#include "gdbuserror.h"
+#include "glib/gstdio.h"
#include
#include
@@ -37,49 +38,69 @@
#include "gapplicationcommandline.h"
#include "gdbusmethodinvocation.h"
-G_GNUC_INTERNAL gboolean
-g_dbus_action_group_sync (GDBusActionGroup *group,
- GCancellable *cancellable,
- GError **error);
-
+#ifdef G_OS_UNIX
+#include "gunixinputstream.h"
+#include "gunixfdlist.h"
+#endif
/* DBus Interface definition {{{1 */
/* For documentation of these interfaces, see
- * http://live.gnome.org/GTK+/GApplication-dbus-apis
+ * https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI
*/
static const gchar org_gtk_Application_xml[] =
""
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
"";
static GDBusInterfaceInfo *org_gtk_Application;
+static const gchar org_freedesktop_Application_xml[] =
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ "";
+
+static GDBusInterfaceInfo *org_freedesktop_Application;
+
static const gchar org_gtk_private_CommandLine_xml[] =
""
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
"";
static GDBusInterfaceInfo *org_gtk_private_CommandLine;
@@ -93,17 +114,59 @@ struct _GApplicationImpl
gchar *object_path;
guint object_id;
+ guint fdo_object_id;
guint actions_id;
gboolean properties_live;
gboolean primary;
- gpointer app;
+ gboolean busy;
+ GApplication *app;
};
static GApplicationCommandLine *
g_dbus_command_line_new (GDBusMethodInvocation *invocation);
+static GVariant *
+g_application_impl_get_property (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error,
+ gpointer user_data)
+{
+ GApplicationImpl *impl = user_data;
+
+ if (strcmp (property_name, "Busy") == 0)
+ return g_variant_new_boolean (impl->busy);
+
+ g_assert_not_reached ();
+
+ return NULL;
+}
+
+static void
+send_property_change (GApplicationImpl *impl)
+{
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "Busy", g_variant_new_boolean (impl->busy));
+
+ g_dbus_connection_emit_signal (impl->session_bus,
+ NULL,
+ impl->object_path,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ g_variant_new ("(sa{sv}as)",
+ "org.gtk.Application",
+ &builder,
+ NULL),
+ NULL);
+}
static void
g_application_impl_method_call (GDBusConnection *connection,
@@ -124,7 +187,10 @@ g_application_impl_method_call (GDBusConnection *connection,
{
GVariant *platform_data;
+ /* Completely the same for both freedesktop and gtk interfaces */
+
g_variant_get (parameters, "(@a{sv})", &platform_data);
+
class->before_emit (impl->app, platform_data);
g_signal_emit_by_name (impl->app, "activate");
class->after_emit (impl->app, platform_data);
@@ -135,14 +201,28 @@ g_application_impl_method_call (GDBusConnection *connection,
else if (strcmp (method_name, "Open") == 0)
{
+ GApplicationFlags flags;
GVariant *platform_data;
const gchar *hint;
GVariant *array;
GFile **files;
gint n, i;
- g_variant_get (parameters, "(@ass@a{sv})",
- &array, &hint, &platform_data);
+ flags = g_application_get_flags (impl->app);
+ if ((flags & G_APPLICATION_HANDLES_OPEN) == 0)
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "Application does not open files");
+ return;
+ }
+
+ /* freedesktop interface has no hint parameter */
+ if (g_str_equal (interface_name, "org.freedesktop.Application"))
+ {
+ g_variant_get (parameters, "(@as@a{sv})", &array, &platform_data);
+ hint = "";
+ }
+ else
+ g_variant_get (parameters, "(@as&s@a{sv})", &array, &hint, &platform_data);
n = g_variant_n_children (array);
files = g_new (GFile *, n + 1);
@@ -172,10 +252,21 @@ g_application_impl_method_call (GDBusConnection *connection,
else if (strcmp (method_name, "CommandLine") == 0)
{
+ GApplicationFlags flags;
GApplicationCommandLine *cmdline;
GVariant *platform_data;
int status;
+ flags = g_application_get_flags (impl->app);
+ if ((flags & G_APPLICATION_HANDLES_COMMAND_LINE) == 0)
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED,
+ "Application does not handle command line arguments");
+ return;
+ }
+
+ /* Only on the GtkApplication interface */
+
cmdline = g_dbus_command_line_new (invocation);
platform_data = g_variant_get_child_value (parameters, 2);
class->before_emit (impl->app, platform_data);
@@ -185,6 +276,30 @@ g_application_impl_method_call (GDBusConnection *connection,
g_variant_unref (platform_data);
g_object_unref (cmdline);
}
+ else if (g_str_equal (method_name, "ActivateAction"))
+ {
+ GVariant *parameter = NULL;
+ GVariant *platform_data;
+ GVariantIter *iter;
+ const gchar *name;
+
+ /* Only on the freedesktop interface */
+
+ g_variant_get (parameters, "(&sav@a{sv})", &name, &iter, &platform_data);
+ g_variant_iter_next (iter, "v", ¶meter);
+ g_variant_iter_free (iter);
+
+ class->before_emit (impl->app, platform_data);
+ g_action_group_activate_action (impl->exported_actions, name, parameter);
+ class->after_emit (impl->app, platform_data);
+
+ if (parameter)
+ g_variant_unref (parameter);
+
+ g_variant_unref (platform_data);
+
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ }
else
g_assert_not_reached ();
}
@@ -227,7 +342,10 @@ g_application_impl_attempt_primary (GApplicationImpl *impl,
{
const static GDBusInterfaceVTable vtable = {
g_application_impl_method_call,
+ g_application_impl_get_property,
+ NULL /* set_property */
};
+ GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app);
GVariant *reply;
guint32 rval;
@@ -243,6 +361,14 @@ g_application_impl_attempt_primary (GApplicationImpl *impl,
g_assert (org_gtk_Application != NULL);
g_dbus_interface_info_ref (org_gtk_Application);
g_dbus_node_info_unref (info);
+
+ info = g_dbus_node_info_new_for_xml (org_freedesktop_Application_xml, &error);
+ if G_UNLIKELY (info == NULL)
+ g_error ("%s", error->message);
+ org_freedesktop_Application = g_dbus_node_info_lookup_interface (info, "org.freedesktop.Application");
+ g_assert (org_freedesktop_Application != NULL);
+ g_dbus_interface_info_ref (org_freedesktop_Application);
+ g_dbus_node_info_unref (info);
}
/* We could possibly have been D-Bus activated as a result of incoming
@@ -265,12 +391,24 @@ g_application_impl_attempt_primary (GApplicationImpl *impl,
if (impl->object_id == 0)
return FALSE;
+ impl->fdo_object_id = g_dbus_connection_register_object (impl->session_bus, impl->object_path,
+ org_freedesktop_Application, &vtable, impl, NULL, error);
+
+ if (impl->fdo_object_id == 0)
+ return FALSE;
+
impl->actions_id = g_dbus_connection_export_action_group (impl->session_bus, impl->object_path,
impl->exported_actions, error);
if (impl->actions_id == 0)
return FALSE;
+ if (!app_class->dbus_register (impl->app,
+ impl->session_bus,
+ impl->object_path,
+ error))
+ return FALSE;
+
if (impl->bus_name == NULL)
{
/* If this is a non-unique application then it is sufficient to
@@ -315,12 +453,24 @@ g_application_impl_attempt_primary (GApplicationImpl *impl,
static void
g_application_impl_stop_primary (GApplicationImpl *impl)
{
+ GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app);
+
+ app_class->dbus_unregister (impl->app,
+ impl->session_bus,
+ impl->object_path);
+
if (impl->object_id)
{
g_dbus_connection_unregister_object (impl->session_bus, impl->object_id);
impl->object_id = 0;
}
+ if (impl->fdo_object_id)
+ {
+ g_dbus_connection_unregister_object (impl->session_bus, impl->fdo_object_id);
+ impl->fdo_object_id = 0;
+ }
+
if (impl->actions_id)
{
g_dbus_connection_unexport_action_group (impl->session_bus, impl->actions_id);
@@ -338,6 +488,17 @@ g_application_impl_stop_primary (GApplicationImpl *impl)
}
void
+g_application_impl_set_busy_state (GApplicationImpl *impl,
+ gboolean busy)
+{
+ if (impl->busy != busy)
+ {
+ impl->busy = busy;
+ send_property_change (impl);
+ }
+}
+
+void
g_application_impl_destroy (GApplicationImpl *impl)
{
g_application_impl_stop_primary (impl);
@@ -406,7 +567,7 @@ g_application_impl_register (GApplication *application,
if (flags & G_APPLICATION_IS_SERVICE)
{
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
- "Unable to acquire bus name `%s'", appid);
+ "Unable to acquire bus name '%s'", appid);
g_application_impl_destroy (impl);
return NULL;
@@ -515,8 +676,12 @@ g_application_impl_cmdline_done (GObject *source,
GError *error = NULL;
GVariant *reply;
- reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source),
- result, &error);
+#ifdef G_OS_UNIX
+ reply = g_dbus_connection_call_with_unix_fd_list_finish (G_DBUS_CONNECTION (source), NULL, result, &error);
+#else
+ reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
+#endif
+
if (reply != NULL)
{
@@ -535,9 +700,9 @@ g_application_impl_cmdline_done (GObject *source,
}
int
-g_application_impl_command_line (GApplicationImpl *impl,
- gchar **arguments,
- GVariant *platform_data)
+g_application_impl_command_line (GApplicationImpl *impl,
+ const gchar * const *arguments,
+ GVariant *platform_data)
{
const static GDBusInterfaceVTable vtable = {
g_application_impl_cmdline_method_call
@@ -571,15 +736,32 @@ g_application_impl_command_line (GApplicationImpl *impl,
/* In theory we should try other paths... */
g_assert (object_id != 0);
- g_dbus_connection_call (impl->session_bus,
- impl->bus_name,
- impl->object_path,
- "org.gtk.Application",
- "CommandLine",
- g_variant_new ("(o^aay@a{sv})", object_path,
- arguments, platform_data),
+#ifdef G_OS_UNIX
+ {
+ GError *error = NULL;
+ GUnixFDList *fd_list;
+
+ /* send along the stdin in case
+ * g_application_command_line_get_stdin_data() is called
+ */
+ fd_list = g_unix_fd_list_new ();
+ g_unix_fd_list_append (fd_list, 0, &error);
+ g_assert_no_error (error);
+
+ g_dbus_connection_call_with_unix_fd_list (impl->session_bus, impl->bus_name, impl->object_path,
+ "org.gtk.Application", "CommandLine",
+ g_variant_new ("(o^aay@a{sv})", object_path, arguments, platform_data),
+ G_VARIANT_TYPE ("(i)"), 0, G_MAXINT, fd_list, NULL,
+ g_application_impl_cmdline_done, &data);
+ g_object_unref (fd_list);
+ }
+#else
+ g_dbus_connection_call (impl->session_bus, impl->bus_name, impl->object_path,
+ "org.gtk.Application", "CommandLine",
+ g_variant_new ("(o^aay@a{sv})", object_path, arguments, platform_data),
G_VARIANT_TYPE ("(i)"), 0, G_MAXINT, NULL,
g_application_impl_cmdline_done, &data);
+#endif
g_main_loop_run (data.loop);
@@ -656,6 +838,35 @@ g_dbus_command_line_printerr_literal (GApplicationCommandLine *cmdline,
NULL, 0, -1, NULL, NULL, NULL);
}
+static GInputStream *
+g_dbus_command_line_get_stdin (GApplicationCommandLine *cmdline)
+{
+#ifdef G_OS_UNIX
+ GDBusCommandLine *gdbcl = (GDBusCommandLine *) cmdline;
+ GInputStream *result = NULL;
+ GDBusMessage *message;
+ GUnixFDList *fd_list;
+
+ message = g_dbus_method_invocation_get_message (gdbcl->invocation);
+ fd_list = g_dbus_message_get_unix_fd_list (message);
+
+ if (fd_list && g_unix_fd_list_get_length (fd_list))
+ {
+ gint *fds, i;
+
+ fds = g_unix_fd_list_peek_fds (fd_list, NULL);
+ result = g_unix_input_stream_new (fds[0], FALSE);
+ g_object_weak_ref (G_OBJECT (result),
+ (GWeakNotify) g_object_unref,
+ g_object_ref (fd_list));
+ }
+
+ return result;
+#else
+ return NULL;
+#endif
+}
+
static void
g_dbus_command_line_finalize (GObject *object)
{
@@ -686,6 +897,7 @@ g_dbus_command_line_class_init (GApplicationCommandLineClass *class)
object_class->finalize = g_dbus_command_line_finalize;
class->printerr_literal = g_dbus_command_line_printerr_literal;
class->print_literal = g_dbus_command_line_print_literal;
+ class->get_stdin = g_dbus_command_line_get_stdin;
}
static GApplicationCommandLine *
@@ -693,13 +905,19 @@ g_dbus_command_line_new (GDBusMethodInvocation *invocation)
{
GDBusCommandLine *gdbcl;
GVariant *args;
+ GVariant *arguments, *platform_data;
args = g_dbus_method_invocation_get_parameters (invocation);
+ arguments = g_variant_get_child_value (args, 1);
+ platform_data = g_variant_get_child_value (args, 2);
gdbcl = g_object_new (g_dbus_command_line_get_type (),
- "arguments", g_variant_get_child_value (args, 1),
- "platform-data", g_variant_get_child_value (args, 2),
+ "arguments", arguments,
+ "platform-data", platform_data,
NULL);
+ g_variant_unref (arguments);
+ g_variant_unref (platform_data);
+
gdbcl->connection = g_dbus_method_invocation_get_connection (invocation);
gdbcl->bus_name = g_dbus_method_invocation_get_sender (invocation);
g_variant_get_child (args, 0, "&o", &gdbcl->object_path);