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