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