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