From fb915ed71679feafd4ed53deb2c5ba84862a9e57 Mon Sep 17 00:00:00 2001 From: Sonny Sasaka 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 + 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