* doc/dbus-specification.xml: document ServiceOwnerChanged signal.
authorOlivier Andrieu <oliv__a@users.sourceforge.net>
Fri, 24 Sep 2004 10:43:36 +0000 (10:43 +0000)
committerOlivier Andrieu <oliv__a@users.sourceforge.net>
Fri, 24 Sep 2004 10:43:36 +0000 (10:43 +0000)
* bus/driver.c, bus/driver.h, bus/services.c: Use ServiceOwnerChanged
signal instead of ServiceCreated and ServiceDeleted.

* bus/dispatch.c: update testcase for the new signal.

ChangeLog
bus/dispatch.c
bus/driver.c
bus/driver.h
bus/services.c
doc/dbus-specification.xml

index db7a787..552211e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2004-09-24  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+       * doc/dbus-specification.xml: document ServiceOwnerChanged
+       signal.
+       
+       * bus/driver.c, bus/driver.h, bus/services.c: Use
+       ServiceOwnerChanged signal instead of ServiceCreated and
+       ServiceDeleted.
+       
+       * bus/dispatch.c: update testcase for the new signal.
+
 2004-09-20  Jon Trowbridge  <trow@ximian.com>
 
        Patch from Nat Friedman <nat@novell.com>
index 54e4583..3cd1c3e 100644 (file)
@@ -93,8 +93,7 @@ bus_dispatch_matches (BusTransaction *transaction,
   matchmaker = bus_context_get_matchmaker (context);
 
   recipients = NULL;
-  if (!bus_matchmaker_get_recipients (matchmaker,
-                                      bus_context_get_connections (context),
+  if (!bus_matchmaker_get_recipients (matchmaker, connections,
                                       sender, addressed_recipient, message,
                                       &recipients))
     {
@@ -482,70 +481,114 @@ verbose_message_received (DBusConnection *connection,
                  connection);
 }
 
+typedef enum
+{
+  SERVICE_CREATED,
+  OWNER_CHANGED,
+  SERVICE_DELETED
+} ServiceInfoKind;
+
 typedef struct
 {
+  ServiceInfoKind expected_kind;
   const char *expected_service_name;
   dbus_bool_t failed;
-} CheckServiceDeletedData;
+  DBusConnection *skip_connection;
+} CheckServiceOwnerChangedData;
 
 static dbus_bool_t
-check_service_deleted_foreach (DBusConnection *connection,
-                               void           *data)
+check_service_owner_changed_foreach (DBusConnection *connection,
+                                    void           *data)
 {
-  CheckServiceDeletedData *d = data;
+  CheckServiceOwnerChangedData *d = data;
   DBusMessage *message;
   DBusError error;
-  char *service_name;
+  char *service_name, *old_owner, *new_owner;
+
+  if (d->expected_kind == SERVICE_CREATED 
+      && connection == d->skip_connection)
+    return TRUE;
 
   dbus_error_init (&error);
   d->failed = TRUE;
-  service_name = NULL;
   
   message = pop_message_waiting_for_memory (connection);
   if (message == NULL)
     {
       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
-                  connection, "ServiceDeleted");
+                  connection, "ServiceOwnerChanged");
       goto out;
     }
   else if (!dbus_message_is_signal (message,
                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                    "ServiceDeleted"))
+                                    "ServiceOwnerChanged"))
     {
-      warn_unexpected (connection, message, "ServiceDeleted");
+      warn_unexpected (connection, message, "ServiceOwnerChanged");
 
       goto out;
     }
   else
     {
-      if (!dbus_message_get_args (message, &error,
-                                  DBUS_TYPE_STRING, &service_name,
-                                  DBUS_TYPE_INVALID))
+    reget_service_info_data:
+      service_name = NULL;
+      old_owner = NULL;
+      new_owner = NULL;
+
+      dbus_message_get_args (message, &error,
+                             DBUS_TYPE_STRING, &service_name,
+                             DBUS_TYPE_STRING, &old_owner,
+                             DBUS_TYPE_STRING, &new_owner,
+                             DBUS_TYPE_INVALID);
+
+      if (dbus_error_is_set (&error))
+       {
+         if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+           {
+              dbus_free (service_name);
+              dbus_free (old_owner);
+              dbus_free (new_owner);
+              dbus_error_free (&error);
+              _dbus_wait_for_memory ();              
+              goto reget_service_info_data;
+           }
+         else
+           {
+             _dbus_warn ("Did not get the expected arguments\n");
+             goto out;
+           }
+       }
+
+      if ((d->expected_kind == SERVICE_CREATED    && ( old_owner[0] || !new_owner[0]))
+          || (d->expected_kind == OWNER_CHANGED   && (!old_owner[0] || !new_owner[0]))
+          || (d->expected_kind == SERVICE_DELETED && (!old_owner[0] ||  new_owner[0])))
         {
-          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
-            {
-              _dbus_verbose ("no memory to get service name arg\n");
-            }
-          else
-            {
-              _dbus_assert (dbus_error_is_set (&error));
-              _dbus_warn ("Did not get the expected single string argument\n");
-              goto out;
-            }
+          _dbus_warn ("inconsistent ServiceOwnerChanged arguments");
+          goto out;
         }
-      else if (strcmp (service_name, d->expected_service_name) != 0)
+
+      if (strcmp (service_name, d->expected_service_name) != 0)
         {
-          _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
+          _dbus_warn ("expected info on service %s, got info on %s\n",
                       d->expected_service_name,
                       service_name);
           goto out;
         }
+
+      if (*service_name == ':' && new_owner[0] 
+          && strcmp (service_name, new_owner) != 0)
+        {
+          _dbus_warn ("inconsistent ServiceOwnedChanged message (\"%s\" [ %s -> %s ])\n",
+                      service_name, old_owner, new_owner);
+          goto out;
+        }
     }
 
   d->failed = FALSE;
   
  out:
   dbus_free (service_name);
