Index: chromeos/dbus/dbus.cc |
diff --git a/chromeos/dbus/dbus.cc b/chromeos/dbus/dbus.cc |
index 33ef997185c69748e5c88a6f9749bb5150a50cd6..24b220e3e68cca83f39cd2bfc1ceedc9f7d0c9ff 100644 |
--- a/chromeos/dbus/dbus.cc |
+++ b/chromeos/dbus/dbus.cc |
@@ -4,10 +4,12 @@ |
#include "chromeos/dbus/dbus.h" |
-#include <dbus/dbus.h> |
-#include <dbus/dbus-glib-bindings.h> |
#include <dbus/dbus-glib-lowlevel.h> |
-#include <base/logging.h> |
+#include <dbus/dbus-glib-bindings.h> |
+#include <dbus/dbus.h> |
+ |
+#include "base/logging.h" |
+#include "base/stringprintf.h" |
namespace chromeos { |
namespace dbus { |
@@ -256,5 +258,71 @@ void SendSignalWithNoArgumentsToSystemBus(const char* path, |
::dbus_message_unref(signal); |
} |
+void SignalWatcher::StartMonitoring(const string& interface, |
+ const string& signal) { |
+ DCHECK(!interface_.empty()) << "StartMonitoring() must be called only once"; |
+ interface_ = interface; |
+ signal_ = signal; |
+ |
+ // Snoop on D-Bus messages so we can get notified about signals. |
+ DBusConnection* dbus_conn = dbus_g_connection_get_connection( |
+ GetSystemBusConnection().g_connection()); |
+ DCHECK(dbus_conn); |
+ |
+ DBusError error; |
+ dbus_error_init(&error); |
+ dbus_bus_add_match(dbus_conn, GetDBusMatchString().c_str(), &error); |
+ if (dbus_error_is_set(&error)) { |
+ LOG(DFATAL) << "Got error while adding D-Bus match rule: " << error.name |
+ << " (" << error.message << ")"; |
+ } |
+ |
+ if (!dbus_connection_add_filter(dbus_conn, |
+ &SignalWatcher::FilterDBusMessage, |
+ this, // user_data |
+ NULL)) { // free_data_function |
+ LOG(DFATAL) << "Unable to add D-Bus filter"; |
+ } |
+} |
+ |
+SignalWatcher::~SignalWatcher() { |
+ if (interface_.empty()) |
+ return; |
+ |
+ DBusConnection* dbus_conn = dbus_g_connection_get_connection( |
+ dbus::GetSystemBusConnection().g_connection()); |
+ DCHECK(dbus_conn); |
+ |
+ dbus_connection_remove_filter(dbus_conn, |
+ &SignalWatcher::FilterDBusMessage, |
+ this); |
+ |
+ DBusError error; |
+ dbus_error_init(&error); |
+ dbus_bus_remove_match(dbus_conn, GetDBusMatchString().c_str(), &error); |
+ if (dbus_error_is_set(&error)) { |
+ LOG(DFATAL) << "Got error while removing D-Bus match rule: " << error.name |
+ << " (" << error.message << ")"; |
+ } |
+} |
+ |
+std::string SignalWatcher::GetDBusMatchString() const { |
+ return StringPrintf("type='signal', interface='%s', member='%s'", |
+ interface_.c_str(), signal_.c_str()); |
+} |
+ |
+/* static */ |
+DBusHandlerResult SignalWatcher::FilterDBusMessage(DBusConnection* dbus_conn, |
+ DBusMessage* message, |
+ void* data) { |
+ SignalWatcher* self = static_cast<SignalWatcher*>(data); |
+ if (dbus_message_is_signal(message, self->interface_, self->signal_)) { |
+ self->OnSignal(message); |
+ return DBUS_HANDLER_RESULT_HANDLED; |
+ } else { |
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
+ } |
+} |
+ |
} // namespace dbus |
} // namespace chromeos |