From ea5451957df86623f9dd52ad2dd2c12c5ecd70a6 Mon Sep 17 00:00:00 2001 From: "nona@chromium.org" Date: Fri, 15 Feb 2013 16:44:40 +0000 Subject: Supporting callback for Disconnected signal. If the connection with dbus-daemon is closed, callback function set with SetDisconnectedCallback will be called. BUG=None TEST=ran dbus_unittests Review URL: https://chromiumcodereview.appspot.com/12224139 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182736 0039d316-1c4b-4281-b951-d872f2087c98 --- dbus/bus.cc | 16 ++++++++++++++-- dbus/bus.h | 14 ++++++++++++++ dbus/end_to_end_async_unittest.cc | 21 +++++++++++++++++++-- 3 files changed, 47 insertions(+), 4 deletions(-) (limited to 'dbus') diff --git a/dbus/bus.cc b/dbus/bus.cc index 1c258d2..30089ab 100644 --- a/dbus/bus.cc +++ b/dbus/bus.cc @@ -189,7 +189,8 @@ Bus::Bus(const Options& options) shutdown_completed_(false), num_pending_watches_(0), num_pending_timeouts_(0), - address_(options.address) { + address_(options.address), + on_disconnected_closure_(options.disconnected_callback) { // This is safe to call multiple times. dbus_threads_init_default(); // The origin message loop is unnecessary if the client uses synchronous @@ -373,6 +374,14 @@ bool Bus::Connect() { return true; } +void Bus::ClosePrivateConnection() { + // dbus_connection_close is blocking call. + AssertOnDBusThread(); + DCHECK_EQ(PRIVATE, connection_type_) + << "non-private connection should not be closed"; + dbus_connection_close(connection_); +} + void Bus::ShutdownAndBlock() { AssertOnDBusThread(); @@ -418,7 +427,7 @@ void Bus::ShutdownAndBlock() { RemoveMatch(kDisconnectedMatchRule, error.get()); if (connection_type_ == PRIVATE) - dbus_connection_close(connection_); + ClosePrivateConnection(); // dbus_connection_close() won't unref. dbus_connection_unref(connection_); } @@ -871,6 +880,9 @@ void Bus::OnDispatchStatusChanged(DBusConnection* connection, void Bus::OnConnectionDisconnected(DBusConnection* connection) { AssertOnDBusThread(); + if (!on_disconnected_closure_.is_null()) + PostTaskToOriginThread(FROM_HERE, on_disconnected_closure_); + if (!connection) return; DCHECK(!dbus_connection_get_is_connected(connection)); diff --git a/dbus/bus.h b/dbus/bus.h index 1bf07d9..87df7c3 100644 --- a/dbus/bus.h +++ b/dbus/bus.h @@ -190,6 +190,12 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe { // // Do something. // std::string address; + + // If the connection with dbus-daemon is closed, |disconnected_callback| + // will be called on the origin thread. This is also called when the + // disonnection by ShutdownAndBlock. |disconnected_callback| can be null + // callback + base::Closure disconnected_callback; }; // Creates a Bus object. The actual connection will be established when @@ -329,6 +335,13 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe { // BLOCKING CALL. virtual bool Connect(); + // Disconnects the bus from the dbus-daemon. + // Safe to call multiple times and no operation after the first call. + // Do not call for shared connection it will be released by libdbus. + // + // BLOCKING CALL. + virtual void ClosePrivateConnection(); + // Requests the ownership of the service name given by |service_name|. // See also RequestOwnershipAndBlock(). // @@ -601,6 +614,7 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe { int num_pending_timeouts_; std::string address_; + base::Closure on_disconnected_closure_; DISALLOW_COPY_AND_ASSIGN(Bus); }; diff --git a/dbus/end_to_end_async_unittest.cc b/dbus/end_to_end_async_unittest.cc index 7715f7d..b91ea77 100644 --- a/dbus/end_to_end_async_unittest.cc +++ b/dbus/end_to_end_async_unittest.cc @@ -32,8 +32,7 @@ const int kHugePayloadSize = 64 << 20; // 64 MB // ExportedObject. class EndToEndAsyncTest : public testing::Test { public: - EndToEndAsyncTest() { - } + EndToEndAsyncTest() : on_disconnected_call_count_(0) {} virtual void SetUp() { // Make the main thread not to allow IO. @@ -59,6 +58,8 @@ class EndToEndAsyncTest : public testing::Test { bus_options.connection_type = dbus::Bus::PRIVATE; bus_options.dbus_thread_message_loop_proxy = dbus_thread_->message_loop_proxy(); + bus_options.disconnected_callback = + base::Bind(&EndToEndAsyncTest::OnDisconnected, base::Unretained(this)); bus_ = new dbus::Bus(bus_options); object_proxy_ = bus_->GetObjectProxy( "org.chromium.TestService", @@ -242,6 +243,12 @@ class EndToEndAsyncTest : public testing::Test { message_loop_.Quit(); } + // Called when the connection with dbus-daemon is disconnected. + void OnDisconnected() { + message_loop_.Quit(); + ++on_disconnected_call_count_; + } + // Wait for the hey signal to be received. void WaitForTestSignal() { // OnTestSignal() will quit the message loop. @@ -260,6 +267,7 @@ class EndToEndAsyncTest : public testing::Test { std::string test_signal_string_; // Text message from "Test" signal delivered to root. std::string root_test_signal_string_; + int on_disconnected_call_count_; }; TEST_F(EndToEndAsyncTest, Echo) { @@ -572,6 +580,15 @@ TEST_F(EndToEndAsyncTest, TestHugeSignal) { ASSERT_EQ(kHugeMessage, test_signal_string_); } +TEST_F(EndToEndAsyncTest, DisconnectedSignal) { + bus_->PostTaskToDBusThread(FROM_HERE, + base::Bind(&dbus::Bus::ClosePrivateConnection, + base::Unretained(bus_.get()))); + // OnDisconnected callback quits message loop. + message_loop_.Run(); + EXPECT_EQ(1, on_disconnected_call_count_); +} + class SignalReplacementTest : public EndToEndAsyncTest { public: SignalReplacementTest() { -- cgit v1.1