1From fb915ed71679feafd4ed53deb2c5ba84862a9e57 Mon Sep 17 00:00:00 2001 2From: Sonny Sasaka <sonnysasaka@chromium.org> 3Date: Mon, 10 Dec 2018 14:03:49 -0800 4Subject: [PATCH] dbus: Support UnexportMethod from an exported object. 5 6Currently there is no way to override a method handler that is already 7registered to an ExportedObject. A support to do so is required to 8correctly implement Chrome OS Bluetooth dispatcher which needs to 9add/remove an interface to an exported object dynamically. Therefore 10this CL adds methods to allow method handlers to be unexported so 11another handler can be exported afterwards. 12 13Bug: 883039 14--- 15 dbus/exported_object.cc | 50 +++++++++++++++++++++++++++++++++++++ 16 dbus/exported_object.h | 34 +++++++++++++++++++++++++ 17 dbus/mock_exported_object.h | 7 ++++++ 18 3 files changed, 91 insertions(+) 19 20diff --git a/dbus/exported_object.cc b/dbus/exported_object.cc 21index 5fa1b916f251..727a5707b869 100644 22--- a/dbus/exported_object.cc 23+++ b/dbus/exported_object.cc 24@@ -68,6 +68,22 @@ bool ExportedObject::ExportMethodAndBlock( 25 return true; 26 } 27 28+bool ExportedObject::UnexportMethodAndBlock(const std::string& interface_name, 29+ const std::string& method_name) { 30+ bus_->AssertOnDBusThread(); 31+ 32+ const std::string absolute_method_name = 33+ GetAbsoluteMemberName(interface_name, method_name); 34+ if (method_table_.find(absolute_method_name) == method_table_.end()) { 35+ LOG(ERROR) << absolute_method_name << " is not exported"; 36+ return false; 37+ } 38+ 39+ method_table_.erase(absolute_method_name); 40+ 41+ return true; 42+} 43+ 44 void ExportedObject::ExportMethod(const std::string& interface_name, 45 const std::string& method_name, 46 MethodCallCallback method_call_callback, 47@@ -83,6 +99,18 @@ void ExportedObject::ExportMethod(const std::string& interface_name, 48 bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task); 49 } 50 51+void ExportedObject::UnexportMethod( 52+ const std::string& interface_name, 53+ const std::string& method_name, 54+ OnUnexportedCallback on_unexported_calback) { 55+ bus_->AssertOnOriginThread(); 56+ 57+ base::Closure task = 58+ base::Bind(&ExportedObject::UnexportMethodInternal, this, interface_name, 59+ method_name, on_unexported_calback); 60+ bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task); 61+} 62+ 63 void ExportedObject::SendSignal(Signal* signal) { 64 // For signals, the object path should be set to the path to the sender 65 // object, which is this exported object here. 66@@ -141,6 +169,19 @@ void ExportedObject::ExportMethodInternal( 67 success)); 68 } 69 70+void ExportedObject::UnexportMethodInternal( 71+ const std::string& interface_name, 72+ const std::string& method_name, 73+ OnUnexportedCallback on_unexported_calback) { 74+ bus_->AssertOnDBusThread(); 75+ 76+ const bool success = UnexportMethodAndBlock(interface_name, method_name); 77+ bus_->GetOriginTaskRunner()->PostTask( 78+ FROM_HERE, 79+ base::Bind(&ExportedObject::OnUnexported, this, on_unexported_calback, 80+ interface_name, method_name, success)); 81+} 82+ 83 void ExportedObject::OnExported(OnExportedCallback on_exported_callback, 84 const std::string& interface_name, 85 const std::string& method_name, 86@@ -150,6 +191,15 @@ void ExportedObject::OnExported(OnExportedCallback on_exported_callback, 87 on_exported_callback.Run(interface_name, method_name, success); 88 } 89 90+void ExportedObject::OnUnexported(OnExportedCallback on_unexported_callback, 91+ const std::string& interface_name, 92+ const std::string& method_name, 93+ bool success) { 94+ bus_->AssertOnOriginThread(); 95+ 96+ on_unexported_callback.Run(interface_name, method_name, success); 97+} 98+ 99 void ExportedObject::SendSignalInternal(base::TimeTicks start_time, 100 DBusMessage* signal_message) { 101 uint32_t serial = 0; 102diff --git a/dbus/exported_object.h b/dbus/exported_object.h 103index 69a63a5e075e..d314083430ef 100644 104--- a/dbus/exported_object.h 105+++ b/dbus/exported_object.h 106@@ -60,6 +60,13 @@ class CHROME_DBUS_EXPORT ExportedObject 107 bool success)> 108 OnExportedCallback; 109 110+ // Called when method unexporting is done. 111+ // |success| indicates whether unexporting was successful or not. 112+ typedef base::Callback<void(const std::string& interface_name, 113+ const std::string& method_name, 114+ bool success)> 115+ OnUnexportedCallback; 116+ 117 // Exports the method specified by |interface_name| and |method_name|, 118 // and blocks until exporting is done. Returns true on success. 119 // 120@@ -81,6 +88,11 @@ class CHROME_DBUS_EXPORT ExportedObject 121 const std::string& method_name, 122 MethodCallCallback method_call_callback); 123 124+ // Unexports the method specified by |interface_name| and |method_name|, 125+ // and blocks until unexporting is done. Returns true on success. 126+ virtual bool UnexportMethodAndBlock(const std::string& interface_name, 127+ const std::string& method_name); 128+ 129 // Requests to export the method specified by |interface_name| and 130 // |method_name|. See Also ExportMethodAndBlock(). 131 // 132@@ -93,6 +105,17 @@ class CHROME_DBUS_EXPORT ExportedObject 133 MethodCallCallback method_call_callback, 134 OnExportedCallback on_exported_callback); 135 136+ // Requests to unexport the method specified by |interface_name| and 137+ // |method_name|. See also UnexportMethodAndBlock(). 138+ // 139+ // |on_unexported_callback| is called when the method is unexported or 140+ // failed to be unexported, in the origin thread. 141+ // 142+ // Must be called in the origin thread. 143+ virtual void UnexportMethod(const std::string& interface_name, 144+ const std::string& method_name, 145+ OnUnexportedCallback on_unexported_callback); 146+ 147 // Requests to send the signal from this object. The signal will be sent 148 // synchronously if this method is called from the message loop in the D-Bus 149 // thread and asynchronously otherwise. 150@@ -117,12 +140,23 @@ class CHROME_DBUS_EXPORT ExportedObject 151 MethodCallCallback method_call_callback, 152 OnExportedCallback exported_callback); 153 154+ // Helper function for UnexportMethod(). 155+ void UnexportMethodInternal(const std::string& interface_name, 156+ const std::string& method_name, 157+ OnUnexportedCallback unexported_callback); 158+ 159 // Called when the object is exported. 160 void OnExported(OnExportedCallback on_exported_callback, 161 const std::string& interface_name, 162 const std::string& method_name, 163 bool success); 164 165+ // Called when a method is unexported. 166+ void OnUnexported(OnExportedCallback on_unexported_callback, 167+ const std::string& interface_name, 168+ const std::string& method_name, 169+ bool success); 170+ 171 // Helper function for SendSignal(). 172 void SendSignalInternal(base::TimeTicks start_time, 173 DBusMessage* signal_message); 174diff --git a/dbus/mock_exported_object.h b/dbus/mock_exported_object.h 175index 99c363f9b532..9d5b3a894179 100644 176--- a/dbus/mock_exported_object.h 177+++ b/dbus/mock_exported_object.h 178@@ -28,6 +28,13 @@ class MockExportedObject : public ExportedObject { 179 const std::string& method_name, 180 MethodCallCallback method_call_callback, 181 OnExportedCallback on_exported_callback)); 182+ MOCK_METHOD2(UnexportMethodAndBlock, 183+ bool(const std::string& interface_name, 184+ const std::string& method_name)); 185+ MOCK_METHOD3(UnexportMethod, 186+ void(const std::string& interface_name, 187+ const std::string& method_name, 188+ OnUnexportedCallback on_unexported_callback)); 189 MOCK_METHOD1(SendSignal, void(Signal* signal)); 190 MOCK_METHOD0(Unregister, void()); 191 192-- 1932.20.0.rc2.403.gdbc3b29805-goog 194 195