(root)/
glib-2.79.0/
gio/
gdbusobjectproxy.c
       1  /* GDBus - GLib D-Bus Library
       2   *
       3   * Copyright (C) 2008-2010 Red Hat, Inc.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   *
       7   * This library is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This library is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General
      18   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19   *
      20   * Author: David Zeuthen <davidz@redhat.com>
      21   */
      22  
      23  #include "config.h"
      24  
      25  #include "gdbusobject.h"
      26  #include "gdbusobjectproxy.h"
      27  #include "gdbusconnection.h"
      28  #include "gdbusprivate.h"
      29  #include "gdbusutils.h"
      30  #include "gdbusproxy.h"
      31  
      32  #include "glibintl.h"
      33  
      34  /**
      35   * GDBusObjectProxy:
      36   *
      37   * A `GDBusObjectProxy` is an object used to represent a remote object
      38   * with one or more D-Bus interfaces. Normally, you don’t instantiate
      39   * a `GDBusObjectProxy` yourself — typically [class@Gio.DBusObjectManagerClient]
      40   * is used to obtain it.
      41   *
      42   * Since: 2.30
      43   */
      44  
      45  struct _GDBusObjectProxyPrivate
      46  {
      47    GMutex lock;
      48    GHashTable *map_name_to_iface;
      49    gchar *object_path;
      50    GDBusConnection *connection;
      51  };
      52  
      53  enum
      54  {
      55    PROP_0,
      56    PROP_G_OBJECT_PATH,
      57    PROP_G_CONNECTION
      58  };
      59  
      60  static void dbus_object_interface_init (GDBusObjectIface *iface);
      61  
      62  G_DEFINE_TYPE_WITH_CODE (GDBusObjectProxy, g_dbus_object_proxy, G_TYPE_OBJECT,
      63                           G_ADD_PRIVATE (GDBusObjectProxy)
      64                           G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, dbus_object_interface_init))
      65  
      66  static void
      67  g_dbus_object_proxy_finalize (GObject *object)
      68  {
      69    GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
      70  
      71    g_hash_table_unref (proxy->priv->map_name_to_iface);
      72  
      73    g_clear_object (&proxy->priv->connection);
      74  
      75    g_free (proxy->priv->object_path);
      76  
      77    g_mutex_clear (&proxy->priv->lock);
      78  
      79    if (G_OBJECT_CLASS (g_dbus_object_proxy_parent_class)->finalize != NULL)
      80      G_OBJECT_CLASS (g_dbus_object_proxy_parent_class)->finalize (object);
      81  }
      82  
      83  static void
      84  g_dbus_object_proxy_get_property (GObject    *object,
      85                                    guint       prop_id,
      86                                    GValue     *value,
      87                                    GParamSpec *pspec)
      88  {
      89    GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
      90  
      91    switch (prop_id)
      92      {
      93      case PROP_G_OBJECT_PATH:
      94        g_mutex_lock (&proxy->priv->lock);
      95        g_value_set_string (value, proxy->priv->object_path);
      96        g_mutex_unlock (&proxy->priv->lock);
      97        break;
      98  
      99      case PROP_G_CONNECTION:
     100        g_value_set_object (value, g_dbus_object_proxy_get_connection (proxy));
     101        break;
     102  
     103      default:
     104        G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec);
     105        break;
     106      }
     107  }
     108  
     109  static void
     110  g_dbus_object_proxy_set_property (GObject       *object,
     111                                    guint          prop_id,
     112                                    const GValue  *value,
     113                                    GParamSpec    *pspec)
     114  {
     115    GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
     116  
     117    switch (prop_id)
     118      {
     119      case PROP_G_OBJECT_PATH:
     120        g_mutex_lock (&proxy->priv->lock);
     121        proxy->priv->object_path = g_value_dup_string (value);
     122        g_mutex_unlock (&proxy->priv->lock);
     123        break;
     124  
     125      case PROP_G_CONNECTION:
     126        g_mutex_lock (&proxy->priv->lock);
     127        proxy->priv->connection = g_value_dup_object (value);
     128        g_mutex_unlock (&proxy->priv->lock);
     129        break;
     130  
     131      default:
     132        G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec);
     133        break;
     134      }
     135  }
     136  
     137  static void
     138  g_dbus_object_proxy_class_init (GDBusObjectProxyClass *klass)
     139  {
     140    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     141  
     142    gobject_class->finalize     = g_dbus_object_proxy_finalize;
     143    gobject_class->set_property = g_dbus_object_proxy_set_property;
     144    gobject_class->get_property = g_dbus_object_proxy_get_property;
     145  
     146    /**
     147     * GDBusObjectProxy:g-object-path:
     148     *
     149     * The object path of the proxy.
     150     *
     151     * Since: 2.30
     152     */
     153    g_object_class_install_property (gobject_class,
     154                                     PROP_G_OBJECT_PATH,
     155                                     g_param_spec_string ("g-object-path", NULL, NULL,
     156                                                          NULL,
     157                                                          G_PARAM_READWRITE |
     158                                                          G_PARAM_CONSTRUCT_ONLY |
     159                                                          G_PARAM_STATIC_STRINGS));
     160  
     161    /**
     162     * GDBusObjectProxy:g-connection:
     163     *
     164     * The connection of the proxy.
     165     *
     166     * Since: 2.30
     167     */
     168    g_object_class_install_property (gobject_class,
     169                                     PROP_G_CONNECTION,
     170                                     g_param_spec_object ("g-connection", NULL, NULL,
     171                                                          G_TYPE_DBUS_CONNECTION,
     172                                                          G_PARAM_READWRITE |
     173                                                          G_PARAM_CONSTRUCT_ONLY |
     174                                                          G_PARAM_STATIC_STRINGS));
     175  }
     176  
     177  static void
     178  g_dbus_object_proxy_init (GDBusObjectProxy *proxy)
     179  {
     180    proxy->priv = g_dbus_object_proxy_get_instance_private (proxy);
     181    g_mutex_init (&proxy->priv->lock);
     182    proxy->priv->map_name_to_iface = g_hash_table_new_full (g_str_hash,
     183                                                            g_str_equal,
     184                                                            g_free,
     185                                                            (GDestroyNotify) g_object_unref);
     186  }
     187  
     188  static const gchar *
     189  g_dbus_object_proxy_get_object_path (GDBusObject *object)
     190  {
     191    GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
     192    const gchar *ret;
     193    g_mutex_lock (&proxy->priv->lock);
     194    ret = proxy->priv->object_path;
     195    g_mutex_unlock (&proxy->priv->lock);
     196    return ret;
     197  }
     198  
     199  /**
     200   * g_dbus_object_proxy_get_connection:
     201   * @proxy: a #GDBusObjectProxy
     202   *
     203   * Gets the connection that @proxy is for.
     204   *
     205   * Returns: (transfer none): A #GDBusConnection. Do not free, the
     206   *   object is owned by @proxy.
     207   *
     208   * Since: 2.30
     209   */
     210  GDBusConnection *
     211  g_dbus_object_proxy_get_connection (GDBusObjectProxy *proxy)
     212  {
     213    GDBusConnection *ret;
     214    g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
     215    g_mutex_lock (&proxy->priv->lock);
     216    ret = proxy->priv->connection;
     217    g_mutex_unlock (&proxy->priv->lock);
     218    return ret;
     219  }
     220  
     221  static GDBusInterface *
     222  g_dbus_object_proxy_get_interface (GDBusObject *object,
     223                                     const gchar *interface_name)
     224  {
     225    GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
     226    GDBusProxy *ret;
     227  
     228    g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
     229    g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
     230  
     231    g_mutex_lock (&proxy->priv->lock);
     232    ret = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
     233    if (ret != NULL)
     234      g_object_ref (ret);
     235    g_mutex_unlock (&proxy->priv->lock);
     236  
     237    return (GDBusInterface *) ret; /* TODO: proper cast */
     238  }
     239  
     240  static GList *
     241  g_dbus_object_proxy_get_interfaces (GDBusObject *object)
     242  {
     243    GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
     244    GList *ret;
     245  
     246    g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
     247  
     248    ret = NULL;
     249  
     250    g_mutex_lock (&proxy->priv->lock);
     251    ret = g_hash_table_get_values (proxy->priv->map_name_to_iface);
     252    g_list_foreach (ret, (GFunc) g_object_ref, NULL);
     253    g_mutex_unlock (&proxy->priv->lock);
     254  
     255    return ret;
     256  }
     257  
     258  /* ---------------------------------------------------------------------------------------------------- */
     259  
     260  /**
     261   * g_dbus_object_proxy_new:
     262   * @connection: a #GDBusConnection
     263   * @object_path: the object path
     264   *
     265   * Creates a new #GDBusObjectProxy for the given connection and
     266   * object path.
     267   *
     268   * Returns: a new #GDBusObjectProxy
     269   *
     270   * Since: 2.30
     271   */
     272  GDBusObjectProxy *
     273  g_dbus_object_proxy_new (GDBusConnection *connection,
     274                           const gchar     *object_path)
     275  {
     276    g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
     277    g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
     278    return G_DBUS_OBJECT_PROXY (g_object_new (G_TYPE_DBUS_OBJECT_PROXY,
     279                                              "g-object-path", object_path,
     280                                              "g-connection", connection,
     281                                              NULL));
     282  }
     283  
     284  void
     285  _g_dbus_object_proxy_add_interface (GDBusObjectProxy *proxy,
     286                                      GDBusProxy       *interface_proxy)
     287  {
     288    const gchar *interface_name;
     289    GDBusProxy *interface_proxy_to_remove;
     290  
     291    g_return_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy));
     292    g_return_if_fail (G_IS_DBUS_PROXY (interface_proxy));
     293  
     294    g_mutex_lock (&proxy->priv->lock);
     295  
     296    interface_name = g_dbus_proxy_get_interface_name (interface_proxy);
     297    interface_proxy_to_remove = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
     298    if (interface_proxy_to_remove != NULL)
     299      {
     300        g_object_ref (interface_proxy_to_remove);
     301        g_warn_if_fail (g_hash_table_remove (proxy->priv->map_name_to_iface, interface_name));
     302      }
     303    g_hash_table_insert (proxy->priv->map_name_to_iface,
     304                         g_strdup (interface_name),
     305                         g_object_ref (interface_proxy));
     306    g_object_ref (interface_proxy);
     307  
     308    g_mutex_unlock (&proxy->priv->lock);
     309  
     310    if (interface_proxy_to_remove != NULL)
     311      {
     312        g_signal_emit_by_name (proxy, "interface-removed", interface_proxy_to_remove);
     313        g_object_unref (interface_proxy_to_remove);
     314      }
     315  
     316    g_signal_emit_by_name (proxy, "interface-added", interface_proxy);
     317    g_object_unref (interface_proxy);
     318  }
     319  
     320  void
     321  _g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy,
     322                                         const gchar      *interface_name)
     323  {
     324    GDBusProxy *interface_proxy;
     325  
     326    g_return_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy));
     327    g_return_if_fail (g_dbus_is_interface_name (interface_name));
     328  
     329    g_mutex_lock (&proxy->priv->lock);
     330  
     331    interface_proxy = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
     332    if (interface_proxy != NULL)
     333      {
     334        g_object_ref (interface_proxy);
     335        g_warn_if_fail (g_hash_table_remove (proxy->priv->map_name_to_iface, interface_name));
     336        g_mutex_unlock (&proxy->priv->lock);
     337        g_signal_emit_by_name (proxy, "interface-removed", interface_proxy);
     338        g_object_unref (interface_proxy);
     339      }
     340    else
     341      {
     342        g_mutex_unlock (&proxy->priv->lock);
     343      }
     344  }
     345  
     346  static void
     347  dbus_object_interface_init (GDBusObjectIface *iface)
     348  {
     349    iface->get_object_path       = g_dbus_object_proxy_get_object_path;
     350    iface->get_interfaces        = g_dbus_object_proxy_get_interfaces;
     351    iface->get_interface         = g_dbus_object_proxy_get_interface;
     352  }