LCOV - code coverage report
Current view: top level - src/plugins/bluez - valent-bluez-profile.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 77.7 % 166 129
Test Date: 2025-11-09 04:19:42 Functions: 81.0 % 21 17
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 41.2 % 102 42

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: GPL-3.0-or-later
       2                 :             : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
       3                 :             : 
       4                 :             : #define G_LOG_DOMAIN "valent-bluez-profile"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <fcntl.h>
       9                 :             : 
      10                 :             : #include <gio/gio.h>
      11                 :             : #include <gio/gunixfdlist.h>
      12                 :             : 
      13                 :             : #include "valent-bluez-profile.h"
      14                 :             : 
      15                 :             : 
      16                 :             : struct _ValentBluezProfile
      17                 :             : {
      18                 :             :   GDBusInterfaceSkeleton  parent_instance;
      19                 :             : 
      20                 :             :   GDBusInterfaceVTable    vtable;
      21                 :             :   GDBusNodeInfo          *node_info;
      22                 :             :   GDBusInterfaceInfo     *iface_info;
      23                 :             :   unsigned int            in_registration : 1;
      24                 :             :   unsigned int            registered : 1;
      25                 :             : };
      26                 :             : 
      27   [ +  +  +  - ]:          17 : G_DEFINE_FINAL_TYPE (ValentBluezProfile, valent_bluez_profile, G_TYPE_DBUS_INTERFACE_SKELETON)
      28                 :             : 
      29                 :             : enum {
      30                 :             :   CONNECTION_OPENED,
      31                 :             :   CONNECTION_CLOSED,
      32                 :             :   N_SIGNALS
      33                 :             : };
      34                 :             : 
      35                 :             : static guint signals[N_SIGNALS] = { 0, };
      36                 :             : 
      37                 :             : 
      38                 :             : /*
      39                 :             :  * org.bluez.Profile1
      40                 :             :  */
      41                 :             : static const char interface_xml[] =
      42                 :             :   "<node>"
      43                 :             :   "  <interface name='org.bluez.Profile1'>"
      44                 :             :   "    <method name='Release'/>"
      45                 :             :   "    <method name='NewConnection'>"
      46                 :             :   "     <arg name='device' type='o' direction='in'/>"
      47                 :             :   "     <arg name='fd' type='h' direction='in'/>"
      48                 :             :   "     <arg name='fd_properties' type='a{sv}' direction='in'/>"
      49                 :             :   "   </method>"
      50                 :             :   "   <method name='RequestDisconnection'>"
      51                 :             :   "     <arg name='object_path' type='o' direction='in'/>"
      52                 :             :   "   </method>"
      53                 :             :   "  </interface>"
      54                 :             :   "</node>";
      55                 :             : 
      56                 :             : 
      57                 :             : /**
      58                 :             :  * valent_bluez_profile_new_connection:
      59                 :             :  * @profile: a `ValentBluezProfile`
      60                 :             :  * @object_path: a DBus object path
      61                 :             :  * @fd: a UNIX file descriptor
      62                 :             :  * @fd_properties: a `GVariant`
      63                 :             :  *
      64                 :             :  * This method gets called when a new service level connection has been made and
      65                 :             :  * authorized.
      66                 :             :  */
      67                 :             : static void
      68                 :           2 : valent_bluez_profile_new_connection (ValentBluezProfile *profile,
      69                 :             :                                      const char         *object_path,
      70                 :             :                                      int                 fd,
      71                 :             :                                      GVariant           *fd_properties)
      72                 :             : {
      73                 :           2 :   g_autoptr (GSocket) socket = NULL;
      74                 :           2 :   g_autoptr (GSocketConnection) connection = NULL;
      75         [ +  - ]:           2 :   g_autoptr (GError) error = NULL;
      76                 :             : 
      77         [ -  + ]:           2 :   g_assert (VALENT_IS_BLUEZ_PROFILE (profile));
      78         [ +  - ]:           2 :   g_assert (g_variant_is_object_path (object_path));
      79                 :             : 
      80                 :           2 :   socket = g_socket_new_from_fd (fd, &error);
      81         [ -  + ]:           2 :   if (socket == NULL)
      82                 :             :     {
      83                 :           0 :       g_warning ("Failed to create socket: %s", error->message);
      84         [ #  # ]:           0 :       return;
      85                 :             :     }
      86                 :             : 
      87                 :           2 :   connection = g_object_new (G_TYPE_SOCKET_CONNECTION,
      88                 :             :                              "socket", socket,
      89                 :             :                              NULL);
      90                 :             : 
      91         [ -  + ]:           2 :   g_signal_emit (G_OBJECT (profile),
      92                 :             :                  signals [CONNECTION_OPENED], 0,
      93                 :             :                  connection,
      94                 :             :                  object_path);
      95                 :             : }
      96                 :             : 
      97                 :             : /**
      98                 :             :  * valent_bluez_profile_request_disconnection:
      99                 :             :  * @profile: a `ValentBluezProfile`
     100                 :             :  * @object_path: a DBus object path
     101                 :             :  *
     102                 :             :  * This method gets called when a profile gets disconnected.
     103                 :             :  *
     104                 :             :  * The file descriptor is no longer owned by the service daemon and the profile
     105                 :             :  * implementation needs to take care of cleaning up all connections.
     106                 :             :  *
     107                 :             :  * If multiple file descriptors are indicated via
     108                 :             :  * valent_bluez_profile_new_connection(), it is expected that all of them are
     109                 :             :  * disconnected before returning from this method call.
     110                 :             :  */
     111                 :             : static void
     112                 :           0 : valent_bluez_profile_request_disconnection (ValentBluezProfile *profile,
     113                 :             :                                             const char         *object_path)
     114                 :             : {
     115         [ #  # ]:           0 :   g_assert (VALENT_IS_BLUEZ_PROFILE (profile));
     116         [ #  # ]:           0 :   g_assert (g_variant_is_object_path (object_path));
     117                 :             : 
     118                 :           0 :   g_signal_emit (G_OBJECT (profile),
     119                 :             :                  signals [CONNECTION_CLOSED], 0,
     120                 :             :                  object_path);
     121                 :           0 : }
     122                 :             : 
     123                 :             : /**
     124                 :             :  * valent_bluez_profile_release:
     125                 :             :  * @profile: a `ValentBluezProfile`
     126                 :             :  *
     127                 :             :  * This method gets called when the service daemon unregisters the profile.
     128                 :             :  * A profile can use it to do cleanup tasks. There is no need to unregister
     129                 :             :  * the profile, because when this method gets called it has already been
     130                 :             :  * unregistered.
     131                 :             :  */
     132                 :             : static void
     133                 :           0 : valent_bluez_profile_release (ValentBluezProfile *profile)
     134                 :             : {
     135                 :           0 :   GDBusInterfaceSkeleton *iface = G_DBUS_INTERFACE_SKELETON (profile);
     136                 :             : 
     137         [ #  # ]:           0 :   g_assert (VALENT_IS_BLUEZ_PROFILE (profile));
     138                 :             : 
     139         [ #  # ]:           0 :   if (g_dbus_interface_skeleton_get_object_path (iface) != NULL)
     140                 :           0 :     g_dbus_interface_skeleton_unexport (iface);
     141                 :             : 
     142                 :           0 :   profile->registered = FALSE;
     143                 :           0 : }
     144                 :             : 
     145                 :             : 
     146                 :             : /*
     147                 :             :  * GDBusInterfaceSkeleton
     148                 :             :  */
     149                 :             : static GDBusInterfaceInfo *
     150                 :           2 : valent_bluez_profile_get_info (GDBusInterfaceSkeleton *skeleton)
     151                 :             : {
     152                 :           2 :   ValentBluezProfile *self = VALENT_BLUEZ_PROFILE (skeleton);
     153                 :             : 
     154                 :           2 :   return self->iface_info;
     155                 :             : }
     156                 :             : 
     157                 :             : static GDBusInterfaceVTable *
     158                 :           4 : valent_bluez_profile_get_vtable (GDBusInterfaceSkeleton *skeleton)
     159                 :             : {
     160                 :           4 :   ValentBluezProfile *self = VALENT_BLUEZ_PROFILE (skeleton);
     161                 :             : 
     162                 :           4 :   return &(self->vtable);
     163                 :             : }
     164                 :             : 
     165                 :             : static void
     166                 :           2 : valent_bluez_profile_method_call (GDBusConnection       *connection,
     167                 :             :                                   const char            *sender,
     168                 :             :                                   const char            *object_path,
     169                 :             :                                   const char            *interface_name,
     170                 :             :                                   const char            *method_name,
     171                 :             :                                   GVariant              *parameters,
     172                 :             :                                   GDBusMethodInvocation *invocation,
     173                 :             :                                   gpointer               user_data)
     174                 :             : {
     175                 :           2 :   ValentBluezProfile *profile = VALENT_BLUEZ_PROFILE (user_data);
     176                 :             : 
     177         [ -  + ]:           2 :   g_assert (VALENT_IS_BLUEZ_PROFILE (profile));
     178                 :             : 
     179         [ +  - ]:           2 :   if (g_strcmp0 (method_name, "NewConnection") == 0)
     180                 :             :     {
     181                 :           2 :       const char *device;
     182                 :           2 :       int32_t fd_idx;
     183                 :           2 :       GDBusMessage *message;
     184                 :           2 :       GUnixFDList *fd_list;
     185                 :           2 :       int fd;
     186                 :           2 :       int fd_flags;
     187                 :           2 :       g_autoptr (GVariant) fd_props = NULL;
     188                 :             : 
     189         [ +  - ]:           2 :       g_assert (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(oha{sv})")));
     190                 :             : 
     191                 :           2 :       message = g_dbus_method_invocation_get_message (invocation);
     192                 :           2 :       fd_list = g_dbus_message_get_unix_fd_list (message);
     193                 :             : 
     194                 :           2 :       g_variant_get (parameters, "(&oh@a{sv})", &device, &fd_idx, &fd_props);
     195                 :           2 :       fd = g_unix_fd_list_get (fd_list, fd_idx, NULL);
     196                 :           2 :       fd_flags = fcntl (fd, F_GETFD);
     197                 :           2 :       fcntl (fd, F_SETFD, fd_flags &~ FD_CLOEXEC);
     198                 :             : 
     199         [ +  - ]:           2 :       valent_bluez_profile_new_connection (profile, device, fd, fd_props);
     200                 :             :     }
     201         [ #  # ]:           0 :   else if (g_strcmp0 (method_name, "RequestDisconnection") == 0)
     202                 :             :     {
     203                 :           0 :       const char *device;
     204                 :             : 
     205         [ #  # ]:           0 :       g_assert (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)")));
     206                 :             : 
     207                 :           0 :       g_variant_get (parameters, "(&o)", &device);
     208                 :           0 :       valent_bluez_profile_request_disconnection (profile, device);
     209                 :             :     }
     210         [ #  # ]:           0 :   else if (g_strcmp0 (method_name, "Release") == 0)
     211                 :             :     {
     212         [ #  # ]:           0 :       g_assert (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("()")));
     213                 :             : 
     214                 :           0 :       valent_bluez_profile_release (profile);
     215                 :             :     }
     216                 :             :   else
     217                 :           0 :     g_assert_not_reached();
     218                 :             : 
     219                 :           2 :   g_dbus_method_invocation_return_value (invocation, NULL);
     220                 :           2 : }
     221                 :             : 
     222                 :             : static GVariant *
     223                 :           0 : valent_bluez_profile_get_properties (GDBusInterfaceSkeleton *skeleton) {
     224                 :           0 :   return NULL;
     225                 :             : }
     226                 :             : 
     227                 :             : static void
     228                 :           0 : valent_bluez_profile_flush (GDBusInterfaceSkeleton *skeleton) {
     229                 :           0 :   return;
     230                 :             : }
     231                 :             : 
     232                 :             : /*
     233                 :             :  * GObject
     234                 :             :  */
     235                 :             : static void
     236                 :           1 : valent_bluez_profile_dispose (GObject *object)
     237                 :             : {
     238                 :           1 :   ValentBluezProfile *self = VALENT_BLUEZ_PROFILE (object);
     239                 :             : 
     240                 :           1 :   valent_bluez_profile_unregister (self);
     241                 :             : 
     242                 :           1 :   G_OBJECT_CLASS (valent_bluez_profile_parent_class)->dispose (object);
     243                 :           1 : }
     244                 :             : 
     245                 :             : static void
     246                 :           1 : valent_bluez_profile_finalize (GObject *object)
     247                 :             : {
     248                 :           1 :   ValentBluezProfile *self = VALENT_BLUEZ_PROFILE (object);
     249                 :             : 
     250         [ +  - ]:           1 :   g_clear_pointer (&self->node_info, g_dbus_node_info_unref);
     251                 :             : 
     252                 :           1 :   G_OBJECT_CLASS (valent_bluez_profile_parent_class)->finalize (object);
     253                 :           1 : }
     254                 :             : 
     255                 :             : static void
     256                 :           1 : valent_bluez_profile_class_init (ValentBluezProfileClass *klass) {
     257                 :           1 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     258                 :           1 :   GDBusInterfaceSkeletonClass *skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
     259                 :             : 
     260                 :           1 :   object_class->dispose = valent_bluez_profile_dispose;
     261                 :           1 :   object_class->finalize = valent_bluez_profile_finalize;
     262                 :             : 
     263                 :           1 :   skeleton_class->get_info = valent_bluez_profile_get_info;
     264                 :           1 :   skeleton_class->get_vtable = valent_bluez_profile_get_vtable;
     265                 :           1 :   skeleton_class->get_properties = valent_bluez_profile_get_properties;
     266                 :           1 :   skeleton_class->flush = valent_bluez_profile_flush;
     267                 :             : 
     268                 :             :   /**
     269                 :             :    * ValentBluezProfile::connection-opened:
     270                 :             :    * @profile: a `ValentBluezProfile`
     271                 :             :    * @connection: a `GSocketConnection`
     272                 :             :    * @device: DBus object path of the device
     273                 :             :    *
     274                 :             :    * The `ValentBluezProfile`::connection-opened signal is emitted when a Bluez
     275                 :             :    * socket for @device has been successfully wrapped in a `GSocketConnection`
     276                 :             :    * and is ready for protocol negotiation.
     277                 :             :    */
     278                 :           2 :   signals [CONNECTION_OPENED] =
     279                 :           1 :     g_signal_new ("connection-opened",
     280                 :             :                   G_TYPE_FROM_CLASS (klass),
     281                 :             :                   G_SIGNAL_RUN_LAST,
     282                 :             :                   0,
     283                 :             :                   NULL, NULL, NULL,
     284                 :             :                   G_TYPE_NONE, 2, G_TYPE_SOCKET_CONNECTION, G_TYPE_STRING);
     285                 :             : 
     286                 :             :   /**
     287                 :             :    * ValentBluezProfile::connection-closed:
     288                 :             :    * @profile: a `ValentBluezProfile`
     289                 :             :    * @device: DBus object path of the device
     290                 :             :    *
     291                 :             :    * The `ValentBluezProfile`::connection-closed signal is emitted when a Bluez
     292                 :             :    * socket for @device has been closed and should be cleaned up.
     293                 :             :    */
     294                 :           2 :   signals [CONNECTION_CLOSED] =
     295                 :           1 :     g_signal_new ("connection-closed",
     296                 :             :                   G_TYPE_FROM_CLASS (klass),
     297                 :             :                   G_SIGNAL_RUN_LAST,
     298                 :             :                   0,
     299                 :             :                   NULL, NULL,
     300                 :             :                   g_cclosure_marshal_VOID__STRING,
     301                 :             :                   G_TYPE_NONE, 1, G_TYPE_STRING);
     302                 :           1 :   g_signal_set_va_marshaller (signals [CONNECTION_CLOSED],
     303                 :             :                               G_TYPE_FROM_CLASS (klass),
     304                 :             :                               g_cclosure_marshal_VOID__STRINGv);
     305                 :           1 : }
     306                 :             : 
     307                 :             : static void
     308                 :           2 : valent_bluez_profile_init (ValentBluezProfile *self)
     309                 :             : {
     310                 :           2 :   self->node_info = g_dbus_node_info_new_for_xml (interface_xml, NULL);
     311                 :           2 :   self->iface_info = g_dbus_node_info_lookup_interface (self->node_info,
     312                 :             :                                                         "org.bluez.Profile1");
     313                 :             : 
     314                 :           2 :   self->vtable.method_call = valent_bluez_profile_method_call;
     315                 :           2 :   self->vtable.get_property = NULL;
     316                 :           2 :   self->vtable.set_property = NULL;
     317                 :           2 : }
     318                 :             : 
     319                 :             : /**
     320                 :             :  * valent_bluez_profile_new:
     321                 :             :  *
     322                 :             :  * Create a service profile for client or server connections.
     323                 :             :  *
     324                 :             :  * Returns: (transfer full): a new `ValentBluezProfile`
     325                 :             :  */
     326                 :             : ValentBluezProfile *
     327                 :           2 : valent_bluez_profile_new (void)
     328                 :             : {
     329                 :           2 :   return g_object_new (VALENT_TYPE_BLUEZ_PROFILE, NULL);
     330                 :             : }
     331                 :             : 
     332                 :             : static void
     333                 :           2 : profile_manager_register_profile_cb (GDBusConnection *connection,
     334                 :             :                                      GAsyncResult    *result,
     335                 :             :                                      gpointer         user_data)
     336                 :             : {
     337                 :           2 :   g_autoptr (GTask) task = G_TASK (g_steal_pointer (&user_data));
     338                 :           2 :   ValentBluezProfile *self = g_task_get_source_object (task);
     339                 :           2 :   GDBusInterfaceSkeleton *iface = G_DBUS_INTERFACE_SKELETON (self);
     340         [ +  - ]:           2 :   g_autoptr (GVariant) reply = NULL;
     341                 :           2 :   GError *error = NULL;
     342                 :             : 
     343                 :           2 :   reply = g_dbus_connection_call_finish (connection, result, &error);
     344         [ -  + ]:           2 :   if (reply == NULL)
     345                 :             :     {
     346         [ #  # ]:           0 :       if (g_dbus_interface_skeleton_get_object_path (iface) != NULL)
     347                 :           0 :         g_dbus_interface_skeleton_unexport (iface);
     348                 :             : 
     349                 :           0 :       g_dbus_error_strip_remote_error (error);
     350                 :           0 :       g_task_return_error (task, g_steal_pointer (&error));
     351                 :             :     }
     352                 :             :   else
     353                 :             :     {
     354                 :           2 :       self->registered = TRUE;
     355                 :           2 :       g_task_return_boolean (task, TRUE);
     356                 :             :     }
     357                 :             : 
     358         [ +  - ]:           2 :   self->in_registration = FALSE;
     359                 :           2 : }
     360                 :             : 
     361                 :             : /**
     362                 :             :  * valent_bluez_profile_register:
     363                 :             :  * @profile: a `ValentBluezProfile`
     364                 :             :  * @connection: a `GDBusConnection`
     365                 :             :  * @cancellable: (nullable): a `GCancellable`
     366                 :             :  * @callback: (scope async): a `GAsyncReadyCallback`
     367                 :             :  * @user_data: user supplied data
     368                 :             :  *
     369                 :             :  * Export the bluez profile for Valent on @connection and register it with the
     370                 :             :  * profile manager (`org.bluez.ProfileManager1`).
     371                 :             :  */
     372                 :             : void
     373                 :           2 : valent_bluez_profile_register (ValentBluezProfile  *profile,
     374                 :             :                                GDBusConnection     *connection,
     375                 :             :                                GCancellable        *cancellable,
     376                 :             :                                GAsyncReadyCallback  callback,
     377                 :             :                                gpointer             user_data)
     378                 :             : {
     379                 :           2 :   GDBusInterfaceSkeleton *iface = G_DBUS_INTERFACE_SKELETON (profile);
     380                 :           2 :   g_autoptr (GTask) task = NULL;
     381                 :           2 :   GVariantDict dict;
     382                 :           2 :   GError *error = NULL;
     383                 :             : 
     384         [ -  + ]:           2 :   g_return_if_fail (VALENT_IS_BLUEZ_PROFILE (profile));
     385   [ +  -  +  -  :           2 :   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
             -  +  -  - ]
     386   [ +  -  +  -  :           2 :   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
             -  +  -  - ]
     387                 :             : 
     388                 :           2 :   task = g_task_new (profile, cancellable, callback, user_data);
     389         [ +  - ]:           2 :   g_task_set_source_tag (task, valent_bluez_profile_register);
     390                 :             : 
     391   [ +  -  -  + ]:           2 :   if (profile->registered || profile->in_registration)
     392                 :             :     {
     393                 :           0 :       g_task_return_boolean (task, TRUE);
     394                 :           0 :       return;
     395                 :             :     }
     396                 :             : 
     397         [ -  + ]:           2 :   if (!g_dbus_interface_skeleton_export (iface,
     398                 :             :                                          connection,
     399                 :             :                                          VALENT_BLUEZ_PROFILE_PATH,
     400                 :             :                                          &error))
     401                 :             :     {
     402                 :           0 :       g_task_return_error (task, g_steal_pointer (&error));
     403                 :           0 :       return;
     404                 :             :     }
     405                 :             : 
     406                 :           2 :   g_variant_dict_init (&dict, NULL);
     407                 :           2 :   g_variant_dict_insert (&dict, "RequireAuthentication", "b", TRUE);
     408                 :           2 :   g_variant_dict_insert (&dict, "RequireAuthorization", "b", FALSE);
     409                 :           2 :   g_variant_dict_insert (&dict, "Service", "s", VALENT_BLUEZ_PROFILE_UUID);
     410                 :           2 :   g_variant_dict_insert (&dict, "Channel", "q", 0x06);
     411                 :             : 
     412                 :           2 :   profile->in_registration = TRUE;
     413         [ +  - ]:           2 :   g_dbus_connection_call (connection,
     414                 :             :                           "org.bluez",
     415                 :             :                           "/org/bluez",
     416                 :             :                           "org.bluez.ProfileManager1",
     417                 :             :                           "RegisterProfile",
     418                 :             :                           g_variant_new ("(os@a{sv})",
     419                 :             :                                          VALENT_BLUEZ_PROFILE_PATH,
     420                 :             :                                          VALENT_BLUEZ_PROFILE_UUID,
     421                 :             :                                          g_variant_dict_end (&dict)),
     422                 :             :                           NULL,
     423                 :             :                           G_DBUS_CALL_FLAGS_NO_AUTO_START,
     424                 :             :                           -1,
     425                 :             :                           cancellable,
     426                 :             :                           (GAsyncReadyCallback)profile_manager_register_profile_cb,
     427                 :             :                           g_object_ref (task));
     428                 :             : }
     429                 :             : 
     430                 :             : /**
     431                 :             :  * valent_bluez_profile_register_finish:
     432                 :             :  * @profile: a `ValentBluezProfile`
     433                 :             :  * @result: a `GAsyncResult`
     434                 :             :  * @error: (nullable): a `GError`
     435                 :             :  *
     436                 :             :  * Finish an operation started with valent_bluez_profile_register().
     437                 :             :  *
     438                 :             :  * Returns: %TRUE if successful, or %FALSE with @error set
     439                 :             :  */
     440                 :             : gboolean
     441                 :           2 : valent_bluez_profile_register_finish (ValentBluezProfile  *profile,
     442                 :             :                                       GAsyncResult        *result,
     443                 :             :                                       GError             **error)
     444                 :             : {
     445         [ -  + ]:           2 :   g_return_val_if_fail (VALENT_IS_BLUEZ_PROFILE (profile), FALSE);
     446         [ +  - ]:           2 :   g_return_val_if_fail (g_task_is_valid (result, profile), FALSE);
     447   [ +  -  +  - ]:           2 :   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
     448                 :             : 
     449                 :           2 :   return g_task_propagate_boolean (G_TASK (result), error);
     450                 :             : }
     451                 :             : 
     452                 :             : static void
     453                 :           1 : profile_manager_unregister_profile_cb (GDBusConnection *connection,
     454                 :             :                                        GAsyncResult    *result,
     455                 :             :                                        gpointer         user_data)
     456                 :             : {
     457                 :           1 :   g_autoptr (ValentBluezProfile) self = g_steal_pointer (&user_data);
     458                 :           1 :   GDBusInterfaceSkeleton *iface = G_DBUS_INTERFACE_SKELETON (self);
     459                 :           1 :   g_autoptr (GVariant) reply = NULL;
     460         [ +  - ]:           1 :   g_autoptr (GError) error = NULL;
     461                 :             : 
     462                 :           1 :   reply = g_dbus_connection_call_finish (connection, result, &error);
     463         [ -  + ]:           1 :   if (reply == NULL)
     464                 :             :     {
     465                 :           0 :       g_dbus_error_strip_remote_error (error);
     466                 :           0 :       g_debug ("%s(): %s", G_STRFUNC, error->message);
     467                 :             :     }
     468                 :             : 
     469         [ +  - ]:           1 :   if (g_dbus_interface_skeleton_get_object_path (iface) != NULL)
     470                 :           1 :     g_dbus_interface_skeleton_unexport (iface);
     471                 :             : 
     472                 :           1 :   self->registered = FALSE;
     473         [ -  + ]:           1 :   self->in_registration = FALSE;
     474                 :           1 : }
     475                 :             : 
     476                 :             : /**
     477                 :             :  * valent_bluez_profile_unregister:
     478                 :             :  * @profile: a `ValentBluezProfile`
     479                 :             :  *
     480                 :             :  * Unexport the bluez profile for Valent from the system bus.
     481                 :             :  */
     482                 :             : void
     483                 :           5 : valent_bluez_profile_unregister (ValentBluezProfile *profile)
     484                 :             : {
     485                 :           5 :   GDBusInterfaceSkeleton *iface = G_DBUS_INTERFACE_SKELETON (profile);
     486                 :           5 :   const char *object_path = NULL;
     487                 :             : 
     488         [ -  + ]:           5 :   g_return_if_fail (VALENT_IS_BLUEZ_PROFILE (profile));
     489                 :             : 
     490   [ +  +  +  + ]:           5 :   if (profile->registered && !profile->in_registration)
     491                 :             :     {
     492                 :           2 :       object_path = g_dbus_interface_skeleton_get_object_path (iface);
     493         [ +  - ]:           2 :       g_return_if_fail (g_variant_is_object_path (object_path));
     494                 :             : 
     495                 :           2 :       profile->in_registration = TRUE;
     496                 :           2 :       g_dbus_connection_call (g_dbus_interface_skeleton_get_connection (iface),
     497                 :             :                               "org.bluez",
     498                 :             :                               "/org/bluez",
     499                 :             :                               "org.bluez.ProfileManager1",
     500                 :             :                               "UnregisterProfile",
     501                 :             :                               g_variant_new ("(o)", object_path),
     502                 :             :                               NULL,
     503                 :             :                               G_DBUS_CALL_FLAGS_NO_AUTO_START,
     504                 :             :                               -1,
     505                 :             :                               NULL,
     506                 :             :                               (GAsyncReadyCallback)profile_manager_unregister_profile_cb,
     507                 :             :                               g_object_ref (profile));
     508                 :             :     }
     509                 :             : }
     510                 :             : 
        

Generated by: LCOV version 2.0-1