+  dbus_free (old_owner);
+  dbus_free (new_owner);
   dbus_error_free (&error);
   
   if (message)
@@ -554,13 +597,14 @@ check_service_deleted_foreach (DBusConnection *connection,
   return !d->failed;
 }
 
+
 static void
 kill_client_connection (BusContext     *context,
                         DBusConnection *connection)
 {
   char *base_service;
   const char *s;
-  CheckServiceDeletedData csdd;
+  CheckServiceOwnerChangedData socd;
 
   _dbus_verbose ("killing connection %p\n", connection);
   
@@ -588,16 +632,18 @@ kill_client_connection (BusContext     *context,
   connection = NULL;
   _dbus_assert (!bus_test_client_listed (connection));
   
-  csdd.expected_service_name = base_service;
-  csdd.failed = FALSE;
-
-  bus_test_clients_foreach (check_service_deleted_foreach,
-                            &csdd);
+  socd.expected_kind = SERVICE_DELETED;
+  socd.expected_service_name = base_service;
+  socd.failed = FALSE;
+  socd.skip_connection = NULL;
+  
+  bus_test_clients_foreach (check_service_owner_changed_foreach,
+                            &socd);
 
   dbus_free (base_service);
   
-  if (csdd.failed)
-    _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
+  if (socd.failed)
+    _dbus_assert_not_reached ("didn't get the expected ServiceOwnerChanged (deletion) messages");
   
   if (!check_no_leftovers (context))
     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
@@ -646,81 +692,6 @@ check_no_messages_foreach (DBusConnection *connection,
   return !d->failed;
 }
 
-typedef struct
-{
-  DBusConnection *skip_connection;
-  const char *expected_service_name;
-  dbus_bool_t failed;
-} CheckServiceCreatedData;
-
-static dbus_bool_t
-check_service_created_foreach (DBusConnection *connection,
-                               void           *data)
-{
-  CheckServiceCreatedData *d = data;
-  DBusMessage *message;
-  DBusError error;
-  char *service_name;
-
-  if (connection == d->skip_connection)
-    return TRUE;
-
-  dbus_error_init (&error);
-  d->failed = TRUE;
-  service_name = NULL;
-  
-  message = pop_message_waiting_for_memory (connection);
-  if (message == NULL)
-    {
-      _dbus_warn ("Did not receive a message on %p, expecting %s\n",
-                  connection, "ServiceCreated");
-      goto out;
-    }
-  else if (!dbus_message_is_signal (message,
-                                    DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                    "ServiceCreated"))
-    {
-      warn_unexpected (connection, message, "ServiceCreated");
-      goto out;
-    }
-  else
-    {
-      if (!dbus_message_get_args (message, &error,
-                                  DBUS_TYPE_STRING, &service_name,
-                                  DBUS_TYPE_INVALID))
-        {
-          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
-            {
-              _dbus_verbose ("no memory to get service name arg\n");
-            }
-          else
-            {
-              _dbus_assert (dbus_error_is_set (&error));
-              _dbus_warn ("Did not get the expected single string argument\n");
-              goto out;
-            }
-        }
-      else if (strcmp (service_name, d->expected_service_name) != 0)
-        {
-          _dbus_warn ("expected creation of service %s, got creation of %s\n",
-                      d->expected_service_name,
-                      service_name);
-          goto out;
-        }
-    }
-
-  d->failed = FALSE;
-  
- out:
-  dbus_free (service_name);
-  dbus_error_free (&error);
-  
-  if (message)
-    dbus_message_unref (message);
-
-  return !d->failed;
-}
-
 static dbus_bool_t
 check_no_leftovers (BusContext *context)
 {
@@ -826,7 +797,7 @@ check_hello_message (BusContext     *context,
     }
   else
     {
-      CheckServiceCreatedData scd;
+      CheckServiceOwnerChangedData socd;
       
       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
         {
@@ -864,13 +835,14 @@ check_hello_message (BusContext     *context,
       while (!dbus_bus_set_base_service (connection, name))
         _dbus_wait_for_memory ();
       
-      scd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
-      scd.failed = FALSE;
-      scd.expected_service_name = name;
-      bus_test_clients_foreach (check_service_created_foreach,
-                                &scd);
+      socd.expected_kind = SERVICE_CREATED;
+      socd.expected_service_name = name;
+      socd.failed = FALSE;
+      socd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                &socd);
       
-      if (scd.failed)
+      if (socd.failed)
         goto out;
       
       /* Client should also have gotten ServiceAcquired */
@@ -882,6 +854,13 @@ check_hello_message (BusContext     *context,
                       "ServiceAcquired");
           goto out;
         }
+      if (! dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                   "ServiceAcquired"))
+        {
+          _dbus_warn ("Expecting %s, got smthg else\n",
+                      "ServiceAcquired");
+          goto out;
+        }
       
     retry_get_acquired_name:
       if (!dbus_message_get_args (message, &error,
@@ -1489,9 +1468,6 @@ check_nonexistent_service_activation (BusContext     *context,
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
-  
-  dbus_error_init (&error);
   
   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
@@ -1593,10 +1569,7 @@ check_nonexistent_service_auto_activation (BusContext     *context,
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
     
-  dbus_error_init (&error);
-
   message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME,
                                           "/org/freedesktop/TestSuite",
                                           "org.freedesktop.TestSuite",
@@ -1690,66 +1663,87 @@ check_base_service_activated (BusContext     *context,
   DBusMessage *message;
   dbus_bool_t retval;
   DBusError error;
-  char *base_service;
+  char *base_service, *base_service_from_bus, *old_owner;
   
-  base_service = NULL;
   retval = FALSE;
   
   dbus_error_init (&error);
+  base_service = NULL;
+  old_owner = NULL;
+  base_service_from_bus = NULL;
 
   message = initial_message;
   dbus_message_ref (message);  
 
   if (dbus_message_is_signal (message,
                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                              "ServiceCreated"))
+                              "ServiceOwnerChanged"))
     {
-      char *service_name;
-      CheckServiceCreatedData scd;
+      CheckServiceOwnerChangedData socd;
 
     reget_service_name_arg:
+      base_service = NULL;
+      old_owner = NULL;
+      base_service_from_bus = NULL;
+
       if (!dbus_message_get_args (message, &error,
-                                  DBUS_TYPE_STRING, &service_name,
+                                  DBUS_TYPE_STRING, &base_service,
+                                 DBUS_TYPE_STRING, &old_owner,
+                                  DBUS_TYPE_STRING, &base_service_from_bus,
                                   DBUS_TYPE_INVALID))
         {
           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
             {
               dbus_error_free (&error);
+              dbus_free (base_service);
+              dbus_free (old_owner);
+              dbus_free (base_service_from_bus);
               _dbus_wait_for_memory ();
               goto reget_service_name_arg;
             }
           else
             {
               _dbus_warn ("Message %s doesn't have a service name: %s\n",
-                          "ServiceCreated",
+                          "ServiceOwnerChanged (creation)",
                           error.message);
-              dbus_error_free (&error);
               goto out;
             }
         }
 
-      if (*service_name != ':')
+      if (*base_service != ':')
         {
           _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
-                      service_name);
+                      base_service);
           goto out;
         }
-              
-      base_service = service_name;
-      service_name = NULL;
-      
-      scd.skip_connection = connection;
-      scd.failed = FALSE;
-      scd.expected_service_name = base_service;
-      bus_test_clients_foreach (check_service_created_foreach,
-                                &scd);
+         
+      if (strcmp (base_service, base_service_from_bus) != 0)
+       {
+          _dbus_warn ("Expected base service activation, got \"%s\" instead with owner \"%s\"\n",
+                      base_service, base_service_from_bus);
+          goto out;
+        }
+
+      if (old_owner[0])
+        {
+          _dbus_warn ("Received an old_owner argument during base service activation, \"%s\"\n",
+                      old_owner);
+          goto out;
+        }
+     
+      socd.expected_kind = SERVICE_CREATED;
+      socd.expected_service_name = base_service;
+      socd.failed = FALSE;
+      socd.skip_connection = connection;
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                &socd);
       
-      if (scd.failed)
+      if (socd.failed)
         goto out;
     }
   else
     {
-      warn_unexpected (connection, message, "ServiceCreated for base service");
+      warn_unexpected (connection, message, "ServiceOwnerChanged (creation) for base service");
 
       goto out;
     }
@@ -1765,10 +1759,11 @@ check_base_service_activated (BusContext     *context,
  out:
   if (message)
     dbus_message_unref (message);
+  dbus_free (base_service);
+  dbus_free (base_service_from_bus);
+  dbus_free (old_owner);
+  dbus_error_free (&error);
 
-  if (base_service)
-    dbus_free (base_service);
-  
   return retval;
 }
 
@@ -1793,28 +1788,39 @@ check_service_activated (BusContext     *context,
 
   if (dbus_message_is_signal (message,
                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                              "ServiceCreated"))
+                              "ServiceOwnerChanged"))
     {
-      char *service_name;
-      CheckServiceCreatedData scd;
+      CheckServiceOwnerChangedData socd;
+      char *service_name, *base_service_from_bus, *old_owner;
 
     reget_service_name_arg:
+      service_name = NULL;
+      old_owner = NULL;
+      base_service_from_bus = NULL;
+
       if (!dbus_message_get_args (message, &error,
                                   DBUS_TYPE_STRING, &service_name,
+                                 DBUS_TYPE_STRING, &old_owner,
+                                  DBUS_TYPE_STRING, &base_service_from_bus,
                                   DBUS_TYPE_INVALID))
         {
           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
             {
               dbus_error_free (&error);
+             dbus_free (service_name);
+             dbus_free (old_owner);
+             dbus_free (base_service_from_bus);
               _dbus_wait_for_memory ();
               goto reget_service_name_arg;
             }
           else
             {
               _dbus_warn ("Message %s doesn't have a service name: %s\n",
-                          "ServiceCreated",
+                          "ServiceOwnerChanged (creation)",
                           error.message);
-              dbus_error_free (&error);
+             dbus_free (service_name);
+             dbus_free (old_owner);
+             dbus_free (base_service_from_bus);
               goto out;
             }
         }
@@ -1824,18 +1830,43 @@ check_service_activated (BusContext     *context,
           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
                       activated_name, service_name);
           dbus_free (service_name);
+          dbus_free (old_owner);
+          dbus_free (base_service_from_bus);
           goto out;
         }
-      
-      scd.skip_connection = connection;
-      scd.failed = FALSE;
-      scd.expected_service_name = service_name;
-      bus_test_clients_foreach (check_service_created_foreach,
-                                &scd);
-          
-      dbus_free (service_name);
 
-      if (scd.failed)
+      if (strcmp (base_service_name, base_service_from_bus) != 0)
+        {
+          _dbus_warn ("ServiceOwnerChanged reports wrong base service: %s owner, expected %s instead\n",
+                      base_service_from_bus, base_service_name);
+          dbus_free (service_name);
+          dbus_free (old_owner);
+          dbus_free (base_service_from_bus);
+          goto out;
+        }
+      dbus_free (base_service_from_bus);
+
+      if (old_owner[0])
+        {
+          _dbus_warn ("expected a %s, got a %s\n",
+                      "ServiceOwnerChanged (creation)",
+                      "ServiceOwnerChanged (change)");
+          dbus_free (service_name);
+          dbus_free (old_owner);
+          goto out;
+        }
+      dbus_free (old_owner);
+
+      socd.expected_kind = SERVICE_CREATED;
+      socd.skip_connection = connection;
+      socd.failed = FALSE;
+      socd.expected_service_name = service_name;
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                &socd);
+
+      dbus_free (service_name);
+          
+      if (socd.failed)
         goto out;
           
       dbus_message_unref (message);
@@ -1849,7 +1880,7 @@ check_service_activated (BusContext     *context,
     }
   else
     {
-      warn_unexpected (connection, message, "ServiceCreated for the activated name");
+      warn_unexpected (connection, message, "ServiceOwnerChanged for the activated name");
       
       goto out;
     }
@@ -1870,7 +1901,6 @@ check_service_activated (BusContext     *context,
         {
           _dbus_warn ("Did not have activation result first argument to %s: %s\n",
                       "ActivateService", error.message);
-          dbus_error_free (&error);
           goto out;
         }
 
@@ -1904,6 +1934,7 @@ check_service_activated (BusContext     *context,
  out:
   if (message)
     dbus_message_unref (message);
+  dbus_error_free (&error);
   
   return retval;
 }
@@ -1928,10 +1959,10 @@ check_service_auto_activated (BusContext     *context,
 
   if (dbus_message_is_signal (message,
                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                              "ServiceCreated"))
+                              "ServiceOwnerChanged"))
     {
       char *service_name;
-      CheckServiceCreatedData scd;
+      CheckServiceOwnerChangedData socd;
       
     reget_service_name_arg:
       if (!dbus_message_get_args (message, &error,
@@ -1947,7 +1978,7 @@ check_service_auto_activated (BusContext     *context,
           else
             {
               _dbus_warn ("Message %s doesn't have a service name: %s\n",
-                          "ServiceCreated",
+                          "ServiceOwnerChanged",
                           error.message);
               dbus_error_free (&error);
               goto out;
@@ -1962,15 +1993,16 @@ check_service_auto_activated (BusContext     *context,
           goto out;
         }
       
-      scd.skip_connection = connection;
-      scd.failed = FALSE;
-      scd.expected_service_name = service_name;
-      bus_test_clients_foreach (check_service_created_foreach,
-                               &scd);
+      socd.expected_kind = SERVICE_CREATED;
+      socd.expected_service_name = service_name;
+      socd.failed = FALSE;
+      socd.skip_connection = connection; 
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                               &socd);
       
       dbus_free (service_name);
       
-      if (scd.failed)
+      if (socd.failed)
         goto out;
       
       /* Note that this differs from regular activation in that we don't get a
@@ -1982,7 +2014,7 @@ check_service_auto_activated (BusContext     *context,
     }
   else
     {
-      warn_unexpected (connection, message, "ServiceCreated for the activated name");
+      warn_unexpected (connection, message, "ServiceOwnerChanged for the activated name");
       
       goto out;
     }
@@ -2003,28 +2035,32 @@ check_service_deactivated (BusContext     *context,
                            const char     *base_service)
 {
   dbus_bool_t retval;
-  CheckServiceDeletedData csdd;
+  CheckServiceOwnerChangedData socd;
 
   retval = FALSE;
   
-  /* Now we are expecting ServiceDeleted messages for the base
+  /* Now we are expecting ServiceOwnerChanged (deletion) messages for the base
    * service and the activated_name.  The base service
    * notification is required to come last.
    */
-  csdd.expected_service_name = activated_name;
-  csdd.failed = FALSE;
-  bus_test_clients_foreach (check_service_deleted_foreach,
-                            &csdd);      
-
-  if (csdd.failed)
+  socd.expected_kind = SERVICE_DELETED;
+  socd.expected_service_name = activated_name;
+  socd.failed = FALSE;
+  socd.skip_connection = NULL;
+  bus_test_clients_foreach (check_service_owner_changed_foreach,
+                            &socd);      
+
+  if (socd.failed)
     goto out;
       
-  csdd.expected_service_name = base_service;
-  csdd.failed = FALSE;
-  bus_test_clients_foreach (check_service_deleted_foreach,
-                            &csdd);
-
-  if (csdd.failed)
+  socd.expected_kind = SERVICE_DELETED;
+  socd.expected_service_name = base_service;
+  socd.failed = FALSE;
+  socd.skip_connection = NULL;
+  bus_test_clients_foreach (check_service_owner_changed_foreach,
+                            &socd);
+
+  if (socd.failed)
     goto out;
 
   retval = TRUE;
@@ -2244,6 +2280,73 @@ check_got_error (BusContext     *context,
   return retval;
 }
           
+typedef enum
+{ 
+  GOT_SERVICE_CREATED,
+  GOT_SERVICE_DELETED,
+  GOT_ERROR,
+  GOT_SOMETHING_ELSE 
+} GotServiceInfo;
+
+static GotServiceInfo
+check_got_service_info (DBusMessage *message)
+{
+  GotServiceInfo message_kind;
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                              "ServiceOwnerChanged"))
+    {
+      DBusError error;
+      char *service_name, *old_owner, *new_owner;
+      dbus_error_init (&error);
+
+    reget_service_info_data:
+      service_name = NULL;
+      old_owner = NULL;
+      new_owner = NULL;
+
+      dbus_message_get_args (message, &error,
+                             DBUS_TYPE_STRING, &service_name,
+                             DBUS_TYPE_STRING, &old_owner,
+                             DBUS_TYPE_STRING, &new_owner,
+                             DBUS_TYPE_INVALID);
+      if (dbus_error_is_set (&error))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_error_free (&error);
+              dbus_free (service_name);
+              dbus_free (old_owner);
+              dbus_free (new_owner);
+              goto reget_service_info_data;
+            }
+          else
+            {
+              _dbus_warn ("unexpected arguments for ServiceOwnerChanged message");
+              message_kind = GOT_SOMETHING_ELSE;
+            }
+        }
+      else if (!old_owner[0])
+        message_kind = GOT_SERVICE_CREATED;
+      else if (!new_owner[0])
+        message_kind = GOT_SERVICE_DELETED;
+      else
+        message_kind = GOT_SOMETHING_ELSE;
+
+      dbus_free (service_name);
+      dbus_free (old_owner);
+      dbus_free (new_owner);
+      dbus_error_free (&error);
+    }
+  else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    message_kind = GOT_ERROR;
+  else
+    message_kind = GOT_SOMETHING_ELSE;
+
+  return message_kind;
+}
+
 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
 
 /* returns TRUE if the correct thing happens,
@@ -2256,13 +2359,10 @@ check_existent_service_activation (BusContext     *context,
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
   char *base_service;
 
   base_service = NULL;
   
-  dbus_error_init (&error);
-  
   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
@@ -2348,8 +2448,7 @@ check_existent_service_activation (BusContext     *context,
     }
   else
     {
-      dbus_bool_t got_service_deleted;
-      dbus_bool_t got_error;
+      GotServiceInfo message_kind;
       
       if (!check_base_service_activated (context, connection,
                                          message, &base_service))
@@ -2368,65 +2467,72 @@ check_existent_service_activation (BusContext     *context,
           goto out;
         }
 
-      got_service_deleted = dbus_message_is_signal (message,
-                                                    DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                                    "ServiceDeleted");
-      got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
-      
+      message_kind = check_got_service_info (message);
+
       dbus_connection_return_message (connection, message);
       message = NULL;
 
-      if (got_error)
-        {
+      switch (message_kind)
+       {
+       case GOT_SOMETHING_ELSE:
+          _dbus_warn ("Unexpected message after ActivateService "
+                      "(should be an error or a service announcement");
+         goto out;
+
+       case GOT_ERROR:
           if (!check_got_error (context, connection,
                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
                                 DBUS_ERROR_NO_MEMORY,
                                 NULL))
             goto out;
-
           /* A service deleted should be coming along now after this error.
            * We can also get the error *after* the service deleted.
            */
-          got_service_deleted = TRUE;
-        }
-      
-      if (got_service_deleted)
-        {
-          /* The service started up and got a base address, but then
-           * failed to register under EXISTENT_SERVICE_NAME
-           */
-          CheckServiceDeletedData csdd;
-          
-          csdd.expected_service_name = base_service;
-          csdd.failed = FALSE;
-          bus_test_clients_foreach (check_service_deleted_foreach,
-                                    &csdd);
 
-          if (csdd.failed)
-            goto out;
+         /* fall through */
 
-          /* Now we should get an error about the service exiting
-           * if we didn't get it before.
-           */
-          if (!got_error)
-            {
-              block_connection_until_message_from_bus (context, connection);
+       case GOT_SERVICE_DELETED:
+         {
+           /* The service started up and got a base address, but then
+            * failed to register under EXISTENT_SERVICE_NAME
+            */
+           CheckServiceOwnerChangedData socd;
+
+           socd.expected_kind = SERVICE_DELETED;
+           socd.expected_service_name = base_service;
+           socd.failed = FALSE;
+           socd.skip_connection = NULL;
+           
+           bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                     &socd);
+
+           if (socd.failed)
+             goto out;
+
+           /* Now we should get an error about the service exiting
+            * if we didn't get it before.
+            */
+           if (message_kind != GOT_ERROR)
+             {
+               block_connection_until_message_from_bus (context, connection);
               
-              /* and process everything again */
-              bus_test_run_everything (context);
+               /* and process everything again */
+               bus_test_run_everything (context);
               
-              if (!check_got_error (context, connection,
-                                    DBUS_ERROR_SPAWN_CHILD_EXITED,
-                                    NULL))
-                goto out;
-            }
-        }
-      else
-        {
+               if (!check_got_error (context, connection,
+                                     DBUS_ERROR_SPAWN_CHILD_EXITED,
+                                     NULL))
+                 goto out;
+             }
+           break;
+         }
+
+       case GOT_SERVICE_CREATED:
           message = pop_message_waiting_for_memory (connection);
           if (message == NULL)
             {
-              _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
+              _dbus_warn ("Failed to pop message we just put back! "
+                         "should have been a ServiceOwnerChanged (creation)\n");
               goto out;
             }
           
