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