2005-01-30 Havoc Pennington <hp@redhat.com>
authorHavoc Pennington <hp@redhat.com>
Sun, 30 Jan 2005 05:18:44 +0000 (05:18 +0000)
committerHavoc Pennington <hp@redhat.com>
Sun, 30 Jan 2005 05:18:44 +0000 (05:18 +0000)
        dbus-viewer introspected and displayed the bus driver

* dbus/dbus-object-tree.c
(object_tree_test_iteration): add tests for a handler registered on "/"

* dbus/dbus-object-tree.c
(_dbus_decompose_path): fix to handle path "/" properly
(run_decompose_tests): add tests for path decomposition

* glib/dbus-gutils.c (_dbus_gutils_split_path): fix to handle "/"
properly

* glib/dbus-gobject.c (handle_introspect): fix quotes

* test/glib/run-test.sh: support launching the bus, then running
dbus-viewer

* test/glib/test-service-glib.c (main): put in a trivial gobject
subclass and register it on the connection

* bus/driver.c (bus_driver_handle_introspect): implement
introspection of the bus driver service

* dbus/dbus-protocol.h: add #defines for the XML namespace,
identifiers, doctype decl

* bus/driver.c (bus_driver_handle_get_service_owner): handle
attempts to get owner of DBUS_SERVICE_ORG_FREEDESKTOP_DBUS by
returning the service unchanged.
(bus_driver_handle_message): remove old check for reply_serial in
method calls, now the message type deals with that
(bus_driver_handle_message): handle NULL interface

* glib/dbus-gproxy.c (dbus_g_proxy_get_bus_name): new function

* glib/dbus-gloader-expat.c (description_load_from_string): allow
-1 for len

* tools/dbus-viewer.c: add support for introspecting a service on
a bus

* glib/dbus-gproxy.c (dbus_g_pending_call_ref): add
(dbus_g_pending_call_unref): add

15 files changed:
ChangeLog
bus/driver.c
dbus/dbus-glib.h
dbus/dbus-marshal-validate.c
dbus/dbus-object-tree.c
dbus/dbus-protocol.h
glib/dbus-gidl.c
glib/dbus-gidl.h
glib/dbus-gloader-expat.c
glib/dbus-gobject.c
glib/dbus-gproxy.c
glib/dbus-gutils.c
test/glib/run-test.sh
test/glib/test-service-glib.c
tools/dbus-viewer.c

index d964d45..dcb3a6d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+2005-01-30  Havoc Pennington  <hp@redhat.com>
+
+        dbus-viewer introspected and displayed the bus driver
+       
+       * dbus/dbus-object-tree.c 
+       (object_tree_test_iteration): add tests for a handler registered on "/"
+
+       * dbus/dbus-object-tree.c
+       (_dbus_decompose_path): fix to handle path "/" properly
+       (run_decompose_tests): add tests for path decomposition
+       
+       * glib/dbus-gutils.c (_dbus_gutils_split_path): fix to handle "/"
+       properly
+
+       * glib/dbus-gobject.c (handle_introspect): fix quotes
+
+       * test/glib/run-test.sh: support launching the bus, then running
+       dbus-viewer
+
+       * test/glib/test-service-glib.c (main): put in a trivial gobject
+       subclass and register it on the connection
+
+       * bus/driver.c (bus_driver_handle_introspect): implement
+       introspection of the bus driver service
+
+       * dbus/dbus-protocol.h: add #defines for the XML namespace,
+       identifiers, doctype decl
+
+       * bus/driver.c (bus_driver_handle_get_service_owner): handle
+       attempts to get owner of DBUS_SERVICE_ORG_FREEDESKTOP_DBUS by 
+       returning the service unchanged.
+       (bus_driver_handle_message): remove old check for reply_serial in
+       method calls, now the message type deals with that
+       (bus_driver_handle_message): handle NULL interface
+
+       * glib/dbus-gproxy.c (dbus_g_proxy_get_bus_name): new function
+
+       * glib/dbus-gloader-expat.c (description_load_from_string): allow
+       -1 for len
+
+       * tools/dbus-viewer.c: add support for introspecting a service on
+       a bus
+
+       * glib/dbus-gproxy.c (dbus_g_pending_call_ref): add
+       (dbus_g_pending_call_unref): add
+
 2005-01-29  Havoc Pennington  <hp@redhat.com>
 
        * tools/dbus-tree-view.c: add support for displaying properties.
@@ -6,7 +52,7 @@
 
        * glib/dbus-gobject.c (handle_introspect): return
        org.freedesktop.Properties and org.freedesktop.Introspectable
-       interfaces when we are introspected.    
+       interfaces when we are introspected.
 
        * doc/dbus-specification.xml: allow empty interface name when 
        Get/Set a property
