Blame bus/dbusimpl.c

Packit Service 1d8f1c
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
Packit Service 1d8f1c
/* vim:set et sts=4: */
Packit Service 1d8f1c
/* ibus - The Input Bus
Packit Service 1d8f1c
 * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
Packit Service 1d8f1c
 * Copyright (C) 2008-2013 Red Hat, Inc.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is free software; you can redistribute it and/or
Packit Service 1d8f1c
 * modify it under the terms of the GNU Lesser General Public
Packit Service 1d8f1c
 * License as published by the Free Software Foundation; either
Packit Service 1d8f1c
 * version 2.1 of the License, or (at your option) any later version.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is distributed in the hope that it will be useful,
Packit Service 1d8f1c
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 1d8f1c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 1d8f1c
 * Lesser General Public License for more details.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * You should have received a copy of the GNU Lesser General Public
Packit Service 1d8f1c
 * License along with this library; if not, write to the Free Software
Packit Service 1d8f1c
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
Packit Service 1d8f1c
 * USA
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
Packit Service 1d8f1c
#include "dbusimpl.h"
Packit Service 1d8f1c
Packit Service 1d8f1c
#include <string.h>
Packit Service 1d8f1c
Packit Service 1d8f1c
#include "global.h"
Packit Service 1d8f1c
#include "ibusimpl.h"
Packit Service 1d8f1c
#include "marshalers.h"
Packit Service 1d8f1c
#include "matchrule.h"
Packit Service 1d8f1c
#include "types.h"
Packit Service 1d8f1c
Packit Service 1d8f1c
enum {
Packit Service 1d8f1c
    NAME_OWNER_CHANGED,
Packit Service 1d8f1c
    NAME_LOST,
Packit Service 1d8f1c
    NAME_ACQUIRED,
Packit Service 1d8f1c
    LAST_SIGNAL,
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
enum {
Packit Service 1d8f1c
    PROP_0,
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
static guint dbus_signals[LAST_SIGNAL] = { 0 };
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _BusDBusImpl {
Packit Service 1d8f1c
    IBusService parent;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* instance members */
Packit Service 1d8f1c
    /* a map from a unique bus name (e.g. ":1.0") to a BusConnection. */
Packit Service 1d8f1c
    GHashTable *unique_names;
Packit Service 1d8f1c
    /* a map from a requested well-known name (e.g. "org.freedesktop.IBus.Panel") to a BusNameService. */
Packit Service 1d8f1c
    GHashTable *names;
Packit Service 1d8f1c
    /* a list of IBusService objects. */
Packit Service 1d8f1c
    GList *objects;
Packit Service 1d8f1c
    /* a list of active BusConnections. */
Packit Service 1d8f1c
    GList *connections;
Packit Service 1d8f1c
    /* a list of BusMatchRules requested by the connections above. */
Packit Service 1d8f1c
    GList *rules;
Packit Service 1d8f1c
    /* a serial number used to generate a unique name of a bus. */
Packit Service 1d8f1c
    guint id;
Packit Service 1d8f1c
Packit Service 1d8f1c
    GMutex dispatch_lock;
Packit Service 1d8f1c
    GList *dispatch_queue;
Packit Service 1d8f1c
Packit Service 1d8f1c
    GMutex forward_lock;
Packit Service 1d8f1c
    GList *forward_queue;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* a list of BusMethodCall to be used to reply when services are
Packit Service 1d8f1c
       really available */
