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