diff options
author | David Zeuthen <davidz@redhat.com> | 2011-03-21 11:45:11 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2011-03-21 11:45:11 -0400 |
commit | d374c17bb083d8aea376185db7a2a3e849ab0c8f (patch) | |
tree | 3f14dd43cd31444bb13b6a2d08419f057f4678c2 | |
parent | 0abd81c74b86820f4728f2ad1414ed3a317ca0f5 (diff) |
Also emit ::authorize-method signals on the enclosing object
Also factor some private functions into a private header file.
Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/gdbuscodegen-marshal.list | 1 | ||||
-rw-r--r-- | src/gdbuscodegenprivate.h | 48 | ||||
-rw-r--r-- | src/gdbusinterfacestub.c | 50 | ||||
-rw-r--r-- | src/gdbusobjectmanagerclient.c | 10 | ||||
-rw-r--r-- | src/gdbusobjectproxy.c | 8 | ||||
-rw-r--r-- | src/gdbusobjectstub.c | 66 | ||||
-rw-r--r-- | src/gdbusobjectstub.h | 7 | ||||
-rw-r--r-- | src/org.project.xml | 1 | ||||
-rw-r--r-- | src/test.c | 70 |
10 files changed, 234 insertions, 28 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index f9467c6..65845c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -66,6 +66,7 @@ libgdbus_codegeninclude_HEADERS = \ gdbusobjectmanagerclient.h \ gdbusobjectmanagerserver.h \ gdbuscodegen-enumtypes.h \ + gdbuscodegenprivate.h \ $(NULL) libgdbus_codegen_la_SOURCES = \ diff --git a/src/gdbuscodegen-marshal.list b/src/gdbuscodegen-marshal.list index 984797b..c527ccd 100644 --- a/src/gdbuscodegen-marshal.list +++ b/src/gdbuscodegen-marshal.list @@ -3,3 +3,4 @@ VOID:OBJECT,OBJECT VOID:OBJECT,OBJECT,STRING,STRING,VARIANT VOID:OBJECT,OBJECT,VARIANT,BOXED BOOL:OBJECT +BOOL:OBJECT,OBJECT diff --git a/src/gdbuscodegenprivate.h b/src/gdbuscodegenprivate.h new file mode 100644 index 0000000..7f8ba1d --- /dev/null +++ b/src/gdbuscodegenprivate.h @@ -0,0 +1,48 @@ +/* GDBus - GLib D-Bus Library + * + * Copyright (C) 2008-2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * 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. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#ifndef __G_DBUS_CODEGEN_PRIVATE_H__ +#define __G_DBUS_CODEGEN_PRIVATE_H__ + +#include <gio/gio.h> + +#include "gdbusobjectproxy.h" + +G_BEGIN_DECLS + +gboolean _g_signal_accumulator_false_handled (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy); + +gboolean _g_dbus_object_stub_has_authorize_method_handlers (GDBusObjectStub *stub); + +GDBusObjectProxy *_g_dbus_object_proxy_new (GDBusConnection *connection, + const gchar *object_path); +void _g_dbus_object_proxy_add_interface (GDBusObjectProxy *proxy, + GDBusProxy *interface_proxy); +void _g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy, + const gchar *interface_name); + +G_END_DECLS + +#endif /* __G_DBUS_CODEGEN_PRIVATE_H__ */ diff --git a/src/gdbusinterfacestub.c b/src/gdbusinterfacestub.c index cb5afea..b573c48 100644 --- a/src/gdbusinterfacestub.c +++ b/src/gdbusinterfacestub.c @@ -23,8 +23,10 @@ #include "config.h" #include "gdbusinterfacestub.h" +#include "gdbusobjectstub.h" #include "gdbuscodegen-marshal.h" #include "gdbuscodegen-enumtypes.h" +#include "gdbuscodegenprivate.h" /** * SECTION:gdbusinterfacestub @@ -121,7 +123,7 @@ g_dbus_interface_stub_set_property (GObject *object, } } -static gboolean +gboolean _g_signal_accumulator_false_handled (GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, @@ -194,13 +196,18 @@ g_dbus_interface_stub_class_init (GDBusInterfaceStubClass *klass) * g_dbus_method_invocation_return_error()). * * Otherwise, if %TRUE is returned, signal emission continues. If no - * handlers return %FALSE, then the method is dispatched. + * handlers return %FALSE, then the method is dispatched. If + * @interface has an enclosing #GDBusObjectStub, then the + * #GDBusObjectStub::authorize-method signal handlers run before the + * handlers for this signal. * * The default class handler just returns %TRUE. * - * Note that the common case is optimized: if no signals handlers - * are connected and the default class handler isn't overridden and - * #GDBusInterfaceStub:g-flags does not have the + * Please note that the common case is optimized: if no signals + * handlers are connected and the default class handler isn't + * overridden (for both @interface and the enclosing + * #GDBusObjectStub, if any) and #GDBusInterfaceStub:g-flags does + * not have the * %G_DBUS_INTERFACE_STUB_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD * flags set, no dedicated thread is ever used and the call will be * handled in the same thread as the object that @interface belongs @@ -431,12 +438,24 @@ dispatch_in_thread_func (GIOSchedulerJob *job, DispatchData *data = user_data; gboolean authorized; - authorized = FALSE; - g_signal_emit (data->stub, - signals[G_AUTHORIZE_METHOD_SIGNAL], - 0, - data->invocation, - &authorized); + /* first check on the enclosing object (if any), then the interface */ + authorized = TRUE; + if (data->stub->priv->object != NULL) + { + g_signal_emit_by_name (data->stub->priv->object, + "authorize-method", + data->stub, + data->invocation, + &authorized); + } + if (authorized) + { + g_signal_emit (data->stub, + signals[G_AUTHORIZE_METHOD_SIGNAL], + 0, + data->invocation, + &authorized); + } if (authorized) { @@ -488,7 +507,7 @@ g_dbus_interface_method_dispatch_helper (GDBusInterfaceStub *stub, /* optimization for the common case where * - * a) no handler is connected and class handler is not overridden; and + * a) no handler is connected and class handler is not overridden (both interface and object); and * b) method calls are not dispatched in a thread */ has_handlers = g_signal_has_handler_pending (stub, @@ -497,7 +516,14 @@ g_dbus_interface_method_dispatch_helper (GDBusInterfaceStub *stub, TRUE); has_default_class_handler = (G_DBUS_INTERFACE_STUB_GET_CLASS (stub)->g_authorize_method == g_dbus_interface_stub_g_authorize_method_default); + emit_authorized_signal = (has_handlers || !has_default_class_handler); + if (!emit_authorized_signal) + { + if (stub->priv->object != NULL) + emit_authorized_signal = _g_dbus_object_stub_has_authorize_method_handlers (G_DBUS_OBJECT_STUB (stub->priv->object)); + } + run_in_thread = (stub->priv->flags & G_DBUS_INTERFACE_STUB_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD); if (!emit_authorized_signal && !run_in_thread) { diff --git a/src/gdbusobjectmanagerclient.c b/src/gdbusobjectmanagerclient.c index e48b207..6e5b521 100644 --- a/src/gdbusobjectmanagerclient.c +++ b/src/gdbusobjectmanagerclient.c @@ -27,6 +27,7 @@ #include "gdbusobjectmanager.h" #include "gdbusobjectmanagerclient.h" #include "gdbusobject.h" +#include "gdbuscodegenprivate.h" /** * SECTION:gdbusobjectmanagerclient @@ -1279,15 +1280,6 @@ async_initable_iface_init (GAsyncInitableIface *async_initable_iface) /* ---------------------------------------------------------------------------------------------------- */ -/* TODO: move to private header file */ -GDBusObjectProxy *_g_dbus_object_proxy_new (GDBusConnection *connection, - const gchar *object_path); -void _g_dbus_object_proxy_add_interface (GDBusObjectProxy *proxy, - GDBusProxy *interface_proxy); -void _g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy, - const gchar *interface_name); - - static void add_interfaces (GDBusObjectManagerClient *manager, const gchar *object_path, diff --git a/src/gdbusobjectproxy.c b/src/gdbusobjectproxy.c index a3ea2ea..dccb1ee 100644 --- a/src/gdbusobjectproxy.c +++ b/src/gdbusobjectproxy.c @@ -24,6 +24,7 @@ #include "gdbusobject.h" #include "gdbusobjectproxy.h" +#include "gdbuscodegenprivate.h" /** * SECTION:gdbusobjectproxy @@ -215,13 +216,6 @@ g_dbus_object_proxy_get_interfaces (GDBusObject *object) /* ---------------------------------------------------------------------------------------------------- */ -GDBusObjectProxy *_g_dbus_object_proxy_new (GDBusConnection *connection, - const gchar *object_path); -void _g_dbus_object_proxy_add_interface (GDBusObjectProxy *proxy, - GDBusProxy *interface_proxy); -void _g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy, - const gchar *interface_name); - GDBusObjectProxy * _g_dbus_object_proxy_new (GDBusConnection *connection, const gchar *object_path) diff --git a/src/gdbusobjectstub.c b/src/gdbusobjectstub.c index 1f7c629..2ae84e1 100644 --- a/src/gdbusobjectstub.c +++ b/src/gdbusobjectstub.c @@ -25,6 +25,8 @@ #include "gdbusobject.h" #include "gdbusobjectstub.h" #include "gdbusinterfacestub.h" +#include "gdbuscodegen-marshal.h" +#include "gdbuscodegenprivate.h" /** * SECTION:gdbusobjectstub @@ -50,6 +52,14 @@ enum PROP_OBJECT_PATH }; +enum +{ + AUTHORIZE_METHOD_SIGNAL, + LAST_SIGNAL, +}; + +static guint signals[LAST_SIGNAL] = {0}; + static void dbus_object_interface_init (GDBusObjectIface *iface); G_DEFINE_TYPE_WITH_CODE (GDBusObjectStub, g_dbus_object_stub, G_TYPE_OBJECT, @@ -108,6 +118,14 @@ g_dbus_object_stub_set_property (GObject *_object, } } +static gboolean +g_dbus_object_stub_authorize_method_default (GDBusObjectStub *object, + GDBusInterfaceStub *interface, + GDBusMethodInvocation *invocation) +{ + return TRUE; +} + static void g_dbus_object_stub_class_init (GDBusObjectStubClass *klass) { @@ -117,6 +135,8 @@ g_dbus_object_stub_class_init (GDBusObjectStubClass *klass) gobject_class->set_property = g_dbus_object_stub_set_property; gobject_class->get_property = g_dbus_object_stub_get_property; + klass->authorize_method = g_dbus_object_stub_authorize_method_default; + /** * GDBusObjectStub:object-path: * @@ -133,6 +153,36 @@ g_dbus_object_stub_class_init (GDBusObjectStubClass *klass) G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + /** + * GDBusObjectStub::authorize-method: + * @object: The #GDBusObjectStub emitting the signal. + * @interface: The #GDBusInterfaceStub that @invocation is on. + * @invocation: A #GDBusMethodInvocation. + * + * Emitted when a method is invoked by a remote caller and used to + * determine if the method call is authorized. + * + * This signal is like #GDBusInterfaceStub<!-- -->'s + * #GDBusInterfaceStub::g-authorize-method signal, except that it is + * for the enclosing object. + * + * The default class handler just returns %TRUE. + * + * Returns: %TRUE if the call is authorized, %FALSE otherwise. + */ + signals[AUTHORIZE_METHOD_SIGNAL] = + g_signal_new ("authorize-method", + G_TYPE_DBUS_OBJECT_STUB, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GDBusObjectStubClass, authorize_method), + _g_signal_accumulator_false_handled, + NULL, + _gdbuscodegen_marshal_BOOL__OBJECT_OBJECT, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_INTERFACE_STUB, + G_TYPE_DBUS_METHOD_INVOCATION); + g_type_class_add_private (klass, sizeof (GDBusObjectStubPrivate)); } @@ -401,3 +451,19 @@ dbus_object_interface_init (GDBusObjectIface *iface) iface->lookup_with_typecheck = g_dbus_object_stub_lookup_with_typecheck; iface->peek_with_typecheck = g_dbus_object_stub_peek_with_typecheck; } + +gboolean +_g_dbus_object_stub_has_authorize_method_handlers (GDBusObjectStub *stub) +{ + gboolean has_handlers; + gboolean has_default_class_handler; + + has_handlers = g_signal_has_handler_pending (stub, + signals[AUTHORIZE_METHOD_SIGNAL], + 0, + TRUE); + has_default_class_handler = (G_DBUS_OBJECT_STUB_GET_CLASS (stub)->authorize_method == + g_dbus_object_stub_authorize_method_default); + + return has_handlers || !has_default_class_handler; +} diff --git a/src/gdbusobjectstub.h b/src/gdbusobjectstub.h index f6fbc9a..d9f63e6 100644 --- a/src/gdbusobjectstub.h +++ b/src/gdbusobjectstub.h @@ -55,12 +55,19 @@ struct _GDBusObjectStub /** * GDBusObjectStubClass: * @parent_class: The parent class. + * @authorize_method: Signal class handler for the #GDBusObjectStub::authorize-method signal. * * Class structure for #GDBusObjectStub. */ struct _GDBusObjectStubClass { GObjectClass parent_class; + + /* Signals */ + gboolean (*authorize_method) (GDBusObjectStub *stub, + GDBusInterfaceStub *interface_stub, + GDBusMethodInvocation *invocation); + /*< private >*/ gpointer padding[8]; }; diff --git a/src/org.project.xml b/src/org.project.xml index 56bccd3..7d04e30 100644 --- a/src/org.project.xml +++ b/src/org.project.xml @@ -211,6 +211,7 @@ <interface name="org.project.Authorize"> <method name="CheckNotAuthorized"/> <method name="CheckAuthorized"/> + <method name="CheckNotAuthorizedFromObject"/> </interface> <!-- End org.project.Authorize --> <!-- Test interfaces for handling methods in a thread --> @@ -289,6 +289,10 @@ my_g_authorize_method_handler (GDBusInterfaceStub *interface, { authorized = TRUE; } + else if (g_strcmp0 (method_name, "CheckNotAuthorizedFromObject") == 0) + { + authorized = TRUE; + } else { g_assert_not_reached (); @@ -305,6 +309,45 @@ my_g_authorize_method_handler (GDBusInterfaceStub *interface, } static gboolean +my_object_authorize_method_handler (GDBusObjectStub *object, + GDBusInterfaceStub *interface, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + const gchar *method_name; + gboolean authorized; + + authorized = FALSE; + + method_name = g_dbus_method_invocation_get_method_name (invocation); + if (g_strcmp0 (method_name, "CheckNotAuthorized") == 0) + { + authorized = TRUE; + } + else if (g_strcmp0 (method_name, "CheckAuthorized") == 0) + { + authorized = TRUE; + } + else if (g_strcmp0 (method_name, "CheckNotAuthorizedFromObject") == 0) + { + authorized = FALSE; + } + else + { + g_assert_not_reached (); + } + + if (!authorized) + { + g_dbus_method_invocation_return_error (invocation, + G_IO_ERROR, + G_IO_ERROR_PENDING, + "not authorized (from object)..."); + } + return authorized; +} + +static gboolean on_handle_check_not_authorized (FooAuthorize *object, GDBusMethodInvocation *invocation, gpointer user_data) @@ -322,6 +365,15 @@ on_handle_check_authorized (FooAuthorize *object, return TRUE; } +static gboolean +on_handle_check_not_authorized_from_object (FooAuthorize *object, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + foo_authorize_complete_check_not_authorized_from_object (object, invocation); + return TRUE; +} + /* ---------------------------------------------------------------------------------------------------- */ static gboolean @@ -343,6 +395,7 @@ static GThread *method_handler_thread = NULL; static FooBar *exported_bar_object = NULL; static FooBat *exported_bat_object = NULL; static FooAuthorize *exported_authorize_object = NULL; +static GDBusObjectStub *authorize_enclosing_object = NULL; static FooMethodThreads *exported_thread_object_1 = NULL; static FooMethodThreads *exported_thread_object_2 = NULL; @@ -420,7 +473,14 @@ on_bus_acquired (GDBusConnection *connection, "force-struct", g_variant_new ("(i)", 4300), NULL); + authorize_enclosing_object = g_dbus_object_stub_new ("/authorize"); + g_signal_connect (authorize_enclosing_object, + "authorize-method", + G_CALLBACK (my_object_authorize_method_handler), + NULL); exported_authorize_object = foo_authorize_stub_new (); + g_dbus_object_stub_add_interface (authorize_enclosing_object, + G_DBUS_INTERFACE_STUB (exported_authorize_object)); g_dbus_interface_stub_export (G_DBUS_INTERFACE_STUB (exported_authorize_object), connection, "/authorize", @@ -438,6 +498,10 @@ on_bus_acquired (GDBusConnection *connection, "handle-check-authorized", FOO_AUTHORIZE_HANDLE_CHECK_AUTHORIZED_CALLBACK (on_handle_check_authorized, gpointer), NULL); + g_signal_connect (exported_authorize_object, + "handle-check-not-authorized-from-object", + FOO_AUTHORIZE_HANDLE_CHECK_NOT_AUTHORIZED_FROM_OBJECT_CALLBACK (on_handle_check_not_authorized_from_object, gpointer), + NULL); /* only object 1 has the G_DBUS_INTERFACE_STUB_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD flag set */ @@ -1004,6 +1068,12 @@ check_authorize_proxy (FooAuthorize *proxy, ret = foo_authorize_call_check_authorized_sync (proxy, NULL, &error); g_assert_no_error (error); g_assert (ret); + + error = NULL; + ret = foo_authorize_call_check_not_authorized_from_object_sync (proxy, NULL, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PENDING); + g_error_free (error); + g_assert (!ret); } /* ---------------------------------------------------------------------------------------------------- */ |