gboolean
hippo_dbus_open_chat_blocking(const char   *server,
                              HippoChatKind kind,
                              const char   *chat_id,
                              GError      **error)
{
    DBusConnection *connection;
    gboolean result;
    DBusError derror;
    DBusMessage *message;
    DBusMessage *reply;
    char *bus_name;
    const char *kind_str;

    g_return_val_if_fail(error == NULL || *error == NULL, FALSE);

    connection = get_connection(error);
    if (connection == NULL)
        return FALSE;

    result = FALSE;
    
    bus_name = hippo_dbus_full_bus_name(server);
    
    message = dbus_message_new_method_call(bus_name,
                                           HIPPO_DBUS_PATH,
                                           HIPPO_DBUS_INTERFACE,
                                           "ShowChatWindow");
    if (message == NULL)
        g_error("out of memory");
        
    /* we don't want to start a client if none is already there */
    dbus_message_set_auto_start(message, FALSE);
    
    kind_str = hippo_chat_kind_as_string(kind);
    
    if (!dbus_message_append_args(message,
                                  DBUS_TYPE_STRING, &chat_id,
                                  DBUS_TYPE_INVALID))
        g_error("out of memory");                                  

    dbus_error_init(&derror);
    reply = dbus_connection_send_with_reply_and_block(connection, message, -1,
                                                      &derror);

    dbus_message_unref (message);

    if (reply == NULL) {
        propagate_dbus_error(error, &derror);
        goto out;
    }

    dbus_message_unref(reply);
    
    result = TRUE;

  out:
    /* any cleanup goes here */

    return result;
}
HippoDBusIpcProviderImpl::HippoDBusIpcProviderImpl(const char *serverName)
{
    refCount_ = 1;
    serverName_ = g_strdup(serverName);
    busName_ = hippo_dbus_full_bus_name(serverName);
    busNameOwnerChangedRule_ =
        g_strdup_printf("type='signal',sender='%s',member='NameOwnerChanged',arg0='%s'",
                        DBUS_SERVICE_DBUS, busName_);
    listener_ = NULL;
    busUniqueName_ = NULL;
    clientConnected_ = false;
    
    /* If for some reason we can't get a bus connection we want to just go into
     * a "no-op" mode; otherwise, we'd suddenly make Firefox rely on having
     * an active dbus, while currently it does not.
     */
    
    GError *gerror = NULL;
    DBusGConnection *gconnection = dbus_g_bus_get(DBUS_BUS_SESSION, &gerror);
    if (gconnection == NULL) {
	g_printerr("Can't get session bus connection: %s", gerror->message);
        g_error_free(gerror);
        return;
    }

    if (!connection_) {
        connection_ = dbus_g_connection_get_connection(gconnection);
        if (!dbus_connection_get_is_connected(connection_)) {
            /* This should be impossible with newer dbus which sets the
             * shared bus connection to NULL when it disconnects,
             * so we should not have gotten a disconnected one.
             * But we check here for old dbus to be sure we'll get
             * a Disconnected message later.
             */
            g_warning("Connection to the session's message bus is disconnected");
            dbus_connection_unref(connection_);
            connection_ = NULL;
            return;
        }
    }
    
    DBusError derror;
    dbus_error_init(&derror);
    /* it's fine if multiple instances do this, the bus refcounts it */
    dbus_bus_add_match(connection_,
                       busNameOwnerChangedRule_,
                       &derror);
    if (dbus_error_is_set(&derror)) {
        g_warning("Failed to add name owner changed rule: %s: %s: %s",
                  busNameOwnerChangedRule_,
                  derror.name,
                  derror.message);
        dbus_error_free(&derror);
        // See comment in forgetBusConnection
        // dbus_connection_unref(connection_);
        // connection_ = NULL;
        return;
    }
    
    if (!dbus_connection_add_filter(connection_, handleMessageCallback,
                                    (void *)this, NULL)) {
        g_error("no memory adding dbus connection filter");
    }

    g_debug("Connected to session bus");
    
    /* this may fail, in which case when we get the NameOwnerChanged indicating a new
     * client started up, we'll retry.
     */
    tryIpcConnect();
}