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