• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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