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