15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/bus.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/task_runner_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/dbus_statistics.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/message.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_proxy.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/scoped_dbus_error.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "dbus/util.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace dbus { 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kErrorServiceUnknown[] = "org.freedesktop.DBus.Error.ServiceUnknown"; 286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const char kErrorObjectUnknown[] = "org.freedesktop.DBus.Error.UnknownObject"; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used for success ratio histograms. 1 for success, 0 for failure. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSuccessRatioHistogramMaxValue = 2; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The path of D-Bus Object sending NameOwnerChanged signal. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kDBusSystemObjectPath[] = "/org/freedesktop/DBus"; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The D-Bus Object interface. 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kDBusSystemObjectInterface[] = "org.freedesktop.DBus"; 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The D-Bus Object address. 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kDBusSystemObjectAddress[] = "org.freedesktop.DBus"; 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The NameOwnerChanged member in |kDBusSystemObjectInterface|. 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kNameOwnerChangedMember[] = "NameOwnerChanged"; 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An empty function used for ObjectProxy::EmptyResponseCallback(). 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EmptyResponseCallbackBody(Response* /*response*/) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy::ObjectProxy(Bus* bus, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& service_name, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjectPath& object_path, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int options) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : bus_(bus), 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_name_(service_name), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_path_(object_path), 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_added_(false), 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_service_unknown_errors_( 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options & IGNORE_SERVICE_UNKNOWN_ERRORS) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy::~ObjectProxy() { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Originally we tried to make |method_call| a const reference, but we 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gave up as dbus_connection_send_with_reply_and_block() takes a 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// non-const pointer of DBusMessage as the second parameter. 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<Response> ObjectProxy::CallMethodAndBlockWithErrorDetails( 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MethodCall* method_call, int timeout_ms, ScopedDBusError* error) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bus_->Connect() || 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !method_call->SetDestination(service_name_) || 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !method_call->SetPath(object_path_)) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<Response>(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* request_message = method_call->raw_message(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the message synchronously. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeTicks start_time = base::TimeTicks::Now(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* response_message = 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bus_->SendWithReplyAndBlock(request_message, timeout_ms, error->get()); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record if the method call is successful, or not. 1 if successful. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("DBus.SyncMethodCallSuccess", 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_message ? 1 : 0, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kSuccessRatioHistogramMaxValue); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statistics::AddBlockingSentMethodCall(service_name_, 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) method_call->GetInterface(), 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) method_call->GetMember()); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!response_message) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogMethodCallFailure(method_call->GetInterface(), 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_call->GetMember(), 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci error->is_set() ? error->name() : "unknown error type", 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci error->is_set() ? error->message() : ""); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<Response>(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record time spent for the method call. Don't include failures. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("DBus.SyncMethodCallTime", 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now() - start_time); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Response::FromRawMessage(response_message); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<Response> ObjectProxy::CallMethodAndBlock(MethodCall* method_call, 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int timeout_ms) { 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScopedDBusError error; 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return CallMethodAndBlockWithErrorDetails(method_call, timeout_ms, &error); 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::CallMethod(MethodCall* method_call, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int timeout_ms, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResponseCallback callback) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CallMethodWithErrorCallback(method_call, timeout_ms, callback, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ObjectProxy::OnCallMethodError, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_call->GetInterface(), 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_call->GetMember(), 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback)); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::CallMethodWithErrorCallback(MethodCall* method_call, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int timeout_ms, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResponseCallback callback, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorCallback error_callback) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnOriginThread(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeTicks start_time = base::TimeTicks::Now(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!method_call->SetDestination(service_name_) || 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !method_call->SetPath(object_path_)) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In case of a failure, run the error callback with NULL. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* response_message = NULL; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_callback, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_message); 14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, task); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Increment the reference count so we can safely reference the 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // underlying request message until the method call is complete. This 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be unref'ed in StartAsyncMethodCall(). 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* request_message = method_call->raw_message(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus_message_ref(request_message); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure task = base::Bind(&ObjectProxy::StartAsyncMethodCall, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timeout_ms, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_message, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_callback, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statistics::AddSentMethodCall(service_name_, 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) method_call->GetInterface(), 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) method_call->GetMember()); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for the response in the D-Bus thread. 16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::ConnectToSignal(const std::string& interface_name, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& signal_name, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalCallback signal_callback, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnConnectedCallback on_connected_callback) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnOriginThread(); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::PostTaskAndReplyWithResult( 17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetDBusTaskRunner(), 17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FROM_HERE, 17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&ObjectProxy::ConnectToSignalInternal, 17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this, 17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) interface_name, 17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) signal_name, 17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) signal_callback), 18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(on_connected_callback, 18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) interface_name, 18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) signal_name)); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ObjectProxy::SetNameOwnerChangedCallback( 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NameOwnerChangedCallback callback) { 1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bus_->AssertOnOriginThread(); 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) name_owner_changed_callback_ = callback; 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ObjectProxy::WaitForServiceToBeAvailable( 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WaitForServiceToBeAvailableCallback callback) { 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bus_->AssertOnOriginThread(); 1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) wait_for_service_to_be_available_callbacks_.push_back(callback); 1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bus_->GetDBusTaskRunner()->PostTask( 1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) FROM_HERE, 1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&ObjectProxy::WaitForServiceToBeAvailableInternal, this)); 2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::Detach() { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filter_added_) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this)) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to remove filter function"; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<std::string>::iterator iter = match_rules_.begin(); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != match_rules_.end(); ++iter) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedDBusError error; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->RemoveMatch(*iter, error.get()); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error.is_set()) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is nothing we can do to recover, so just print the error. 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to remove match rule: " << *iter; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match_rules_.clear(); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy::ResponseCallback ObjectProxy::EmptyResponseCallback() { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::Bind(&EmptyResponseCallbackBody); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy::OnPendingCallIsCompleteData::OnPendingCallIsCompleteData( 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjectProxy* in_object_proxy, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResponseCallback in_response_callback, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorCallback in_error_callback, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks in_start_time) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : object_proxy(in_object_proxy), 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_callback(in_response_callback), 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_callback(in_error_callback), 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time(in_start_time) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy::OnPendingCallIsCompleteData::~OnPendingCallIsCompleteData() { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::StartAsyncMethodCall(int timeout_ms, 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* request_message, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResponseCallback response_callback, 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorCallback error_callback, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks start_time) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In case of a failure, run the error callback with NULL. 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* response_message = NULL; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback, 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_callback, 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_callback, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_message); 25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, task); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus_message_unref(request_message); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusPendingCall* pending_call = NULL; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->SendWithReply(request_message, &pending_call, timeout_ms); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prepare the data we'll be passing to OnPendingCallIsCompleteThunk(). 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The data will be deleted in OnPendingCallIsCompleteThunk(). 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPendingCallIsCompleteData* data = 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new OnPendingCallIsCompleteData(this, response_callback, error_callback, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This returns false only when unable to allocate memory. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool success = dbus_pending_call_set_notify( 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_call, 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ObjectProxy::OnPendingCallIsCompleteThunk, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(success) << "Unable to allocate memory"; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus_pending_call_unref(pending_call); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's now safe to unref the request message. 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus_message_unref(request_message); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResponseCallback response_callback, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorCallback error_callback, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks start_time) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback, 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_callback, 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_callback, 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time, 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_message); 30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, task); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::RunResponseCallback(ResponseCallback response_callback, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorCallback error_callback, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks start_time, 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* response_message) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnOriginThread(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool method_call_successful = false; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!response_message) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The response is not received. 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_callback.Run(NULL); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (dbus_message_get_type(response_message) == 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBUS_MESSAGE_TYPE_ERROR) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will take |response_message| and release (unref) it. 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<ErrorResponse> error_response( 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ErrorResponse::FromRawMessage(response_message)); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_callback.Run(error_response.get()); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the message on the D-Bus thread. See below for why. 32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetDBusTaskRunner()->PostTask( 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&base::DeletePointer<ErrorResponse>, 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_response.release())); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will take |response_message| and release (unref) it. 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<Response> response(Response::FromRawMessage(response_message)); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The response is successfully received. 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_callback.Run(response.get()); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The message should be deleted on the D-Bus thread for a complicated 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reason: 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // libdbus keeps track of the number of bytes in the incoming message 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // queue to ensure that the data size in the queue is manageable. The 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bookkeeping is partly done via dbus_message_unref(), and immediately 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // asks the client code (Chrome) to stop monitoring the underlying 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // socket, if the number of bytes exceeds a certian number, which is set 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to 63MB, per dbus-transport.cc: 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // /* Try to default to something that won't totally hose the system, 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * but doesn't impose too much of a limitation. 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // */ 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The monitoring of the socket is done on the D-Bus thread (see Watch 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // class in bus.cc), hence we should stop the monitoring from D-Bus 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread, not from the current thread here, which is likely UI thread. 34768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetDBusTaskRunner()->PostTask( 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&base::DeletePointer<Response>, response.release())); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_call_successful = true; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record time spent for the method call. Don't include failures. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("DBus.AsyncMethodCallTime", 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now() - start_time); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record if the method call is successful, or not. 1 if successful. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("DBus.AsyncMethodCallSuccess", 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_call_successful, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kSuccessRatioHistogramMaxValue); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::OnPendingCallIsCompleteThunk(DBusPendingCall* pending_call, 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* user_data) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPendingCallIsCompleteData* data = 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<OnPendingCallIsCompleteData*>(user_data); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjectProxy* self = data->object_proxy; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self->OnPendingCallIsComplete(pending_call, 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->response_callback, 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->error_callback, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->start_time); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete data; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool ObjectProxy::ConnectToNameOwnerChangedSignal() { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) 37868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 38068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // We should add the filter only once. Otherwise, HandleMessage() will 38168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // be called more than once. 38268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!filter_added_) { 38368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (bus_->AddFilterFunction(&ObjectProxy::HandleMessageThunk, this)) { 38468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) filter_added_ = true; 38568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) LOG(ERROR) << "Failed to add filter function"; 38768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 38968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Add a match_rule listening NameOwnerChanged for the well-known name 39068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // |service_name_|. 39168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string name_owner_changed_match_rule = 39268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::StringPrintf( 39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "type='signal',interface='org.freedesktop.DBus'," 39468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "member='NameOwnerChanged',path='/org/freedesktop/DBus'," 39568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "sender='org.freedesktop.DBus',arg0='%s'", 39668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) service_name_.c_str()); 39768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 39868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const bool success = 39968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) AddMatchRuleWithoutCallback(name_owner_changed_match_rule, 40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "org.freedesktop.DBus.NameOwnerChanged"); 40168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 40268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Try getting the current name owner. It's not guaranteed that we can get 40368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // the name owner at this moment, as the service may not yet be started. If 40468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // that's the case, we'll get the name owner via NameOwnerChanged signal, 40568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // as soon as the service is started. 40668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) UpdateNameOwnerAndBlock(); 40768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return success; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool ObjectProxy::ConnectToSignalInternal(const std::string& interface_name, 4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& signal_name, 4134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SignalCallback signal_callback) { 4144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bus_->AssertOnDBusThread(); 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!ConnectToNameOwnerChangedSignal()) 4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string absolute_signal_name = 4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetAbsoluteMemberName(interface_name, signal_name); 4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Add a match rule so the signal goes through HandleMessage(). 4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string match_rule = 4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::StringPrintf("type='signal', interface='%s', path='%s'", 4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) interface_name.c_str(), 4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) object_path_.value().c_str()); 4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return AddMatchRuleWithCallback(match_rule, 4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) absolute_signal_name, 4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) signal_callback); 4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ObjectProxy::WaitForServiceToBeAvailableInternal() { 4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bus_->AssertOnDBusThread(); 4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!ConnectToNameOwnerChangedSignal()) { // Failed to connect to the signal. 4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const bool service_is_ready = false; 4374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bus_->GetOriginTaskRunner()->PostTask( 4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) FROM_HERE, 4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&ObjectProxy::RunWaitForServiceToBeAvailableCallbacks, 4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this, service_is_ready)); 4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const bool service_is_available = !service_name_owner_.empty(); 4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (service_is_available) { // Service is already available. 4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bus_->GetOriginTaskRunner()->PostTask( 4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) FROM_HERE, 4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&ObjectProxy::RunWaitForServiceToBeAvailableCallbacks, 4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this, service_is_available)); 4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DBusHandlerResult ObjectProxy::HandleMessage( 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusConnection* connection, 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* raw_message) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_SIGNAL) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // raw_message will be unrefed on exit of the function. Increment the 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reference so we can use it in Signal. 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus_message_ref(raw_message); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Signal> signal( 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Signal::FromRawMessage(raw_message)); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify the signal comes from the object we're proxying for, this is 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our last chance to return DBUS_HANDLER_RESULT_NOT_YET_HANDLED and 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allow other object proxies to handle instead. 471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ObjectPath path = signal->GetPath(); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path != object_path_) { 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (path.value() == kDBusSystemObjectPath && 474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) signal->GetMember() == kNameOwnerChangedMember) { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle NameOwnerChanged separately 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return HandleNameOwnerChanged(signal.Pass()); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string interface = signal->GetInterface(); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string member = signal->GetMember(); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statistics::AddReceivedSignal(service_name_, interface, member); 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we know about the signal. 4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string absolute_signal_name = GetAbsoluteMemberName( 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interface, member); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MethodTable::const_iterator iter = method_table_.find(absolute_signal_name); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter == method_table_.end()) { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't know about the signal. 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Signal received: " << signal->ToString(); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string sender = signal->GetSender(); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (service_name_owner_ != sender) { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Rejecting a message from a wrong sender."; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("DBus.RejectedSignalCount", 1); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeTicks start_time = base::TimeTicks::Now(); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bus_->HasDBusThread()) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Post a task to run the method in the origin thread. 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Transfer the ownership of |signal| to RunMethod(). 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |released_signal| will be deleted in RunMethod(). 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Signal* released_signal = signal.release(); 50968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, 51068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&ObjectProxy::RunMethod, 51168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this, 51268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) start_time, 51368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) iter->second, 51468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) released_signal)); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeTicks start_time = base::TimeTicks::Now(); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the D-Bus thread is not used, just call the callback on the 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current thread. Transfer the ownership of |signal| to RunMethod(). 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Signal* released_signal = signal.release(); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunMethod(start_time, iter->second, released_signal); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We don't return DBUS_HANDLER_RESULT_HANDLED for signals because other 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // objects may be interested in them. (e.g. Signals from org.freedesktop.DBus) 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::RunMethod(base::TimeTicks start_time, 529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector<SignalCallback> signal_callbacks, 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Signal* signal) { 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnOriginThread(); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (std::vector<SignalCallback>::iterator iter = signal_callbacks.begin(); 534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) iter != signal_callbacks.end(); ++iter) 535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) iter->Run(signal); 536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the message on the D-Bus thread. See comments in 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RunResponseCallback(). 53968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetDBusTaskRunner()->PostTask( 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&base::DeletePointer<Signal>, signal)); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record time spent for handling the signal. 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("DBus.SignalHandleTime", 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now() - start_time); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DBusHandlerResult ObjectProxy::HandleMessageThunk( 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusConnection* connection, 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusMessage* raw_message, 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* user_data) { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjectProxy* self = reinterpret_cast<ObjectProxy*>(user_data); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self->HandleMessage(connection, raw_message); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::LogMethodCallFailure( 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece& interface_name, 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece& method_name, 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece& error_name, 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece& error_message) const { 5616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (ignore_service_unknown_errors_ && 5626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (error_name == kErrorServiceUnknown || error_name == kErrorObjectUnknown)) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) logging::LogSeverity severity = logging::LOG_ERROR; 5656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // "UnknownObject" indicates that an object or service is no longer available, 5666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // e.g. a Shill network service has gone out of range. Treat these as warnings 5676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // not errors. 5686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (error_name == kErrorObjectUnknown) 5696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) severity = logging::LOG_WARNING; 5706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::ostringstream msg; 5716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) msg << "Failed to call method: " << interface_name << "." << method_name 5726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << ": object_path= " << object_path_.value() 5736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << ": " << error_name << ": " << error_message; 5746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) logging::LogAtLevel(severity, msg.str()); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::OnCallMethodError(const std::string& interface_name, 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& method_name, 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResponseCallback response_callback, 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorResponse* error_response) { 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_response) { 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error message may contain the error message as string. 583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MessageReader reader(error_response); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error_message; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader.PopString(&error_message); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogMethodCallFailure(interface_name, 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_name, 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_response->GetErrorName(), 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_message); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_callback.Run(NULL); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ObjectProxy::AddMatchRuleWithCallback( 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& match_rule, 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& absolute_signal_name, 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalCallback signal_callback) { 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!match_rule.empty()); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!absolute_signal_name.empty()); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (match_rules_.find(match_rule) == match_rules_.end()) { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedDBusError error; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AddMatch(match_rule, error.get()); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error.is_set()) { 606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got " 607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << error.name() << ": " << error.message(); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store the match rule, so that we can remove this in Detach(). 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match_rules_.insert(match_rule); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the signal callback to the method table. 613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) method_table_[absolute_signal_name].push_back(signal_callback); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We already have the match rule. 618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) method_table_[absolute_signal_name].push_back(signal_callback); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ObjectProxy::AddMatchRuleWithoutCallback( 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& match_rule, 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& absolute_signal_name) { 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!match_rule.empty()); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!absolute_signal_name.empty()); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (match_rules_.find(match_rule) != match_rules_.end()) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedDBusError error; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AddMatch(match_rule, error.get()); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error.is_set()) { 636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got " 637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << error.name() << ": " << error.message(); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store the match rule, so that we can remove this in Detach(). 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match_rules_.insert(match_rule); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::UpdateNameOwnerAndBlock() { 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 6473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Errors should be suppressed here, as the service may not be yet running 6483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // when connecting to signals of the service, which is just fine. 6493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The ObjectProxy will be notified when the service is launched via 6503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // NameOwnerChanged signal. See also comments in ConnectToSignalInternal(). 651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) service_name_owner_ = 6523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS); 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DBusHandlerResult ObjectProxy::HandleNameOwnerChanged( 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<Signal> signal) { 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(signal); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->AssertOnDBusThread(); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Confirm the validity of the NameOwnerChanged signal. 661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (signal->GetMember() == kNameOwnerChangedMember && 662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) signal->GetInterface() == kDBusSystemObjectInterface && 663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) signal->GetSender() == kDBusSystemObjectAddress) { 6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessageReader reader(signal.get()); 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name, old_owner, new_owner; 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reader.PopString(&name) && 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader.PopString(&old_owner) && 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader.PopString(&new_owner) && 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name == service_name_) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_name_owner_ = new_owner; 6714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bus_->GetOriginTaskRunner()->PostTask( 6724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) FROM_HERE, 6734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&ObjectProxy::RunNameOwnerChangedCallback, 6744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this, old_owner, new_owner)); 6754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 6764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const bool service_is_available = !service_name_owner_.empty(); 6774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (service_is_available) { 67868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bus_->GetOriginTaskRunner()->PostTask( 67968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FROM_HERE, 6804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&ObjectProxy::RunWaitForServiceToBeAvailableCallbacks, 6814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this, service_is_available)); 6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Always return unhandled to let other object proxies handle the same 6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // signal. 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ObjectProxy::RunNameOwnerChangedCallback(const std::string& old_owner, 6924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& new_owner) { 6934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bus_->AssertOnOriginThread(); 6944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!name_owner_changed_callback_.is_null()) 6954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) name_owner_changed_callback_.Run(old_owner, new_owner); 6964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 6974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 6984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ObjectProxy::RunWaitForServiceToBeAvailableCallbacks( 6994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool service_is_available) { 7004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bus_->AssertOnOriginThread(); 7014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 7024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::vector<WaitForServiceToBeAvailableCallback> callbacks; 7034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) callbacks.swap(wait_for_service_to_be_available_callbacks_); 7044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (size_t i = 0; i < callbacks.size(); ++i) 7054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) callbacks[i].Run(service_is_available); 7064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 7074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace dbus 709