@@ -2437,7 +2543,6 @@ check_existent_service_activation (BusContext     *context,
           dbus_message_unref (message);
           message = NULL;
 
-
           if (!check_no_leftovers (context))
             {
               _dbus_warn ("Messages were left over after successful activation\n");
@@ -2447,9 +2552,11 @@ check_existent_service_activation (BusContext     *context,
           if (!check_send_exit_to_service (context, connection,
                                            EXISTENT_SERVICE_NAME, base_service))
             goto out;
-        }
+
+         break;
+       }
     }
-  
+
   retval = TRUE;
   
  out:
@@ -2472,9 +2579,6 @@ check_segfault_service_activation (BusContext     *context,
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
-  
-  dbus_error_init (&error);
   
   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
@@ -2578,11 +2682,6 @@ check_segfault_service_auto_activation (BusContext     *context,
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
-
-  dbus_error_init (&error);
-
-  dbus_error_init (&error);
 
   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService",
                                           "/org/freedesktop/TestSuite",
@@ -2679,13 +2778,10 @@ check_existent_service_auto_activation (BusContext     *context,
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
   char *base_service;
 
   base_service = NULL;
 
-  dbus_error_init (&error);
-
   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
                                           "/org/freedesktop/TestSuite",
                                           "org.freedesktop.TestSuite",
@@ -2729,7 +2825,6 @@ check_existent_service_auto_activation (BusContext     *context,
 
   retval = FALSE;
   
-  /* Should get ServiceCreated for the base service, or an error. */
   message = pop_message_waiting_for_memory (connection);
   if (message == NULL)
     {
@@ -2739,38 +2834,13 @@ check_existent_service_auto_activation (BusContext     *context,
     }
 
   verbose_message_received (connection, message);
-  _dbus_verbose ("  (after sending %s)\n", "ActivateService");
+  _dbus_verbose ("  (after sending %s)\n", "auto activation");
 
-  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+  /* we should get zero or two ServiceOwnerChanged signals */
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
     {
-      if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
-        {
-          _dbus_warn ("Message has wrong sender %s\n",
-                      dbus_message_get_sender (message) ?
-                      dbus_message_get_sender (message) : "(none)");
-         goto out;
-        }
+      GotServiceInfo message_kind;
 
-      if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY) ||
-         dbus_message_is_error (message, DBUS_ERROR_SPAWN_CHILD_EXITED) ||
-         dbus_message_is_error (message, DBUS_ERROR_TIMED_OUT))
-        {
-          ; /* good, those are expected */
-         retval = TRUE;
-         goto out;
-        }
-      else
-        {
-          _dbus_warn ("Did not expect error %s\n",
-                      dbus_message_get_error_name (message));
-          goto out;
-        }
-    }
-  else
-    {
-      dbus_bool_t got_service_deleted;
-      dbus_bool_t got_error;
-      
       if (!check_base_service_activated (context, connection,
                                          message, &base_service))
        goto out;
@@ -2781,113 +2851,101 @@ check_existent_service_auto_activation (BusContext     *context,
       /* We may need to block here for the test service to exit or finish up */
       block_connection_until_message_from_bus (context, connection);
 
-      /* Should get ServiceCreated for the activated service name,
-       * ServiceDeleted on the base service name, or an error.
+      /* Should get a service creation notification for the activated
+       * service name, or a service deletion on the base service name
        */
       message = dbus_connection_borrow_message (connection);
       if (message == NULL)
         {
-          _dbus_warn ("Did not receive any messages after base service creation notification\n");
+         _dbus_warn ("No message after auto activation "
+                     "(should be a service announcement)");
+         dbus_connection_return_message (connection, message);
+         message = NULL;
           goto out;
         }
 
-      got_service_deleted = dbus_message_is_signal (message,
-                                                    DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                                    "ServiceDeleted");
-      got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
+      message_kind = check_got_service_info (message);
 
       dbus_connection_return_message (connection, message);
       message = NULL;
 
-      if (got_error)
-        {
-          if (!check_got_error (context, connection,
-                                DBUS_ERROR_SPAWN_CHILD_EXITED,
-                                DBUS_ERROR_NO_MEMORY,
-                                NULL))
-            goto out;
-
-          /* A service deleted should be coming along now after this error.
-           * We can also get the error *after* the service deleted.
-           */
-          got_service_deleted = TRUE;
-        }
-      
-      if (got_service_deleted)
-        {
-          /* The service started up and got a base address, but then
-           * failed to register under EXISTENT_SERVICE_NAME
-           */
-          CheckServiceDeletedData csdd;
-          
-          csdd.expected_service_name = base_service;
-          csdd.failed = FALSE;
-          bus_test_clients_foreach (check_service_deleted_foreach,
-                                    &csdd);
-
-          if (csdd.failed)
-            goto out;
-         
-          /* Now we should get an error about the service exiting
-           * if we didn't get it before.
-           */
-          if (!got_error)
-            {
-              block_connection_until_message_from_bus (context, connection);
-              
-              /* and process everything again */
-              bus_test_run_everything (context);
-
-              if (!check_got_error (context, connection,
-                                    DBUS_ERROR_SPAWN_CHILD_EXITED,
-                                    NULL))
-                goto out;
-            }
-        }
-      else
-        {
+      switch (message_kind) 
+       {
+       case GOT_SERVICE_CREATED:
          message = pop_message_waiting_for_memory (connection);
          if (message == NULL)
-            {
-              _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
-              goto out;
-            }
-
-         /* Check that ServiceCreated was correctly received */
-          if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME,
+           {
+             _dbus_warn ("Failed to pop message we just put back! "
+                         "should have been a ServiceOwnerChanged (creation)\n");
+             goto out;
+           }
+           
+         /* Check that ServiceOwnerChanged (creation) was correctly received */
+         if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME,
                                             base_service, message))
-            goto out;
+           goto out;
+         
+         dbus_message_unref (message);
+         message = NULL;
 
-          dbus_message_unref (message);
-          message = NULL;
-       }
+         break;
 
-      /* Note: if this test is run in OOM mode, it will block when the bus
-       * doesn't send a reply due to OOM.
-       */
-      block_connection_until_message_from_bus (context, connection);
-      
-      message = pop_message_waiting_for_memory (connection);
-      if (message == NULL)
-       {
-         _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
-         goto out;
-       }
+       case GOT_SERVICE_DELETED:
+         {
+           /* The service started up and got a base address, but then
+            * failed to register under EXISTENT_SERVICE_NAME
+            */
+           CheckServiceOwnerChangedData socd;
+          
+           socd.expected_kind = SERVICE_DELETED;
+           socd.expected_service_name = base_service;
+           socd.failed = FALSE;
+           socd.skip_connection = NULL;
+           bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                     &socd);
+
+           if (socd.failed)
+             goto out;
 
-      if (dbus_message_get_reply_serial (message) != serial)
-       {
-         _dbus_warn ("Wrong reply serial\n");
+           break;
+         }
+
+        case GOT_ERROR:
+       case GOT_SOMETHING_ELSE:
+         _dbus_warn ("Unexpected message after auto activation\n");
          goto out;
        }
+    }
 
-      dbus_message_unref (message);
-      message = NULL;
+  /* OK, now we've dealt with ServiceOwnerChanged signals, now should
+   * come the method reply (or error) from the initial method call
+   */
+
+  /* Note: if this test is run in OOM mode, it will block when the bus
+   * doesn't send a reply due to OOM.
+   */
+  block_connection_until_message_from_bus (context, connection);
       
-      if (!check_send_exit_to_service (context, connection,
-                                      EXISTENT_SERVICE_NAME,
-                                      base_service))
-       goto out;
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
+      goto out;
+    }
+
+  if (dbus_message_get_reply_serial (message) != serial)
+    {
+      _dbus_warn ("Wrong reply serial\n");
+      goto out;
     }
+
+  dbus_message_unref (message);
+  message = NULL;
+      
+  if (!check_send_exit_to_service (context, connection,
+                                  EXISTENT_SERVICE_NAME,
+                                  base_service))
+    goto out;
   
   retval = TRUE;
 
index 39d8b12..b426912 100644 (file)
@@ -39,20 +39,25 @@ static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
                                                     DBusError      *error);
 
 dbus_bool_t
