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(); }