object_proxy.cc revision 45779228f8c9e40851cfd23f727e2bd8ffdd4714
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 50d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "dbus/object_proxy.h" 60d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 70d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include <stddef.h> 80d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include <utility> 9ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 10ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/bind.h" 11ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/logging.h" 12ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/message_loop/message_loop.h" 13ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/metrics/histogram.h" 14ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/strings/string_piece.h" 15ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/strings/stringprintf.h" 16ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/task_runner_util.h" 17ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/threading/thread.h" 18ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "base/threading/thread_restrictions.h" 190d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "dbus/bus.h" 20ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "dbus/dbus_statistics.h" 21ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "dbus/message.h" 22ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "dbus/object_path.h" 23ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "dbus/scoped_dbus_error.h" 24ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat#include "dbus/util.h" 25ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 26ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratnamespace dbus { 27ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 28ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratnamespace { 29ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 30ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratconst char kErrorServiceUnknown[] = "org.freedesktop.DBus.Error.ServiceUnknown"; 31ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratconst char kErrorObjectUnknown[] = "org.freedesktop.DBus.Error.UnknownObject"; 32ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 33ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// Used for success ratio histograms. 1 for success, 0 for failure. 34ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratconst int kSuccessRatioHistogramMaxValue = 2; 35ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 36ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// The path of D-Bus Object sending NameOwnerChanged signal. 37ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratconst char kDBusSystemObjectPath[] = "/org/freedesktop/DBus"; 38ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 39ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// The D-Bus Object interface. 40ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratconst char kDBusSystemObjectInterface[] = "org.freedesktop.DBus"; 41ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 42ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// The D-Bus Object address. 43ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratconst char kDBusSystemObjectAddress[] = "org.freedesktop.DBus"; 44ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 45ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// The NameOwnerChanged member in |kDBusSystemObjectInterface|. 46ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratconst char kNameOwnerChangedMember[] = "NameOwnerChanged"; 47ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 48ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// An empty function used for ObjectProxy::EmptyResponseCallback(). 49ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid EmptyResponseCallbackBody(Response* /*response*/) { 50ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 51ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 52ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} // namespace 53ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 54ae6a045d2239408e25198ad17e2413bdde105788Daniel EratObjectProxy::ObjectProxy(Bus* bus, 55ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string& service_name, 56ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const ObjectPath& object_path, 57ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat int options) 58ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat : bus_(bus), 59ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat service_name_(service_name), 60ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat object_path_(object_path), 61ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ignore_service_unknown_errors_( 62ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat options & IGNORE_SERVICE_UNKNOWN_ERRORS) { 63ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 64ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 65ae6a045d2239408e25198ad17e2413bdde105788Daniel EratObjectProxy::~ObjectProxy() { 66ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DCHECK(pending_calls_.empty()); 67ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 68ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 69ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// Originally we tried to make |method_call| a const reference, but we 70ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// gave up as dbus_connection_send_with_reply_and_block() takes a 71ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// non-const pointer of DBusMessage as the second parameter. 72ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratscoped_ptr<Response> ObjectProxy::CallMethodAndBlockWithErrorDetails( 73ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat MethodCall* method_call, int timeout_ms, ScopedDBusError* error) { 74ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 75ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 76ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (!bus_->Connect() || 77ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat !method_call->SetDestination(service_name_) || 78ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat !method_call->SetPath(object_path_)) 79ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return scoped_ptr<Response>(); 80ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 81ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusMessage* request_message = method_call->raw_message(); 82ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 83ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Send the message synchronously. 84ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const base::TimeTicks start_time = base::TimeTicks::Now(); 85ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusMessage* response_message = 86ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->SendWithReplyAndBlock(request_message, timeout_ms, error->get()); 87ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Record if the method call is successful, or not. 1 if successful. 88ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat UMA_HISTOGRAM_ENUMERATION("DBus.SyncMethodCallSuccess", 89ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat response_message ? 1 : 0, 90ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat kSuccessRatioHistogramMaxValue); 91ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat statistics::AddBlockingSentMethodCall(service_name_, 92ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_call->GetInterface(), 93ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_call->GetMember()); 94ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 95ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (!response_message) { 96ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat LogMethodCallFailure(method_call->GetInterface(), 97ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_call->GetMember(), 98ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error->is_set() ? error->name() : "unknown error type", 99ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error->is_set() ? error->message() : ""); 100ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return scoped_ptr<Response>(); 101ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 102ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Record time spent for the method call. Don't include failures. 103ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat UMA_HISTOGRAM_TIMES("DBus.SyncMethodCallTime", 104ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::TimeTicks::Now() - start_time); 105ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 106ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return Response::FromRawMessage(response_message); 107ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 108ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 109ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratscoped_ptr<Response> ObjectProxy::CallMethodAndBlock(MethodCall* method_call, 110ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat int timeout_ms) { 111ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ScopedDBusError error; 112ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return CallMethodAndBlockWithErrorDetails(method_call, timeout_ms, &error); 113ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 114ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 115ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::CallMethod(MethodCall* method_call, 116ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat int timeout_ms, 117ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ResponseCallback callback) { 118ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat CallMethodWithErrorCallback(method_call, timeout_ms, callback, 119ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&ObjectProxy::OnCallMethodError, 120ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat this, 121ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_call->GetInterface(), 122ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_call->GetMember(), 123ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat callback)); 124ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 125ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 126ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::CallMethodWithErrorCallback(MethodCall* method_call, 127ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat int timeout_ms, 128ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ResponseCallback callback, 129ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ErrorCallback error_callback) { 130ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnOriginThread(); 131ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 132ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const base::TimeTicks start_time = base::TimeTicks::Now(); 133ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 134ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (!method_call->SetDestination(service_name_) || 135ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat !method_call->SetPath(object_path_)) { 136ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // In case of a failure, run the error callback with NULL. 137ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusMessage* response_message = NULL; 138ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback, 139ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat this, 140ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat callback, 141ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error_callback, 142ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat start_time, 143ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat response_message); 144ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, task); 145ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return; 146ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 147ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 148ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Increment the reference count so we can safely reference the 149ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // underlying request message until the method call is complete. This 150ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // will be unref'ed in StartAsyncMethodCall(). 151ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusMessage* request_message = method_call->raw_message(); 152ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat dbus_message_ref(request_message); 153ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 154ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Closure task = base::Bind(&ObjectProxy::StartAsyncMethodCall, 155ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat this, 156ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat timeout_ms, 157ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat request_message, 158ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat callback, 159ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error_callback, 160ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat start_time); 161ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat statistics::AddSentMethodCall(service_name_, 162ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_call->GetInterface(), 163ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_call->GetMember()); 164ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 165ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Wait for the response in the D-Bus thread. 166ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task); 167ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 168ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 169ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::ConnectToSignal(const std::string& interface_name, 170ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string& signal_name, 171ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat SignalCallback signal_callback, 172ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat OnConnectedCallback on_connected_callback) { 173ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnOriginThread(); 174ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 175ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (bus_->HasDBusThread()) { 176ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::PostTaskAndReplyWithResult( 177ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetDBusTaskRunner(), FROM_HERE, 178ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&ObjectProxy::ConnectToSignalInternal, this, interface_name, 179ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat signal_name, signal_callback), 180ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(on_connected_callback, interface_name, signal_name)); 181ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } else { 182ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // If the bus doesn't have a dedicated dbus thread we need to call 183ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // ConnectToSignalInternal directly otherwise we might miss a signal 184ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // that is currently queued if we do a PostTask. 185ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const bool success = 186ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ConnectToSignalInternal(interface_name, signal_name, signal_callback); 187ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat on_connected_callback.Run(interface_name, signal_name, success); 188ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 189ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 190ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 191ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::SetNameOwnerChangedCallback( 192ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat NameOwnerChangedCallback callback) { 193ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnOriginThread(); 194ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 195ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat name_owner_changed_callback_ = callback; 196ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 197ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 198ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::WaitForServiceToBeAvailable( 199ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat WaitForServiceToBeAvailableCallback callback) { 200ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnOriginThread(); 201ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 202ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat wait_for_service_to_be_available_callbacks_.push_back(callback); 203ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetDBusTaskRunner()->PostTask( 204ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat FROM_HERE, 205ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&ObjectProxy::WaitForServiceToBeAvailableInternal, this)); 206ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 207ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 208ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::Detach() { 209ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 210ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 211ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (bus_->is_connected()) 212ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this); 213ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 214ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat for (const auto& match_rule : match_rules_) { 215ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ScopedDBusError error; 216ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->RemoveMatch(match_rule, error.get()); 217ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (error.is_set()) { 218ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // There is nothing we can do to recover, so just print the error. 219ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat LOG(ERROR) << "Failed to remove match rule: " << match_rule; 220ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 221ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 222ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat match_rules_.clear(); 223ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 224ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat for (auto* pending_call : pending_calls_) { 225ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat dbus_pending_call_cancel(pending_call); 226ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat dbus_pending_call_unref(pending_call); 227ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 228ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat pending_calls_.clear(); 229ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 230ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 231ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat// static 232ae6a045d2239408e25198ad17e2413bdde105788Daniel EratObjectProxy::ResponseCallback ObjectProxy::EmptyResponseCallback() { 233ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return base::Bind(&EmptyResponseCallbackBody); 234ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 235ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 236ae6a045d2239408e25198ad17e2413bdde105788Daniel EratObjectProxy::OnPendingCallIsCompleteData::OnPendingCallIsCompleteData( 237ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ObjectProxy* in_object_proxy, 238ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ResponseCallback in_response_callback, 239ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ErrorCallback in_error_callback, 240ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::TimeTicks in_start_time) 241ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat : object_proxy(in_object_proxy), 242ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat response_callback(in_response_callback), 243ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error_callback(in_error_callback), 244ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat start_time(in_start_time) { 245ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 246ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 247ae6a045d2239408e25198ad17e2413bdde105788Daniel EratObjectProxy::OnPendingCallIsCompleteData::~OnPendingCallIsCompleteData() { 248ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 249ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 250ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::StartAsyncMethodCall(int timeout_ms, 251ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusMessage* request_message, 252ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ResponseCallback response_callback, 253ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ErrorCallback error_callback, 254ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::TimeTicks start_time) { 255ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 256ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 257ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) { 258ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // In case of a failure, run the error callback with NULL. 259ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusMessage* response_message = NULL; 260ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback, 261ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat this, 262ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat response_callback, 263ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error_callback, 264ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat start_time, 265ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat response_message); 266ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, task); 267ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 268ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat dbus_message_unref(request_message); 269ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return; 270ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 271ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 272ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusPendingCall* pending_call = NULL; 273ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 274ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->SendWithReply(request_message, &pending_call, timeout_ms); 275ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 276ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Prepare the data we'll be passing to OnPendingCallIsCompleteThunk(). 277ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // The data will be deleted in OnPendingCallIsCompleteThunk(). 278ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat OnPendingCallIsCompleteData* data = 279ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat new OnPendingCallIsCompleteData(this, response_callback, error_callback, 280ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat start_time); 281ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 282ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // This returns false only when unable to allocate memory. 283ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const bool success = dbus_pending_call_set_notify( 284ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat pending_call, 285ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat &ObjectProxy::OnPendingCallIsCompleteThunk, 286ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat data, 287ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat &DeleteVoidPointer<OnPendingCallIsCompleteData>); 288ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat CHECK(success) << "Unable to allocate memory"; 289ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat pending_calls_.insert(pending_call); 290ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 291ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // It's now safe to unref the request message. 292ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat dbus_message_unref(request_message); 293ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 294ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 295ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call, 296ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ResponseCallback response_callback, 297ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ErrorCallback error_callback, 298ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::TimeTicks start_time) { 299ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 300ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 301ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call); 302ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback, 303ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat this, 304ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat response_callback, 305ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error_callback, 306ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat start_time, 307ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat response_message); 308ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, task); 309ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 310ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Remove the pending call from the set. 311ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat pending_calls_.erase(pending_call); 312ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat dbus_pending_call_unref(pending_call); 313ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 314ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 315ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::RunResponseCallback(ResponseCallback response_callback, 316ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ErrorCallback error_callback, 317ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::TimeTicks start_time, 318ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusMessage* response_message) { 319ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnOriginThread(); 320ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 321ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bool method_call_successful = false; 322ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (!response_message) { 323ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // The response is not received. 324ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error_callback.Run(NULL); 325ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } else if (dbus_message_get_type(response_message) == 326ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBUS_MESSAGE_TYPE_ERROR) { 327ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // This will take |response_message| and release (unref) it. 328ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat scoped_ptr<ErrorResponse> error_response( 329ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ErrorResponse::FromRawMessage(response_message)); 330ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error_callback.Run(error_response.get()); 331ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Delete the message on the D-Bus thread. See below for why. 332ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetDBusTaskRunner()->PostTask( 333ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat FROM_HERE, 334ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&base::DeletePointer<ErrorResponse>, 335ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error_response.release())); 336ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } else { 337ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // This will take |response_message| and release (unref) it. 338ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat scoped_ptr<Response> response(Response::FromRawMessage(response_message)); 339ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // The response is successfully received. 340ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat response_callback.Run(response.get()); 341ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // The message should be deleted on the D-Bus thread for a complicated 342ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // reason: 343ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // 344ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // libdbus keeps track of the number of bytes in the incoming message 345ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // queue to ensure that the data size in the queue is manageable. The 346ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // bookkeeping is partly done via dbus_message_unref(), and immediately 347ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // asks the client code (Chrome) to stop monitoring the underlying 348ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // socket, if the number of bytes exceeds a certian number, which is set 349ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // to 63MB, per dbus-transport.cc: 350ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // 351ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // /* Try to default to something that won't totally hose the system, 352ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // * but doesn't impose too much of a limitation. 353ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // */ 354ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; 355ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // 356ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // The monitoring of the socket is done on the D-Bus thread (see Watch 357ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // class in bus.cc), hence we should stop the monitoring from D-Bus 358ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // thread, not from the current thread here, which is likely UI thread. 359ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetDBusTaskRunner()->PostTask( 360ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat FROM_HERE, 361ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&base::DeletePointer<Response>, response.release())); 362ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 363ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_call_successful = true; 364ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Record time spent for the method call. Don't include failures. 365ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat UMA_HISTOGRAM_TIMES("DBus.AsyncMethodCallTime", 366ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::TimeTicks::Now() - start_time); 367ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 368ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Record if the method call is successful, or not. 1 if successful. 369ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat UMA_HISTOGRAM_ENUMERATION("DBus.AsyncMethodCallSuccess", 370ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_call_successful, 371ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat kSuccessRatioHistogramMaxValue); 372ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 373ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 374ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::OnPendingCallIsCompleteThunk(DBusPendingCall* pending_call, 375ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat void* user_data) { 376ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat OnPendingCallIsCompleteData* data = 377ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat reinterpret_cast<OnPendingCallIsCompleteData*>(user_data); 378ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ObjectProxy* self = data->object_proxy; 379ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat self->OnPendingCallIsComplete(pending_call, 380ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat data->response_callback, 381ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat data->error_callback, 382ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat data->start_time); 383ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 384ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 385ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratbool ObjectProxy::ConnectToNameOwnerChangedSignal() { 386ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 387ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 388ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) 389ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return false; 390ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 391ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AddFilterFunction(&ObjectProxy::HandleMessageThunk, this); 392ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 393ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Add a match_rule listening NameOwnerChanged for the well-known name 394ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // |service_name_|. 395ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string name_owner_changed_match_rule = 396ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::StringPrintf( 397ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat "type='signal',interface='org.freedesktop.DBus'," 398ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat "member='NameOwnerChanged',path='/org/freedesktop/DBus'," 399ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat "sender='org.freedesktop.DBus',arg0='%s'", 400ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat service_name_.c_str()); 401ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 402ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const bool success = 403ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat AddMatchRuleWithoutCallback(name_owner_changed_match_rule, 404ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat "org.freedesktop.DBus.NameOwnerChanged"); 405ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 406ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Try getting the current name owner. It's not guaranteed that we can get 407ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // the name owner at this moment, as the service may not yet be started. If 408ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // that's the case, we'll get the name owner via NameOwnerChanged signal, 409ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // as soon as the service is started. 410ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat UpdateNameOwnerAndBlock(); 411ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 412ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return success; 413ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 414ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 415ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratbool ObjectProxy::ConnectToSignalInternal(const std::string& interface_name, 416ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string& signal_name, 417ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat SignalCallback signal_callback) { 418ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 419ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 420ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (!ConnectToNameOwnerChangedSignal()) 421ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return false; 422ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 423ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string absolute_signal_name = 424ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat GetAbsoluteMemberName(interface_name, signal_name); 425ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 426ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Add a match rule so the signal goes through HandleMessage(). 427ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string match_rule = 428ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::StringPrintf("type='signal', interface='%s', path='%s'", 429ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat interface_name.c_str(), 430ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat object_path_.value().c_str()); 431ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return AddMatchRuleWithCallback(match_rule, 432ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat absolute_signal_name, 433ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat signal_callback); 434ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 435ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 436ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::WaitForServiceToBeAvailableInternal() { 437ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 438ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 439ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (!ConnectToNameOwnerChangedSignal()) { // Failed to connect to the signal. 440ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const bool service_is_ready = false; 441ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetOriginTaskRunner()->PostTask( 442ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat FROM_HERE, 443ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&ObjectProxy::RunWaitForServiceToBeAvailableCallbacks, 444ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat this, service_is_ready)); 445ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return; 446ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 447ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 448ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const bool service_is_available = !service_name_owner_.empty(); 449ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (service_is_available) { // Service is already available. 450ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetOriginTaskRunner()->PostTask( 451ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat FROM_HERE, 452ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&ObjectProxy::RunWaitForServiceToBeAvailableCallbacks, 453ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat this, service_is_available)); 454ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return; 455ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 456ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 457ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 458ae6a045d2239408e25198ad17e2413bdde105788Daniel EratDBusHandlerResult ObjectProxy::HandleMessage( 45960d96a4a9e0d8c78d46c1f86dec60f9ecdbedbdbChristopher Wiley DBusConnection* /* connection */, 460ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusMessage* raw_message) { 461ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 462ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 463ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_SIGNAL) 464ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 465ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 466ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // raw_message will be unrefed on exit of the function. Increment the 467ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // reference so we can use it in Signal. 468ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat dbus_message_ref(raw_message); 469ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat scoped_ptr<Signal> signal( 470ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat Signal::FromRawMessage(raw_message)); 471ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 472ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Verify the signal comes from the object we're proxying for, this is 473ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // our last chance to return DBUS_HANDLER_RESULT_NOT_YET_HANDLED and 474ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // allow other object proxies to handle instead. 475ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const ObjectPath path = signal->GetPath(); 476ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (path != object_path_) { 477ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (path.value() == kDBusSystemObjectPath && 478ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat signal->GetMember() == kNameOwnerChangedMember) { 479ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Handle NameOwnerChanged separately 4800d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return HandleNameOwnerChanged(std::move(signal)); 481ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 482ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 483ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 484ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 485ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string interface = signal->GetInterface(); 486ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string member = signal->GetMember(); 487ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 488ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat statistics::AddReceivedSignal(service_name_, interface, member); 489ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 490ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Check if we know about the signal. 491ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string absolute_signal_name = GetAbsoluteMemberName( 492ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat interface, member); 493ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat MethodTable::const_iterator iter = method_table_.find(absolute_signal_name); 494ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (iter == method_table_.end()) { 495ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Don't know about the signal. 496ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 497ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 498ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat VLOG(1) << "Signal received: " << signal->ToString(); 499ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 500ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat std::string sender = signal->GetSender(); 501ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (service_name_owner_ != sender) { 502ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat LOG(ERROR) << "Rejecting a message from a wrong sender."; 503ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat UMA_HISTOGRAM_COUNTS("DBus.RejectedSignalCount", 1); 504ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 505ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 506ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 507ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const base::TimeTicks start_time = base::TimeTicks::Now(); 508ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (bus_->HasDBusThread()) { 509ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Post a task to run the method in the origin thread. 510ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Transfer the ownership of |signal| to RunMethod(). 511ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // |released_signal| will be deleted in RunMethod(). 512ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat Signal* released_signal = signal.release(); 513ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, 514ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&ObjectProxy::RunMethod, 515ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat this, 516ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat start_time, 517ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat iter->second, 518ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat released_signal)); 519ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } else { 520ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const base::TimeTicks start_time = base::TimeTicks::Now(); 521ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // If the D-Bus thread is not used, just call the callback on the 522ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // current thread. Transfer the ownership of |signal| to RunMethod(). 523ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat Signal* released_signal = signal.release(); 524ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat RunMethod(start_time, iter->second, released_signal); 525ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 526ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 527ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // We don't return DBUS_HANDLER_RESULT_HANDLED for signals because other 528ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // objects may be interested in them. (e.g. Signals from org.freedesktop.DBus) 529ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 530ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 531ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 532ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::RunMethod(base::TimeTicks start_time, 533ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat std::vector<SignalCallback> signal_callbacks, 534ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat Signal* signal) { 535ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnOriginThread(); 536ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 537ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat for (std::vector<SignalCallback>::iterator iter = signal_callbacks.begin(); 538ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat iter != signal_callbacks.end(); ++iter) 539ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat iter->Run(signal); 540ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 541ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Delete the message on the D-Bus thread. See comments in 542ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // RunResponseCallback(). 543ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetDBusTaskRunner()->PostTask( 544ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat FROM_HERE, 545ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&base::DeletePointer<Signal>, signal)); 546ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 547ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Record time spent for handling the signal. 548ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat UMA_HISTOGRAM_TIMES("DBus.SignalHandleTime", 549ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::TimeTicks::Now() - start_time); 550ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 551ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 552ae6a045d2239408e25198ad17e2413bdde105788Daniel EratDBusHandlerResult ObjectProxy::HandleMessageThunk( 553ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusConnection* connection, 554ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DBusMessage* raw_message, 555ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat void* user_data) { 556ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ObjectProxy* self = reinterpret_cast<ObjectProxy*>(user_data); 557ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return self->HandleMessage(connection, raw_message); 558ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 559ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 560ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::LogMethodCallFailure( 561ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const base::StringPiece& interface_name, 562ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const base::StringPiece& method_name, 563ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const base::StringPiece& error_name, 564ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const base::StringPiece& error_message) const { 565ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (ignore_service_unknown_errors_ && 566ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat (error_name == kErrorServiceUnknown || error_name == kErrorObjectUnknown)) 567ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return; 56845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 569ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat std::ostringstream msg; 570ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat msg << "Failed to call method: " << interface_name << "." << method_name 571ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat << ": object_path= " << object_path_.value() 572ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat << ": " << error_name << ": " << error_message; 57345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 57445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // "UnknownObject" indicates that an object or service is no longer available, 57545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // e.g. a Shill network service has gone out of range. Treat these as warnings 57645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // not errors. 57745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (error_name == kErrorObjectUnknown) 57845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko LOG(WARNING) << msg.str(); 57945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko else 58045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko LOG(ERROR) << msg.str(); 581ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 582ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 583ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::OnCallMethodError(const std::string& interface_name, 584ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string& method_name, 585ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ResponseCallback response_callback, 586ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ErrorResponse* error_response) { 587ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (error_response) { 588ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Error message may contain the error message as string. 589ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat MessageReader reader(error_response); 590ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat std::string error_message; 591ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat reader.PopString(&error_message); 592ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat LogMethodCallFailure(interface_name, 593ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_name, 594ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error_response->GetErrorName(), 595ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat error_message); 596ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 597ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat response_callback.Run(NULL); 598ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 599ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 600ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratbool ObjectProxy::AddMatchRuleWithCallback( 601ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string& match_rule, 602ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string& absolute_signal_name, 603ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat SignalCallback signal_callback) { 604ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DCHECK(!match_rule.empty()); 605ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DCHECK(!absolute_signal_name.empty()); 606ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 607ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 608ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (match_rules_.find(match_rule) == match_rules_.end()) { 609ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ScopedDBusError error; 610ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AddMatch(match_rule, error.get()); 611ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (error.is_set()) { 612ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got " 613ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat << error.name() << ": " << error.message(); 614ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return false; 615ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } else { 616ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Store the match rule, so that we can remove this in Detach(). 617ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat match_rules_.insert(match_rule); 618ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Add the signal callback to the method table. 619ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_table_[absolute_signal_name].push_back(signal_callback); 620ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return true; 621ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 622ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } else { 623ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // We already have the match rule. 624ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat method_table_[absolute_signal_name].push_back(signal_callback); 625ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return true; 626ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 627ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 628ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 629ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratbool ObjectProxy::AddMatchRuleWithoutCallback( 630ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string& match_rule, 631ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string& absolute_signal_name) { 632ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DCHECK(!match_rule.empty()); 633ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DCHECK(!absolute_signal_name.empty()); 634ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 635ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 636ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (match_rules_.find(match_rule) != match_rules_.end()) 637ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return true; 638ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 639ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat ScopedDBusError error; 640ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AddMatch(match_rule, error.get()); 641ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (error.is_set()) { 642ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got " 643ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat << error.name() << ": " << error.message(); 644ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return false; 645ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 646ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Store the match rule, so that we can remove this in Detach(). 647ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat match_rules_.insert(match_rule); 648ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return true; 649ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 650ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 651ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::UpdateNameOwnerAndBlock() { 652ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 653ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Errors should be suppressed here, as the service may not be yet running 654ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // when connecting to signals of the service, which is just fine. 655ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // The ObjectProxy will be notified when the service is launched via 656ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // NameOwnerChanged signal. See also comments in ConnectToSignalInternal(). 657ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat service_name_owner_ = 658ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS); 659ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 660ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 661ae6a045d2239408e25198ad17e2413bdde105788Daniel EratDBusHandlerResult ObjectProxy::HandleNameOwnerChanged( 662ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat scoped_ptr<Signal> signal) { 663ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat DCHECK(signal); 664ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnDBusThread(); 665ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 666ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Confirm the validity of the NameOwnerChanged signal. 667ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (signal->GetMember() == kNameOwnerChangedMember && 668ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat signal->GetInterface() == kDBusSystemObjectInterface && 669ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat signal->GetSender() == kDBusSystemObjectAddress) { 670ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat MessageReader reader(signal.get()); 671ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat std::string name, old_owner, new_owner; 672ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (reader.PopString(&name) && 673ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat reader.PopString(&old_owner) && 674ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat reader.PopString(&new_owner) && 675ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat name == service_name_) { 676ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat service_name_owner_ = new_owner; 677ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetOriginTaskRunner()->PostTask( 678ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat FROM_HERE, 679ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&ObjectProxy::RunNameOwnerChangedCallback, 680ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat this, old_owner, new_owner)); 681ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 682ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const bool service_is_available = !service_name_owner_.empty(); 683ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (service_is_available) { 684ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->GetOriginTaskRunner()->PostTask( 685ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat FROM_HERE, 686ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat base::Bind(&ObjectProxy::RunWaitForServiceToBeAvailableCallbacks, 687ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat this, service_is_available)); 688ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 689ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 690ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat } 691ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 692ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // Always return unhandled to let other object proxies handle the same 693ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat // signal. 694ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 695ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 696ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 697ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::RunNameOwnerChangedCallback(const std::string& old_owner, 698ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat const std::string& new_owner) { 699ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnOriginThread(); 700ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat if (!name_owner_changed_callback_.is_null()) 701ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat name_owner_changed_callback_.Run(old_owner, new_owner); 702ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 703ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 704ae6a045d2239408e25198ad17e2413bdde105788Daniel Eratvoid ObjectProxy::RunWaitForServiceToBeAvailableCallbacks( 705ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bool service_is_available) { 706ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat bus_->AssertOnOriginThread(); 707ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 708ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat std::vector<WaitForServiceToBeAvailableCallback> callbacks; 709ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat callbacks.swap(wait_for_service_to_be_available_callbacks_); 710ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat for (size_t i = 0; i < callbacks.size(); ++i) 711ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat callbacks[i].Run(service_is_available); 712ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} 713ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat 714ae6a045d2239408e25198ad17e2413bdde105788Daniel Erat} // namespace dbus 715