OffsetY() is only used by InfoBarView. Move it there.
[chromium-blink-merge.git] / dbus / object_proxy.cc
blobd506392cf05417282800a1fc10880203efecd976
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.
5 #include "dbus/bus.h"
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"
22 namespace dbus {
24 namespace {
26 const char kErrorServiceUnknown[] = "org.freedesktop.DBus.Error.ServiceUnknown";
28 // Used for success ratio histograms. 1 for success, 0 for failure.
29 const int kSuccessRatioHistogramMaxValue = 2;
31 // The path of D-Bus Object sending NameOwnerChanged signal.
32 const char kDBusSystemObjectPath[] = "/org/freedesktop/DBus";
34 // The D-Bus Object interface.
35 const char kDBusSystemObjectInterface[] = "org.freedesktop.DBus";
37 // The D-Bus Object address.
38 const char kDBusSystemObjectAddress[] = "org.freedesktop.DBus";
40 // The NameOwnerChanged member in |kDBusSystemObjectInterface|.
41 const char kNameOwnerChangedMember[] = "NameOwnerChanged";
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.
46 std::string GetAbsoluteSignalName(
47 const std::string& interface_name,
48 const std::string& signal_name) {
49 return interface_name + "." + signal_name;
52 // An empty function used for ObjectProxy::EmptyResponseCallback().
53 void EmptyResponseCallbackBody(Response* /*response*/) {
56 } // namespace
58 ObjectProxy::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) {
70 ObjectProxy::~ObjectProxy() {
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.
76 scoped_ptr<Response> ObjectProxy::CallMethodAndBlock(MethodCall* method_call,
77 int timeout_ms) {
78 bus_->AssertOnDBusThread();
80 if (!bus_->Connect() ||
81 !method_call->SetDestination(service_name_) ||
82 !method_call->SetPath(object_path_))
83 return scoped_ptr<Response>();
85 DBusMessage* request_message = method_call->raw_message();
87 ScopedDBusError error;
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());
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>();
108 // Record time spent for the method call. Don't include failures.
109 UMA_HISTOGRAM_TIMES("DBus.SyncMethodCallTime",
110 base::TimeTicks::Now() - start_time);
112 return Response::FromRawMessage(response_message);
115 void 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));
126 void ObjectProxy::CallMethodWithErrorCallback(MethodCall* method_call,
127 int timeout_ms,
128 ResponseCallback callback,
129 ErrorCallback error_callback) {
130 bus_->AssertOnOriginThread();
132 const base::TimeTicks start_time = base::TimeTicks::Now();
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;
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);
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());
165 // Wait for the response in the D-Bus thread.
166 bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task);
169 void 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();
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));
188 void ObjectProxy::SetNameOwnerChangedCallback(
189 NameOwnerChangedCallback callback) {
190 bus_->AssertOnOriginThread();
192 name_owner_changed_callback_ = callback;
195 void ObjectProxy::WaitForServiceToBeAvailable(
196 WaitForServiceToBeAvailableCallback callback) {
197 bus_->AssertOnOriginThread();
199 wait_for_service_to_be_available_callbacks_.push_back(callback);
200 bus_->GetDBusTaskRunner()->PostTask(
201 FROM_HERE,
202 base::Bind(&ObjectProxy::WaitForServiceToBeAvailableInternal, this));
205 void ObjectProxy::Detach() {
206 bus_->AssertOnDBusThread();
208 if (filter_added_) {
209 if (!bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this)) {
210 LOG(ERROR) << "Failed to remove filter function";
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;
223 match_rules_.clear();
226 // static
227 ObjectProxy::ResponseCallback ObjectProxy::EmptyResponseCallback() {
228 return base::Bind(&EmptyResponseCallbackBody);
231 ObjectProxy::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) {
242 ObjectProxy::OnPendingCallIsCompleteData::~OnPendingCallIsCompleteData() {
245 void 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();
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);
263 dbus_message_unref(request_message);
264 return;
267 DBusPendingCall* pending_call = NULL;
269 bus_->SendWithReply(request_message, &pending_call, timeout_ms);
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);
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);
286 // It's now safe to unref the request message.
287 dbus_message_unref(request_message);
290 void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call,
291 ResponseCallback response_callback,
292 ErrorCallback error_callback,
293 base::TimeTicks start_time) {
294 bus_->AssertOnDBusThread();
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);
306 void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
307 ErrorCallback error_callback,
308 base::TimeTicks start_time,
309 DBusMessage* response_message) {
310 bus_->AssertOnOriginThread();
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:
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:
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;
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()));
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);
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);
365 void 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;
377 bool ObjectProxy::ConnectToNameOwnerChangedSignal() {
378 bus_->AssertOnDBusThread();
380 if (!bus_->Connect() || !bus_->SetUpAsyncOperations())
381 return false;
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";
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());
401 const bool success =
402 AddMatchRuleWithoutCallback(name_owner_changed_match_rule,
403 "org.freedesktop.DBus.NameOwnerChanged");
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();
411 return success;
414 bool ObjectProxy::ConnectToSignalInternal(const std::string& interface_name,
415 const std::string& signal_name,
416 SignalCallback signal_callback) {
417 bus_->AssertOnDBusThread();
419 if (!ConnectToNameOwnerChangedSignal())
420 return false;
422 const std::string absolute_signal_name =
423 GetAbsoluteSignalName(interface_name, signal_name);
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);
435 void ObjectProxy::WaitForServiceToBeAvailableInternal() {
436 bus_->AssertOnDBusThread();
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;
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;
457 DBusHandlerResult ObjectProxy::HandleMessage(
458 DBusConnection* connection,
459 DBusMessage* raw_message) {
460 bus_->AssertOnDBusThread();
462 if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_SIGNAL)
463 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
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));
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());
481 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
484 const std::string interface = signal->GetInterface();
485 const std::string member = signal->GetMember();
487 statistics::AddReceivedSignal(service_name_, interface, member);
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;
497 VLOG(1) << "Signal received: " << signal->ToString();
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;
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);
526 return DBUS_HANDLER_RESULT_HANDLED;
529 void ObjectProxy::RunMethod(base::TimeTicks start_time,
530 std::vector<SignalCallback> signal_callbacks,
531 Signal* signal) {
532 bus_->AssertOnOriginThread();
534 for (std::vector<SignalCallback>::iterator iter = signal_callbacks.begin();
535 iter != signal_callbacks.end(); ++iter)
536 iter->Run(signal);
538 // Delete the message on the D-Bus thread. See comments in
539 // RunResponseCallback().
540 bus_->GetDBusTaskRunner()->PostTask(
541 FROM_HERE,
542 base::Bind(&base::DeletePointer<Signal>, signal));
544 // Record time spent for handling the signal.
545 UMA_HISTOGRAM_TIMES("DBus.SignalHandleTime",
546 base::TimeTicks::Now() - start_time);
549 DBusHandlerResult ObjectProxy::HandleMessageThunk(
550 DBusConnection* connection,
551 DBusMessage* raw_message,
552 void* user_data) {
553 ObjectProxy* self = reinterpret_cast<ObjectProxy*>(user_data);
554 return self->HandleMessage(connection, raw_message);
557 void ObjectProxy::LogMethodCallFailure(
558 const base::StringPiece& interface_name,
559 const base::StringPiece& method_name,
560 const base::StringPiece& error_name,
561 const base::StringPiece& error_message) const {
562 if (ignore_service_unknown_errors_ && error_name == kErrorServiceUnknown)
563 return;
564 LOG(ERROR) << "Failed to call method: "
565 << interface_name << "." << method_name
566 << ": object_path= " << object_path_.value()
567 << ": " << error_name << ": " << error_message;
570 void ObjectProxy::OnCallMethodError(const std::string& interface_name,
571 const std::string& method_name,
572 ResponseCallback response_callback,
573 ErrorResponse* error_response) {
574 if (error_response) {
575 // Error message may contain the error message as string.
576 MessageReader reader(error_response);
577 std::string error_message;
578 reader.PopString(&error_message);
579 LogMethodCallFailure(interface_name,
580 method_name,
581 error_response->GetErrorName(),
582 error_message);
584 response_callback.Run(NULL);
587 bool ObjectProxy::AddMatchRuleWithCallback(
588 const std::string& match_rule,
589 const std::string& absolute_signal_name,
590 SignalCallback signal_callback) {
591 DCHECK(!match_rule.empty());
592 DCHECK(!absolute_signal_name.empty());
593 bus_->AssertOnDBusThread();
595 if (match_rules_.find(match_rule) == match_rules_.end()) {
596 ScopedDBusError error;
597 bus_->AddMatch(match_rule, error.get());
598 if (error.is_set()) {
599 LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got "
600 << error.name() << ": " << error.message();
601 return false;
602 } else {
603 // Store the match rule, so that we can remove this in Detach().
604 match_rules_.insert(match_rule);
605 // Add the signal callback to the method table.
606 method_table_[absolute_signal_name].push_back(signal_callback);
607 return true;
609 } else {
610 // We already have the match rule.
611 method_table_[absolute_signal_name].push_back(signal_callback);
612 return true;
616 bool ObjectProxy::AddMatchRuleWithoutCallback(
617 const std::string& match_rule,
618 const std::string& absolute_signal_name) {
619 DCHECK(!match_rule.empty());
620 DCHECK(!absolute_signal_name.empty());
621 bus_->AssertOnDBusThread();
623 if (match_rules_.find(match_rule) != match_rules_.end())
624 return true;
626 ScopedDBusError error;
627 bus_->AddMatch(match_rule, error.get());
628 if (error.is_set()) {
629 LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got "
630 << error.name() << ": " << error.message();
631 return false;
633 // Store the match rule, so that we can remove this in Detach().
634 match_rules_.insert(match_rule);
635 return true;
638 void ObjectProxy::UpdateNameOwnerAndBlock() {
639 bus_->AssertOnDBusThread();
640 // Errors should be suppressed here, as the service may not be yet running
641 // when connecting to signals of the service, which is just fine.
642 // The ObjectProxy will be notified when the service is launched via
643 // NameOwnerChanged signal. See also comments in ConnectToSignalInternal().
644 service_name_owner_ =
645 bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS);
648 DBusHandlerResult ObjectProxy::HandleNameOwnerChanged(
649 scoped_ptr<Signal> signal) {
650 DCHECK(signal);
651 bus_->AssertOnDBusThread();
653 // Confirm the validity of the NameOwnerChanged signal.
654 if (signal->GetMember() == kNameOwnerChangedMember &&
655 signal->GetInterface() == kDBusSystemObjectInterface &&
656 signal->GetSender() == kDBusSystemObjectAddress) {
657 MessageReader reader(signal.get());
658 std::string name, old_owner, new_owner;
659 if (reader.PopString(&name) &&
660 reader.PopString(&old_owner) &&
661 reader.PopString(&new_owner) &&
662 name == service_name_) {
663 service_name_owner_ = new_owner;
664 bus_->GetOriginTaskRunner()->PostTask(
665 FROM_HERE,
666 base::Bind(&ObjectProxy::RunNameOwnerChangedCallback,
667 this, old_owner, new_owner));
669 const bool service_is_available = !service_name_owner_.empty();
670 if (service_is_available) {
671 bus_->GetOriginTaskRunner()->PostTask(
672 FROM_HERE,
673 base::Bind(&ObjectProxy::RunWaitForServiceToBeAvailableCallbacks,
674 this, service_is_available));
679 // Always return unhandled to let other object proxies handle the same
680 // signal.
681 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
684 void ObjectProxy::RunNameOwnerChangedCallback(const std::string& old_owner,
685 const std::string& new_owner) {
686 bus_->AssertOnOriginThread();
687 if (!name_owner_changed_callback_.is_null())
688 name_owner_changed_callback_.Run(old_owner, new_owner);
691 void ObjectProxy::RunWaitForServiceToBeAvailableCallbacks(
692 bool service_is_available) {
693 bus_->AssertOnOriginThread();
695 std::vector<WaitForServiceToBeAvailableCallback> callbacks;
696 callbacks.swap(wait_for_service_to_be_available_callbacks_);
697 for (size_t i = 0; i < callbacks.size(); ++i)
698 callbacks[i].Run(service_is_available);
701 } // namespace dbus