index 3a9e555..58b8fcb 100644 (file)
@@ -792,24 +792,34 @@ bus_driver_handle_get_service_owner (DBusConnection *connection,
 
   _dbus_string_init_const (&str, text);
   service = bus_registry_lookup (registry, &str);
-  if (service == NULL)
+  if (service == NULL &&
+      _dbus_string_equal_c_str (&str, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
+    {
+      /* ORG_FREEDESKTOP_DBUS owns itself */
+      base_name = DBUS_SERVICE_ORG_FREEDESKTOP_DBUS;
+    }
+  else if (service == NULL)
     {
       dbus_set_error (error, 
-                     DBUS_ERROR_NAME_HAS_NO_OWNER,
-                     "Could not get owner of name '%s': no such name", text);
+                      DBUS_ERROR_NAME_HAS_NO_OWNER,
+                      "Could not get owner of name '%s': no such name", text);
       goto failed;
     }
-
-  base_name = bus_connection_get_name (bus_service_get_primary_owner (service));
-  if (base_name == NULL)
+  else
     {
-      /* FIXME - how is this error possible? */
-      dbus_set_error (error,
-                     DBUS_ERROR_FAILED,
-                     "Could not determine unique name for '%s'", text);
-      goto failed;
+      base_name = bus_connection_get_name (bus_service_get_primary_owner (service));
+      if (base_name == NULL)
+        {
+          /* FIXME - how is this error possible? */
+          dbus_set_error (error,
+                          DBUS_ERROR_FAILED,
+                          "Could not determine unique name for '%s'", text);
+          goto failed;
+        }
+      _dbus_assert (*base_name == ':');      
     }
-  _dbus_assert (*base_name == ':');
+
+  _dbus_assert (base_name != NULL);
 
   reply = dbus_message_new_method_return (message);
   if (reply == NULL)
@@ -1040,13 +1050,89 @@ struct
   { "ReloadConfig", bus_driver_handle_reload_config }
 };
 
+static dbus_bool_t
+bus_driver_handle_introspect (DBusConnection *connection,
+                              BusTransaction *transaction,
+                              DBusMessage    *message,
+                              DBusError      *error)
+{
+  DBusString xml;
+  DBusMessage *reply;
+  const char *v_STRING;
+
+  _dbus_verbose ("Introspect() on bus driver\n");
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  reply = NULL;
+
+  if (! dbus_message_get_args (message, error,
+                              DBUS_TYPE_INVALID))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&xml))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
+    goto oom;
+  if (!_dbus_string_append (&xml, "<node>\n"))
+    goto oom;
+  if (!_dbus_string_append (&xml, "  <interface name=\"org.freedesktop.Introspectable\">\n"))
+    goto oom;
+  if (!_dbus_string_append (&xml, "    <method name=\"Introspect\">\n"))
+    goto oom;
+  if (!_dbus_string_append (&xml, "      <arg name=\"data\" direction=\"out\" type=\"string\"/>\n"))
+    goto oom;
+  if (!_dbus_string_append (&xml, "    </method>\n"))
+    goto oom;
+  if (!_dbus_string_append (&xml, "  </interface>\n"))
+    goto oom;
+  
+  if (!_dbus_string_append (&xml, "</node>\n"))
+    goto oom;
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  v_STRING = _dbus_string_get_const_data (&xml);
+  if (! dbus_message_append_args (reply,
+                                  DBUS_TYPE_STRING, &v_STRING,
+                                  DBUS_TYPE_INVALID))
+    goto oom;
+
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+  _dbus_string_free (&xml);
+
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+  if (reply)
+    dbus_message_unref (reply);
+
+  _dbus_string_free (&xml);
+  
+  return FALSE;
+}
+
 dbus_bool_t
 bus_driver_handle_message (DBusConnection *connection,
                            BusTransaction *transaction,
                           DBusMessage    *message,
                            DBusError      *error)
 {
-  const char *name, *sender;
+  const char *name, *sender, *interface;
   int i;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -1057,17 +1143,25 @@ bus_driver_handle_message (DBusConnection *connection,
       return TRUE; /* we just ignore this */
     }
 
-  _dbus_assert (dbus_message_get_interface (message) != NULL);
+  if (dbus_message_is_method_call (message,
+                                   DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE,
+                                   "Introspect"))
+    return bus_driver_handle_introspect (connection, transaction, message, error);
+  
+  interface = dbus_message_get_interface (message);
+  if (interface == NULL)
+    interface = DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS;
+  
   _dbus_assert (dbus_message_get_member (message) != NULL);
-
+  
   name = dbus_message_get_member (message);
   sender = dbus_message_get_sender (message);
   
-  if (strcmp (dbus_message_get_interface (message),
+  if (strcmp (interface,
               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS) != 0)
     {
       _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
-                     dbus_message_get_interface (message));
+                     interface);
       goto unknown;
     }
   
@@ -1076,12 +1170,6 @@ bus_driver_handle_message (DBusConnection *connection,
   
   /* security checks should have kept this from getting here */
   _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
-
-  if (dbus_message_get_reply_serial (message) != 0)
-    {
-      _dbus_verbose ("Client sent a reply to the bus driver, ignoring it\n");
-      return TRUE;
-    }
   
   i = 0;
   while (i < _DBUS_N_ELEMENTS (message_handlers))
index de53d14..3e73b98 100644 (file)
@@ -145,7 +145,10 @@ void              dbus_g_proxy_call_no_reply         (DBusGProxy        *proxy,
                                                       const char        *method,
                                                       int                first_arg_type,
                                                       ...);
+const char*       dbus_g_proxy_get_bus_name          (DBusGProxy        *proxy);
 
+DBusGPendingCall* dbus_g_pending_call_ref            (DBusGPendingCall  *call);
+void              dbus_g_pending_call_unref          (DBusGPendingCall  *call);
 
 #undef DBUS_INSIDE_DBUS_GLIB_H
 
index e57be5c..d9b85cb 100644 (file)
@@ -573,7 +573,7 @@ _dbus_validate_path (const DBusString  *str,
   _dbus_assert (start >= 0);
   _dbus_assert (len >= 0);
   _dbus_assert (start <= _dbus_string_get_length (str));
-
+  
   if (len > _dbus_string_get_length (str) - start)
     return FALSE;
 
index 694185f..f879759 100644 (file)
@@ -630,6 +630,9 @@ handle_default_introspect_unlocked (DBusObjectTree          *tree,
   if (!_dbus_object_tree_list_registered_unlocked (tree, path, &children))
     goto out;
 
+  if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
+    goto out;
+  
   if (!_dbus_string_append (&xml, "<node>\n"))
     goto out;
 
@@ -945,6 +948,7 @@ _dbus_object_tree_list_registered_and_unlock (DBusObjectTree *tree,
 /**
  * Decompose an object path.  A path of just "/" is
  * represented as an empty vector of strings.
+ * The path need not be nul terminated.
  * 
  * @param data the path data
  * @param len  the length of the path string
@@ -962,19 +966,22 @@ _dbus_decompose_path (const char*     data,
   int i, j, comp;
 
   _dbus_assert (data != NULL);
-
+  
 #if VERBOSE_DECOMPOSE
   _dbus_verbose ("Decomposing path \"%s\"\n",
                  data);
 #endif
   
   n_components = 0;
-  i = 0;
-  while (i < len)
+  if (len > 1) /* if path is not just "/" */
     {
-      if (data[i] == '/')
-        n_components += 1;
-      ++i;
+      i = 0;
+      while (i < len)
+        {
+          if (data[i] == '/')
+            n_components += 1;
+          ++i;
+        }
     }
   
   retval = dbus_new0 (char*, n_components + 1);
@@ -983,9 +990,14 @@ _dbus_decompose_path (const char*     data,
     return FALSE;
 
   comp = 0;
-  i = 0;
-  while (i < len)
+  if (n_components == 0)
+    i = 1;
+  else
+    i = 0;
+  while (comp < n_components)
     {
+      _dbus_assert (i < len);
+      
       if (data[i] == '/')
         ++i;
       j = i;
@@ -1037,22 +1049,31 @@ static char*
 flatten_path (const char **path)
 {
   DBusString str;
-  int i;
   char *s;
 
   if (!_dbus_string_init (&str))
     return NULL;
 
-  i = 0;
-  while (path[i])
+  if (path[0] == NULL)
     {
       if (!_dbus_string_append_byte (&str, '/'))
         goto nomem;
-
-      if (!_dbus_string_append (&str, path[i]))
-        goto nomem;
-
-      ++i;
+    }
+  else
+    {
+      int i;
+      
+      i = 0;
+      while (path[i])
+        {
+          if (!_dbus_string_append_byte (&str, '/'))
+            goto nomem;
+          
+          if (!_dbus_string_append (&str, path[i]))
+            goto nomem;
+          
+          ++i;
+        }
     }
 
   if (!_dbus_string_steal_data (&str, &s))
@@ -1191,7 +1212,7 @@ do_register (DBusObjectTree *tree,
 {
   DBusObjectPathVTable vtable = { test_unregister_function,
                                   test_message_function, NULL };
-
+  
   tree_test_data[i].message_handled = FALSE;
   tree_test_data[i].handler_unregistered = FALSE;
   tree_test_data[i].handler_fallback = fallback;
@@ -1278,17 +1299,82 @@ do_test_dispatch (DBusObjectTree *tree,
 }
 
 static size_t
-string_array_length (char **array)
+string_array_length (const char **array)
 {
   size_t i;
   for (i = 0; array[i]; i++) ;
   return i;
 }
 
+typedef struct
+{
+  const char *path;
+  const char *result[20];
+} DecomposePathTest;
+
+static DecomposePathTest decompose_tests[] = {
+  { "/foo", { "foo", NULL } },
+  { "/foo/bar", { "foo", "bar", NULL } },
+  { "/", { NULL } },
+  { "/a/b", { "a", "b", NULL } },
+  { "/a/b/c", { "a", "b", "c", NULL } },
+  { "/a/b/c/d", { "a", "b", "c", "d", NULL } },
+  { "/foo/bar/q", { "foo", "bar", "q", NULL } },
+  { "/foo/bar/this/is/longer", { "foo", "bar", "this", "is", "longer", NULL } }
+};
+
+static dbus_bool_t
+run_decompose_tests (void)
+{
+  int i;
+
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (decompose_tests))
+    {
+      char **result;
+      int    result_len;
+      int    expected_len;
+
+      if (!_dbus_decompose_path (decompose_tests[i].path,
+                                 strlen (decompose_tests[i].path),
+                                 &result, &result_len))
+        return FALSE;
+
+      expected_len = string_array_length (decompose_tests[i].result);
+      
+      if (result_len != (int) string_array_length ((const char**)result) ||
+          expected_len != result_len ||
+          path_contains (decompose_tests[i].result,
+                         (const char**) result) != STR_EQUAL)
+        {
+          int real_len = string_array_length ((const char**)result);
+          _dbus_warn ("Expected decompose of %s to have len %d, returned %d, appears to have %d\n",
+                      decompose_tests[i].path, expected_len, result_len,
+                      real_len);
+          _dbus_warn ("Decompose resulted in elements: { ");
+          i = 0;
+          while (i < real_len)
+            {
+              _dbus_warn ("\"%s\"%s", result[i],
+                          (i + 1) == real_len ? "" : ", ");
+              ++i;
+            }
+          _dbus_warn ("}\n");
+          _dbus_assert_not_reached ("path decompose failed\n");
+        }
+
+      dbus_free_string_array (result);
+
+      ++i;
+    }
+  
+  return TRUE;
+}
 
 static dbus_bool_t
 object_tree_test_iteration (void *data)
 {
+  const char *path0[] = { NULL };
   const char *path1[] = { "foo", NULL };
   const char *path2[] = { "foo", "bar", NULL };
   const char *path3[] = { "foo", "bar", "baz", NULL };
@@ -1298,19 +1384,46 @@ object_tree_test_iteration (void *data)
   const char *path7[] = { "blah", "boof", "this", "is", "really", "long", NULL };
   const char *path8[] = { "childless", NULL };
   DBusObjectTree *tree;
-  TreeTestData tree_test_data[8];
+  TreeTestData tree_test_data[9];
   int i;
   dbus_bool_t exact_match;
 
+  if (!run_decompose_tests ())
+    return FALSE;
+  
   tree = NULL;
 
   tree = _dbus_object_tree_new (NULL);
   if (tree == NULL)
     goto out;
 
-  if (!do_register (tree, path1, TRUE, 0, tree_test_data))
+  if (!do_register (tree, path0, TRUE, 0, tree_test_data))
+    goto out;
+
+  _dbus_assert (find_subtree (tree, path0, NULL));
+  _dbus_assert (!find_subtree (tree, path1, NULL));
+  _dbus_assert (!find_subtree (tree, path2, NULL));
+  _dbus_assert (!find_subtree (tree, path3, NULL));
+  _dbus_assert (!find_subtree (tree, path4, NULL));
+  _dbus_assert (!find_subtree (tree, path5, NULL));
+  _dbus_assert (!find_subtree (tree, path6, NULL));
+  _dbus_assert (!find_subtree (tree, path7, NULL));
+  _dbus_assert (!find_subtree (tree, path8, NULL));
+
+  _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match);
+  _dbus_assert (find_handler (tree, path1, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path2, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path3, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path4, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
+  
+  if (!do_register (tree, path1, TRUE, 1, tree_test_data))
     goto out;
 
+  _dbus_assert (find_subtree (tree, path0, NULL));
   _dbus_assert (find_subtree (tree, path1, NULL));
   _dbus_assert (!find_subtree (tree, path2, NULL));
   _dbus_assert (!find_subtree (tree, path3, NULL));
@@ -1320,6 +1433,7 @@ object_tree_test_iteration (void *data)
   _dbus_assert (!find_subtree (tree, path7, NULL));
   _dbus_assert (!find_subtree (tree, path8, NULL));
 
+  _dbus_assert (find_handler (tree, path0, &exact_match) &&  exact_match);
   _dbus_assert (find_handler (tree, path1, &exact_match) &&  exact_match);
   _dbus_assert (find_handler (tree, path2, &exact_match) && !exact_match);
   _dbus_assert (find_handler (tree, path3, &exact_match) && !exact_match);
@@ -1329,7 +1443,7 @@ object_tree_test_iteration (void *data)
   _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match);
   _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
 
-  if (!do_register (tree, path2, TRUE, 1, tree_test_data))
+  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
     goto out;
 
   _dbus_assert (find_subtree (tree, path1, NULL));
@@ -1341,9 +1455,10 @@ object_tree_test_iteration (void *data)
   _dbus_assert (!find_subtree (tree, path7, NULL));
   _dbus_assert (!find_subtree (tree, path8, NULL));
 
-  if (!do_register (tree, path3, TRUE, 2, tree_test_data))
+  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
     goto out;
 
+  _dbus_assert (find_subtree (tree, path0, NULL));
   _dbus_assert (find_subtree (tree, path1, NULL));
   _dbus_assert (find_subtree (tree, path2, NULL));
   _dbus_assert (find_subtree (tree, path3, NULL));
@@ -1353,9 +1468,10 @@ object_tree_test_iteration (void *data)
   _dbus_assert (!find_subtree (tree, path7, NULL));
   _dbus_assert (!find_subtree (tree, path8, NULL));
   
-  if (!do_register (tree, path4, TRUE, 3, tree_test_data))
+  if (!do_register (tree, path4, TRUE, 4, tree_test_data))
     goto out;
 
+  _dbus_assert (find_subtree (tree, path0, NULL));
   _dbus_assert (find_subtree (tree, path1, NULL));
   _dbus_assert (find_subtree (tree, path2, NULL));
   _dbus_assert (find_subtree (tree, path3, NULL));  
@@ -1365,9 +1481,10 @@ object_tree_test_iteration (void *data)
   _dbus_assert (!find_subtree (tree, path7, NULL));
   _dbus_assert (!find_subtree (tree, path8, NULL));
   
-  if (!do_register (tree, path5, TRUE, 4, tree_test_data))
+  if (!do_register (tree, path5, TRUE, 5, tree_test_data))
     goto out;
 
+  _dbus_assert (find_subtree (tree, path0, NULL));
   _dbus_assert (find_subtree (tree, path1, NULL));
   _dbus_assert (find_subtree (tree, path2, NULL));
   _dbus_assert (find_subtree (tree, path3, NULL));
@@ -1376,7 +1493,8 @@ object_tree_test_iteration (void *data)
   _dbus_assert (!find_subtree (tree, path6, NULL));
   _dbus_assert (!find_subtree (tree, path7, NULL));
   _dbus_assert (!find_subtree (tree, path8, NULL));
-  
+
+  _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root &&  exact_match);
   _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root &&  exact_match);
   _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root &&  exact_match);
   _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root &&  exact_match);
@@ -1386,9 +1504,10 @@ object_tree_test_iteration (void *data)
   _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && !exact_match);
   _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
 
-  if (!do_register (tree, path6, TRUE, 5, tree_test_data))
+  if (!do_register (tree, path6, TRUE, 6, tree_test_data))
     goto out;
 
+  _dbus_assert (find_subtree (tree, path0, NULL));
   _dbus_assert (find_subtree (tree, path1, NULL));
   _dbus_assert (find_subtree (tree, path2, NULL));
   _dbus_assert (find_subtree (tree, path3, NULL));
@@ -1398,9 +1517,10 @@ object_tree_test_iteration (void *data)
   _dbus_assert (!find_subtree (tree, path7, NULL));
   _dbus_assert (!find_subtree (tree, path8, NULL));
 
-  if (!do_register (tree, path7, TRUE, 6, tree_test_data))
+  if (!do_register (tree, path7, TRUE, 7, tree_test_data))
     goto out;
 
+  _dbus_assert (find_subtree (tree, path0, NULL));
   _dbus_assert (find_subtree (tree, path1, NULL));
   _dbus_assert (find_subtree (tree, path2, NULL));
   _dbus_assert (find_subtree (tree, path3, NULL));
@@ -1410,9 +1530,10 @@ object_tree_test_iteration (void *data)
   _dbus_assert (find_subtree (tree, path7, NULL));
   _dbus_assert (!find_subtree (tree, path8, NULL));
 
-  if (!do_register (tree, path8, TRUE, 7, tree_test_data))
+  if (!do_register (tree, path8, TRUE, 8, tree_test_data))
     goto out;
 
+  _dbus_assert (find_subtree (tree, path0, NULL));
   _dbus_assert (find_subtree (tree, path1, NULL));
   _dbus_assert (find_subtree (tree, path2, NULL));
   _dbus_assert (find_subtree (tree, path3, NULL));
@@ -1421,7 +1542,8 @@ object_tree_test_iteration (void *data)
   _dbus_assert (find_subtree (tree, path6, NULL));
   _dbus_assert (find_subtree (tree, path7, NULL));
   _dbus_assert (find_subtree (tree, path8, NULL));
-  
+
+  _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root &&  exact_match);
   _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match);
   _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match);
   _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match);
@@ -1441,7 +1563,7 @@ object_tree_test_iteration (void *data)
     _dbus_object_tree_list_registered_unlocked (tree, path1, &child_entries);
     if (child_entries != NULL)
       {
-       nb = string_array_length (child_entries);
+       nb = string_array_length ((const char**)child_entries);
        _dbus_assert (nb == 1);
        dbus_free_string_array (child_entries);
       }
@@ -1449,7 +1571,7 @@ object_tree_test_iteration (void *data)
     _dbus_object_tree_list_registered_unlocked (tree, path2, &child_entries);
     if (child_entries != NULL)
       {
-       nb = string_array_length (child_entries);
+       nb = string_array_length ((const char**)child_entries);
        _dbus_assert (nb == 2);
        dbus_free_string_array (child_entries);
       }
@@ -1457,7 +1579,7 @@ object_tree_test_iteration (void *data)
     _dbus_object_tree_list_registered_unlocked (tree, path8, &child_entries);
     if (child_entries != NULL)
       {
-       nb = string_array_length (child_entries);
+       nb = string_array_length ((const char**)child_entries);
        _dbus_assert (nb == 0);
        dbus_free_string_array (child_entries);
       }
@@ -1465,7 +1587,7 @@ object_tree_test_iteration (void *data)
     _dbus_object_tree_list_registered_unlocked (tree, root, &child_entries);
     if (child_entries != NULL)
       {
-       nb = string_array_length (child_entries);
+       nb = string_array_length ((const char**)child_entries);
        _dbus_assert (nb == 3);
        dbus_free_string_array (child_entries);
       }
@@ -1487,25 +1609,40 @@ object_tree_test_iteration (void *data)
   if (tree == NULL)
     goto out;
 
-  if (!do_register (tree, path1, TRUE, 0, tree_test_data))
+  if (!do_register (tree, path0, TRUE, 0, tree_test_data))
+    goto out;
+  if (!do_register (tree, path1, TRUE, 1, tree_test_data))
     goto out;
-  if (!do_register (tree, path2, TRUE, 1, tree_test_data))
+  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
     goto out;
-  if (!do_register (tree, path3, TRUE, 2, tree_test_data))
+  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
     goto out;
-  if (!do_register (tree, path4, TRUE, 3, tree_test_data))
+  if (!do_register (tree, path4, TRUE, 4, tree_test_data))
     goto out;
-  if (!do_register (tree, path5, TRUE, 4, tree_test_data))
+  if (!do_register (tree, path5, TRUE, 5, tree_test_data))
     goto out;
-  if (!do_register (tree, path6, TRUE, 5, tree_test_data))
+  if (!do_register (tree, path6, TRUE, 6, tree_test_data))
     goto out;
-  if (!do_register (tree, path7, TRUE, 6, tree_test_data))
+  if (!do_register (tree, path7, TRUE, 7, tree_test_data))
     goto out;
-  if (!do_register (tree, path8, TRUE, 7, tree_test_data))
+  if (!do_register (tree, path8, TRUE, 8, tree_test_data))
     goto out;
+
+  _dbus_object_tree_unregister_and_unlock (tree, path0);
+
+  _dbus_assert (!find_subtree (tree, path0, NULL));
+  _dbus_assert (find_subtree (tree, path1, NULL));
+  _dbus_assert (find_subtree (tree, path2, NULL));
+  _dbus_assert (find_subtree (tree, path3, NULL));
+  _dbus_assert (find_subtree (tree, path4, NULL));
+  _dbus_assert (find_subtree (tree, path5, NULL));
+  _dbus_assert (find_subtree (tree, path6, NULL));
+  _dbus_assert (find_subtree (tree, path7, NULL));
+  _dbus_assert (find_subtree (tree, path8, NULL));
   
   _dbus_object_tree_unregister_and_unlock (tree, path1);
 
+  _dbus_assert (!find_subtree (tree, path0, NULL));
   _dbus_assert (!find_subtree (tree, path1, NULL));
   _dbus_assert (find_subtree (tree, path2, NULL));
   _dbus_assert (find_subtree (tree, path3, NULL));
@@ -1517,6 +1654,7 @@ object_tree_test_iteration (void *data)
 
   _dbus_object_tree_unregister_and_unlock (tree, path2);
 
+  _dbus_assert (!find_subtree (tree, path0, NULL));
   _dbus_assert (!find_subtree (tree, path1, NULL));
   _dbus_assert (!find_subtree (tree, path2, NULL));
   _dbus_assert (find_subtree (tree, path3, NULL));
@@ -1528,6 +1666,7 @@ object_tree_test_iteration (void *data)
   
   _dbus_object_tree_unregister_and_unlock (tree, path3);
 
+  _dbus_assert (!find_subtree (tree, path0, NULL));
   _dbus_assert (!find_subtree (tree, path1, NULL));
   _dbus_assert (!find_subtree (tree, path2, NULL));
   _dbus_assert (!find_subtree (tree, path3, NULL));
@@ -1539,6 +1678,7 @@ object_tree_test_iteration (void *data)
   
   _dbus_object_tree_unregister_and_unlock (tree, path4);
 
+  _dbus_assert (!find_subtree (tree, path0, NULL));
   _dbus_assert (!find_subtree (tree, path1, NULL));
   _dbus_assert (!find_subtree (tree, path2, NULL));
   _dbus_assert (!find_subtree (tree, path3, NULL));
@@ -1550,6 +1690,7 @@ object_tree_test_iteration (void *data)
   
   _dbus_object_tree_unregister_and_unlock (tree, path5);
 
+  _dbus_assert (!find_subtree (tree, path0, NULL));
   _dbus_assert (!find_subtree (tree, path1, NULL));
   _dbus_assert (!find_subtree (tree, path2, NULL));
   _dbus_assert (!find_subtree (tree, path3, NULL));
@@ -1561,6 +1702,7 @@ object_tree_test_iteration (void *data)
   
   _dbus_object_tree_unregister_and_unlock (tree, path6);
 
+  _dbus_assert (!find_subtree (tree, path0, NULL));
   _dbus_assert (!find_subtree (tree, path1, NULL));
   _dbus_assert (!find_subtree (tree, path2, NULL));
   _dbus_assert (!find_subtree (tree, path3, NULL));
@@ -1572,6 +1714,7 @@ object_tree_test_iteration (void *data)
 
   _dbus_object_tree_unregister_and_unlock (tree, path7);
 
+  _dbus_assert (!find_subtree (tree, path0, NULL));
   _dbus_assert (!find_subtree (tree, path1, NULL));
   _dbus_assert (!find_subtree (tree, path2, NULL));
   _dbus_assert (!find_subtree (tree, path3, NULL));
@@ -1583,6 +1726,7 @@ object_tree_test_iteration (void *data)
 
   _dbus_object_tree_unregister_and_unlock (tree, path8);
 
+  _dbus_assert (!find_subtree (tree, path0, NULL));
   _dbus_assert (!find_subtree (tree, path1, NULL));
   _dbus_assert (!find_subtree (tree, path2, NULL));
   _dbus_assert (!find_subtree (tree, path3, NULL));
@@ -1601,43 +1745,47 @@ object_tree_test_iteration (void *data)
     }
 
   /* Register it all again, and test dispatch */
