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