blob: 1a797bf2a9d31afe39ce38fa6dc16994d6e33949 [file] [log] [blame]
From fb915ed71679feafd4ed53deb2c5ba84862a9e57 Mon Sep 17 00:00:00 2001
From: Sonny Sasaka <sonnysasaka@chromium.org>
Date: Mon, 10 Dec 2018 14:03:49 -0800
Subject: [PATCH] dbus: Support UnexportMethod from an exported object.
Currently there is no way to override a method handler that is already
registered to an ExportedObject. A support to do so is required to
correctly implement Chrome OS Bluetooth dispatcher which needs to
add/remove an interface to an exported object dynamically. Therefore
this CL adds methods to allow method handlers to be unexported so
another handler can be exported afterwards.
Bug: 883039
---
dbus/exported_object.cc | 50 +++++++++++++++++++++++++++++++++++++
dbus/exported_object.h | 34 +++++++++++++++++++++++++
dbus/mock_exported_object.h | 7 ++++++
3 files changed, 91 insertions(+)
diff --git a/dbus/exported_object.cc b/dbus/exported_object.cc
index 5fa1b916f251..727a5707b869 100644
--- a/dbus/exported_object.cc
+++ b/dbus/exported_object.cc
@@ -68,6 +68,22 @@ bool ExportedObject::ExportMethodAndBlock(
return true;
}
+bool ExportedObject::UnexportMethodAndBlock(const std::string& interface_name,
+ const std::string& method_name) {
+ bus_->AssertOnDBusThread();
+
+ const std::string absolute_method_name =
+ GetAbsoluteMemberName(interface_name, method_name);
+ if (method_table_.find(absolute_method_name) == method_table_.end()) {
+ LOG(ERROR) << absolute_method_name << " is not exported";
+ return false;
+ }
+
+ method_table_.erase(absolute_method_name);
+
+ return true;
+}
+
void ExportedObject::ExportMethod(const std::string& interface_name,
const std::string& method_name,
MethodCallCallback method_call_callback,
@@ -83,6 +99,18 @@ void ExportedObject::ExportMethod(const std::string& interface_name,
bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task);
}
+void ExportedObject::UnexportMethod(
+ const std::string& interface_name,
+ const std::string& method_name,
+ OnUnexportedCallback on_unexported_calback) {
+ bus_->AssertOnOriginThread();
+
+ base::Closure task =
+ base::Bind(&ExportedObject::UnexportMethodInternal, this, interface_name,
+ method_name, on_unexported_calback);
+ bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task);
+}
+
void ExportedObject::SendSignal(Signal* signal) {
// For signals, the object path should be set to the path to the sender
// object, which is this exported object here.
@@ -141,6 +169,19 @@ void ExportedObject::ExportMethodInternal(
success));
}
+void ExportedObject::UnexportMethodInternal(
+ const std::string& interface_name,
+ const std::string& method_name,
+ OnUnexportedCallback on_unexported_calback) {
+ bus_->AssertOnDBusThread();
+
+ const bool success = UnexportMethodAndBlock(interface_name, method_name);
+ bus_->GetOriginTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&ExportedObject::OnUnexported, this, on_unexported_calback,
+ interface_name, method_name, success));
+}
+
void ExportedObject::OnExported(OnExportedCallback on_exported_callback,
const std::string& interface_name,
const std::string& method_name,
@@ -150,6 +191,15 @@ void ExportedObject::OnExported(OnExportedCallback on_exported_callback,
on_exported_callback.Run(interface_name, method_name, success);
}
+void ExportedObject::OnUnexported(OnExportedCallback on_unexported_callback,
+ const std::string& interface_name,
+ const std::string& method_name,
+ bool success) {
+ bus_->AssertOnOriginThread();
+
+ on_unexported_callback.Run(interface_name, method_name, success);
+}
+
void ExportedObject::SendSignalInternal(base::TimeTicks start_time,
DBusMessage* signal_message) {
uint32_t serial = 0;
diff --git a/dbus/exported_object.h b/dbus/exported_object.h
index 69a63a5e075e..d314083430ef 100644
--- a/dbus/exported_object.h
+++ b/dbus/exported_object.h
@@ -60,6 +60,13 @@ class CHROME_DBUS_EXPORT ExportedObject
bool success)>
OnExportedCallback;
+ // Called when method unexporting is done.
+ // |success| indicates whether unexporting was successful or not.
+ typedef base::Callback<void(const std::string& interface_name,
+ const std::string& method_name,
+ bool success)>
+ OnUnexportedCallback;
+
// Exports the method specified by |interface_name| and |method_name|,
// and blocks until exporting is done. Returns true on success.
//
@@ -81,6 +88,11 @@ class CHROME_DBUS_EXPORT ExportedObject
const std::string& method_name,
MethodCallCallback method_call_callback);
+ // Unexports the method specified by |interface_name| and |method_name|,
+ // and blocks until unexporting is done. Returns true on success.
+ virtual bool UnexportMethodAndBlock(const std::string& interface_name,
+ const std::string& method_name);
+
// Requests to export the method specified by |interface_name| and
// |method_name|. See Also ExportMethodAndBlock().
//
@@ -93,6 +105,17 @@ class CHROME_DBUS_EXPORT ExportedObject
MethodCallCallback method_call_callback,
OnExportedCallback on_exported_callback);
+ // Requests to unexport the method specified by |interface_name| and
+ // |method_name|. See also UnexportMethodAndBlock().
+ //
+ // |on_unexported_callback| is called when the method is unexported or
+ // failed to be unexported, in the origin thread.
+ //
+ // Must be called in the origin thread.
+ virtual void UnexportMethod(const std::string& interface_name,
+ const std::string& method_name,
+ OnUnexportedCallback on_unexported_callback);
+
// Requests to send the signal from this object. The signal will be sent
// synchronously if this method is called from the message loop in the D-Bus
// thread and asynchronously otherwise.
@@ -117,12 +140,23 @@ class CHROME_DBUS_EXPORT ExportedObject
MethodCallCallback method_call_callback,
OnExportedCallback exported_callback);
+ // Helper function for UnexportMethod().
+ void UnexportMethodInternal(const std::string& interface_name,
+ const std::string& method_name,
+ OnUnexportedCallback unexported_callback);
+
// Called when the object is exported.
void OnExported(OnExportedCallback on_exported_callback,
const std::string& interface_name,
const std::string& method_name,
bool success);
+ // Called when a method is unexported.
+ void OnUnexported(OnExportedCallback on_unexported_callback,
+ const std::string& interface_name,
+ const std::string& method_name,
+ bool success);
+
// Helper function for SendSignal().
void SendSignalInternal(base::TimeTicks start_time,
DBusMessage* signal_message);
diff --git a/dbus/mock_exported_object.h b/dbus/mock_exported_object.h
index 99c363f9b532..9d5b3a894179 100644
--- a/dbus/mock_exported_object.h
+++ b/dbus/mock_exported_object.h
@@ -28,6 +28,13 @@ class MockExportedObject : public ExportedObject {
const std::string& method_name,
MethodCallCallback method_call_callback,
OnExportedCallback on_exported_callback));
+ MOCK_METHOD2(UnexportMethodAndBlock,
+ bool(const std::string& interface_name,
+ const std::string& method_name));
+ MOCK_METHOD3(UnexportMethod,
+ void(const std::string& interface_name,
+ const std::string& method_name,
+ OnUnexportedCallback on_unexported_callback));
MOCK_METHOD1(SendSignal, void(Signal* signal));
MOCK_METHOD0(Unregister, void());
--
2.20.0.rc2.403.gdbc3b29805-goog