-
-  if (!do_register (tree, path1, FALSE, 0, tree_test_data))
+  
+  if (!do_register (tree, path0, TRUE, 0, tree_test_data))
+    goto out;
+  if (!do_register (tree, path1, FALSE, 1, tree_test_data))
     goto out;
-  if (!do_register (tree, path2, TRUE, 1, tree_test_data))
+  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
     goto out;
-  if (!do_register (tree, path3, TRUE, 2, tree_test_data))
+  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
     goto out;
-  if (!do_register (tree, path4, TRUE, 3, tree_test_data))
+  if (!do_register (tree, path4, TRUE, 4, tree_test_data))
     goto out;
-  if (!do_register (tree, path5, TRUE, 4, tree_test_data))
+  if (!do_register (tree, path5, TRUE, 5, tree_test_data))
     goto out;
-  if (!do_register (tree, path6, FALSE, 5, tree_test_data))
+  if (!do_register (tree, path6, FALSE, 6, tree_test_data))
     goto out;
-  if (!do_register (tree, path7, TRUE, 6, tree_test_data))
+  if (!do_register (tree, path7, TRUE, 7, tree_test_data))
     goto out;
-  if (!do_register (tree, path8, TRUE, 7, tree_test_data))
+  if (!do_register (tree, path8, TRUE, 8, tree_test_data))
     goto out;
 
 #if 0
   spew_tree (tree);
 #endif