Packit Service 1d8f1c
    GList *start_service_calls;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _BusDBusImplClass {
Packit Service 1d8f1c
    IBusServiceClass parent;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* class members */
Packit Service 1d8f1c
    void    (* name_owner_changed) (BusDBusImpl     *dbus,
Packit Service 1d8f1c
                                    BusConnection   *connection,
Packit Service 1d8f1c
                                    gchar           *name,
Packit Service 1d8f1c
                                    gchar           *old_name,
Packit Service 1d8f1c
                                    gchar           *new_name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    void    (* name_lost)          (BusDBusImpl     *dbus,
Packit Service 1d8f1c
                                    BusConnection   *connection,
Packit Service 1d8f1c
                                    gchar           *name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    void    (* name_acquired)      (BusDBusImpl     *dbus,
Packit Service 1d8f1c
                                    BusConnection   *connection,
Packit Service 1d8f1c
                                    gchar           *name);
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
typedef struct _BusDispatchData BusDispatchData;
Packit Service 1d8f1c
struct _BusDispatchData {
Packit Service 1d8f1c
    GDBusMessage *message;
Packit Service 1d8f1c
    BusConnection *skip_connection;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
typedef struct _BusNameService BusNameService;
Packit Service 1d8f1c
struct _BusNameService {
Packit Service 1d8f1c
    gchar *name;
Packit Service 1d8f1c
    GSList *owners;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
typedef struct _BusConnectionOwner BusConnectionOwner;
Packit Service 1d8f1c
struct _BusConnectionOwner {
Packit Service 1d8f1c
    BusConnection *conn;
Packit Service 1d8f1c
Packit Service 1d8f1c
    guint allow_replacement : 1;
Packit Service 1d8f1c
    guint do_not_queue : 1;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
typedef struct _BusMethodCall BusMethodCall;
Packit Service 1d8f1c
struct _BusMethodCall {
Packit Service 1d8f1c
    BusDBusImpl *dbus;
Packit Service 1d8f1c
    BusConnection *connection;
Packit Service 1d8f1c
    GVariant *parameters;
Packit Service 1d8f1c
    GDBusMethodInvocation *invocation;
Packit Service 1d8f1c
    guint timeout_id;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
/* functions prototype */
Packit Service 1d8f1c
static void     bus_dbus_impl_destroy           (BusDBusImpl        *dbus);
Packit Service 1d8f1c
static void     bus_dbus_impl_service_method_call
Packit Service 1d8f1c
                                                (IBusService        *service,
Packit Service 1d8f1c
                                                 GDBusConnection    *dbus_connection,
Packit Service 1d8f1c
                                                 const gchar        *sender,
Packit Service 1d8f1c
                                                 const gchar        *object_path,
Packit Service 1d8f1c
                                                 const gchar        *interface_name,
Packit Service 1d8f1c
                                                 const gchar        *method_name,
Packit Service 1d8f1c
                                                 GVariant           *parameters,
Packit Service 1d8f1c
                                                 GDBusMethodInvocation
Packit Service 1d8f1c
                                                                    *invocation);
Packit Service 1d8f1c
static GVariant *bus_dbus_impl_service_get_property
Packit Service 1d8f1c
                                                (IBusService        *service,
Packit Service 1d8f1c
                                                 GDBusConnection    *connection,
Packit Service 1d8f1c
                                                 const gchar        *sender,
Packit Service 1d8f1c
                                                 const gchar        *object_path,
Packit Service 1d8f1c
                                                 const gchar        *interface_name,
Packit Service 1d8f1c
                                                 const gchar        *property_name,
Packit Service 1d8f1c
                                                 GError            **error);
Packit Service 1d8f1c
static gboolean  bus_dbus_impl_service_set_property
Packit Service 1d8f1c
                                                (IBusService        *service,
Packit Service 1d8f1c
                                                 GDBusConnection    *connection,
Packit Service 1d8f1c
                                                 const gchar        *sender,
Packit Service 1d8f1c
                                                 const gchar        *object_path,
Packit Service 1d8f1c
                                                 const gchar        *interface_name,
Packit Service 1d8f1c
                                                 const gchar        *property_name,
Packit Service 1d8f1c
                                                 GVariant           *value,
Packit Service 1d8f1c
                                                 GError            **error);
Packit Service 1d8f1c
static void      bus_dbus_impl_name_owner_changed
Packit Service 1d8f1c
                                                (BusDBusImpl        *dbus,
Packit Service 1d8f1c
                                                 BusConnection      *connection,
Packit Service 1d8f1c
                                                 gchar              *name,
Packit Service 1d8f1c
                                                 gchar              *old_name,
Packit Service 1d8f1c
                                                 gchar              *new_name);
Packit Service 1d8f1c
static void      bus_dbus_impl_name_lost
Packit Service 1d8f1c
                                                (BusDBusImpl        *dbus,
Packit Service 1d8f1c
                                                 BusConnection      *connection,
Packit Service 1d8f1c
                                                 gchar              *name);
Packit Service 1d8f1c
static void      bus_dbus_impl_name_acquired
Packit Service 1d8f1c
                                                (BusDBusImpl        *dbus,
Packit Service 1d8f1c
                                                 BusConnection      *connection,
Packit Service 1d8f1c
                                                 gchar              *name);
Packit Service 1d8f1c
static void      bus_dbus_impl_connection_destroy_cb
Packit Service 1d8f1c
                                                (BusConnection      *connection,
Packit Service 1d8f1c
                                                 BusDBusImpl        *dbus);
Packit Service 1d8f1c
static void      bus_dbus_impl_rule_destroy_cb  (BusMatchRule       *rule,
Packit Service 1d8f1c
                                                 BusDBusImpl        *dbus);
Packit Service 1d8f1c
static void      bus_dbus_impl_object_destroy_cb(IBusService        *object,
Packit Service 1d8f1c
                                                 BusDBusImpl        *dbus);
Packit Service 1d8f1c
Packit Service 1d8f1c
G_DEFINE_TYPE(BusDBusImpl, bus_dbus_impl, IBUS_TYPE_SERVICE)
Packit Service 1d8f1c
Packit Service 1d8f1c
/* The D-Bus interfaces available in this class, which consists of a list of methods this class implements and
Packit Service 1d8f1c
 * a list of signals this class may emit. See bus_dbus_impl_new_connection and ibusservice.c for more details. */
Packit Service 1d8f1c
static const gchar introspection_xml[] =
Packit Service 1d8f1c
    "<node>"
Packit Service 1d8f1c
    "  <interface name='org.freedesktop.DBus'>"
Packit Service 1d8f1c
    "    <method name='Hello'>"
Packit Service 1d8f1c
    "      <arg direction='out' type='s' name='unique_name' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='RequestName'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' name='name' />"
Packit Service 1d8f1c
    "      <arg direction='in'  type='u' name='flags' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='u' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='ReleaseName'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' name='name' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='u' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='StartServiceByName'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' />"
Packit Service 1d8f1c
    "      <arg direction='in'  type='u' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='u' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='UpdateActivationEnvironment'>"
Packit Service 1d8f1c
    "      <arg direction='in' type='a{ss}'/>"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='NameHasOwner'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' name='name' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='b' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='ListNames'>"
Packit Service 1d8f1c
    "      <arg direction='out' type='as' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='ListActivatableNames'>"
Packit Service 1d8f1c
    "      <arg direction='out' type='as' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='AddMatch'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' name='match_rule' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='RemoveMatch'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' name='match_rule' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='GetNameOwner'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' name='name' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='s' name='unique_name' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='ListQueuedOwners'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' name='name' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='as' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='GetConnectionUnixUser'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='u' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='GetConnectionUnixProcessID'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='u' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='GetAdtAuditSessionData'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='ay' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='GetConnectionSELinuxSecurityContext'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='ay' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <method name='ReloadConfig' />"
Packit Service 1d8f1c
    "    <method name='GetId'>"
Packit Service 1d8f1c
    "      <arg direction='out' type='s' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "    <signal name='NameOwnerChanged'>"
Packit Service 1d8f1c
    "      <arg type='s' name='name' />"
Packit Service 1d8f1c
    "      <arg type='s' name='old_owner' />"
Packit Service 1d8f1c
    "      <arg type='s' name='new_owner' />"
Packit Service 1d8f1c
    "    </signal>"
Packit Service 1d8f1c
    "    <signal name='NameLost'>"
Packit Service 1d8f1c
    "      <arg type='s' name='name' />"
Packit Service 1d8f1c
    "    </signal>"
Packit Service 1d8f1c
    "    <signal name='NameAcquired'>"
Packit Service 1d8f1c
    "      <arg type='s' name='name' />"
Packit Service 1d8f1c
    "    </signal>"
Packit Service 1d8f1c
    "  </interface>"
Packit Service 1d8f1c
    "</node>";
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_connection_owner_set_flags (BusConnectionOwner *owner,
Packit Service 1d8f1c
                                guint32             flags)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    owner->allow_replacement =
Packit Service 1d8f1c
        (flags & IBUS_BUS_NAME_FLAG_ALLOW_REPLACEMENT) != 0;
Packit Service 1d8f1c
Packit Service 1d8f1c
    owner->do_not_queue =
Packit Service 1d8f1c
        (flags & IBUS_BUS_NAME_FLAG_DO_NOT_QUEUE) != 0;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static BusConnectionOwner *
Packit Service 1d8f1c
bus_connection_owner_new (BusConnection *connection,
Packit Service 1d8f1c
                          guint32        flags)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    BusConnectionOwner *owner = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (BUS_IS_CONNECTION (connection));
Packit Service 1d8f1c
Packit Service 1d8f1c
    owner = g_slice_new (BusConnectionOwner);
Packit Service 1d8f1c
    if (owner != NULL) {
Packit Service 1d8f1c
        owner->conn = g_object_ref (connection);
Packit Service 1d8f1c
        bus_connection_owner_set_flags (owner, flags);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return owner;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_connection_owner_free (BusConnectionOwner *owner)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (owner != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_object_unref (owner->conn);
Packit Service 1d8f1c
    owner->conn = NULL;
Packit Service 1d8f1c
    g_slice_free (BusConnectionOwner, owner);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static GSList *
Packit Service 1d8f1c
bus_name_service_find_owner_link (BusNameService *service,
Packit Service 1d8f1c
                                   BusConnection  *connection)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GSList *owners = service->owners;
Packit Service 1d8f1c
Packit Service 1d8f1c
    while (owners) {
Packit Service 1d8f1c
        BusConnectionOwner *owner = (BusConnectionOwner *) owners->data;
Packit Service 1d8f1c
        if (owner->conn == connection) {
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        owners = owners->next;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return owners;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static BusNameService *
Packit Service 1d8f1c
bus_name_service_new (const gchar *name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    BusNameService *service = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (name != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    service = g_slice_new (BusNameService);
Packit Service 1d8f1c
    g_assert (service != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    service->name = g_strdup (name);
Packit Service 1d8f1c
    service->owners = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    return service;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_name_service_free (BusNameService *service)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (service != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_slist_free_full (service->owners,
Packit Service 1d8f1c
                       (GDestroyNotify) bus_connection_owner_free);
Packit Service 1d8f1c
    service->owners = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_free (service->name);
Packit Service 1d8f1c
    g_slice_free (BusNameService, service);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_name_service_set_primary_owner (BusNameService     *service,
Packit Service 1d8f1c
                                    BusConnectionOwner *owner,
Packit Service 1d8f1c
                                    BusDBusImpl        *dbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (service != NULL);
Packit Service 1d8f1c
    g_assert (owner != NULL);
Packit Service 1d8f1c
    g_assert (dbus != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusConnectionOwner *old = service->owners != NULL ?
Packit Service 1d8f1c
            (BusConnectionOwner *)service->owners->data : NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (old != NULL) {
Packit Service 1d8f1c
        g_signal_emit (dbus,
Packit Service 1d8f1c
                       dbus_signals[NAME_LOST],
Packit Service 1d8f1c
                       0,
Packit Service 1d8f1c
                       old->conn,
Packit Service 1d8f1c
                       service->name);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_emit (dbus,
Packit Service 1d8f1c
                   dbus_signals[NAME_ACQUIRED],
Packit Service 1d8f1c
                   0,
Packit Service 1d8f1c
                   owner->conn,
Packit Service 1d8f1c
                   service->name ? service->name : "");
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_emit (dbus,
Packit Service 1d8f1c
                   dbus_signals[NAME_OWNER_CHANGED],
Packit Service 1d8f1c
                   0,
Packit Service 1d8f1c
                   owner->conn,
Packit Service 1d8f1c
                   service->name,
Packit Service 1d8f1c
                   old != NULL ? bus_connection_get_unique_name (old->conn) : "",
Packit Service 1d8f1c
                   bus_connection_get_unique_name (owner->conn));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (old != NULL && old->do_not_queue != 0) {
Packit Service 1d8f1c
        /* If old primary owner does not want to be in queue, we remove it. */
Packit Service 1d8f1c
        service->owners = g_slist_remove (service->owners, old);
Packit Service 1d8f1c
        bus_connection_remove_name (old->conn, service->name);
Packit Service 1d8f1c
        bus_connection_owner_free (old);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    service->owners = g_slist_prepend (service->owners, (gpointer) owner);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static BusConnectionOwner *
Packit Service 1d8f1c
bus_name_service_get_primary_owner (BusNameService *service)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (service != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (service->owners == NULL) {
Packit Service 1d8f1c
        return NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return (BusConnectionOwner *) service->owners->data;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_name_service_add_non_primary_owner (BusNameService     *service,
Packit Service 1d8f1c
                                        BusConnectionOwner *owner,
Packit Service 1d8f1c
                                        BusDBusImpl        *dbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (service != NULL);
Packit Service 1d8f1c
    g_assert (owner != NULL);
Packit Service 1d8f1c
    g_assert (dbus != NULL);
Packit Service 1d8f1c
    g_assert (service->owners != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    service->owners = g_slist_append (service->owners, (gpointer) owner);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static BusConnectionOwner *
Packit Service 1d8f1c
bus_name_service_find_owner (BusNameService *service,
Packit Service 1d8f1c
                             BusConnection  *connection)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (service != NULL);
Packit Service 1d8f1c
    g_assert (connection != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    GSList *owners = bus_name_service_find_owner_link (service, connection);
Packit Service 1d8f1c
    if (owners != NULL)
Packit Service 1d8f1c
        return (BusConnectionOwner *)owners->data;
Packit Service 1d8f1c
    return NULL;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_name_service_remove_owner (BusNameService     *service,
Packit Service 1d8f1c
                               BusConnectionOwner *owner,
Packit Service 1d8f1c
                               BusDBusImpl        *dbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GSList *owners;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (service != NULL);
Packit Service 1d8f1c
    g_assert (owner != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
    owners = bus_name_service_find_owner_link (service, owner->conn);
Packit Service 1d8f1c
    g_assert (owners != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (owners->data == bus_name_service_get_primary_owner (service)) {
Packit Service 1d8f1c
        BusConnectionOwner *_new = NULL;
Packit Service 1d8f1c
        if (owners->next != NULL) {
Packit Service 1d8f1c
            _new = (BusConnectionOwner *)owners->next->data;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (dbus != NULL) {
Packit Service 1d8f1c
            g_signal_emit (dbus,
Packit Service 1d8f1c
                           dbus_signals[NAME_LOST],
Packit Service 1d8f1c
                           0,
Packit Service 1d8f1c
                           owner->conn,
Packit Service 1d8f1c
                           service->name);
Packit Service 1d8f1c
            if (_new != NULL) {
Packit Service 1d8f1c
                g_signal_emit (dbus,
Packit Service 1d8f1c
                               dbus_signals[NAME_ACQUIRED],
Packit Service 1d8f1c
                               0,
Packit Service 1d8f1c
                               _new->conn,
Packit Service 1d8f1c
                               service->name);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            g_signal_emit (dbus,
Packit Service 1d8f1c
                    dbus_signals[NAME_OWNER_CHANGED],
Packit Service 1d8f1c
                    0,
Packit Service 1d8f1c
                    _new != NULL ? _new->conn : NULL,
Packit Service 1d8f1c
                    service->name,
Packit Service 1d8f1c
                    bus_connection_get_unique_name (owner->conn),
Packit Service 1d8f1c
                    _new != NULL ? bus_connection_get_unique_name (_new->conn) : "");
Packit Service 1d8f1c
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    service->owners = g_slist_remove_link (service->owners, (gpointer) owners);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
bus_name_service_get_allow_replacement (BusNameService *service)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    BusConnectionOwner *owner = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (service != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    owner = bus_name_service_get_primary_owner (service);
Packit Service 1d8f1c
    if (owner == NULL) {
Packit Service 1d8f1c
        return TRUE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return owner->allow_replacement;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static BusMethodCall *
Packit Service 1d8f1c
bus_method_call_new (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                     BusConnection         *connection,
Packit Service 1d8f1c
                     GVariant              *parameters,
Packit Service 1d8f1c
                     GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    BusMethodCall *call = g_slice_new0 (BusMethodCall);
Packit Service 1d8f1c
    call->dbus = g_object_ref (dbus);
Packit Service 1d8f1c
    call->connection = g_object_ref (connection);
Packit Service 1d8f1c
    call->parameters = g_variant_ref (parameters);
Packit Service 1d8f1c
    call->invocation = g_object_ref (invocation);
Packit Service 1d8f1c
    return call;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_method_call_free (BusMethodCall *call)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (call->timeout_id != 0) {
Packit Service 1d8f1c
        g_source_remove (call->timeout_id);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_object_unref (call->dbus);
Packit Service 1d8f1c
    g_object_unref (call->connection);
Packit Service 1d8f1c
    g_variant_unref (call->parameters);
Packit Service 1d8f1c
    g_object_unref (call->invocation);
Packit Service 1d8f1c
    g_slice_free (BusMethodCall, call);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_class_init (BusDBusImplClass *class)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GObjectClass *gobject_class = G_OBJECT_CLASS (class);
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBUS_OBJECT_CLASS (gobject_class)->destroy = (IBusObjectDestroyFunc) bus_dbus_impl_destroy;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* override the default implementations in the parent class. */
Packit Service 1d8f1c
    IBUS_SERVICE_CLASS (class)->service_method_call =  bus_dbus_impl_service_method_call;
Packit Service 1d8f1c
    IBUS_SERVICE_CLASS (class)->service_get_property = bus_dbus_impl_service_get_property;
Packit Service 1d8f1c
    IBUS_SERVICE_CLASS (class)->service_set_property = bus_dbus_impl_service_set_property;
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* register a handler of the name-owner-changed signal below. */
Packit Service 1d8f1c
    class->name_owner_changed = bus_dbus_impl_name_owner_changed;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* register a handler of the name-lost signal below. */
Packit Service 1d8f1c
    class->name_lost = bus_dbus_impl_name_lost;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* register a handler of the name-acquired signal below. */
Packit Service 1d8f1c
    class->name_acquired = bus_dbus_impl_name_acquired;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* install signals */
Packit Service 1d8f1c
    dbus_signals[NAME_OWNER_CHANGED] =
Packit Service 1d8f1c
        g_signal_new (I_("name-owner-changed"),
Packit Service 1d8f1c
            G_TYPE_FROM_CLASS (class),
Packit Service 1d8f1c
            G_SIGNAL_RUN_FIRST,
Packit Service 1d8f1c
            G_STRUCT_OFFSET (BusDBusImplClass, name_owner_changed),
Packit Service 1d8f1c
            NULL, NULL,
Packit Service 1d8f1c
            bus_marshal_VOID__OBJECT_STRING_STRING_STRING,
Packit Service 1d8f1c
            G_TYPE_NONE,
Packit Service 1d8f1c
            4,
Packit Service 1d8f1c
            BUS_TYPE_CONNECTION,
Packit Service 1d8f1c
            G_TYPE_STRING,
Packit Service 1d8f1c
            G_TYPE_STRING,
Packit Service 1d8f1c
            G_TYPE_STRING);
Packit Service 1d8f1c
Packit Service 1d8f1c
    dbus_signals[NAME_LOST] =
Packit Service 1d8f1c
        g_signal_new (I_("name-lost"),
Packit Service 1d8f1c
            G_TYPE_FROM_CLASS (class),
Packit Service 1d8f1c
            G_SIGNAL_RUN_FIRST,
Packit Service 1d8f1c
            G_STRUCT_OFFSET (BusDBusImplClass, name_lost),
Packit Service 1d8f1c
            NULL, NULL,
Packit Service 1d8f1c
            bus_marshal_VOID__OBJECT_STRING,
Packit Service 1d8f1c
            G_TYPE_NONE,
Packit Service 1d8f1c
            2,
Packit Service 1d8f1c
            BUS_TYPE_CONNECTION,
Packit Service 1d8f1c
            G_TYPE_STRING);
Packit Service 1d8f1c
Packit Service 1d8f1c
    dbus_signals[NAME_ACQUIRED] =
Packit Service 1d8f1c
        g_signal_new (I_("name-acquired"),
Packit Service 1d8f1c
            G_TYPE_FROM_CLASS (class),
Packit Service 1d8f1c
            G_SIGNAL_RUN_FIRST,
Packit Service 1d8f1c
            G_STRUCT_OFFSET (BusDBusImplClass, name_acquired),
Packit Service 1d8f1c
            NULL, NULL,
Packit Service 1d8f1c
            bus_marshal_VOID__OBJECT_STRING,
Packit Service 1d8f1c
            G_TYPE_NONE,
Packit Service 1d8f1c
            2,
Packit Service 1d8f1c
            BUS_TYPE_CONNECTION,
Packit Service 1d8f1c
            G_TYPE_STRING);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_init (BusDBusImpl *dbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    dbus->unique_names = g_hash_table_new (g_str_hash, g_str_equal);
Packit Service 1d8f1c
    dbus->names = g_hash_table_new_full (g_str_hash, g_str_equal,
Packit Service 1d8f1c
                                         NULL,
Packit Service 1d8f1c
                                         (GDestroyNotify) bus_name_service_free);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_mutex_init (&dbus->dispatch_lock);
Packit Service 1d8f1c
    g_mutex_init (&dbus->forward_lock);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* other members are automatically zero-initialized. */
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_destroy (BusDBusImpl *dbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (p = dbus->objects; p != NULL; p = p->next) {
Packit Service 1d8f1c
        IBusService *object = (IBusService *) p->data;
Packit Service 1d8f1c
        g_signal_handlers_disconnect_by_func (object,
Packit Service 1d8f1c
                G_CALLBACK (bus_dbus_impl_object_destroy_cb), dbus);
Packit Service 1d8f1c
        ibus_object_destroy ((IBusObject *) object);
Packit Service 1d8f1c
        g_object_unref (object);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_list_free (dbus->objects);
Packit Service 1d8f1c
    dbus->objects = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (p = dbus->rules; p != NULL; p = p->next) {
Packit Service 1d8f1c
        BusMatchRule *rule = BUS_MATCH_RULE (p->data);
Packit Service 1d8f1c
        g_signal_handlers_disconnect_by_func (rule,
Packit Service 1d8f1c
                        G_CALLBACK (bus_dbus_impl_rule_destroy_cb), dbus);
Packit Service 1d8f1c
        ibus_object_destroy ((IBusObject *) rule);
Packit Service 1d8f1c
        g_object_unref (rule);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_list_free (dbus->rules);
Packit Service 1d8f1c
    dbus->rules = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (p = dbus->connections; p != NULL; p = p->next) {
Packit Service 1d8f1c
        BusConnection *connection = BUS_CONNECTION (p->data);
Packit Service 1d8f1c
        g_signal_handlers_disconnect_by_func (connection,
Packit Service 1d8f1c
                bus_dbus_impl_connection_destroy_cb, dbus);
Packit Service 1d8f1c
        ibus_object_destroy (IBUS_OBJECT (connection));
Packit Service 1d8f1c
        g_object_unref (connection);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_list_free (dbus->connections);
Packit Service 1d8f1c
    dbus->connections = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_hash_table_remove_all (dbus->unique_names);
Packit Service 1d8f1c
    g_hash_table_remove_all (dbus->names);
Packit Service 1d8f1c
Packit Service 1d8f1c
    dbus->unique_names = NULL;
Packit Service 1d8f1c
    dbus->names = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_list_free_full (dbus->start_service_calls,
Packit Service 1d8f1c
                      (GDestroyNotify) bus_method_call_free);
Packit Service 1d8f1c
    dbus->start_service_calls = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_mutex_clear (&dbus->dispatch_lock);
Packit Service 1d8f1c
    g_mutex_clear (&dbus->forward_lock);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* FIXME destruct _lock and _queue members. */
Packit Service 1d8f1c
    IBUS_OBJECT_CLASS(bus_dbus_impl_parent_class)->destroy ((IBusObject *) dbus);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_hello:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "Hello" method call of the org.freedesktop.DBus interface.
Packit Service 1d8f1c
 * Assign a unique bus name like ":1.0" for the connection and return the name (as a D-Bus reply.)
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_hello (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                     BusConnection         *connection,
Packit Service 1d8f1c
                     GVariant              *parameters,
Packit Service 1d8f1c
                     GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (bus_connection_get_unique_name (connection) != NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                        "Already handled an Hello message");
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        gchar *name = g_strdup_printf (":1.%u", ++dbus->id);
Packit Service 1d8f1c
        bus_connection_set_unique_name (connection, name);
Packit Service 1d8f1c
        g_free (name);
Packit Service 1d8f1c
Packit Service 1d8f1c
        name = (gchar *) bus_connection_get_unique_name (connection);
Packit Service 1d8f1c
        g_hash_table_insert (dbus->unique_names, name, connection);
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", name));
Packit Service 1d8f1c
Packit Service 1d8f1c
        g_signal_emit (dbus,
Packit Service 1d8f1c
                       dbus_signals[NAME_OWNER_CHANGED],
Packit Service 1d8f1c
                       0,
Packit Service 1d8f1c
                       connection,
Packit Service 1d8f1c
                       name,
Packit Service 1d8f1c
                       "",
Packit Service 1d8f1c
                       name);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_list_names:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "ListNames" method call of the org.freedesktop.DBus interface.
Packit Service 1d8f1c
 * Return all bus names (e.g. ":1.0", "org.freedesktop.IBus.Panel") as a D-Bus reply.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_list_names (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                          BusConnection         *connection,
Packit Service 1d8f1c
                          GVariant              *parameters,
Packit Service 1d8f1c
                          GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GVariantBuilder builder;
Packit Service 1d8f1c
    g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* FIXME should add them? */
Packit Service 1d8f1c
    g_variant_builder_add (&builder, "s", "org.freedesktop.DBus");
Packit Service 1d8f1c
    g_variant_builder_add (&builder, "s", "org.freedesktop.IBus");
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* append well-known names */
Packit Service 1d8f1c
    GList *names, *name;
Packit Service 1d8f1c
    names = g_hash_table_get_keys (dbus->names);
Packit Service 1d8f1c
    for (name = names; name != NULL; name = name->next) {
Packit Service 1d8f1c
        g_variant_builder_add (&builder, "s", name->data);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_list_free (names);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* append unique names */
Packit Service 1d8f1c
    names = g_hash_table_get_keys (dbus->unique_names);
Packit Service 1d8f1c
    for (name = names; name != NULL; name = name->next) {
Packit Service 1d8f1c
        g_variant_builder_add (&builder, "s", name->data);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_list_free (names);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                    g_variant_new ("(as)", &builder));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_list_names:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "NameHasOwner" method call of the org.freedesktop.DBus interface.
Packit Service 1d8f1c
 * Return TRUE (as a D-Bus reply) if the name is available in dbus->unique_names or is a well-known name.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_name_has_owner (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                              BusConnection         *connection,
Packit Service 1d8f1c
                              GVariant              *parameters,
Packit Service 1d8f1c
                              GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *name = NULL;
Packit Service 1d8f1c
    g_variant_get (parameters, "(&s)", &name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    gboolean has_owner;
Packit Service 1d8f1c
    if (!g_dbus_is_name (name)) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                                               G_DBUS_ERROR,
Packit Service 1d8f1c
                                               G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                                               "'%s' is not a legal bus name",
Packit Service 1d8f1c
                                               name ? name : "(null)");
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_dbus_is_unique_name (name)) {
Packit Service 1d8f1c
        has_owner = g_hash_table_lookup (dbus->unique_names, name) != NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        if (g_strcmp0 (name, "org.freedesktop.DBus") == 0 ||
Packit Service 1d8f1c
            g_strcmp0 (name, "org.freedesktop.IBus") == 0)
Packit Service 1d8f1c
            has_owner = TRUE;
Packit Service 1d8f1c
        else
Packit Service 1d8f1c
            has_owner = g_hash_table_lookup (dbus->names, name) != NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                    g_variant_new ("(b)", has_owner));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_get_name_owner:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "GetNameOwner" method call of the org.freedesktop.DBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_get_name_owner (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                              BusConnection         *connection,
Packit Service 1d8f1c
                              GVariant              *parameters,
Packit Service 1d8f1c
                              GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *name_owner = NULL;
Packit Service 1d8f1c
    const gchar *name = NULL;
Packit Service 1d8f1c
    g_variant_get (parameters, "(&s)", &name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (name, "org.freedesktop.DBus") == 0 ||
Packit Service 1d8f1c
        g_strcmp0 (name, "org.freedesktop.IBus") == 0) {
Packit Service 1d8f1c
        name_owner = name;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        BusConnection *owner = bus_dbus_impl_get_connection_by_name (dbus, name);
Packit Service 1d8f1c
        if (owner != NULL) {
Packit Service 1d8f1c
            name_owner = bus_connection_get_unique_name (owner);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (name_owner == NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
Packit Service 1d8f1c
                        "Can not get name owner of '%s': no such name", name);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                        g_variant_new ("(s)", name_owner));
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_list_queued_owners:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "ListQueuedOwners" method call of the org.freedesktop.DBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_list_queued_owners (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                                  BusConnection         *connection,
Packit Service 1d8f1c
                                  GVariant              *parameters,
Packit Service 1d8f1c
                                  GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *name = NULL;
Packit Service 1d8f1c
    const gchar *name_owner = NULL;
Packit Service 1d8f1c
    GVariantBuilder builder;
Packit Service 1d8f1c
    BusConnection *named_conn = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_get (parameters, "(&s)", &name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (name != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (G_LIKELY (g_dbus_is_unique_name (name))) {
Packit Service 1d8f1c
        named_conn = (BusConnection *) g_hash_table_lookup (dbus->unique_names, name);
Packit Service 1d8f1c
        if (named_conn == NULL) {
Packit Service 1d8f1c
            g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                    g_variant_new ("(as)", &builder));
Packit Service 1d8f1c
            return;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        name_owner = bus_connection_get_unique_name (named_conn);
Packit Service 1d8f1c
        if (name_owner == NULL) {
Packit Service 1d8f1c
            g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                            G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
Packit Service 1d8f1c
                            "Can not get name owner of '%s': no such name", name);
Packit Service 1d8f1c
            return;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        g_variant_builder_add (&builder, "s", name_owner);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        BusNameService *service;
Packit Service 1d8f1c
        GSList *owners;
Packit Service 1d8f1c
Packit Service 1d8f1c
        service = (BusNameService *) g_hash_table_lookup (dbus->names, name);
Packit Service 1d8f1c
        if (service == NULL) {
Packit Service 1d8f1c
            g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                    g_variant_new ("(as)", &builder));
Packit Service 1d8f1c
            return;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        for (owners = service->owners; owners; owners = owners->next) {
Packit Service 1d8f1c
            BusConnectionOwner *owner = (BusConnectionOwner *) owners->data;
Packit Service 1d8f1c
            if (owner == NULL) {
Packit Service 1d8f1c
                continue;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            named_conn = owner->conn;
Packit Service 1d8f1c
            if (named_conn == NULL) {
Packit Service 1d8f1c
                continue;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            name_owner = bus_connection_get_unique_name (named_conn);
Packit Service 1d8f1c
            if (name_owner == NULL) {
Packit Service 1d8f1c
                g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                            G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
Packit Service 1d8f1c
                            "Can not get name owner of '%s': no such name", name);
Packit Service 1d8f1c
                return;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            g_variant_builder_add (&builder, "s", name_owner);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                    g_variant_new ("(as)", &builder));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_get_id:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "GetId" method call of the org.freedesktop.DBus interface.
Packit Service 1d8f1c
 * This function is not implemented yet and always returns a dummy string - "FIXME".
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_get_id (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                      BusConnection         *connection,
Packit Service 1d8f1c
                      GVariant              *parameters,
Packit Service 1d8f1c
                      GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    /* FIXME */
Packit Service 1d8f1c
    const gchar *uuid = "FIXME";
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                    g_variant_new ("(s)", uuid));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_rule_destroy_cb:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * A function to be called when one of the dbus->rules is destroyed.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_rule_destroy_cb (BusMatchRule *rule,
Packit Service 1d8f1c
                               BusDBusImpl  *dbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    dbus->rules = g_list_remove (dbus->rules, rule);
Packit Service 1d8f1c
    g_object_unref (rule);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_get_id:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "AddMatch" method call of the org.freedesktop.DBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_add_match (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                         BusConnection         *connection,
Packit Service 1d8f1c
                         GVariant              *parameters,
Packit Service 1d8f1c
                         GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *rule_text = NULL;
Packit Service 1d8f1c
    g_variant_get (parameters, "(&s)", &rule_text);
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusMatchRule *rule = bus_match_rule_new (rule_text);
Packit Service 1d8f1c
    if (rule == NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
Packit Service 1d8f1c
                        "Parse match rule [%s] failed", rule_text);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
    for (p = dbus->rules; p != NULL; p = p->next) {
Packit Service 1d8f1c
        if (bus_match_rule_is_equal (rule, (BusMatchRule *) p->data)) {
Packit Service 1d8f1c
            /* The same rule is already registered. Just reuse it. */
Packit Service 1d8f1c
            bus_match_rule_add_recipient ((BusMatchRule *) p->data, connection);
Packit Service 1d8f1c
            g_object_unref (rule);
Packit Service 1d8f1c
            return;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (rule) {
Packit Service 1d8f1c
        bus_match_rule_add_recipient (rule, connection);
Packit Service 1d8f1c
        dbus->rules = g_list_append (dbus->rules, rule);
Packit Service 1d8f1c
        g_signal_connect (rule, "destroy", G_CALLBACK (bus_dbus_impl_rule_destroy_cb), dbus);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_get_id:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "RemoveMatch" method call of the org.freedesktop.DBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_remove_match (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                            BusConnection         *connection,
Packit Service 1d8f1c
                            GVariant              *parameters,
Packit Service 1d8f1c
                            GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *rule_text = NULL;
Packit Service 1d8f1c
    g_variant_get (parameters, "(&s)", &rule_text);
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusMatchRule *rule = bus_match_rule_new (rule_text);
Packit Service 1d8f1c
    if (rule == NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
Packit Service 1d8f1c
                        "Parse match rule [%s] failed", rule_text);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
    for (p = dbus->rules; p != NULL; p = p->next) {
Packit Service 1d8f1c
        if (bus_match_rule_is_equal (rule, (BusMatchRule *) p->data)) {
Packit Service 1d8f1c
            /* p->data will be destroyed when the final recipient is removed.  */
Packit Service 1d8f1c
            bus_match_rule_remove_recipient ((BusMatchRule *) p->data, connection);
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        /* FIXME should we return G_DBUS_ERROR if rule is not found in dbus->rules */
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_object_unref (rule);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_request_name:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "RequestName" method call of the org.freedesktop.DBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_request_name (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                            BusConnection         *connection,
Packit Service 1d8f1c
                            GVariant              *parameters,
Packit Service 1d8f1c
                            GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *name = NULL;  // e.g. "org.freedesktop.IBus.Panel"
Packit Service 1d8f1c
    guint32 flags = 0;
Packit Service 1d8f1c
    BusNameService *service = NULL;
Packit Service 1d8f1c
    BusConnectionOwner *primary_owner = NULL;
Packit Service 1d8f1c
    BusConnectionOwner *owner = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_get (parameters, "(&su)", &name, &flags);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (name == NULL ||
Packit Service 1d8f1c
        !g_dbus_is_name (name) ||
Packit Service 1d8f1c
        g_dbus_is_unique_name (name)) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit Service 1d8f1c
                        "'%s' is not a legal service name.", name);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (name, "org.freedesktop.DBus") == 0 ||
Packit Service 1d8f1c
        g_strcmp0 (name, "org.freedesktop.IBus") == 0) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit Service 1d8f1c
                        "Can not acquire the service name '%s', it is reserved by IBus", name);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    enum {
Packit Service 1d8f1c
        ACTION_INVALID,
Packit Service 1d8f1c
        ACTION_IN_QUEUE,
Packit Service 1d8f1c
        ACTION_REPLACE,
Packit Service 1d8f1c
        ACTION_EXISTS,
Packit Service 1d8f1c
        ACTION_ALREADY_OWN,
Packit Service 1d8f1c
    } action = ACTION_INVALID;
Packit Service 1d8f1c
Packit Service 1d8f1c
    service = (BusNameService *) g_hash_table_lookup (dbus->names, name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* If the name servise does not exist, we will create one. */
Packit Service 1d8f1c
    if (service == NULL) {
Packit Service 1d8f1c
        service = bus_name_service_new (name);
Packit Service 1d8f1c
        g_hash_table_insert (dbus->names,
Packit Service 1d8f1c
                             service->name,
Packit Service 1d8f1c
                             service);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        primary_owner = bus_name_service_get_primary_owner (service);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (primary_owner != NULL) {
Packit Service 1d8f1c
        if (primary_owner->conn == connection) {
Packit Service 1d8f1c
            action = ACTION_ALREADY_OWN;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else {
Packit Service 1d8f1c
            action = (flags & IBUS_BUS_NAME_FLAG_DO_NOT_QUEUE) ?
Packit Service 1d8f1c
                    ACTION_EXISTS : ACTION_IN_QUEUE;
Packit Service 1d8f1c
            if ((bus_name_service_get_allow_replacement (service) == TRUE) &&
Packit Service 1d8f1c
                (flags & IBUS_BUS_NAME_FLAG_REPLACE_EXISTING)) {
Packit Service 1d8f1c
                action = ACTION_REPLACE;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        action = ACTION_REPLACE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (action == ACTION_ALREADY_OWN) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                g_variant_new ("(u)", IBUS_BUS_REQUEST_NAME_REPLY_ALREADY_OWNER));
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    owner = bus_name_service_find_owner (service, connection);
Packit Service 1d8f1c
    /* If connection already in queue, we need remove it at first. */
Packit Service 1d8f1c
    if (owner != NULL) {
Packit Service 1d8f1c
        bus_connection_remove_name (connection, name);
Packit Service 1d8f1c
        bus_name_service_remove_owner (service, owner, NULL);
Packit Service 1d8f1c
        bus_connection_owner_free (owner);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    switch (action) {
Packit Service 1d8f1c
    case ACTION_EXISTS:
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                g_variant_new ("(u)", IBUS_BUS_REQUEST_NAME_REPLY_EXISTS));
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    case ACTION_IN_QUEUE:
Packit Service 1d8f1c
        owner = bus_connection_owner_new (connection, flags);
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                g_variant_new ("(u)", IBUS_BUS_REQUEST_NAME_REPLY_IN_QUEUE));
Packit Service 1d8f1c
        bus_name_service_add_non_primary_owner (service, owner, dbus);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    case ACTION_REPLACE:
Packit Service 1d8f1c
        bus_connection_add_name (connection, name);
Packit Service 1d8f1c
        owner = bus_connection_owner_new (connection, flags);
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                g_variant_new ("(u)", IBUS_BUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
Packit Service 1d8f1c
        bus_name_service_set_primary_owner (service, owner, dbus);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        g_assert_not_reached ();
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_release_name:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "ReleaseName" method call of the org.freedesktop.DBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_release_name (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                            BusConnection         *connection,
Packit Service 1d8f1c
                            GVariant              *parameters,
Packit Service 1d8f1c
                            GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *name= NULL;
Packit Service 1d8f1c
    BusNameService *service;
Packit Service 1d8f1c
    g_variant_get (parameters, "(&s)", &name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (name == NULL ||
Packit Service 1d8f1c
        !g_dbus_is_name (name) ||
Packit Service 1d8f1c
        g_dbus_is_unique_name (name)) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit Service 1d8f1c
                        "'%s' is not a legal service name.", name);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (name, "org.freedesktop.DBus") == 0 ||
Packit Service 1d8f1c
        g_strcmp0 (name, "org.freedesktop.IBus") == 0) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit Service 1d8f1c
                        "Service name '%s' is owned by IBus.", name);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    guint retval;
Packit Service 1d8f1c
    service = g_hash_table_lookup (dbus->names, name);
Packit Service 1d8f1c
    if (service == NULL) {
Packit Service 1d8f1c
        retval = 2; /* DBUS_RELEASE_NAME_REPLY_NON_EXISTENT */
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        /* "ReleaseName" method removes the name in connection->names
Packit Service 1d8f1c
         * and the connection owner.
Packit Service 1d8f1c
         * bus_dbus_impl_connection_destroy_cb() removes all
Packit Service 1d8f1c
         * connection->names and the connection owners.
Packit Service 1d8f1c
         * See also comments in bus_dbus_impl_connection_destroy_cb().
Packit Service 1d8f1c
         */
Packit Service 1d8f1c
        if (bus_connection_remove_name (connection, name)) {
Packit Service 1d8f1c
            BusConnectionOwner *owner =
Packit Service 1d8f1c
                    bus_name_service_find_owner (service, connection);
Packit Service 1d8f1c
            bus_name_service_remove_owner (service, owner, dbus);
Packit Service 1d8f1c
            if (service->owners == NULL) {
Packit Service 1d8f1c
                g_hash_table_remove (dbus->names, service->name);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            bus_connection_owner_free (owner);
Packit Service 1d8f1c
            retval = 1; /* DBUS_RELEASE_NAME_REPLY_RELEASED */
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else {
Packit Service 1d8f1c
            retval = 3; /* DBUS_RELEASE_NAME_REPLY_NOT_OWNER */
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", retval));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
start_service_timeout_cb (BusMethodCall *call)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *name= NULL;
Packit Service 1d8f1c
    guint32 flags;              /* currently not used in the D-Bus spec */
Packit Service 1d8f1c
    g_variant_get (call->parameters, "(&su)", &name, &flags);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_error (call->invocation,
Packit Service 1d8f1c
                    G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                    "Timeout reached before starting %s", name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    GList *p = g_list_find (call->dbus->start_service_calls, call);
Packit Service 1d8f1c
    g_return_val_if_fail (p != NULL, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_method_call_free ((BusMethodCall *) p->data);
Packit Service 1d8f1c
    call->dbus->start_service_calls =
Packit Service 1d8f1c
        g_list_delete_link (call->dbus->start_service_calls, p);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return FALSE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_start_service_by_name:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "StartServiceByName" method call of the
Packit Service 1d8f1c
 * org.freedesktop.DBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_start_service_by_name (BusDBusImpl           *dbus,
Packit Service 1d8f1c
                                     BusConnection         *connection,
Packit Service 1d8f1c
                                     GVariant              *parameters,
Packit Service 1d8f1c
                                     GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *name= NULL;
Packit Service 1d8f1c
    guint32 flags;              /* currently not used in the D-Bus spec */
Packit Service 1d8f1c
    g_variant_get (parameters, "(&su)", &name, &flags);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (name == NULL ||
Packit Service 1d8f1c
        !g_dbus_is_name (name) ||
Packit Service 1d8f1c
        g_dbus_is_unique_name (name)) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit Service 1d8f1c
                        "'%s' is not a legal service name.", name);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (name, "org.freedesktop.DBus") == 0 ||
Packit Service 1d8f1c
        g_strcmp0 (name, "org.freedesktop.IBus") == 0) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit Service 1d8f1c
                        "Service name '%s' is owned by IBus.", name);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_hash_table_lookup (dbus->names, name) != NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                        g_variant_new ("(u)",
Packit Service 1d8f1c
                                       IBUS_BUS_START_REPLY_ALREADY_RUNNING));
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusComponent *component = bus_ibus_impl_lookup_component_by_name (
Packit Service 1d8f1c
            BUS_DEFAULT_IBUS, name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (component == NULL || !bus_component_start (component, g_verbose)) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                        "Failed to start %s", name);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusMethodCall *call = bus_method_call_new (dbus,
Packit Service 1d8f1c
                                               connection,
Packit Service 1d8f1c
                                               parameters,
Packit Service 1d8f1c
                                               invocation);
Packit Service 1d8f1c
    call->timeout_id = g_timeout_add (g_gdbus_timeout,
Packit Service 1d8f1c
                                      (GSourceFunc) start_service_timeout_cb,
Packit Service 1d8f1c
                                      call);
Packit Service 1d8f1c
    dbus->start_service_calls = g_list_prepend (dbus->start_service_calls,
Packit Service 1d8f1c
                                                (gpointer) call);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_name_owner_changed:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * The function is called on name-owner-changed signal, typically when g_signal_emit (dbus, NAME_OWNER_CHANGED)
Packit Service 1d8f1c
 * is called, and broadcasts the signal to clients.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_name_owner_changed (BusDBusImpl   *dbus,
Packit Service 1d8f1c
                                  BusConnection *connection,
Packit Service 1d8f1c
                                  gchar         *name,
Packit Service 1d8f1c
                                  gchar         *old_owner,
Packit Service 1d8f1c
                                  gchar         *new_owner)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (name != NULL);
Packit Service 1d8f1c
    g_assert (old_owner != NULL);
Packit Service 1d8f1c
    g_assert (new_owner != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
Packit Service 1d8f1c
                                                       "org.freedesktop.DBus",
Packit Service 1d8f1c
                                                       "NameOwnerChanged");
Packit Service 1d8f1c
    g_dbus_message_set_sender (message, "org.freedesktop.DBus");
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* set a non-zero serial to make libdbus happy */
Packit Service 1d8f1c
    g_dbus_message_set_serial (message, 1);
Packit Service 1d8f1c
    g_dbus_message_set_body (message,
Packit Service 1d8f1c
                             g_variant_new ("(sss)", name, old_owner, new_owner));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* broadcast the message to clients that listen to the signal. */
Packit Service 1d8f1c
    bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL);
Packit Service 1d8f1c
    g_object_unref (message);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_name_lost:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * The function is called on name-lost signal, typically when g_signal_emit (dbus, NAME_LOST)
Packit Service 1d8f1c
 * is called, and broadcasts the signal to clients.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_name_lost (BusDBusImpl   *dbus,
Packit Service 1d8f1c
                         BusConnection *connection,
Packit Service 1d8f1c
                         gchar         *name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (name != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
Packit Service 1d8f1c
                                                       "org.freedesktop.DBus",
Packit Service 1d8f1c
                                                       "NameLost");
Packit Service 1d8f1c
    g_dbus_message_set_sender (message, "org.freedesktop.DBus");
Packit Service 1d8f1c
    g_dbus_message_set_destination (message, bus_connection_get_unique_name (connection));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* set a non-zero serial to make libdbus happy */
Packit Service 1d8f1c
    g_dbus_message_set_serial (message, 1);
Packit Service 1d8f1c
    g_dbus_message_set_body (message,
Packit Service 1d8f1c
                             g_variant_new ("(s)", name));
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_dbus_impl_forward_message (dbus, connection, message);
Packit Service 1d8f1c
    g_object_unref (message);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_name_acquired:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * The function is called on name-acquired signal, typically when g_signal_emit (dbus, NAME_ACQUIRED)
Packit Service 1d8f1c
 * is called, and broadcasts the signal to clients.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_name_acquired (BusDBusImpl   *dbus,
Packit Service 1d8f1c
                             BusConnection *connection,
Packit Service 1d8f1c
                             gchar         *name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (name != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
Packit Service 1d8f1c
                                                       "org.freedesktop.DBus",
Packit Service 1d8f1c
                                                       "NameAcquired");
Packit Service 1d8f1c
    g_dbus_message_set_sender (message, "org.freedesktop.DBus");
Packit Service 1d8f1c
    g_dbus_message_set_destination (message, bus_connection_get_unique_name (connection));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* set a non-zero serial to make libdbus happy */
Packit Service 1d8f1c
    g_dbus_message_set_serial (message, 1);
Packit Service 1d8f1c
    g_dbus_message_set_body (message,
Packit Service 1d8f1c
                             g_variant_new ("(s)", name));
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_dbus_impl_forward_message (dbus, connection, message);
Packit Service 1d8f1c
    g_object_unref (message);
Packit Service 1d8f1c
Packit Service 1d8f1c
    GList *p = dbus->start_service_calls;
Packit Service 1d8f1c
    while (p != NULL) {
Packit Service 1d8f1c
        BusMethodCall *call = p->data;
Packit Service 1d8f1c
        const gchar *_name= NULL;
Packit Service 1d8f1c
        guint32 flags;
Packit Service 1d8f1c
        GList *next = p->next;
Packit Service 1d8f1c
Packit Service 1d8f1c
        g_variant_get (call->parameters, "(&su)", &_name, &flags);
Packit Service 1d8f1c
        if (g_strcmp0 (name, _name) == 0) {
Packit Service 1d8f1c
            g_dbus_method_invocation_return_value (call->invocation,
Packit Service 1d8f1c
                            g_variant_new ("(u)",
Packit Service 1d8f1c
                                           IBUS_BUS_START_REPLY_SUCCESS));
Packit Service 1d8f1c
            bus_method_call_free ((BusMethodCall *) p->data);
Packit Service 1d8f1c
Packit Service 1d8f1c
            dbus->start_service_calls =
Packit Service 1d8f1c
                g_list_delete_link (dbus->start_service_calls, p);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        p = next;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_service_method_call:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Handle a D-Bus method call from a client. This function overrides an implementation in src/ibusservice.c.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_service_method_call (IBusService           *service,
Packit Service 1d8f1c
                                   GDBusConnection       *dbus_connection,
Packit Service 1d8f1c
                                   const gchar           *sender,
Packit Service 1d8f1c
                                   const gchar           *object_path,
Packit Service 1d8f1c
                                   const gchar           *interface_name,
Packit Service 1d8f1c
                                   const gchar           *method_name,
Packit Service 1d8f1c
                                   GVariant              *parameters,
Packit Service 1d8f1c
                                   GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    BusDBusImpl *dbus = BUS_DBUS_IMPL (service);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (interface_name, "org.freedesktop.DBus") != 0) {
Packit Service 1d8f1c
        IBUS_SERVICE_CLASS (bus_dbus_impl_parent_class)->service_method_call (
Packit Service 1d8f1c
                                        (IBusService *) dbus,
Packit Service 1d8f1c
                                        dbus_connection,
Packit Service 1d8f1c
                                        sender,
Packit Service 1d8f1c
                                        object_path,
Packit Service 1d8f1c
                                        interface_name,
Packit Service 1d8f1c
                                        method_name,
Packit Service 1d8f1c
                                        parameters,
Packit Service 1d8f1c
                                        invocation);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    static const struct {
Packit Service 1d8f1c
        const gchar *method_name;
Packit Service 1d8f1c
        void (* method) (BusDBusImpl *, BusConnection *, GVariant *, GDBusMethodInvocation *);
Packit Service 1d8f1c
    } methods[] =  {
Packit Service 1d8f1c
        /* DBus interface */
Packit Service 1d8f1c
        { "Hello",              bus_dbus_impl_hello },
Packit Service 1d8f1c
        { "ListNames",          bus_dbus_impl_list_names },
Packit Service 1d8f1c
        { "NameHasOwner",       bus_dbus_impl_name_has_owner },
Packit Service 1d8f1c
        { "GetNameOwner",       bus_dbus_impl_get_name_owner },
Packit Service 1d8f1c
        { "ListQueuedOwners",   bus_dbus_impl_list_queued_owners },
Packit Service 1d8f1c
        { "GetId",              bus_dbus_impl_get_id },
Packit Service 1d8f1c
        { "AddMatch",           bus_dbus_impl_add_match },
Packit Service 1d8f1c
        { "RemoveMatch",        bus_dbus_impl_remove_match },
Packit Service 1d8f1c
        { "RequestName",        bus_dbus_impl_request_name },
Packit Service 1d8f1c
        { "ReleaseName",        bus_dbus_impl_release_name },
Packit Service 1d8f1c
        { "StartServiceByName", bus_dbus_impl_start_service_by_name },
Packit Service 1d8f1c
    };
Packit Service 1d8f1c
Packit Service 1d8f1c
    gint i;
Packit Service 1d8f1c
    for (i = 0; i < G_N_ELEMENTS (methods); i++) {
Packit Service 1d8f1c
        if (g_strcmp0 (method_name, methods[i].method_name) == 0) {
Packit Service 1d8f1c
            BusConnection *connection = bus_connection_lookup (dbus_connection);
Packit Service 1d8f1c
            g_assert (BUS_IS_CONNECTION (connection));
Packit Service 1d8f1c
            methods[i].method (dbus, connection, parameters, invocation);
Packit Service 1d8f1c
            return;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* unsupported methods */
Packit Service 1d8f1c
    g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
Packit Service 1d8f1c
                                           "org.freedesktop.DBus does not support %s", method_name);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_service_get_property:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Handle a D-Bus method call from a client. This function overrides an implementation in src/ibusservice.c.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
bus_dbus_impl_service_get_property (IBusService        *service,
Packit Service 1d8f1c
                                    GDBusConnection    *connection,
Packit Service 1d8f1c
                                    const gchar        *sender,
Packit Service 1d8f1c
                                    const gchar        *object_path,
Packit Service 1d8f1c
                                    const gchar        *interface_name,
Packit Service 1d8f1c
                                    const gchar        *property_name,
Packit Service 1d8f1c
                                    GError            **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    /* FIXME implement the function. */
Packit Service 1d8f1c
    return IBUS_SERVICE_CLASS (bus_dbus_impl_parent_class)->
Packit Service 1d8f1c
                service_get_property (service,
Packit Service 1d8f1c
                                      connection,
Packit Service 1d8f1c
                                      sender,
Packit Service 1d8f1c
                                      object_path,
Packit Service 1d8f1c
                                      interface_name,
Packit Service 1d8f1c
                                      property_name,
Packit Service 1d8f1c
                                      error);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_service_set_property:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Handle a D-Bus method call from a client. This function overrides an implementation in src/ibusservice.c.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
bus_dbus_impl_service_set_property (IBusService        *service,
Packit Service 1d8f1c
                                    GDBusConnection    *connection,
Packit Service 1d8f1c
                                    const gchar        *sender,
Packit Service 1d8f1c
                                    const gchar        *object_path,
Packit Service 1d8f1c
                                    const gchar        *interface_name,
Packit Service 1d8f1c
                                    const gchar        *property_name,
Packit Service 1d8f1c
                                    GVariant           *value,
Packit Service 1d8f1c
                                    GError            **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    /* FIXME implement the function. */
Packit Service 1d8f1c
    return IBUS_SERVICE_CLASS (bus_dbus_impl_parent_class)->
Packit Service 1d8f1c
                service_set_property (service,
Packit Service 1d8f1c
                                      connection,
Packit Service 1d8f1c
                                      sender,
Packit Service 1d8f1c
                                      object_path,
Packit Service 1d8f1c
                                      interface_name,
Packit Service 1d8f1c
                                      property_name,
Packit Service 1d8f1c
                                      value,
Packit Service 1d8f1c
                                      error);
Packit Service 1d8f1c
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_connection_filter_cb:
Packit Service 1d8f1c
 * @returns: A GDBusMessage that will be processed by bus_dbus_impl_service_method_call. NULL when dropping the message.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * A filter function that is called for all incoming and outgoing messages.
Packit Service 1d8f1c
 * WARNING - this function could be called by the GDBus's worker thread. So you should not call thread unsafe IBus functions.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GDBusMessage *
Packit Service 1d8f1c
bus_dbus_impl_connection_filter_cb (GDBusConnection *dbus_connection,
Packit Service 1d8f1c
                                    GDBusMessage    *message,
Packit Service 1d8f1c
                                    gboolean         incoming,
Packit Service 1d8f1c
                                    gpointer         user_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (G_IS_DBUS_CONNECTION (dbus_connection));
Packit Service 1d8f1c
    g_assert (G_IS_DBUS_MESSAGE (message));
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (user_data));
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusDBusImpl *dbus = (BusDBusImpl *) user_data;
Packit Service 1d8f1c
    BusConnection *connection = bus_connection_lookup (dbus_connection);
Packit Service 1d8f1c
    g_assert (connection != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (incoming) {
Packit Service 1d8f1c
        /* is incoming message */
Packit Service 1d8f1c
Packit Service 1d8f1c
        /* get the destination aka bus name of the message. the destination is set by g_dbus_connection_call_sync (for DBus and IBus messages
Packit Service 1d8f1c
         * in the IBusBus class) or g_initable_new (for config and context messages in the IBusProxy sub classes.) */
Packit Service 1d8f1c
        const gchar *destination = g_dbus_message_get_destination (message);
Packit Service 1d8f1c
        GDBusMessageType message_type = g_dbus_message_get_message_type (message);
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (g_dbus_message_get_locked (message)) {
Packit Service 1d8f1c
            /* If the message is locked, we need make a copy of it. */
Packit Service 1d8f1c
            GDBusMessage *new_message = g_dbus_message_copy (message, NULL);
Packit Service 1d8f1c
            g_assert (new_message != NULL);
Packit Service 1d8f1c
            g_object_unref (message);
Packit Service 1d8f1c
            message = new_message;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        /* connection unique name as sender of the message*/
Packit Service 1d8f1c
        g_dbus_message_set_sender (message, bus_connection_get_unique_name (connection));
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (g_strcmp0 (destination, "org.freedesktop.IBus") == 0) {
Packit Service 1d8f1c
            /* the message is sent to IBus service. messages from ibusbus and ibuscontext may fall into this category. */
Packit Service 1d8f1c
            switch (message_type) {
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_ERROR:
Packit Service 1d8f1c
                /* dispatch messages by match rule */
Packit Service 1d8f1c
                bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL);
Packit Service 1d8f1c
                return message;
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_SIGNAL:
Packit Service 1d8f1c
                /* notreached - signals should not be sent to IBus service. dispatch signal messages by match rule, just in case. */
Packit Service 1d8f1c
                bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL);
Packit Service 1d8f1c
                g_object_unref (message);
Packit Service 1d8f1c
                g_return_val_if_reached (NULL);  /* return NULL since the service does not handle signals. */
Packit Service 1d8f1c
            default:
Packit Service 1d8f1c
                g_object_unref (message);
Packit Service 1d8f1c
                g_return_val_if_reached (NULL);  /* return NULL since the service does not handle signals. */
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else if (g_strcmp0 (destination, "org.freedesktop.DBus") == 0) {
Packit Service 1d8f1c
            /* the message is sent to DBus service. messages from ibusbus may fall into this category. */
Packit Service 1d8f1c
            switch (message_type) {
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_ERROR:
Packit Service 1d8f1c
                /* dispatch messages by match rule */
Packit Service 1d8f1c
                bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL);
Packit Service 1d8f1c
                return message;
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_SIGNAL:
Packit Service 1d8f1c
                /* notreached - signals should not be sent to IBus service. dispatch signal messages by match rule, just in case. */
Packit Service 1d8f1c
                bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL);
Packit Service 1d8f1c
                g_object_unref (message);
Packit Service 1d8f1c
                g_return_val_if_reached (NULL);  /* return NULL since the service does not handle signals. */
Packit Service 1d8f1c
            default:
Packit Service 1d8f1c
                g_object_unref (message);
Packit Service 1d8f1c
                g_return_val_if_reached (NULL);  /* return NULL since the service does not handle signals. */
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else if (destination == NULL) {
Packit Service 1d8f1c
            /* the message is sent to the current connection. communications between ibus-daemon and panel/engines may fall into this
Packit Service 1d8f1c
             * category since the panel/engine proxies created by ibus-daemon does not set bus name. */
Packit Service 1d8f1c
            switch (message_type) {
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_SIGNAL:
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_ERROR:
Packit Service 1d8f1c
                /* dispatch messages by match rule */
Packit Service 1d8f1c
                bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL);
Packit Service 1d8f1c
                return message;
Packit Service 1d8f1c
            case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
Packit Service 1d8f1c
                g_warning ("Unknown method call: destination=NULL, path='%s', interface='%s', member='%s'",
Packit Service 1d8f1c
                           g_dbus_message_get_path (message),
Packit Service 1d8f1c
                           g_dbus_message_get_interface (message),
Packit Service 1d8f1c
                           g_dbus_message_get_member (message));
Packit Service 1d8f1c
                bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL);
Packit Service 1d8f1c
                return message; /* return the message, GDBus library will handle it */
Packit Service 1d8f1c
            default:
Packit Service 1d8f1c
                /* notreached. */
Packit Service 1d8f1c
                g_object_unref (message);
Packit Service 1d8f1c
                g_return_val_if_reached (NULL);  /* return NULL since the service does not handle messages. */
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else {
Packit Service 1d8f1c
            /* The message is sent to an other service. Forward it.
Packit Service 1d8f1c
             * For example, the config proxy class in src/ibusconfig.c sets its "g-name" property (i.e. destination) to IBUS_SERVICE_CONFIG. */
Packit Service 1d8f1c
            bus_dbus_impl_forward_message (dbus, connection, message);
Packit Service 1d8f1c
            g_object_unref (message);
Packit Service 1d8f1c
            return NULL;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        /* is outgoing message */
Packit Service 1d8f1c
        if (g_dbus_message_get_sender (message) == NULL) {
Packit Service 1d8f1c
            if (g_dbus_message_get_locked (message)) {
Packit Service 1d8f1c
                GDBusMessage *new_message = g_dbus_message_copy (message, NULL);
Packit Service 1d8f1c
                g_assert (new_message != NULL);
Packit Service 1d8f1c
                g_object_unref (message);
Packit Service 1d8f1c
                message = new_message;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            /* If the message is sending from ibus-daemon directly,
Packit Service 1d8f1c
             * we set the sender to org.freedesktop.DBus */
Packit Service 1d8f1c
            g_dbus_message_set_sender (message, "org.freedesktop.DBus");
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        /* dispatch the outgoing message by rules. */
Packit Service 1d8f1c
        bus_dbus_impl_dispatch_message_by_rule (dbus, message, connection);
Packit Service 1d8f1c
        return message;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
BusDBusImpl *
Packit Service 1d8f1c
bus_dbus_impl_get_default (void)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    static BusDBusImpl *dbus = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (dbus == NULL) {
Packit Service 1d8f1c
        dbus = (BusDBusImpl *) g_object_new (BUS_TYPE_DBUS_IMPL,
Packit Service 1d8f1c
                                             "object-path", "/org/freedesktop/DBus",
Packit Service 1d8f1c
                                             NULL);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return dbus;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_connection_destroy_cb (BusConnection *connection,
Packit Service 1d8f1c
                                     BusDBusImpl   *dbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *unique_name = bus_connection_get_unique_name (connection);
Packit Service 1d8f1c
    const GList *names = NULL;
Packit Service 1d8f1c
    BusNameService *service = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (unique_name != NULL) {
Packit Service 1d8f1c
        GList *p = dbus->start_service_calls;
Packit Service 1d8f1c
        while (p != NULL) {
Packit Service 1d8f1c
            BusMethodCall *call = p->data;
Packit Service 1d8f1c
            GList *next = p->next;
Packit Service 1d8f1c
Packit Service 1d8f1c
            if (call->connection == connection) {
Packit Service 1d8f1c
                bus_method_call_free ((BusMethodCall *) p->data);
Packit Service 1d8f1c
                dbus->start_service_calls =
Packit Service 1d8f1c
                    g_list_delete_link (dbus->start_service_calls, p);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            p = next;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        g_hash_table_remove (dbus->unique_names, unique_name);
Packit Service 1d8f1c
        g_signal_emit (dbus,
Packit Service 1d8f1c
                       dbus_signals[NAME_OWNER_CHANGED],
Packit Service 1d8f1c
                       0,
Packit Service 1d8f1c
                       connection,
Packit Service 1d8f1c
                       unique_name,
Packit Service 1d8f1c
                       unique_name,
Packit Service 1d8f1c
                       "");
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* service->owners is the queue of connections.
Packit Service 1d8f1c
     * If the connection is the primary owner and
Packit Service 1d8f1c
     * bus_name_service_remove_owner() is called, the owner is removed
Packit Service 1d8f1c
     * in the queue and the next owner will become the primary owner
Packit Service 1d8f1c
     * automatically because service->owners is just a GSList.
Packit Service 1d8f1c
     * If service->owners == NULL, it's good to remove the service in
Packit Service 1d8f1c
     * dbus->names.
Packit Service 1d8f1c
     * I suppose dbus->names are the global queue for every connection
Packit Service 1d8f1c
     * and connection->names are the private queue of the connection.
Packit Service 1d8f1c
     */
Packit Service 1d8f1c
    names = bus_connection_get_names (connection);
Packit Service 1d8f1c
    while (names != NULL) {
Packit Service 1d8f1c
        const gchar *name = (const gchar *)names->data;
Packit Service 1d8f1c
        service = (BusNameService *) g_hash_table_lookup (dbus->names,
Packit Service 1d8f1c
                                                          name);
Packit Service 1d8f1c
        g_assert (service != NULL);
Packit Service 1d8f1c
        BusConnectionOwner *owner = bus_name_service_find_owner (service,
Packit Service 1d8f1c
                connection);
Packit Service 1d8f1c
        g_assert (owner != NULL);
Packit Service 1d8f1c
        bus_name_service_remove_owner (service, owner, dbus);
Packit Service 1d8f1c
        if (service->owners == NULL) {
Packit Service 1d8f1c
            g_hash_table_remove (dbus->names, service->name);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        bus_connection_owner_free (owner);
Packit Service 1d8f1c
        names = names->next;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    dbus->connections = g_list_remove (dbus->connections, connection);
Packit Service 1d8f1c
    g_object_unref (connection);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
gboolean
Packit Service 1d8f1c
bus_dbus_impl_new_connection (BusDBusImpl   *dbus,
Packit Service 1d8f1c
                              BusConnection *connection)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (BUS_IS_CONNECTION (connection));
Packit Service 1d8f1c
    g_assert (g_list_find (dbus->connections, connection) == NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_object_ref_sink (connection);
Packit Service 1d8f1c
    dbus->connections = g_list_append (dbus->connections, connection);
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_connection_set_filter (connection,
Packit Service 1d8f1c
                    bus_dbus_impl_connection_filter_cb, g_object_ref (dbus), g_object_unref);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (connection,
Packit Service 1d8f1c
                      "destroy",
Packit Service 1d8f1c
                      G_CALLBACK (bus_dbus_impl_connection_destroy_cb),
Packit Service 1d8f1c
                      dbus);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* add introspection_xml[] (see above) to the connection. */
Packit Service 1d8f1c
    ibus_service_register ((IBusService *) dbus,
Packit Service 1d8f1c
                    bus_connection_get_dbus_connection (connection), NULL);
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
    for (p = dbus->objects; p != NULL; p = p->next) {
Packit Service 1d8f1c
        /* add all introspection xmls in dbus->objects to the connection. */
Packit Service 1d8f1c
        ibus_service_register ((IBusService *) p->data,
Packit Service 1d8f1c
                        bus_connection_get_dbus_connection (connection), NULL);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
BusConnection *
Packit Service 1d8f1c
bus_dbus_impl_get_connection_by_name (BusDBusImpl    *dbus,
Packit Service 1d8f1c
                                      const gchar    *name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (name != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (G_LIKELY (g_dbus_is_unique_name (name))) {
Packit Service 1d8f1c
        return (BusConnection *) g_hash_table_lookup (dbus->unique_names, name);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        BusNameService *service;
Packit Service 1d8f1c
        BusConnectionOwner *owner;
Packit Service 1d8f1c
Packit Service 1d8f1c
        service = (BusNameService *) g_hash_table_lookup (dbus->names, name);
Packit Service 1d8f1c
        if (service == NULL) {
Packit Service 1d8f1c
            return NULL;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        owner = bus_name_service_get_primary_owner (service);
Packit Service 1d8f1c
        return owner ? owner->conn : NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
typedef struct _BusForwardData BusForwardData;
Packit Service 1d8f1c
struct _BusForwardData {
Packit Service 1d8f1c
    GDBusMessage *message;
Packit Service 1d8f1c
    BusConnection *sender_connection;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_forward_message_ible_cb:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Process the first element of the dbus->forward_queue. The first element is forwarded by g_dbus_connection_send_message.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
bus_dbus_impl_forward_message_idle_cb (BusDBusImpl   *dbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (dbus->forward_queue != NULL, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_mutex_lock (&dbus->forward_lock);
Packit Service 1d8f1c
    BusForwardData *data = (BusForwardData *) dbus->forward_queue->data;
Packit Service 1d8f1c
    dbus->forward_queue = g_list_delete_link (dbus->forward_queue, dbus->forward_queue);
Packit Service 1d8f1c
    gboolean has_message = (dbus->forward_queue != NULL);
Packit Service 1d8f1c
    g_mutex_unlock (&dbus->forward_lock);
Packit Service 1d8f1c
Packit Service 1d8f1c
    do {
Packit Service 1d8f1c
        const gchar *destination = g_dbus_message_get_destination (data->message);
Packit Service 1d8f1c
        BusConnection *dest_connection = NULL;
Packit Service 1d8f1c
        if (destination != NULL)
Packit Service 1d8f1c
            dest_connection = bus_dbus_impl_get_connection_by_name (dbus, destination);
Packit Service 1d8f1c
        if (dest_connection != NULL) {
Packit Service 1d8f1c
            /* FIXME workaround for gdbus. gdbus can not set an empty body message with signature '()' */
Packit Service 1d8f1c
            if (g_dbus_message_get_body (data->message) == NULL)
Packit Service 1d8f1c
                g_dbus_message_set_signature (data->message, NULL);
Packit Service 1d8f1c
            GError *error = NULL;
Packit Service 1d8f1c
            gboolean retval = g_dbus_connection_send_message (
Packit Service 1d8f1c
                                        bus_connection_get_dbus_connection (dest_connection),
Packit Service 1d8f1c
                                        data->message,
Packit Service 1d8f1c
                                        G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL,
Packit Service 1d8f1c
                                        NULL, &error);
Packit Service 1d8f1c
            if (retval)
Packit Service 1d8f1c
                break;
Packit Service 1d8f1c
            g_warning ("forward message failed:  %s.", error->message);
Packit Service 1d8f1c
            g_error_free (error);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        /* can not forward message */
Packit Service 1d8f1c
        if (g_dbus_message_get_message_type (data->message) != G_DBUS_MESSAGE_TYPE_METHOD_CALL) {
Packit Service 1d8f1c
            /* skip non method messages */
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        /* reply an error message, if forward method call message failed. */
Packit Service 1d8f1c
        GDBusMessage *reply_message = g_dbus_message_new_method_error (data->message,
Packit Service 1d8f1c
                            "org.freedesktop.DBus.Error.ServiceUnknown ",
Packit Service 1d8f1c
                            "The service name is '%s'.", destination);
Packit Service 1d8f1c
        g_dbus_message_set_sender (reply_message, "org.freedesktop.DBus");
Packit Service 1d8f1c
        g_dbus_message_set_destination (reply_message, bus_connection_get_unique_name (data->sender_connection));
Packit Service 1d8f1c
        g_dbus_connection_send_message (bus_connection_get_dbus_connection (data->sender_connection),
Packit Service 1d8f1c
                                        reply_message,
Packit Service 1d8f1c
                                        G_DBUS_SEND_MESSAGE_FLAGS_NONE,
Packit Service 1d8f1c
                                        NULL, NULL);
Packit Service 1d8f1c
        g_object_unref (reply_message);
Packit Service 1d8f1c
    } while (0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_object_unref (data->message);
Packit Service 1d8f1c
    g_object_unref (data->sender_connection);
Packit Service 1d8f1c
    g_slice_free (BusForwardData, data);
Packit Service 1d8f1c
    return has_message;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
void
Packit Service 1d8f1c
bus_dbus_impl_forward_message (BusDBusImpl   *dbus,
Packit Service 1d8f1c
                               BusConnection *connection,
Packit Service 1d8f1c
                               GDBusMessage  *message)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    /* WARNING - this function could be called by the GDBus's worker thread. So you should not call thread unsafe IBus functions. */
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (BUS_IS_CONNECTION (connection));
Packit Service 1d8f1c
    g_assert (G_IS_DBUS_MESSAGE (message));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (G_UNLIKELY (IBUS_OBJECT_DESTROYED (dbus)))
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    /* FIXME the check above might not be sufficient. dbus object could be destroyed in the main thread right after the check, though the
Packit Service 1d8f1c
     * dbus structure itself would not be freed (since the dbus object is ref'ed in bus_dbus_impl_new_connection.)
Packit Service 1d8f1c
     * Anyway, it'd be better to investigate whether the thread safety issue could cause any real problems. */
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusForwardData *data = g_slice_new (BusForwardData);
Packit Service 1d8f1c
    data->message = g_object_ref (message);
Packit Service 1d8f1c
    data->sender_connection = g_object_ref (connection);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_mutex_lock (&dbus->forward_lock);
Packit Service 1d8f1c
    gboolean is_running = (dbus->forward_queue != NULL);
Packit Service 1d8f1c
    dbus->forward_queue = g_list_append (dbus->forward_queue, data);
Packit Service 1d8f1c
    g_mutex_unlock (&dbus->forward_lock);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!is_running) {
Packit Service 1d8f1c
        g_idle_add_full (G_PRIORITY_DEFAULT,
Packit Service 1d8f1c
                (GSourceFunc) bus_dbus_impl_forward_message_idle_cb,
Packit Service 1d8f1c
                g_object_ref (dbus), (GDestroyNotify) g_object_unref);
Packit Service 1d8f1c
        /* the idle callback function will be called from the ibus's main thread. */
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static BusDispatchData *
Packit Service 1d8f1c
bus_dispatch_data_new (GDBusMessage  *message,
Packit Service 1d8f1c
                       BusConnection *skip_connection)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    BusDispatchData *data = g_slice_new (BusDispatchData);
Packit Service 1d8f1c
Packit Service 1d8f1c
    data->message = (GDBusMessage *) g_object_ref (message);
Packit Service 1d8f1c
    if (skip_connection) {
Packit Service 1d8f1c
        data->skip_connection = (BusConnection *) g_object_ref (skip_connection);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        data->skip_connection = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return data;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dispatch_data_free (BusDispatchData *data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_object_unref (data->message);
Packit Service 1d8f1c
    if (data->skip_connection)
Packit Service 1d8f1c
        g_object_unref (data->skip_connection);
Packit Service 1d8f1c
    g_slice_free (BusDispatchData, data);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_dbus_impl_dispatch_message_by_rule_idle_cb:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Process the first element of the dbus->dispatch_queue.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
bus_dbus_impl_dispatch_message_by_rule_idle_cb (BusDBusImpl *dbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (dbus->dispatch_queue != NULL, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (G_UNLIKELY (IBUS_OBJECT_DESTROYED (dbus))) {
Packit Service 1d8f1c
        /* dbus was destryed */
Packit Service 1d8f1c
        g_mutex_lock (&dbus->dispatch_lock);
Packit Service 1d8f1c
        g_list_free_full (dbus->dispatch_queue,
Packit Service 1d8f1c
                          (GDestroyNotify) bus_dispatch_data_free);
Packit Service 1d8f1c
        dbus->dispatch_queue = NULL;
Packit Service 1d8f1c
        g_mutex_unlock (&dbus->dispatch_lock);
Packit Service 1d8f1c
        return FALSE; /* return FALSE to prevent this callback to be called again. */
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* remove fist node */
Packit Service 1d8f1c
    g_mutex_lock (&dbus->dispatch_lock);
Packit Service 1d8f1c
    BusDispatchData *data = (BusDispatchData *) dbus->dispatch_queue->data;
Packit Service 1d8f1c
    dbus->dispatch_queue = g_list_delete_link (dbus->dispatch_queue, dbus->dispatch_queue);
Packit Service 1d8f1c
    gboolean has_message = (dbus->dispatch_queue != NULL);
Packit Service 1d8f1c
    g_mutex_unlock (&dbus->dispatch_lock);
Packit Service 1d8f1c
Packit Service 1d8f1c
    GList *link = NULL;
Packit Service 1d8f1c
    GList *recipients = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* check each match rules, and get recipients */
Packit Service 1d8f1c
    for (link = dbus->rules; link != NULL; link = link->next) {
Packit Service 1d8f1c
        GList *list = bus_match_rule_get_recipients ((BusMatchRule *) link->data,
Packit Service 1d8f1c
                                                     data->message);
Packit Service 1d8f1c
        recipients = g_list_concat (recipients, list);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* send message to each recipients */
Packit Service 1d8f1c
    for (link = recipients; link != NULL; link = link->next) {
Packit Service 1d8f1c
        BusConnection *connection = (BusConnection *) link->data;
Packit Service 1d8f1c
        if (G_LIKELY (connection != data->skip_connection)) {
Packit Service 1d8f1c
            g_dbus_connection_send_message (bus_connection_get_dbus_connection (connection),
Packit Service 1d8f1c
                                            data->message,
Packit Service 1d8f1c
                                            G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL,
Packit Service 1d8f1c
                                            NULL, NULL);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_list_free (recipients);
Packit Service 1d8f1c
    bus_dispatch_data_free (data);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return has_message;  /* remove this idle callback if no message is left by returning FALSE. */
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
void
Packit Service 1d8f1c
bus_dbus_impl_dispatch_message_by_rule (BusDBusImpl     *dbus,
Packit Service 1d8f1c
                                        GDBusMessage    *message,
Packit Service 1d8f1c
                                        BusConnection   *skip_connection)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    /* WARNING - this function could be called by the GDBus's worker thread. So you should not call thread unsafe IBus functions. */
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (message != NULL);
Packit Service 1d8f1c
    g_assert (skip_connection == NULL || BUS_IS_CONNECTION (skip_connection));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (G_UNLIKELY (IBUS_OBJECT_DESTROYED (dbus)))
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    /* FIXME - see the FIXME comment in bus_dbus_impl_forward_message. */
Packit Service 1d8f1c
Packit Service 1d8f1c
    static GQuark dispatched_quark = 0;
Packit Service 1d8f1c
    if (dispatched_quark == 0) {
Packit Service 1d8f1c
        dispatched_quark = g_quark_from_static_string ("DISPATCHED");
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* A message sent or forwarded by bus_dbus_impl_dispatch_message_by_rule_idle_cb is also processed by the filter callback.
Packit Service 1d8f1c
     * If this message has been dispatched by rule, do nothing. */
Packit Service 1d8f1c
    if (g_object_get_qdata ((GObject *) message, dispatched_quark) != NULL)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    g_object_set_qdata ((GObject *) message, dispatched_quark, GINT_TO_POINTER (1));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* append dispatch data into the queue, and start idle task if necessary */
Packit Service 1d8f1c
    g_mutex_lock (&dbus->dispatch_lock);
Packit Service 1d8f1c
    gboolean is_running = (dbus->dispatch_queue != NULL);
Packit Service 1d8f1c
    dbus->dispatch_queue = g_list_append (dbus->dispatch_queue,
Packit Service 1d8f1c
                    bus_dispatch_data_new (message, skip_connection));
Packit Service 1d8f1c
    g_mutex_unlock (&dbus->dispatch_lock);
Packit Service 1d8f1c
    if (!is_running) {
Packit Service 1d8f1c
        g_idle_add_full (G_PRIORITY_DEFAULT,
Packit Service 1d8f1c
                         (GSourceFunc) bus_dbus_impl_dispatch_message_by_rule_idle_cb,
Packit Service 1d8f1c
                         g_object_ref (dbus),
Packit Service 1d8f1c
                         (GDestroyNotify) g_object_unref);
Packit Service 1d8f1c
        /* the idle callback function will be called from the ibus's main thread. */
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_dbus_impl_object_destroy_cb (IBusService *object,
Packit Service 1d8f1c
                                 BusDBusImpl *dbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    bus_dbus_impl_unregister_object (dbus, object);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
gboolean
Packit Service 1d8f1c
bus_dbus_impl_register_object (BusDBusImpl *dbus,
Packit Service 1d8f1c
                               IBusService *object)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (IBUS_IS_SERVICE (object));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (G_UNLIKELY (IBUS_OBJECT_DESTROYED (dbus))) {
Packit Service 1d8f1c
        return FALSE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    dbus->objects = g_list_prepend (dbus->objects, g_object_ref (object));
Packit Service 1d8f1c
    g_signal_connect (object, "destroy",
Packit Service 1d8f1c
                      G_CALLBACK (bus_dbus_impl_object_destroy_cb), dbus);
Packit Service 1d8f1c
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
    for (p = dbus->connections; p != NULL; p = p->next) {
Packit Service 1d8f1c
        GDBusConnection *connection = bus_connection_get_dbus_connection ((BusConnection *) p->data);
Packit Service 1d8f1c
        if (connection != ibus_service_get_connection ((IBusService *) object))
Packit Service 1d8f1c
            ibus_service_register ((IBusService *) object,
Packit Service 1d8f1c
                            bus_connection_get_dbus_connection ((BusConnection *) p->data), NULL);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
gboolean
Packit Service 1d8f1c
bus_dbus_impl_unregister_object (BusDBusImpl *dbus,
Packit Service 1d8f1c
                                 IBusService *object)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (IBUS_IS_SERVICE (object));
Packit Service 1d8f1c
Packit Service 1d8f1c
    GList *p = g_list_find (dbus->objects, object);
Packit Service 1d8f1c
    if (p == NULL)
Packit Service 1d8f1c
        return FALSE;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_handlers_disconnect_by_func (object,
Packit Service 1d8f1c
                    G_CALLBACK (bus_dbus_impl_object_destroy_cb), dbus);
Packit Service 1d8f1c
    dbus->objects = g_list_delete_link (dbus->objects, p);
Packit Service 1d8f1c
    if (!IBUS_OBJECT_DESTROYED (object)) {
Packit Service 1d8f1c
        GList *p;
Packit Service 1d8f1c
        for (p = dbus->connections; p != NULL; p = p->next) {
Packit Service 1d8f1c
            ibus_service_unregister ((IBusService *) object,
Packit Service 1d8f1c
                            bus_connection_get_dbus_connection ((BusConnection *) p->data));
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_object_unref (object);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c