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