object_proxy.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
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"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/dbus_statistics.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/message.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_proxy.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/scoped_dbus_error.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace dbus {
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kErrorServiceUnknown[] = "org.freedesktop.DBus.Error.ServiceUnknown";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used for success ratio histograms. 1 for success, 0 for failure.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSuccessRatioHistogramMaxValue = 2;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The path of D-Bus Object sending NameOwnerChanged signal.
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kDBusSystemObjectPath[] = "/org/freedesktop/DBus";
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The D-Bus Object interface.
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kDBusSystemObjectInterface[] = "org.freedesktop.DBus";
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The D-Bus Object address.
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kDBusSystemObjectAddress[] = "org.freedesktop.DBus";
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The NameOwnerChanged member in |kDBusSystemObjectInterface|.
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kNameOwnerChangedMember[] = "NameOwnerChanged";
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets the absolute signal name by concatenating the interface name and
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the signal name. Used for building keys for method_table_ in
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ObjectProxy.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetAbsoluteSignalName(
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& interface_name,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& signal_name) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return interface_name + "." + signal_name;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An empty function used for ObjectProxy::EmptyResponseCallback().
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EmptyResponseCallbackBody(Response* /*response*/) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy::ObjectProxy(Bus* bus,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const std::string& service_name,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const ObjectPath& object_path,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int options)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : bus_(bus),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_name_(service_name),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      object_path_(object_path),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filter_added_(false),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ignore_service_unknown_errors_(
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          options & IGNORE_SERVICE_UNKNOWN_ERRORS) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy::~ObjectProxy() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Originally we tried to make |method_call| a const reference, but we
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gave up as dbus_connection_send_with_reply_and_block() takes a
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// non-const pointer of DBusMessage as the second parameter.
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<Response> ObjectProxy::CallMethodAndBlock(MethodCall* method_call,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                     int timeout_ms) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnDBusThread();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bus_->Connect() ||
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !method_call->SetDestination(service_name_) ||
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !method_call->SetPath(object_path_))
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return scoped_ptr<Response>();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusMessage* request_message = method_call->raw_message();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedDBusError error;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send the message synchronously.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeTicks start_time = base::TimeTicks::Now();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusMessage* response_message =
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bus_->SendWithReplyAndBlock(request_message, timeout_ms, error.get());
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record if the method call is successful, or not. 1 if successful.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("DBus.SyncMethodCallSuccess",
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            response_message ? 1 : 0,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            kSuccessRatioHistogramMaxValue);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  statistics::AddBlockingSentMethodCall(service_name_,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        method_call->GetInterface(),
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        method_call->GetMember());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_message) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogMethodCallFailure(method_call->GetInterface(),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         method_call->GetMember(),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         error.is_set() ? error.name() : "unknown error type",
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         error.is_set() ? error.message() : "");
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return scoped_ptr<Response>();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record time spent for the method call. Don't include failures.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("DBus.SyncMethodCallTime",
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::TimeTicks::Now() - start_time);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Response::FromRawMessage(response_message);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::CallMethod(MethodCall* method_call,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int timeout_ms,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ResponseCallback callback) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallMethodWithErrorCallback(method_call, timeout_ms, callback,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              base::Bind(&ObjectProxy::OnCallMethodError,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         this,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         method_call->GetInterface(),
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         method_call->GetMember(),
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         callback));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::CallMethodWithErrorCallback(MethodCall* method_call,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              int timeout_ms,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              ResponseCallback callback,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              ErrorCallback error_callback) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnOriginThread();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeTicks start_time = base::TimeTicks::Now();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!method_call->SetDestination(service_name_) ||
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !method_call->SetPath(object_path_)) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In case of a failure, run the error callback with NULL.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusMessage* response_message = NULL;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    this,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    callback,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    error_callback,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    start_time,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    response_message);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus_->PostTaskToOriginThread(FROM_HERE, task);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Increment the reference count so we can safely reference the
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // underlying request message until the method call is complete. This
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will be unref'ed in StartAsyncMethodCall().
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusMessage* request_message = method_call->raw_message();
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_message_ref(request_message);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure task = base::Bind(&ObjectProxy::StartAsyncMethodCall,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  this,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  timeout_ms,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  request_message,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  callback,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  error_callback,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  start_time);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  statistics::AddSentMethodCall(service_name_,
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                method_call->GetInterface(),
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                method_call->GetMember());
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the response in the D-Bus thread.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->PostTaskToDBusThread(FROM_HERE, task);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::ConnectToSignal(const std::string& interface_name,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const std::string& signal_name,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  SignalCallback signal_callback,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  OnConnectedCallback on_connected_callback) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnOriginThread();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->PostTaskToDBusThread(FROM_HERE,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base::Bind(&ObjectProxy::ConnectToSignalInternal,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        this,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        interface_name,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        signal_name,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        signal_callback,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        on_connected_callback));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::Detach() {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnDBusThread();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (filter_added_) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this)) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to remove filter function";
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<std::string>::iterator iter = match_rules_.begin();
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != match_rules_.end(); ++iter) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedDBusError error;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus_->RemoveMatch(*iter, error.get());
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error.is_set()) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // There is nothing we can do to recover, so just print the error.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to remove match rule: " << *iter;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  match_rules_.clear();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy::ResponseCallback ObjectProxy::EmptyResponseCallback() {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::Bind(&EmptyResponseCallbackBody);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy::OnPendingCallIsCompleteData::OnPendingCallIsCompleteData(
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ObjectProxy* in_object_proxy,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCallback in_response_callback,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ErrorCallback in_error_callback,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeTicks in_start_time)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : object_proxy(in_object_proxy),
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_callback(in_response_callback),
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_callback(in_error_callback),
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_time(in_start_time) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy::OnPendingCallIsCompleteData::~OnPendingCallIsCompleteData() {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::StartAsyncMethodCall(int timeout_ms,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       DBusMessage* request_message,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       ResponseCallback response_callback,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       ErrorCallback error_callback,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       base::TimeTicks start_time) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnDBusThread();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In case of a failure, run the error callback with NULL.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusMessage* response_message = NULL;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    this,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    response_callback,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    error_callback,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    start_time,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    response_message);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus_->PostTaskToOriginThread(FROM_HERE, task);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus_message_unref(request_message);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusPendingCall* pending_call = NULL;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->SendWithReply(request_message, &pending_call, timeout_ms);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prepare the data we'll be passing to OnPendingCallIsCompleteThunk().
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The data will be deleted in OnPendingCallIsCompleteThunk().
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnPendingCallIsCompleteData* data =
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new OnPendingCallIsCompleteData(this, response_callback, error_callback,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      start_time);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This returns false only when unable to allocate memory.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_pending_call_set_notify(
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_call,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &ObjectProxy::OnPendingCallIsCompleteThunk,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_pending_call_unref(pending_call);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's now safe to unref the request message.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_message_unref(request_message);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          ResponseCallback response_callback,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          ErrorCallback error_callback,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          base::TimeTicks start_time) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnDBusThread();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  this,
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  response_callback,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  error_callback,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  start_time,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  response_message);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->PostTaskToOriginThread(FROM_HERE, task);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      ErrorCallback error_callback,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::TimeTicks start_time,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      DBusMessage* response_message) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnOriginThread();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool method_call_successful = false;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_message) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The response is not received.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_callback.Run(NULL);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (dbus_message_get_type(response_message) ==
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             DBUS_MESSAGE_TYPE_ERROR) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will take |response_message| and release (unref) it.
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<ErrorResponse> error_response(
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ErrorResponse::FromRawMessage(response_message));
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_callback.Run(error_response.get());
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Delete the message  on the D-Bus thread. See below for why.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus_->PostTaskToDBusThread(
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&base::DeletePointer<ErrorResponse>,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   error_response.release()));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will take |response_message| and release (unref) it.
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<Response> response(Response::FromRawMessage(response_message));
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The response is successfully received.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_callback.Run(response.get());
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The message should be deleted on the D-Bus thread for a complicated
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // reason:
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // libdbus keeps track of the number of bytes in the incoming message
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // queue to ensure that the data size in the queue is manageable. The
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // bookkeeping is partly done via dbus_message_unref(), and immediately
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // asks the client code (Chrome) to stop monitoring the underlying
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // socket, if the number of bytes exceeds a certian number, which is set
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to 63MB, per dbus-transport.cc:
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //   /* Try to default to something that won't totally hose the system,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //    * but doesn't impose too much of a limitation.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //    */
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //   transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The monitoring of the socket is done on the D-Bus thread (see Watch
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // class in bus.cc), hence we should stop the monitoring from D-Bus
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // thread, not from the current thread here, which is likely UI thread.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus_->PostTaskToDBusThread(
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&base::DeletePointer<Response>, response.release()));
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    method_call_successful = true;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Record time spent for the method call. Don't include failures.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_TIMES("DBus.AsyncMethodCallTime",
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        base::TimeTicks::Now() - start_time);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record if the method call is successful, or not. 1 if successful.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("DBus.AsyncMethodCallSuccess",
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            method_call_successful,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            kSuccessRatioHistogramMaxValue);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::OnPendingCallIsCompleteThunk(DBusPendingCall* pending_call,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               void* user_data) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnPendingCallIsCompleteData* data =
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<OnPendingCallIsCompleteData*>(user_data);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObjectProxy* self = data->object_proxy;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  self->OnPendingCallIsComplete(pending_call,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                data->response_callback,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                data->error_callback,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                data->start_time);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete data;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::ConnectToSignalInternal(
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& interface_name,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& signal_name,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SignalCallback signal_callback,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnConnectedCallback on_connected_callback) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnDBusThread();
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string absolute_signal_name =
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetAbsoluteSignalName(interface_name, signal_name);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Will become true, if everything is successful.
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = false;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bus_->Connect() && bus_->SetUpAsyncOperations()) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We should add the filter only once. Otherwise, HandleMessage() will
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // be called more than once.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!filter_added_) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (bus_->AddFilterFunction(&ObjectProxy::HandleMessageThunk, this)) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        filter_added_ = true;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "Failed to add filter function";
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add a match rule so the signal goes through HandleMessage().
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string match_rule =
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringPrintf("type='signal', interface='%s', path='%s'",
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           interface_name.c_str(),
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           object_path_.value().c_str());
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add a match_rule listening NameOwnerChanged for the well-known name
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |service_name_|.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string name_owner_changed_match_rule =
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringPrintf(
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "type='signal',interface='org.freedesktop.DBus',"
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "member='NameOwnerChanged',path='/org/freedesktop/DBus',"
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "sender='org.freedesktop.DBus',arg0='%s'",
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            service_name_.c_str());
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (AddMatchRuleWithCallback(match_rule,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 absolute_signal_name,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 signal_callback) &&
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddMatchRuleWithoutCallback(name_owner_changed_match_rule,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    "org.freedesktop.DBus.NameOwnerChanged")) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      success = true;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Try getting the current name owner. It's not guaranteed that we can get
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the name owner at this moment, as the service may not yet be started. If
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that's the case, we'll get the name owner via NameOwnerChanged signal,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // as soon as the service is started.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateNameOwnerAndBlock();
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run on_connected_callback in the origin thread.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->PostTaskToOriginThread(
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ObjectProxy::OnConnected,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 this,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 on_connected_callback,
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 interface_name,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 signal_name,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 success));
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::OnConnected(OnConnectedCallback on_connected_callback,
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string& interface_name,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string& signal_name,
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool success) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnOriginThread();
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  on_connected_callback.Run(interface_name, signal_name, success);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ObjectProxy::SetNameOwnerChangedCallback(SignalCallback callback) {
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bus_->AssertOnOriginThread();
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  name_owner_changed_callback_ = callback;
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DBusHandlerResult ObjectProxy::HandleMessage(
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusConnection* connection,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusMessage* raw_message) {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnDBusThread();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_SIGNAL)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // raw_message will be unrefed on exit of the function. Increment the
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference so we can use it in Signal.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_message_ref(raw_message);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Signal> signal(
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Signal::FromRawMessage(raw_message));
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the signal comes from the object we're proxying for, this is
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // our last chance to return DBUS_HANDLER_RESULT_NOT_YET_HANDLED and
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allow other object proxies to handle instead.
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const ObjectPath path = signal->GetPath();
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path != object_path_) {
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (path.value() == kDBusSystemObjectPath &&
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        signal->GetMember() == kNameOwnerChangedMember) {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Handle NameOwnerChanged separately
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return HandleNameOwnerChanged(signal.Pass());
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string interface = signal->GetInterface();
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string member = signal->GetMember();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  statistics::AddReceivedSignal(service_name_, interface, member);
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we know about the signal.
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string absolute_signal_name = GetAbsoluteSignalName(
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      interface, member);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MethodTable::const_iterator iter = method_table_.find(absolute_signal_name);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == method_table_.end()) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't know about the signal.
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Signal received: " << signal->ToString();
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sender = signal->GetSender();
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service_name_owner_ != sender) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Rejecting a message from a wrong sender.";
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("DBus.RejectedSignalCount", 1);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeTicks start_time = base::TimeTicks::Now();
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bus_->HasDBusThread()) {
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Post a task to run the method in the origin thread.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Transfer the ownership of |signal| to RunMethod().
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |released_signal| will be deleted in RunMethod().
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Signal* released_signal = signal.release();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus_->PostTaskToOriginThread(FROM_HERE,
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 base::Bind(&ObjectProxy::RunMethod,
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            this,
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            start_time,
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            iter->second,
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            released_signal));
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::TimeTicks start_time = base::TimeTicks::Now();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the D-Bus thread is not used, just call the callback on the
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // current thread. Transfer the ownership of |signal| to RunMethod().
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Signal* released_signal = signal.release();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunMethod(start_time, iter->second, released_signal);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DBUS_HANDLER_RESULT_HANDLED;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::RunMethod(base::TimeTicks start_time,
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            std::vector<SignalCallback> signal_callbacks,
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            Signal* signal) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnOriginThread();
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (std::vector<SignalCallback>::iterator iter = signal_callbacks.begin();
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       iter != signal_callbacks.end(); ++iter)
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    iter->Run(signal);
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete the message on the D-Bus thread. See comments in
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RunResponseCallback().
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->PostTaskToDBusThread(
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&base::DeletePointer<Signal>, signal));
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record time spent for handling the signal.
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("DBus.SignalHandleTime",
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::TimeTicks::Now() - start_time);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DBusHandlerResult ObjectProxy::HandleMessageThunk(
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusConnection* connection,
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusMessage* raw_message,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* user_data) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObjectProxy* self = reinterpret_cast<ObjectProxy*>(user_data);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return self->HandleMessage(connection, raw_message);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::LogMethodCallFailure(
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& interface_name,
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& method_name,
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& error_name,
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& error_message) const {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ignore_service_unknown_errors_ && error_name == kErrorServiceUnknown)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "Failed to call method: "
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << interface_name << "." << method_name
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << ": object_path= " << object_path_.value()
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << ": " << error_name << ": " << error_message;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::OnCallMethodError(const std::string& interface_name,
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const std::string& method_name,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    ResponseCallback response_callback,
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    ErrorResponse* error_response) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_response) {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Error message may contain the error message as string.
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MessageReader reader(error_response);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string error_message;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reader.PopString(&error_message);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogMethodCallFailure(interface_name,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         method_name,
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         error_response->GetErrorName(),
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         error_message);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_callback.Run(NULL);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ObjectProxy::AddMatchRuleWithCallback(
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& match_rule,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& absolute_signal_name,
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SignalCallback signal_callback) {
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!match_rule.empty());
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!absolute_signal_name.empty());
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnDBusThread();
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (match_rules_.find(match_rule) == match_rules_.end()) {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedDBusError error;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus_->AddMatch(match_rule, error.get());
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error.is_set()) {
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got "
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << error.name() << ": " << error.message();
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Store the match rule, so that we can remove this in Detach().
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match_rules_.insert(match_rule);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Add the signal callback to the method table.
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      method_table_[absolute_signal_name].push_back(signal_callback);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We already have the match rule.
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    method_table_[absolute_signal_name].push_back(signal_callback);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ObjectProxy::AddMatchRuleWithoutCallback(
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& match_rule,
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& absolute_signal_name) {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!match_rule.empty());
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!absolute_signal_name.empty());
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnDBusThread();
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (match_rules_.find(match_rule) != match_rules_.end())
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedDBusError error;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AddMatch(match_rule, error.get());
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error.is_set()) {
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got "
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error.name() << ": " << error.message();
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store the match rule, so that we can remove this in Detach().
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  match_rules_.insert(match_rule);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObjectProxy::UpdateNameOwnerAndBlock() {
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnDBusThread();
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  service_name_owner_ =
616b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bus_->GetServiceOwnerAndBlock(service_name_, Bus::REPORT_ERRORS);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DBusHandlerResult ObjectProxy::HandleNameOwnerChanged(
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<Signal> signal) {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(signal);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus_->AssertOnDBusThread();
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Confirm the validity of the NameOwnerChanged signal.
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (signal->GetMember() == kNameOwnerChangedMember &&
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      signal->GetInterface() == kDBusSystemObjectInterface &&
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      signal->GetSender() == kDBusSystemObjectAddress) {
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessageReader reader(signal.get());
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name, old_owner, new_owner;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (reader.PopString(&name) &&
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reader.PopString(&old_owner) &&
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reader.PopString(&new_owner) &&
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        name == service_name_) {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_name_owner_ = new_owner;
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!name_owner_changed_callback_.is_null()) {
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const base::TimeTicks start_time = base::TimeTicks::Now();
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Signal* released_signal = signal.release();
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        std::vector<SignalCallback> callbacks;
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        callbacks.push_back(name_owner_changed_callback_);
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bus_->PostTaskToOriginThread(FROM_HERE,
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     base::Bind(&ObjectProxy::RunMethod,
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                this,
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                start_time,
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                callbacks,
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                released_signal));
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Always return unhandled to let other object proxies handle the same
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // signal.
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace dbus
656