-bus_driver_send_service_deleted (const char     *service_name,
-                                 BusTransaction *transaction,
-                                 DBusError      *error)
+bus_driver_send_service_owner_changed (const char     *service_name,
+                                      const char     *old_owner,
+                                      const char     *new_owner,
+                                      BusTransaction *transaction,
+                                      DBusError      *error)
 {
   DBusMessage *message;
   dbus_bool_t retval;
+  const char null_service[] = { '\000' };
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  _dbus_verbose ("sending service deleted: %s\n", service_name);
+  _dbus_verbose ("sending service owner changed: %s [%s -> %s]", service_name, 
+                 old_owner ? old_owner : null_service, 
+                 new_owner ? new_owner : null_service);
 
   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                     "ServiceDeleted");
+                                     "ServiceOwnerChanged");
   
   if (message == NULL)
     {
@@ -60,62 +65,25 @@ bus_driver_send_service_deleted (const char     *service_name,
       return FALSE;
     }
   
-  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) ||
-      !dbus_message_append_args (message,
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
+    goto oom;
+
+  if (!dbus_message_append_args (message,
                                  DBUS_TYPE_STRING, service_name,
+                                 DBUS_TYPE_STRING, old_owner ? old_owner : null_service,
+                                 DBUS_TYPE_STRING, new_owner ? new_owner : null_service,
                                  DBUS_TYPE_INVALID))
-    {
-      dbus_message_unref (message);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
+    goto oom;
 
   retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
   dbus_message_unref (message);
 
   return retval;
-}
 
-dbus_bool_t
-bus_driver_send_service_created (const char     *service_name,
-                                 BusTransaction *transaction,
-                                 DBusError      *error)
-{
-  DBusMessage *message;
-  dbus_bool_t retval;
-
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
-  message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
-                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                     "ServiceCreated");
-  
-  if (message == NULL)
-    {
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-  
-  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
-    {
-      dbus_message_unref (message);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-  
-  if (!dbus_message_append_args (message,
-                                 DBUS_TYPE_STRING, service_name,
-                                 DBUS_TYPE_INVALID))
-    {
-      dbus_message_unref (message);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-  
-  retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
+ oom:
   dbus_message_unref (message);
-
-  return retval;
+  BUS_SET_OOM (error);
+  return FALSE;
 }
 
 dbus_bool_t
index f971838..bc43052 100644 (file)
@@ -32,9 +32,6 @@ dbus_bool_t bus_driver_handle_message        (DBusConnection *connection,
                                               BusTransaction *transaction,
                                               DBusMessage    *message,
                                               DBusError      *error);
-dbus_bool_t bus_driver_send_service_deleted  (const char     *service_name,
-                                              BusTransaction *transaction,
-                                              DBusError      *error);
 dbus_bool_t bus_driver_send_service_lost     (DBusConnection *connection,
                                               const char     *service_name,
                                               BusTransaction *transaction,
@@ -43,8 +40,10 @@ dbus_bool_t bus_driver_send_service_acquired (DBusConnection *connection,
                                               const char     *service_name,
                                               BusTransaction *transaction,
                                               DBusError      *error);
-dbus_bool_t bus_driver_send_service_created  (const char     *service_name,
-                                              BusTransaction *transaction,
-                                              DBusError      *error);
+dbus_bool_t bus_driver_send_service_owner_changed  (const char     *service_name,
+                                                   const char     *old_owner,
+                                                   const char     *new_owner,
+                                                   BusTransaction *transaction,
+                                                   DBusError      *error);
 
 #endif /* BUS_DRIVER_H */
index f5ef4cc..0ba3225 100644 (file)
@@ -164,7 +164,10 @@ bus_registry_ensure (BusRegistry               *registry,
       return NULL;
     }
 
-  if (!bus_driver_send_service_created (service->name, transaction, error))
+  if (!bus_driver_send_service_owner_changed (service->name, 
+                                             NULL,
+                                             bus_connection_get_name (owner_if_created),
+                                             transaction, error))
     {
       bus_service_unref (service);
       return NULL;
@@ -726,20 +729,31 @@ bus_service_remove_owner (BusService     *service,
     }
   else if (_dbus_list_length_is_one (&service->owners))
     {
-      if (!bus_driver_send_service_deleted (service->name,
-                                            transaction, error))
+      if (!bus_driver_send_service_owner_changed (service->name,
+                                                 bus_connection_get_name (owner),
+                                                 NULL,
+                                                 transaction, error))
         return FALSE;
     }
   else
     {
       DBusList *link;
+      DBusConnection *new_owner;
       link = _dbus_list_get_first_link (&service->owners);
       _dbus_assert (link != NULL);
       link = _dbus_list_get_next_link (&service->owners, link);
       _dbus_assert (link != NULL);
 
+      new_owner = link->data;
+
+      if (!bus_driver_send_service_owner_changed (service->name,
+                                                 bus_connection_get_name (owner),
+                                                 bus_connection_get_name (new_owner),
+                                                 transaction, error))
+        return FALSE;
+
       /* This will be our new owner */
-      if (!bus_driver_send_service_acquired (link->data,
+      if (!bus_driver_send_service_acquired (new_owner,
                                              service->name,
                                              transaction,
                                              error))
index f0d1727..4793278 100644 (file)
         <para>
           This message is sent to a specific application when it loses primary
           ownership of a service.
-
-          [FIXME instead of ServiceLost/ServiceCreated going only to 
-          a specific app, why not just OwnerChanged that covers both 
-          lost and created and changed owner and deleted]
         </para>
       </sect3>
 
-      <sect3 id="bus-messages-service-created">
-        <title><literal>org.freedesktop.DBus.ServiceCreated</literal></title>
+      <sect3 id="bus-messages-service-owner-changed">
+        <title><literal>org.freedesktop.DBus.ServiceOwnerChanged</literal></title>
         <para>
-          As a method:
           <programlisting>
-            ServiceCreated (in STRING service_name)
+            ServiceOwnerChanged (STRING service_name, STRING old_owner, STRING new_owner)
           </programlisting>
           Message arguments:
           <informaltable>
                 </row>
                <row>
                  <entry>1</entry>
-                 <entry>UINT32</entry>
-                 <entry>Flags</entry>
+                 <entry>STRING</entry>
+                 <entry>Base service of previous owner, empty string if the
+                 service is newly created</entry>
                </row>
-              </tbody>
-            </tgroup>
-          </informaltable>
-        </para>
-        <para>
-          This message is broadcast to all applications when a service has been
-          successfully registered on the message bus.
-        </para>
-      </sect3>
-
-      <sect3 id="bus-messages-service-deleted">
-        <title><literal>org.freedesktop.DBus.ServiceDeleted</literal></title>
-        <para>
-          As a method:
-          <programlisting>
-            ServiceDeleted (in STRING service_name)
-          </programlisting>
-          Message arguments:
-          <informaltable>
-            <tgroup cols="3">
-              <thead>
-                <row>
-                  <entry>Argument</entry>
-                  <entry>Type</entry>
-                  <entry>Description</entry>
-                </row>
-              </thead>
-              <tbody>
-                <row>
-                  <entry>0</entry>
-                  <entry>STRING</entry>
-                  <entry>Name of the service</entry>
-                </row>
                <row>
-                 <entry>1</entry>
-                 <entry>UINT32</entry>
-                 <entry>Flags</entry>
+                 <entry>2</entry>
+                 <entry>STRING</entry>
+                 <entry>Base service of new owner, empty string if the
+                 service is no longer available</entry>
                </row>
               </tbody>
             </tgroup>
         </para>
         <para>
           This message is broadcast to all applications when a service has been
-          deleted from the message bus.
+          successfully registered on the message bus, has been deleted
+          or its primary owner has changed.
         </para>
       </sect3>