summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dbus/bus.cc16
-rw-r--r--dbus/bus.h14
-rw-r--r--dbus/end_to_end_async_unittest.cc21
3 files changed, 47 insertions, 4 deletions
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<Bus> {
// // 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<Bus> {
// 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<Bus> {
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() {