diff options
-rw-r--r-- | dbus/end_to_end_async_unittest.cc | 56 | ||||
-rw-r--r-- | dbus/object_proxy.cc | 6 | ||||
-rw-r--r-- | dbus/object_proxy.h | 7 |
3 files changed, 61 insertions, 8 deletions
diff --git a/dbus/end_to_end_async_unittest.cc b/dbus/end_to_end_async_unittest.cc index 600c83a..9be24e0 100644 --- a/dbus/end_to_end_async_unittest.cc +++ b/dbus/end_to_end_async_unittest.cc @@ -343,3 +343,59 @@ TEST_F(EndToEndAsyncTest, TestSignalFromRoot) { // Verify the string WAS received by the root proxy. ASSERT_EQ(kMessage, root_test_signal_string_); } + +class SignalReplacementTest : public EndToEndAsyncTest { + public: + SignalReplacementTest() { + } + + virtual void SetUp() { + // Set up base class. + EndToEndAsyncTest::SetUp(); + + // Reconnect the root object proxy's signal handler to a new handler + // so that we can verify that a second call to ConnectSignal() delivers + // to our new handler and not the old. + object_proxy_->ConnectToSignal( + "org.chromium.TestInterface", + "Test", + base::Bind(&SignalReplacementTest::OnReplacementTestSignal, + base::Unretained(this)), + base::Bind(&SignalReplacementTest::OnReplacementConnected, + base::Unretained(this))); + // Wait until the object proxy is connected to the signal. + message_loop_.Run(); + } + + protected: + // Called when the "Test" signal is received, in the main thread. + // Copy the string payload to |replacement_test_signal_string_|. + void OnReplacementTestSignal(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + ASSERT_TRUE(reader.PopString(&replacement_test_signal_string_)); + message_loop_.Quit(); + } + + // Called when connected to the signal. + void OnReplacementConnected(const std::string& interface_name, + const std::string& signal_name, + bool success) { + ASSERT_TRUE(success); + message_loop_.Quit(); + } + + // Text message from "Test" signal delivered to replacement handler. + std::string replacement_test_signal_string_; +}; + +TEST_F(SignalReplacementTest, TestSignalReplacement) { + const char kMessage[] = "hello, world"; + // Send the test signal from the exported object. + test_service_->SendTestSignal(kMessage); + // Receive the signal with the object proxy. + WaitForTestSignal(); + // Verify the string WAS NOT received by the original handler. + ASSERT_TRUE(test_signal_string_.empty()); + // Verify the signal WAS received by the replacement handler. + ASSERT_EQ(kMessage, replacement_test_signal_string_); +} diff --git a/dbus/object_proxy.cc b/dbus/object_proxy.cc index 0784ea7..0cbd93e 100644 --- a/dbus/object_proxy.cc +++ b/dbus/object_proxy.cc @@ -281,14 +281,8 @@ void ObjectProxy::ConnectToSignalInternal( OnConnectedCallback on_connected_callback) { bus_->AssertOnDBusThread(); - // Check if the object is already connected to the signal. const std::string absolute_signal_name = GetAbsoluteSignalName(interface_name, signal_name); - if (method_table_.find(absolute_signal_name) != method_table_.end()) { - LOG(ERROR) << "The object proxy is already connected to " - << absolute_signal_name; - return; - } // Will become true, if everything is successful. bool success = false; diff --git a/dbus/object_proxy.h b/dbus/object_proxy.h index 3a9fab1..6c786ab4 100644 --- a/dbus/object_proxy.h +++ b/dbus/object_proxy.h @@ -29,7 +29,9 @@ class Signal; // calling methods of these objects. // // ObjectProxy is a ref counted object, to ensure that |this| of the -// object is is alive when callbacks referencing |this| are called. +// object is is alive when callbacks referencing |this| are called; the +// bus always holds at least one of those references so object proxies +// always last as long as the bus that created them. class ObjectProxy : public base::RefCountedThreadSafe<ObjectProxy> { public: // Client code should use Bus::GetObjectProxy() or @@ -96,7 +98,8 @@ class ObjectProxy : public base::RefCountedThreadSafe<ObjectProxy> { int timeout_ms, ResponseCallback callback); - // Requests to connect to the signal from the remote object. + // Requests to connect to the signal from the remote object, replacing + // any previous |signal_callback| connected to that signal. // // |signal_callback| will be called in the origin thread, when the // signal is received from the remote object. As it's called in the |