summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2011-03-21 11:45:11 -0400
committerDavid Zeuthen <davidz@redhat.com>2011-03-21 11:45:11 -0400
commitd374c17bb083d8aea376185db7a2a3e849ab0c8f (patch)
tree3f14dd43cd31444bb13b6a2d08419f057f4678c2
parent0abd81c74b86820f4728f2ad1414ed3a317ca0f5 (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.am1
-rw-r--r--src/gdbuscodegen-marshal.list1
-rw-r--r--src/gdbuscodegenprivate.h48
-rw-r--r--src/gdbusinterfacestub.c50
-rw-r--r--src/gdbusobjectmanagerclient.c10
-rw-r--r--src/gdbusobjectproxy.c8
-rw-r--r--src/gdbusobjectstub.c66
-rw-r--r--src/gdbusobjectstub.h7
-rw-r--r--src/org.project.xml1
-rw-r--r--src/test.c70
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 -->
diff --git a/src/test.c b/src/test.c
index 0b14ed0..b2e0040 100644
--- a/src/test.c
+++ b/src/test.c
@@ -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);
}
/* ---------------------------------------------------------------------------------------------------- */