-  
-  if (!do_test_dispatch (tree, path1, 0, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+
+  if (!do_test_dispatch (tree, path0, 0, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+    goto out;
+  if (!do_test_dispatch (tree, path1, 1, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
     goto out;
-  if (!do_test_dispatch (tree, path2, 1, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+  if (!do_test_dispatch (tree, path2, 2, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
     goto out;
-  if (!do_test_dispatch (tree, path3, 2, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+  if (!do_test_dispatch (tree, path3, 3, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
     goto out;
-  if (!do_test_dispatch (tree, path4, 3, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+  if (!do_test_dispatch (tree, path4, 4, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
     goto out;
-  if (!do_test_dispatch (tree, path5, 4, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+  if (!do_test_dispatch (tree, path5, 5, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
     goto out;
-  if (!do_test_dispatch (tree, path6, 5, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+  if (!do_test_dispatch (tree, path6, 6, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
     goto out;
-  if (!do_test_dispatch (tree, path7, 6, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+  if (!do_test_dispatch (tree, path7, 7, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
     goto out;
-  if (!do_test_dispatch (tree, path8, 7, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+  if (!do_test_dispatch (tree, path8, 8, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
     goto out;
   
  out:
index f72efb6..c662d72 100644 (file)
@@ -272,6 +272,12 @@ extern "C" {
 #define DBUS_ERROR_SPAWN_FAILED               "org.freedesktop.DBus.Error.Spawn.Failed"
 #define DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN    "org.freedesktop.DBus.Error.UnixProcessIdUnknown"
 
+#define DBUS_INTROSPECT_1_0_XML_NAMESPACE         "http://www.freedesktop.org/standards/dbus"
+#define DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+#define DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"
+#define DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<!DOCTYPE node PUBLIC \""DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER"\"\n\""DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER"\">\n"
+
+
 #ifdef __cplusplus
 }
 #endif
index cabc406..8e0dc0d 100644 (file)
@@ -303,6 +303,20 @@ node_info_add_node (NodeInfo *info,
   info->nodes = g_slist_append (info->nodes, node);
 }
 
+void
+node_info_replace_node (NodeInfo            *info,
+                        NodeInfo            *old_child,
+                        NodeInfo            *new_child)
+{
+  GSList *link;
+
+  node_info_ref (new_child); /* before unref old_child in case they are the same */
+  link = g_slist_find (info->nodes, old_child);
+  g_assert (link != NULL);
+  node_info_unref (old_child);
+  link->data = new_child;
+}
+
 InterfaceInfo*
 interface_info_new (const char *name)
 {
index fffbddf..88d5c6e 100644 (file)
@@ -83,6 +83,9 @@ void                node_info_add_interface       (NodeInfo            *info,
                                                    InterfaceInfo       *interface);
 void                node_info_add_node            (NodeInfo            *info,
                                                    NodeInfo            *child);
+void                node_info_replace_node        (NodeInfo            *info,
+                                                   NodeInfo            *old_child,
+                                                   NodeInfo            *new_child);
 InterfaceInfo*      interface_info_new            (const char          *name);
 InterfaceInfo*      interface_info_ref            (InterfaceInfo       *info);
 void                interface_info_unref          (InterfaceInfo       *info);
index fa7e369..609f316 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "dbus-gparser.h"
 #include <expat.h>
+#include <string.h>
 
 static void*
 expat_g_malloc (size_t sz)
@@ -192,6 +193,9 @@ description_load_from_string (const char  *str,
   
   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
+  if (len < 0)
+    len = strlen (str);
+  
   expat = NULL;
   context.parser = NULL;
   context.error = error;
index f08bf39..245ebf1 100644 (file)
@@ -289,26 +289,28 @@ handle_introspect (DBusConnection *connection,
   
   xml = g_string_new (NULL);
 
+  g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
+  
   g_string_append (xml, "<node>\n");
 
   /* We are introspectable, though I guess that was pretty obvious */
   g_string_append (xml, "  <interface name=\"org.freedesktop.Introspectable\">\n");
   g_string_append (xml, "    <method name=\"Introspect\">\n");
-  g_string_append (xml, "      <arg name=\"data\" direction=\"out\" type=\"string\"\"/>\n");
+  g_string_append (xml, "      <arg name=\"data\" direction=\"out\" type=\"string\"/>\n");
   g_string_append (xml, "    </method>\n");
   g_string_append (xml, "  </interface>\n");
 
   /* We support get/set properties */
   g_string_append (xml, "  <interface name=\"org.freedesktop.Properties\">\n");
   g_string_append (xml, "    <method name=\"Get\">\n");
-  g_string_append (xml, "      <arg name=\"interface\" direction=\"in\" type=\"string\"\"/>\n");
-  g_string_append (xml, "      <arg name=\"propname\" direction=\"in\" type=\"string\"\"/>\n");
-  g_string_append (xml, "      <arg name=\"value\" direction=\"out\" type=\"variant\"\"/>\n");
+  g_string_append (xml, "      <arg name=\"interface\" direction=\"in\" type=\"string\"/>\n");
+  g_string_append (xml, "      <arg name=\"propname\" direction=\"in\" type=\"string\"/>\n");
+  g_string_append (xml, "      <arg name=\"value\" direction=\"out\" type=\"variant\"/>\n");
   g_string_append (xml, "    </method>\n");
   g_string_append (xml, "    <method name=\"Set\">\n");
-  g_string_append (xml, "      <arg name=\"interface\" direction=\"in\" type=\"string\"\"/>\n");
-  g_string_append (xml, "      <arg name=\"propname\" direction=\"in\" type=\"string\"\"/>\n");
-  g_string_append (xml, "      <arg name=\"value\" direction=\"in\" type=\"variant\"\"/>\n");
+  g_string_append (xml, "      <arg name=\"interface\" direction=\"in\" type=\"string\"/>\n");
+  g_string_append (xml, "      <arg name=\"propname\" direction=\"in\" type=\"string\"/>\n");
+  g_string_append (xml, "      <arg name=\"value\" direction=\"in\" type=\"variant\"/>\n");
   g_string_append (xml, "    </method>\n");
   g_string_append (xml, "  </interface>\n");
   
index 624a95c..39f8ba8 100644 (file)
@@ -1032,12 +1032,31 @@ dbus_g_proxy_new_for_peer (DBusGConnection          *connection,
   g_return_val_if_fail (interface_name != NULL, NULL);
 
   proxy = dbus_g_proxy_new (connection, NULL,
-                           path_name, interface_name);
+                            path_name, interface_name);
 
   return proxy;
 }
 
 /**
+ * Gets the bus name a proxy is bound to (may be #NULL in some cases).
+ * If you created the proxy with dbus_g_proxy_new_for_name(), then
+ * the name you passed to that will be returned.
+ * If you created it with dbus_g_proxy_new_for_name_owner(), then the
+ * unique connection name will be returned. If you created it
+ * with dbus_g_proxy_new_for_peer() then #NULL will be returned.
+ *
+ * @param proxy the proxy
+ * @returns the bus name the proxy sends messages to
+ */
+const char*
+dbus_g_proxy_get_bus_name (DBusGProxy        *proxy)
+{
+  g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
+
+  return proxy->name;
+}
+
+/**
  * Invokes a method on a remote interface. This function does not
  * block; instead it returns an opaque #DBusPendingCall object that
  * tracks the pending call.  The method call will not be sent over the
@@ -1113,23 +1132,28 @@ dbus_g_proxy_begin_call (DBusGProxy *proxy,
  *
  * Otherwise, the "out" parameters and return value of the
  * method are stored in the provided varargs list.
- * The list should be terminated with DBUS_TYPE_INVALID.
+ * The list should be terminated with #DBUS_TYPE_INVALID.
  *
  * This function doesn't affect the reference count of the
  * #DBusPendingCall, the caller of dbus_g_proxy_begin_call() still owns
  * a reference.
  *
+ * @todo this should be changed to make a g_malloc() copy of the
+ * data returned probably; right now the data vanishes
+ * when you free the PendingCall which is sort of strange.
+ *
  * @param proxy a proxy for a remote interface
  * @param pending the pending call from dbus_g_proxy_begin_call()
  * @param error return location for an error
  * @param first_arg_type type of first "out" argument
- * @returns #FALSE if an error is set */
+ * @returns #FALSE if an error is set
+ */
 gboolean
 dbus_g_proxy_end_call (DBusGProxy          *proxy,
-                      DBusGPendingCall    *pending,
-                      GError             **error,
-                      int                  first_arg_type,
-                      ...)
+                       DBusGPendingCall    *pending,
+                       GError             **error,
+                       int                  first_arg_type,
+                       ...)
 {
   DBusMessage *message;
   va_list args;
@@ -1223,6 +1247,30 @@ dbus_g_proxy_call_no_reply (DBusGProxy               *proxy,
 }
 
 /**
+ * Increments refcount on a pending call.
+ *
+ * @param call the call
+ * @returns the same call
+ */
+DBusGPendingCall*
+dbus_g_pending_call_ref (DBusGPendingCall  *call)
+{
+  dbus_pending_call_ref (DBUS_PENDING_CALL_FROM_G_PENDING_CALL (call));
+  return call;
+}
+
+/**
+ * Decrements refcount on a pending call.
+ *
+ * @param call the call
+ */
+void
+dbus_g_pending_call_unref (DBusGPendingCall  *call)
+{
+  dbus_pending_call_unref (DBUS_PENDING_CALL_FROM_G_PENDING_CALL (call));
+}
+
+/**
  * Sends a message to the interface we're proxying for.  Does not
  * block or wait for a reply. The message is only actually written out
  * when you return to the main loop or block in
index ff48e7f..cf12245 100644 (file)
@@ -39,19 +39,25 @@ _dbus_gutils_split_path (const char *path)
   len = strlen (path);
 
   n_components = 0;
-  i = 0;
-  while (i < len)
+  if (path[1] != '\0') /* if not "/" */
     {
-      if (path[i] == '/')
-        n_components += 1;
-      ++i;
+      i = 0;
+      while (i < len)
+        {
+          if (path[i] == '/')
+            n_components += 1;
+          ++i;
+        }
     }
 
   split = g_new0 (char*, n_components + 1);
 
   comp = 0;
-  i = 0;
-  while (i < len)
+  if (n_components == 0)
+    i = 1;
+  else
+    i = 0;
+  while (comp < n_components)
     {
       if (path[i] == '/')
         ++i;
index eddea5f..0a5e3f6 100755 (executable)
@@ -57,12 +57,21 @@ echo "Started test bus pid $DBUS_SESSION_BUS_PID at $DBUS_SESSION_BUS_ADDRESS"
 export DBUS_TEST_GLIB_RUN_TEST_SCRIPT=1
 
 if test x$MODE = xprofile ; then
+  echo "profiling type $PROFILE_TYPE"
   sleep 2 ## this lets the bus get started so its startup time doesn't affect the profile too much
   if test x$PROFILE_TYPE = x ; then
       PROFILE_TYPE=all
   fi
   libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/glib/test-profile $PROFILE_TYPE || die "test-profile failed"
+elif test x$MODE = xviewer ; then
+  echo "Launching dbus-viewer"
+  ARGS=
+  if test x$DEBUG = x ; then
+      ARGS="--services org.freedesktop.DBus"
+  fi
+  libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/tools/dbus-viewer $ARGS || die "could not run dbus-viewer"
 else
+  echo "running test-dbus-glib"
   libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/glib/test-dbus-glib || die "test-dbus-glib failed"
 fi
 
index cad6f16..9b1be0a 100644 (file)
@@ -4,6 +4,43 @@
 #include <stdlib.h>
 #include <string.h>
 
+typedef struct MyObject MyObject;
+typedef struct MyObjectClass MyObjectClass;
+
+GType my_object_get_type (void);
+
+struct MyObject
+{
+  GObject parent;
+};
+
+struct MyObjectClass
+{
+  GObjectClass parent;
+};
+
+#define MY_TYPE_OBJECT              (my_object_get_type ())
+#define MY_OBJECT_OBJECT(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_OBJECT, MyObject))
+#define MY_OBJECT_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), MY_TYPE_OBJECT, MyObjectClass))
+#define MY_IS_OBJECT(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), MY_TYPE_OBJECT))
+#define MY_IS_OBJECT_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_TYPE_OBJECT))
+#define MY_OBJECT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), MY_TYPE_OBJECT, MyObjectClass))
+
+G_DEFINE_TYPE(MyObject, my_object, G_TYPE_OBJECT)
+
+
+static void
+my_object_init (MyObject *obj)
+{
+  
+}
+
+static void
+my_object_class_init (MyObjectClass *obj_class)
+{
+  
+}
+     
 static GMainLoop *loop;
 
 int
@@ -11,6 +48,7 @@ main (int argc, char **argv)
 {
   DBusGConnection *connection;
   GError *error;
+  GObject *obj;
   
   g_type_init ();
   
@@ -27,7 +65,15 @@ main (int argc, char **argv)
       exit (1);
     }
 
+  obj = g_object_new (MY_TYPE_OBJECT, NULL);
+
+  dbus_g_connection_register_g_object (connection,
+                                       "/org/freedesktop/my_test_object",
+                                       obj);
   
+  g_print ("GLib test service entering main loop\n");
+
+  g_main_loop_run (loop);
   
   g_print ("Successfully completed %s\n", argv[0]);
   
index 9c57b22..c32e6fd 100644 (file)
@@ -29,6 +29,7 @@
 #include "dbus-tree-view.h"
 #include <glib/dbus-gparser.h>
 #include <glib/dbus-gutils.h>
+#include <dbus/dbus-glib.h>
 
 #include <libintl.h>
 #define _(x) dgettext (GETTEXT_PACKAGE, x)
@@ -188,6 +189,133 @@ show_error_dialog (GtkWindow *transient_parent,
     }
 }
 
+static gboolean
+load_child_nodes (const char *service_name,
+                  NodeInfo   *parent,
+                  GError    **error)
+{
+  DBusGConnection *connection;
+  GSList *tmp;
+  
+  connection = dbus_g_bus_get (DBUS_BUS_SESSION, error);
+  if (connection == NULL)
+    return FALSE;
+
+  tmp = node_info_get_nodes (parent);
+  while (tmp != NULL)
+    {
+      DBusGProxy *proxy;
+      DBusGPendingCall *call;
+      const char *data;
+      NodeInfo *child;
+      NodeInfo *complete_child;
+
+      complete_child = NULL;
+      
+      child = tmp->data;
+
+      g_assert (*service_name == ':'); /* so we don't need new_for_name_owner */
+      proxy = dbus_g_proxy_new_for_name (connection,
+                                         service_name,
+                                         "/",
+                                         DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE);
+      g_assert (proxy != NULL);
+  
+      call = dbus_g_proxy_begin_call (proxy, "Introspect",
+                                      DBUS_TYPE_INVALID);
+      
+      data = NULL;
+      if (!dbus_g_proxy_end_call (proxy, call, error, DBUS_TYPE_STRING, &data,
+                                  DBUS_TYPE_INVALID))
+        goto done;
+      
+      complete_child = description_load_from_string (data, -1, error);
+      if (complete_child == NULL)
+        goto done;
+      
+    done:
+      dbus_g_pending_call_unref (call);
+      g_object_unref (proxy);
+
+      if (complete_child == NULL)
+        return FALSE;
+
+      /* change complete_child's name to relative */
+      base_info_set_name ((BaseInfo*)complete_child,
+                          base_info_get_name ((BaseInfo*)child));
+      
+      /* Stitch in complete_child rather than child */
+      node_info_replace_node (parent, child, complete_child);
+      node_info_unref (complete_child); /* ref still held by parent */
+      
+      /* Now recurse */
+      if (!load_child_nodes (service_name, complete_child, error))
+        return FALSE;
+      
+      tmp = tmp->next;
+    }
+
+  return TRUE;
+}
+
+static NodeInfo*
+load_from_service (const char *service_name,
+                   GError    **error)
+{
+  DBusGConnection *connection;
+  DBusGProxy *root_proxy;
+  DBusGPendingCall *call;
+  const char *data;
+  NodeInfo *node;
+
+  node = NULL;
+  call = NULL;
+  
+  connection = dbus_g_bus_get (DBUS_BUS_SESSION, error);
+  if (connection == NULL)
+    return NULL;
+
+  root_proxy = dbus_g_proxy_new_for_name_owner (connection,
+                                                service_name,
+                                                "/",
+                                                DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE,
+                                                error);
+  if (root_proxy == NULL)
+    return NULL;
+  
+  call = dbus_g_proxy_begin_call (root_proxy, "Introspect",
+                                  DBUS_TYPE_INVALID);
+
+  data = NULL;
+  if (!dbus_g_proxy_end_call (root_proxy, call, error, DBUS_TYPE_STRING, &data,
+                              DBUS_TYPE_INVALID))
+    goto out;
+
+  node = description_load_from_string (data, -1, error);
+
+  /* g_print ("%s\n", data); */
+  
+  if (node == NULL)
+    goto out;
+
+  base_info_set_name ((BaseInfo*)node, "/");
+  
+  if (!load_child_nodes (dbus_g_proxy_get_bus_name (root_proxy),
+                         node, error))
+    {
+      node_info_unref (node);
+      node = NULL;
+      goto out;
+    }
+  
+ out:
+  if (call)
+    dbus_g_pending_call_unref (call);
+    
+  g_object_unref (root_proxy);
+  return node;
+}
+
 static void
 usage (int ecode)
 {
@@ -214,6 +342,7 @@ main (int argc, char **argv)
   GSList *files;
   gboolean end_of_args;
   GSList *tmp;
+  gboolean services;
   
   bindtextdomain (GETTEXT_PACKAGE, DBUS_LOCALEDIR);
   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
@@ -221,6 +350,7 @@ main (int argc, char **argv)
   
   gtk_init (&argc, &argv);
 
+  services = FALSE;
   end_of_args = FALSE;
   files = NULL;
   prev_arg = NULL;
@@ -237,6 +367,8 @@ main (int argc, char **argv)
             usage (0);
           else if (strcmp (arg, "--version") == 0)
             version ();
+          else if (strcmp (arg, "--services") == 0)
+            services = TRUE;
           else if (arg[0] == '-' &&
                    arg[1] == '-' &&
                    arg[2] == '\0')
@@ -270,8 +402,12 @@ main (int argc, char **argv)
       filename = tmp->data;
 
       error = NULL;
-      node = description_load_from_file (filename,
-                                         &error);
+      if (services)
+        node = load_from_service (filename, &error);
+      else
+        node = description_load_from_file (filename,
+                                           &error);
+      
       if (node == NULL)
         {
           g_assert (error != NULL);
@@ -313,8 +449,3 @@ main (int argc, char **argv)
   return 0;
 }
 
-
-
-
-
-