15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/exported_object.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/bus.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/message.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/scoped_dbus_error.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace dbus { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used for success ratio histograms. 1 for success, 0 for failure. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSuccessRatioHistogramMaxValue = 2; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets the absolute method name by concatenating the interface name and 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the method name. Used for building keys for method_table_ in 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ExportedObject. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetAbsoluteMethodName( 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& interface_name, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& method_name) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return interface_name + "." + method_name; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExportedObject::ExportedObject(Bus* bus, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjectPath& object_path) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : bus_(bus), 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_path_(object_path), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_is_registered_(false) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExportedObject::~ExportedObject() { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!object_is_registered_); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExportedObject::ExportMethodAndBlock( 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& interface_name, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& method_name, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MethodCallCallback method_call_callback) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the method is already exported. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string absolute_method_name = 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAbsoluteMethodName(interface_name, method_name); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (method_table_.find(absolute_method_name) != method_table_.end()) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << absolute_method_name << " is already exported"; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bus_->Connect()) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bus_->SetUpAsyncOperations()) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Register()) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the method callback to the method table. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_table_[absolute_method_name] = method_call_callback; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExportedObject::ExportMethod(const std::string& interface_name, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& method_name, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MethodCallCallback method_call_callback, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnExportedCallback on_exported_calback) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnOriginThread(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure task = base::Bind(&ExportedObject::ExportMethodInternal, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interface_name, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_name, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_call_callback, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) on_exported_calback); 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExportedObject::SendSignal(Signal* signal) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For signals, the object path should be set to the path to the sender 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // object, which is this exported object here. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(signal->SetPath(object_path_)); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Increment the reference count so we can safely reference the 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // underlying signal message until the signal sending is complete. This 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be unref'ed in SendSignalInternal(). 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* signal_message = signal->raw_message(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus_message_ref(signal_message); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeTicks start_time = base::TimeTicks::Now(); 10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetDBusTaskRunner()->PostTask( 10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FROM_HERE, 10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&ExportedObject::SendSignalInternal, 10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this, 10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) start_time, 10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) signal_message)); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExportedObject::Unregister() { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!object_is_registered_) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->UnregisterObjectPath(object_path_); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_is_registered_ = false; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExportedObject::ExportMethodInternal( 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& interface_name, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& method_name, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MethodCallCallback method_call_callback, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnExportedCallback on_exported_calback) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool success = ExportMethodAndBlock(interface_name, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_name, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_call_callback); 13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, 13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&ExportedObject::OnExported, 13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this, 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) on_exported_calback, 13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) interface_name, 13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) method_name, 13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) success)); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExportedObject::OnExported(OnExportedCallback on_exported_callback, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& interface_name, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& method_name, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnOriginThread(); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) on_exported_callback.Run(interface_name, method_name, success); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExportedObject::SendSignalInternal(base::TimeTicks start_time, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* signal_message) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 serial = 0; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->Send(signal_message, &serial); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus_message_unref(signal_message); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record time spent to send the the signal. This is not accurate as the 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // signal will actually be sent from the next run of the message loop, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but we can at least tell the number of signals sent. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("DBus.SignalSendTime", 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now() - start_time); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExportedObject::Register() { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (object_is_registered_) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedDBusError error; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusObjectPathVTable vtable = {}; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vtable.message_function = &ExportedObject::HandleMessageThunk; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vtable.unregister_function = &ExportedObject::OnUnregisteredThunk; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool success = bus_->TryRegisterObjectPath(object_path_, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &vtable, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error.get()); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!success) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to register the object: " << object_path_.value() 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ": " << (error.is_set() ? error.message() : ""); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_is_registered_ = true; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DBusHandlerResult ExportedObject::HandleMessage( 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusConnection* connection, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* raw_message) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(DBUS_MESSAGE_TYPE_METHOD_CALL, dbus_message_get_type(raw_message)); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // raw_message will be unrefed on exit of the function. Increment the 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reference so we can use it in MethodCall. 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus_message_ref(raw_message); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<MethodCall> method_call( 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MethodCall::FromRawMessage(raw_message)); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string interface = method_call->GetInterface(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string member = method_call->GetMember(); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (interface.empty()) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't support method calls without interface. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Interface is missing: " << method_call->ToString(); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we know about the method. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string absolute_method_name = GetAbsoluteMethodName( 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interface, member); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MethodTable::const_iterator iter = method_table_.find(absolute_method_name); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter == method_table_.end()) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't know about the method. 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Unknown method: " << method_call->ToString(); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeTicks start_time = base::TimeTicks::Now(); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bus_->HasDBusThread()) { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Post a task to run the method in the origin thread. 21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, 21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&ExportedObject::RunMethod, 22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this, 22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) iter->second, 22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Passed(&method_call), 22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) start_time)); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the D-Bus thread is not used, just call the method directly. 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MethodCall* method = method_call.get(); 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter->second.Run(method, 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ExportedObject::SendResponse, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time, 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Passed(&method_call))); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's valid to say HANDLED here, and send a method response at a later 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time from OnMethodCompleted() asynchronously. 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DBUS_HANDLER_RESULT_HANDLED; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExportedObject::RunMethod(MethodCallCallback method_call_callback, 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<MethodCall> method_call, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks start_time) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnOriginThread(); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MethodCall* method = method_call.get(); 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) method_call_callback.Run(method, 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ExportedObject::SendResponse, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time, 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Passed(&method_call))); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExportedObject::SendResponse(base::TimeTicks start_time, 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<MethodCall> method_call, 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<Response> response) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(method_call); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bus_->HasDBusThread()) { 25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetDBusTaskRunner()->PostTask( 25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FROM_HERE, 25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&ExportedObject::OnMethodCompleted, 25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this, 26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Passed(&method_call), 26168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Passed(&response), 26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) start_time)); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnMethodCompleted(method_call.Pass(), response.Pass(), start_time); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExportedObject::OnMethodCompleted(scoped_ptr<MethodCall> method_call, 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<Response> response, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks start_time) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record if the method call is successful, or not. 1 if successful. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("DBus.ExportedMethodHandleSuccess", 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response ? 1 : 0, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kSuccessRatioHistogramMaxValue); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the bus is still connected. If the method takes long to 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // complete, the bus may be shut down meanwhile. 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bus_->is_connected()) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!response) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Something bad happened in the method call. 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<ErrorResponse> error_response( 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorResponse::FromMethodCall( 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) method_call.get(), 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBUS_ERROR_FAILED, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "error occurred in " + method_call->GetMember())); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->Send(error_response->raw_message(), NULL); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The method call was successful. 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->Send(response->raw_message(), NULL); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record time spent to handle the the method call. Don't include failures. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("DBus.ExportedMethodHandleTime", 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now() - start_time); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExportedObject::OnUnregistered(DBusConnection* connection) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DBusHandlerResult ExportedObject::HandleMessageThunk( 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusConnection* connection, 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* raw_message, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* user_data) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExportedObject* self = reinterpret_cast<ExportedObject*>(user_data); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self->HandleMessage(connection, raw_message); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExportedObject::OnUnregisteredThunk(DBusConnection *connection, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* user_data) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExportedObject* self = reinterpret_cast<ExportedObject*>(user_data); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self->OnUnregistered(connection); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace dbus 320