xref: /aosp_15_r20/external/libchrome/dbus/exported_object.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "dbus/exported_object.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
8*635a8641SAndroid Build Coastguard Worker #include <utility>
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/memory/ref_counted.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/task_runner.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/time/time.h"
17*635a8641SAndroid Build Coastguard Worker #include "dbus/bus.h"
18*635a8641SAndroid Build Coastguard Worker #include "dbus/message.h"
19*635a8641SAndroid Build Coastguard Worker #include "dbus/object_path.h"
20*635a8641SAndroid Build Coastguard Worker #include "dbus/scoped_dbus_error.h"
21*635a8641SAndroid Build Coastguard Worker #include "dbus/util.h"
22*635a8641SAndroid Build Coastguard Worker 
23*635a8641SAndroid Build Coastguard Worker namespace dbus {
24*635a8641SAndroid Build Coastguard Worker 
25*635a8641SAndroid Build Coastguard Worker namespace {
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker // Used for success ratio histograms. 1 for success, 0 for failure.
28*635a8641SAndroid Build Coastguard Worker const int kSuccessRatioHistogramMaxValue = 2;
29*635a8641SAndroid Build Coastguard Worker 
30*635a8641SAndroid Build Coastguard Worker }  // namespace
31*635a8641SAndroid Build Coastguard Worker 
ExportedObject(Bus * bus,const ObjectPath & object_path)32*635a8641SAndroid Build Coastguard Worker ExportedObject::ExportedObject(Bus* bus,
33*635a8641SAndroid Build Coastguard Worker                                const ObjectPath& object_path)
34*635a8641SAndroid Build Coastguard Worker     : bus_(bus),
35*635a8641SAndroid Build Coastguard Worker       object_path_(object_path),
36*635a8641SAndroid Build Coastguard Worker       object_is_registered_(false) {
37*635a8641SAndroid Build Coastguard Worker   LOG_IF(FATAL, !object_path_.IsValid()) << object_path_.value();
38*635a8641SAndroid Build Coastguard Worker }
39*635a8641SAndroid Build Coastguard Worker 
~ExportedObject()40*635a8641SAndroid Build Coastguard Worker ExportedObject::~ExportedObject() {
41*635a8641SAndroid Build Coastguard Worker   DCHECK(!object_is_registered_);
42*635a8641SAndroid Build Coastguard Worker }
43*635a8641SAndroid Build Coastguard Worker 
ExportMethodAndBlock(const std::string & interface_name,const std::string & method_name,MethodCallCallback method_call_callback)44*635a8641SAndroid Build Coastguard Worker bool ExportedObject::ExportMethodAndBlock(
45*635a8641SAndroid Build Coastguard Worker     const std::string& interface_name,
46*635a8641SAndroid Build Coastguard Worker     const std::string& method_name,
47*635a8641SAndroid Build Coastguard Worker     MethodCallCallback method_call_callback) {
48*635a8641SAndroid Build Coastguard Worker   bus_->AssertOnDBusThread();
49*635a8641SAndroid Build Coastguard Worker 
50*635a8641SAndroid Build Coastguard Worker   // Check if the method is already exported.
51*635a8641SAndroid Build Coastguard Worker   const std::string absolute_method_name =
52*635a8641SAndroid Build Coastguard Worker       GetAbsoluteMemberName(interface_name, method_name);
53*635a8641SAndroid Build Coastguard Worker   if (method_table_.find(absolute_method_name) != method_table_.end()) {
54*635a8641SAndroid Build Coastguard Worker     LOG(ERROR) << absolute_method_name << " is already exported";
55*635a8641SAndroid Build Coastguard Worker     return false;
56*635a8641SAndroid Build Coastguard Worker   }
57*635a8641SAndroid Build Coastguard Worker 
58*635a8641SAndroid Build Coastguard Worker   if (!bus_->Connect())
59*635a8641SAndroid Build Coastguard Worker     return false;
60*635a8641SAndroid Build Coastguard Worker   if (!bus_->SetUpAsyncOperations())
61*635a8641SAndroid Build Coastguard Worker     return false;
62*635a8641SAndroid Build Coastguard Worker   if (!Register())
63*635a8641SAndroid Build Coastguard Worker     return false;
64*635a8641SAndroid Build Coastguard Worker 
65*635a8641SAndroid Build Coastguard Worker   // Add the method callback to the method table.
66*635a8641SAndroid Build Coastguard Worker   method_table_[absolute_method_name] = method_call_callback;
67*635a8641SAndroid Build Coastguard Worker 
68*635a8641SAndroid Build Coastguard Worker   return true;
69*635a8641SAndroid Build Coastguard Worker }
70*635a8641SAndroid Build Coastguard Worker 
ExportMethod(const std::string & interface_name,const std::string & method_name,MethodCallCallback method_call_callback,OnExportedCallback on_exported_calback)71*635a8641SAndroid Build Coastguard Worker void ExportedObject::ExportMethod(const std::string& interface_name,
72*635a8641SAndroid Build Coastguard Worker                                   const std::string& method_name,
73*635a8641SAndroid Build Coastguard Worker                                   MethodCallCallback method_call_callback,
74*635a8641SAndroid Build Coastguard Worker                                   OnExportedCallback on_exported_calback) {
75*635a8641SAndroid Build Coastguard Worker   bus_->AssertOnOriginThread();
76*635a8641SAndroid Build Coastguard Worker 
77*635a8641SAndroid Build Coastguard Worker   base::Closure task = base::Bind(&ExportedObject::ExportMethodInternal,
78*635a8641SAndroid Build Coastguard Worker                                   this,
79*635a8641SAndroid Build Coastguard Worker                                   interface_name,
80*635a8641SAndroid Build Coastguard Worker                                   method_name,
81*635a8641SAndroid Build Coastguard Worker                                   method_call_callback,
82*635a8641SAndroid Build Coastguard Worker                                   on_exported_calback);
83*635a8641SAndroid Build Coastguard Worker   bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task);
84*635a8641SAndroid Build Coastguard Worker }
85*635a8641SAndroid Build Coastguard Worker 
SendSignal(Signal * signal)86*635a8641SAndroid Build Coastguard Worker void ExportedObject::SendSignal(Signal* signal) {
87*635a8641SAndroid Build Coastguard Worker   // For signals, the object path should be set to the path to the sender
88*635a8641SAndroid Build Coastguard Worker   // object, which is this exported object here.
89*635a8641SAndroid Build Coastguard Worker   CHECK(signal->SetPath(object_path_));
90*635a8641SAndroid Build Coastguard Worker 
91*635a8641SAndroid Build Coastguard Worker   // Increment the reference count so we can safely reference the
92*635a8641SAndroid Build Coastguard Worker   // underlying signal message until the signal sending is complete. This
93*635a8641SAndroid Build Coastguard Worker   // will be unref'ed in SendSignalInternal().
94*635a8641SAndroid Build Coastguard Worker   DBusMessage* signal_message = signal->raw_message();
95*635a8641SAndroid Build Coastguard Worker   dbus_message_ref(signal_message);
96*635a8641SAndroid Build Coastguard Worker 
97*635a8641SAndroid Build Coastguard Worker   const base::TimeTicks start_time = base::TimeTicks::Now();
98*635a8641SAndroid Build Coastguard Worker   if (bus_->GetDBusTaskRunner()->RunsTasksInCurrentSequence()) {
99*635a8641SAndroid Build Coastguard Worker     // The Chrome OS power manager doesn't use a dedicated TaskRunner for
100*635a8641SAndroid Build Coastguard Worker     // sending DBus messages.  Sending signals asynchronously can cause an
101*635a8641SAndroid Build Coastguard Worker     // inversion in the message order if the power manager calls
102*635a8641SAndroid Build Coastguard Worker     // ObjectProxy::CallMethodAndBlock() before going back to the top level of
103*635a8641SAndroid Build Coastguard Worker     // the MessageLoop: crbug.com/472361.
104*635a8641SAndroid Build Coastguard Worker     SendSignalInternal(start_time, signal_message);
105*635a8641SAndroid Build Coastguard Worker   } else {
106*635a8641SAndroid Build Coastguard Worker     bus_->GetDBusTaskRunner()->PostTask(
107*635a8641SAndroid Build Coastguard Worker         FROM_HERE,
108*635a8641SAndroid Build Coastguard Worker         base::Bind(&ExportedObject::SendSignalInternal,
109*635a8641SAndroid Build Coastguard Worker                    this,
110*635a8641SAndroid Build Coastguard Worker                    start_time,
111*635a8641SAndroid Build Coastguard Worker                    signal_message));
112*635a8641SAndroid Build Coastguard Worker   }
113*635a8641SAndroid Build Coastguard Worker }
114*635a8641SAndroid Build Coastguard Worker 
Unregister()115*635a8641SAndroid Build Coastguard Worker void ExportedObject::Unregister() {
116*635a8641SAndroid Build Coastguard Worker   bus_->AssertOnDBusThread();
117*635a8641SAndroid Build Coastguard Worker 
118*635a8641SAndroid Build Coastguard Worker   if (!object_is_registered_)
119*635a8641SAndroid Build Coastguard Worker     return;
120*635a8641SAndroid Build Coastguard Worker 
121*635a8641SAndroid Build Coastguard Worker   bus_->UnregisterObjectPath(object_path_);
122*635a8641SAndroid Build Coastguard Worker   object_is_registered_ = false;
123*635a8641SAndroid Build Coastguard Worker }
124*635a8641SAndroid Build Coastguard Worker 
ExportMethodInternal(const std::string & interface_name,const std::string & method_name,MethodCallCallback method_call_callback,OnExportedCallback on_exported_calback)125*635a8641SAndroid Build Coastguard Worker void ExportedObject::ExportMethodInternal(
126*635a8641SAndroid Build Coastguard Worker     const std::string& interface_name,
127*635a8641SAndroid Build Coastguard Worker     const std::string& method_name,
128*635a8641SAndroid Build Coastguard Worker     MethodCallCallback method_call_callback,
129*635a8641SAndroid Build Coastguard Worker     OnExportedCallback on_exported_calback) {
130*635a8641SAndroid Build Coastguard Worker   bus_->AssertOnDBusThread();
131*635a8641SAndroid Build Coastguard Worker 
132*635a8641SAndroid Build Coastguard Worker   const bool success = ExportMethodAndBlock(interface_name,
133*635a8641SAndroid Build Coastguard Worker                                             method_name,
134*635a8641SAndroid Build Coastguard Worker                                             method_call_callback);
135*635a8641SAndroid Build Coastguard Worker   bus_->GetOriginTaskRunner()->PostTask(FROM_HERE,
136*635a8641SAndroid Build Coastguard Worker                                         base::Bind(&ExportedObject::OnExported,
137*635a8641SAndroid Build Coastguard Worker                                                    this,
138*635a8641SAndroid Build Coastguard Worker                                                    on_exported_calback,
139*635a8641SAndroid Build Coastguard Worker                                                    interface_name,
140*635a8641SAndroid Build Coastguard Worker                                                    method_name,
141*635a8641SAndroid Build Coastguard Worker                                                    success));
142*635a8641SAndroid Build Coastguard Worker }
143*635a8641SAndroid Build Coastguard Worker 
OnExported(OnExportedCallback on_exported_callback,const std::string & interface_name,const std::string & method_name,bool success)144*635a8641SAndroid Build Coastguard Worker void ExportedObject::OnExported(OnExportedCallback on_exported_callback,
145*635a8641SAndroid Build Coastguard Worker                                 const std::string& interface_name,
146*635a8641SAndroid Build Coastguard Worker                                 const std::string& method_name,
147*635a8641SAndroid Build Coastguard Worker                                 bool success) {
148*635a8641SAndroid Build Coastguard Worker   bus_->AssertOnOriginThread();
149*635a8641SAndroid Build Coastguard Worker 
150*635a8641SAndroid Build Coastguard Worker   on_exported_callback.Run(interface_name, method_name, success);
151*635a8641SAndroid Build Coastguard Worker }
152*635a8641SAndroid Build Coastguard Worker 
SendSignalInternal(base::TimeTicks start_time,DBusMessage * signal_message)153*635a8641SAndroid Build Coastguard Worker void ExportedObject::SendSignalInternal(base::TimeTicks start_time,
154*635a8641SAndroid Build Coastguard Worker                                         DBusMessage* signal_message) {
155*635a8641SAndroid Build Coastguard Worker   uint32_t serial = 0;
156*635a8641SAndroid Build Coastguard Worker   bus_->Send(signal_message, &serial);
157*635a8641SAndroid Build Coastguard Worker   dbus_message_unref(signal_message);
158*635a8641SAndroid Build Coastguard Worker   // Record time spent to send the the signal. This is not accurate as the
159*635a8641SAndroid Build Coastguard Worker   // signal will actually be sent from the next run of the message loop,
160*635a8641SAndroid Build Coastguard Worker   // but we can at least tell the number of signals sent.
161*635a8641SAndroid Build Coastguard Worker   UMA_HISTOGRAM_TIMES("DBus.SignalSendTime",
162*635a8641SAndroid Build Coastguard Worker                       base::TimeTicks::Now() - start_time);
163*635a8641SAndroid Build Coastguard Worker }
164*635a8641SAndroid Build Coastguard Worker 
Register()165*635a8641SAndroid Build Coastguard Worker bool ExportedObject::Register() {
166*635a8641SAndroid Build Coastguard Worker   bus_->AssertOnDBusThread();
167*635a8641SAndroid Build Coastguard Worker 
168*635a8641SAndroid Build Coastguard Worker   if (object_is_registered_)
169*635a8641SAndroid Build Coastguard Worker     return true;
170*635a8641SAndroid Build Coastguard Worker 
171*635a8641SAndroid Build Coastguard Worker   ScopedDBusError error;
172*635a8641SAndroid Build Coastguard Worker 
173*635a8641SAndroid Build Coastguard Worker   DBusObjectPathVTable vtable = {};
174*635a8641SAndroid Build Coastguard Worker   vtable.message_function = &ExportedObject::HandleMessageThunk;
175*635a8641SAndroid Build Coastguard Worker   vtable.unregister_function = &ExportedObject::OnUnregisteredThunk;
176*635a8641SAndroid Build Coastguard Worker   const bool success = bus_->TryRegisterObjectPath(object_path_,
177*635a8641SAndroid Build Coastguard Worker                                                    &vtable,
178*635a8641SAndroid Build Coastguard Worker                                                    this,
179*635a8641SAndroid Build Coastguard Worker                                                    error.get());
180*635a8641SAndroid Build Coastguard Worker   if (!success) {
181*635a8641SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to register the object: " << object_path_.value()
182*635a8641SAndroid Build Coastguard Worker                << ": " << (error.is_set() ? error.message() : "");
183*635a8641SAndroid Build Coastguard Worker     return false;
184*635a8641SAndroid Build Coastguard Worker   }
185*635a8641SAndroid Build Coastguard Worker 
186*635a8641SAndroid Build Coastguard Worker   object_is_registered_ = true;
187*635a8641SAndroid Build Coastguard Worker   return true;
188*635a8641SAndroid Build Coastguard Worker }
189*635a8641SAndroid Build Coastguard Worker 
HandleMessage(DBusConnection * connection,DBusMessage * raw_message)190*635a8641SAndroid Build Coastguard Worker DBusHandlerResult ExportedObject::HandleMessage(
191*635a8641SAndroid Build Coastguard Worker     DBusConnection* connection,
192*635a8641SAndroid Build Coastguard Worker     DBusMessage* raw_message) {
193*635a8641SAndroid Build Coastguard Worker   bus_->AssertOnDBusThread();
194*635a8641SAndroid Build Coastguard Worker   // ExportedObject only handles method calls. Ignore other message types (e.g.
195*635a8641SAndroid Build Coastguard Worker   // signal).
196*635a8641SAndroid Build Coastguard Worker   if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
197*635a8641SAndroid Build Coastguard Worker     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
198*635a8641SAndroid Build Coastguard Worker 
199*635a8641SAndroid Build Coastguard Worker   // raw_message will be unrefed on exit of the function. Increment the
200*635a8641SAndroid Build Coastguard Worker   // reference so we can use it in MethodCall.
201*635a8641SAndroid Build Coastguard Worker   dbus_message_ref(raw_message);
202*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<MethodCall> method_call(
203*635a8641SAndroid Build Coastguard Worker       MethodCall::FromRawMessage(raw_message));
204*635a8641SAndroid Build Coastguard Worker   const std::string interface = method_call->GetInterface();
205*635a8641SAndroid Build Coastguard Worker   const std::string member = method_call->GetMember();
206*635a8641SAndroid Build Coastguard Worker 
207*635a8641SAndroid Build Coastguard Worker   if (interface.empty()) {
208*635a8641SAndroid Build Coastguard Worker     // We don't support method calls without interface.
209*635a8641SAndroid Build Coastguard Worker     LOG(WARNING) << "Interface is missing: " << method_call->ToString();
210*635a8641SAndroid Build Coastguard Worker     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
211*635a8641SAndroid Build Coastguard Worker   }
212*635a8641SAndroid Build Coastguard Worker 
213*635a8641SAndroid Build Coastguard Worker   // Check if we know about the method.
214*635a8641SAndroid Build Coastguard Worker   const std::string absolute_method_name = GetAbsoluteMemberName(
215*635a8641SAndroid Build Coastguard Worker       interface, member);
216*635a8641SAndroid Build Coastguard Worker   MethodTable::const_iterator iter = method_table_.find(absolute_method_name);
217*635a8641SAndroid Build Coastguard Worker   if (iter == method_table_.end()) {
218*635a8641SAndroid Build Coastguard Worker     // Don't know about the method.
219*635a8641SAndroid Build Coastguard Worker     LOG(WARNING) << "Unknown method: " << method_call->ToString();
220*635a8641SAndroid Build Coastguard Worker     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
221*635a8641SAndroid Build Coastguard Worker   }
222*635a8641SAndroid Build Coastguard Worker 
223*635a8641SAndroid Build Coastguard Worker   const base::TimeTicks start_time = base::TimeTicks::Now();
224*635a8641SAndroid Build Coastguard Worker   if (bus_->HasDBusThread()) {
225*635a8641SAndroid Build Coastguard Worker     // Post a task to run the method in the origin thread.
226*635a8641SAndroid Build Coastguard Worker     bus_->GetOriginTaskRunner()->PostTask(
227*635a8641SAndroid Build Coastguard Worker         FROM_HERE,
228*635a8641SAndroid Build Coastguard Worker         base::BindOnce(&ExportedObject::RunMethod, this, iter->second,
229*635a8641SAndroid Build Coastguard Worker                        std::move(method_call), start_time));
230*635a8641SAndroid Build Coastguard Worker   } else {
231*635a8641SAndroid Build Coastguard Worker     // If the D-Bus thread is not used, just call the method directly.
232*635a8641SAndroid Build Coastguard Worker     MethodCall* method = method_call.get();
233*635a8641SAndroid Build Coastguard Worker     iter->second.Run(method,
234*635a8641SAndroid Build Coastguard Worker                      base::Bind(&ExportedObject::SendResponse,
235*635a8641SAndroid Build Coastguard Worker                                 this,
236*635a8641SAndroid Build Coastguard Worker                                 start_time,
237*635a8641SAndroid Build Coastguard Worker                                 base::Passed(&method_call)));
238*635a8641SAndroid Build Coastguard Worker   }
239*635a8641SAndroid Build Coastguard Worker 
240*635a8641SAndroid Build Coastguard Worker   // It's valid to say HANDLED here, and send a method response at a later
241*635a8641SAndroid Build Coastguard Worker   // time from OnMethodCompleted() asynchronously.
242*635a8641SAndroid Build Coastguard Worker   return DBUS_HANDLER_RESULT_HANDLED;
243*635a8641SAndroid Build Coastguard Worker }
244*635a8641SAndroid Build Coastguard Worker 
RunMethod(MethodCallCallback method_call_callback,std::unique_ptr<MethodCall> method_call,base::TimeTicks start_time)245*635a8641SAndroid Build Coastguard Worker void ExportedObject::RunMethod(MethodCallCallback method_call_callback,
246*635a8641SAndroid Build Coastguard Worker                                std::unique_ptr<MethodCall> method_call,
247*635a8641SAndroid Build Coastguard Worker                                base::TimeTicks start_time) {
248*635a8641SAndroid Build Coastguard Worker   bus_->AssertOnOriginThread();
249*635a8641SAndroid Build Coastguard Worker   MethodCall* method = method_call.get();
250*635a8641SAndroid Build Coastguard Worker   method_call_callback.Run(method,
251*635a8641SAndroid Build Coastguard Worker                            base::Bind(&ExportedObject::SendResponse,
252*635a8641SAndroid Build Coastguard Worker                                       this,
253*635a8641SAndroid Build Coastguard Worker                                       start_time,
254*635a8641SAndroid Build Coastguard Worker                                       base::Passed(&method_call)));
255*635a8641SAndroid Build Coastguard Worker }
256*635a8641SAndroid Build Coastguard Worker 
SendResponse(base::TimeTicks start_time,std::unique_ptr<MethodCall> method_call,std::unique_ptr<Response> response)257*635a8641SAndroid Build Coastguard Worker void ExportedObject::SendResponse(base::TimeTicks start_time,
258*635a8641SAndroid Build Coastguard Worker                                   std::unique_ptr<MethodCall> method_call,
259*635a8641SAndroid Build Coastguard Worker                                   std::unique_ptr<Response> response) {
260*635a8641SAndroid Build Coastguard Worker   DCHECK(method_call);
261*635a8641SAndroid Build Coastguard Worker   if (bus_->HasDBusThread()) {
262*635a8641SAndroid Build Coastguard Worker     bus_->GetDBusTaskRunner()->PostTask(
263*635a8641SAndroid Build Coastguard Worker         FROM_HERE, base::BindOnce(&ExportedObject::OnMethodCompleted, this,
264*635a8641SAndroid Build Coastguard Worker                                   std::move(method_call), std::move(response),
265*635a8641SAndroid Build Coastguard Worker                                   start_time));
266*635a8641SAndroid Build Coastguard Worker   } else {
267*635a8641SAndroid Build Coastguard Worker     OnMethodCompleted(std::move(method_call), std::move(response), start_time);
268*635a8641SAndroid Build Coastguard Worker   }
269*635a8641SAndroid Build Coastguard Worker }
270*635a8641SAndroid Build Coastguard Worker 
OnMethodCompleted(std::unique_ptr<MethodCall> method_call,std::unique_ptr<Response> response,base::TimeTicks start_time)271*635a8641SAndroid Build Coastguard Worker void ExportedObject::OnMethodCompleted(std::unique_ptr<MethodCall> method_call,
272*635a8641SAndroid Build Coastguard Worker                                        std::unique_ptr<Response> response,
273*635a8641SAndroid Build Coastguard Worker                                        base::TimeTicks start_time) {
274*635a8641SAndroid Build Coastguard Worker   bus_->AssertOnDBusThread();
275*635a8641SAndroid Build Coastguard Worker 
276*635a8641SAndroid Build Coastguard Worker   // Record if the method call is successful, or not. 1 if successful.
277*635a8641SAndroid Build Coastguard Worker   UMA_HISTOGRAM_ENUMERATION("DBus.ExportedMethodHandleSuccess",
278*635a8641SAndroid Build Coastguard Worker                             response ? 1 : 0,
279*635a8641SAndroid Build Coastguard Worker                             kSuccessRatioHistogramMaxValue);
280*635a8641SAndroid Build Coastguard Worker 
281*635a8641SAndroid Build Coastguard Worker   // Check if the bus is still connected. If the method takes long to
282*635a8641SAndroid Build Coastguard Worker   // complete, the bus may be shut down meanwhile.
283*635a8641SAndroid Build Coastguard Worker   if (!bus_->is_connected())
284*635a8641SAndroid Build Coastguard Worker     return;
285*635a8641SAndroid Build Coastguard Worker 
286*635a8641SAndroid Build Coastguard Worker   if (!response) {
287*635a8641SAndroid Build Coastguard Worker     // Something bad happened in the method call.
288*635a8641SAndroid Build Coastguard Worker     std::unique_ptr<ErrorResponse> error_response(ErrorResponse::FromMethodCall(
289*635a8641SAndroid Build Coastguard Worker         method_call.get(), DBUS_ERROR_FAILED,
290*635a8641SAndroid Build Coastguard Worker         "error occurred in " + method_call->GetMember()));
291*635a8641SAndroid Build Coastguard Worker     bus_->Send(error_response->raw_message(), nullptr);
292*635a8641SAndroid Build Coastguard Worker     return;
293*635a8641SAndroid Build Coastguard Worker   }
294*635a8641SAndroid Build Coastguard Worker 
295*635a8641SAndroid Build Coastguard Worker   // The method call was successful.
296*635a8641SAndroid Build Coastguard Worker   bus_->Send(response->raw_message(), nullptr);
297*635a8641SAndroid Build Coastguard Worker 
298*635a8641SAndroid Build Coastguard Worker   // Record time spent to handle the the method call. Don't include failures.
299*635a8641SAndroid Build Coastguard Worker   UMA_HISTOGRAM_TIMES("DBus.ExportedMethodHandleTime",
300*635a8641SAndroid Build Coastguard Worker                       base::TimeTicks::Now() - start_time);
301*635a8641SAndroid Build Coastguard Worker }
302*635a8641SAndroid Build Coastguard Worker 
OnUnregistered(DBusConnection * connection)303*635a8641SAndroid Build Coastguard Worker void ExportedObject::OnUnregistered(DBusConnection* connection) {
304*635a8641SAndroid Build Coastguard Worker }
305*635a8641SAndroid Build Coastguard Worker 
HandleMessageThunk(DBusConnection * connection,DBusMessage * raw_message,void * user_data)306*635a8641SAndroid Build Coastguard Worker DBusHandlerResult ExportedObject::HandleMessageThunk(
307*635a8641SAndroid Build Coastguard Worker     DBusConnection* connection,
308*635a8641SAndroid Build Coastguard Worker     DBusMessage* raw_message,
309*635a8641SAndroid Build Coastguard Worker     void* user_data) {
310*635a8641SAndroid Build Coastguard Worker   ExportedObject* self = reinterpret_cast<ExportedObject*>(user_data);
311*635a8641SAndroid Build Coastguard Worker   return self->HandleMessage(connection, raw_message);
312*635a8641SAndroid Build Coastguard Worker }
313*635a8641SAndroid Build Coastguard Worker 
OnUnregisteredThunk(DBusConnection * connection,void * user_data)314*635a8641SAndroid Build Coastguard Worker void ExportedObject::OnUnregisteredThunk(DBusConnection *connection,
315*635a8641SAndroid Build Coastguard Worker                                          void* user_data) {
316*635a8641SAndroid Build Coastguard Worker   ExportedObject* self = reinterpret_cast<ExportedObject*>(user_data);
317*635a8641SAndroid Build Coastguard Worker   return self->OnUnregistered(connection);
318*635a8641SAndroid Build Coastguard Worker }
319*635a8641SAndroid Build Coastguard Worker 
320*635a8641SAndroid Build Coastguard Worker }  // namespace dbus
321