Two changes to the DBus C++ library.
- Added GetPrivateBusConnection() which is necessary to implement language switcher integrated with Chrome (http://bit.ly/8LUDJE). We have to make a DBus connection for the language switcher private, since im_ibus.so (GTK_IM_MODULE for Chrome) establishes a DBus connection to the same address and the IM module does not expect that the connection is shared with other code in the same process. If we don't make the connection private, im_ibus.so dies with g_assert.
- Added another constructor to the Proxy class so that the language switcher can connect to IME candidate window using ::::dbus_g_proxy_new_for_name_owner() API.
This change is for http://codereview.chromium.org/460107
BUG=494
Review URL: http://codereview.chromium.org/500008
diff --git a/chromeos/dbus/dbus.cc b/chromeos/dbus/dbus.cc
index 9ca4104..26e3c76 100644
--- a/chromeos/dbus/dbus.cc
+++ b/chromeos/dbus/dbus.cc
@@ -44,6 +44,38 @@
return BusConnection(result);
}
+BusConnection GetPrivateBusConnection(const char* address) {
+ // Since dbus-glib does not have an API like dbus_g_connection_open_private(),
+ // we have to implement our own.
+
+ // We have to call _dbus_g_value_types_init() to register standard marshalers
+ // just like as dbus_g_bus_get() and dbus_g_connection_open() do, but the
+ // function is not exported. So we call GetPrivateBusConnection() which calls
+ // dbus_g_bus_get() here instead. Note that if we don't call
+ // _dbus_g_value_types_init(), we might get "WARNING **: No demarshaller
+ // registered for type xxxxx" error and might not be able to handle incoming
+ // signals nor method calls.
+ GetSystemBusConnection();
+
+ ::DBusGConnection* result = NULL;
+ ::DBusConnection* raw_connection
+ = ::dbus_connection_open_private(address, NULL);
+ CHECK(raw_connection);
+
+ ::dbus_connection_setup_with_g_main(raw_connection, NULL);
+ // A reference count of |raw_connection| is transferred to |result|. You don't
+ // have to (and should not) unref the |raw_connection|.
+ result = ::dbus_connection_get_g_connection(raw_connection);
+ CHECK(result);
+
+ ::dbus_connection_set_exit_on_disconnect(
+ ::dbus_g_connection_get_connection(result), FALSE);
+
+ // TODO(yusukes): We should call dbus_connection_close() for private
+ // connections.
+ return BusConnection(result);
+}
+
bool RetrieveProperties(const Proxy& proxy,
const char* interface,
glib::ScopedHashTable* result) {
@@ -61,6 +93,36 @@
return true;
}
+/* static */
+Proxy::value_type Proxy::GetGProxy(const BusConnection& connection,
+ const char* name,
+ const char* path,
+ const char* interface,
+ bool connect_to_name_owner) {
+ value_type result = NULL;
+ if (connect_to_name_owner) {
+ glib::ScopedError error;
+ result = ::dbus_g_proxy_new_for_name_owner(connection.object_,
+ name,
+ path,
+ interface,
+ &Resetter(&error).lvalue());
+ if (!result) {
+ LOG(ERROR) << "Failed to construct proxy: "
+ << (error->message ? error->message : "Unknown Error")
+ << ": " << path;
+ }
+ } else {
+ result = ::dbus_g_proxy_new_for_name(connection.object_,
+ name,
+ path,
+ interface);
+ if (!result) {
+ LOG(ERROR) << "Failed to construct proxy: " << path;
+ }
+ }
+ return result;
+}
} // namespace dbus
} // namespace chromeos
diff --git a/chromeos/dbus/dbus.h b/chromeos/dbus/dbus.h
index 1f7253e..f11a7ef 100644
--- a/chromeos/dbus/dbus.h
+++ b/chromeos/dbus/dbus.h
@@ -51,6 +51,7 @@
friend class Proxy;
friend BusConnection GetSystemBusConnection();
+ friend BusConnection GetPrivateBusConnection(const char* address);
// Constructor takes ownership
explicit BusConnection(::DBusGConnection* x)
@@ -80,13 +81,23 @@
: object_(NULL) {
}
+ // Set |connect_to_name_owner| true if you'd like to use
+ // dbus_g_proxy_new_for_name_owner() rather than dbus_g_proxy_new_for_name().
+ Proxy(const BusConnection& connection,
+ const char* name,
+ const char* path,
+ const char* interface,
+ bool connect_to_name_owner)
+ : object_(GetGProxy(
+ connection, name, path, interface, connect_to_name_owner)) {
+ }
+
+ // Equivalent to Proxy(connection, name, path, interface, false).
Proxy(const BusConnection& connection,
const char* name,
const char* path,
const char* interface)
- : object_(::dbus_g_proxy_new_for_name(connection.object_, name, path,
- interface)) {
- DCHECK(object_) << "Failed to construct proxy.";
+ : object_(GetGProxy(connection, name, path, interface, false)) {
}
Proxy(const Proxy& x)
@@ -123,6 +134,12 @@
}
private:
+ static value_type GetGProxy(const BusConnection& connection,
+ const char* name,
+ const char* path,
+ const char* interface,
+ bool connect_to_name_owner);
+
operator int() const; // for safe bool cast
friend void swap(Proxy& x, Proxy& y);
@@ -280,7 +297,8 @@
G_TYPE_INVALID,
G_TYPE_VALUE, &value,
G_TYPE_INVALID)){
- LOG(ERROR) << "Getting property failed: " << (error->message ? error->message : "Unknown Error.");
+ LOG(ERROR) << "Getting property failed: "
+ << (error->message ? error->message : "Unknown Error.");
return false;
}
@@ -298,6 +316,10 @@
BusConnection GetSystemBusConnection();
+// \brief Returns a private connection to a bus at |address|.
+
+BusConnection GetPrivateBusConnection(const char* address);
+
} // namespace dbus
} // namespace chromeos