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