OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "dbus/bus.h" | 5 #include "dbus/bus.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 signal_name)); | 185 signal_name)); |
186 } | 186 } |
187 | 187 |
188 void ObjectProxy::SetNameOwnerChangedCallback( | 188 void ObjectProxy::SetNameOwnerChangedCallback( |
189 NameOwnerChangedCallback callback) { | 189 NameOwnerChangedCallback callback) { |
190 bus_->AssertOnOriginThread(); | 190 bus_->AssertOnOriginThread(); |
191 | 191 |
192 name_owner_changed_callback_ = callback; | 192 name_owner_changed_callback_ = callback; |
193 } | 193 } |
194 | 194 |
| 195 void 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 |
195 void ObjectProxy::Detach() { | 205 void ObjectProxy::Detach() { |
196 bus_->AssertOnDBusThread(); | 206 bus_->AssertOnDBusThread(); |
197 | 207 |
198 if (filter_added_) { | 208 if (filter_added_) { |
199 if (!bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this)) { | 209 if (!bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this)) { |
200 LOG(ERROR) << "Failed to remove filter function"; | 210 LOG(ERROR) << "Failed to remove filter function"; |
201 } | 211 } |
202 } | 212 } |
203 | 213 |
204 for (std::set<std::string>::iterator iter = match_rules_.begin(); | 214 for (std::set<std::string>::iterator iter = match_rules_.begin(); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 OnPendingCallIsCompleteData* data = | 367 OnPendingCallIsCompleteData* data = |
358 reinterpret_cast<OnPendingCallIsCompleteData*>(user_data); | 368 reinterpret_cast<OnPendingCallIsCompleteData*>(user_data); |
359 ObjectProxy* self = data->object_proxy; | 369 ObjectProxy* self = data->object_proxy; |
360 self->OnPendingCallIsComplete(pending_call, | 370 self->OnPendingCallIsComplete(pending_call, |
361 data->response_callback, | 371 data->response_callback, |
362 data->error_callback, | 372 data->error_callback, |
363 data->start_time); | 373 data->start_time); |
364 delete data; | 374 delete data; |
365 } | 375 } |
366 | 376 |
367 bool ObjectProxy::ConnectToSignalInternal(const std::string& interface_name, | 377 bool ObjectProxy::ConnectToNameOwnerChangedSignal() { |
368 const std::string& signal_name, | |
369 SignalCallback signal_callback) { | |
370 bus_->AssertOnDBusThread(); | 378 bus_->AssertOnDBusThread(); |
371 | 379 |
372 const std::string absolute_signal_name = | |
373 GetAbsoluteSignalName(interface_name, signal_name); | |
374 | |
375 if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) | 380 if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) |
376 return false; | 381 return false; |
377 | 382 |
378 // We should add the filter only once. Otherwise, HandleMessage() will | 383 // We should add the filter only once. Otherwise, HandleMessage() will |
379 // be called more than once. | 384 // be called more than once. |
380 if (!filter_added_) { | 385 if (!filter_added_) { |
381 if (bus_->AddFilterFunction(&ObjectProxy::HandleMessageThunk, this)) { | 386 if (bus_->AddFilterFunction(&ObjectProxy::HandleMessageThunk, this)) { |
382 filter_added_ = true; | 387 filter_added_ = true; |
383 } else { | 388 } else { |
384 LOG(ERROR) << "Failed to add filter function"; | 389 LOG(ERROR) << "Failed to add filter function"; |
385 } | 390 } |
386 } | 391 } |
387 // Add a match rule so the signal goes through HandleMessage(). | |
388 const std::string match_rule = | |
389 base::StringPrintf("type='signal', interface='%s', path='%s'", | |
390 interface_name.c_str(), | |
391 object_path_.value().c_str()); | |
392 // Add a match_rule listening NameOwnerChanged for the well-known name | 392 // Add a match_rule listening NameOwnerChanged for the well-known name |
393 // |service_name_|. | 393 // |service_name_|. |
394 const std::string name_owner_changed_match_rule = | 394 const std::string name_owner_changed_match_rule = |
395 base::StringPrintf( | 395 base::StringPrintf( |
396 "type='signal',interface='org.freedesktop.DBus'," | 396 "type='signal',interface='org.freedesktop.DBus'," |
397 "member='NameOwnerChanged',path='/org/freedesktop/DBus'," | 397 "member='NameOwnerChanged',path='/org/freedesktop/DBus'," |
398 "sender='org.freedesktop.DBus',arg0='%s'", | 398 "sender='org.freedesktop.DBus',arg0='%s'", |
399 service_name_.c_str()); | 399 service_name_.c_str()); |
400 | 400 |
401 const bool success = | 401 const bool success = |
402 AddMatchRuleWithCallback(match_rule, | |
403 absolute_signal_name, | |
404 signal_callback) && | |
405 AddMatchRuleWithoutCallback(name_owner_changed_match_rule, | 402 AddMatchRuleWithoutCallback(name_owner_changed_match_rule, |
406 "org.freedesktop.DBus.NameOwnerChanged"); | 403 "org.freedesktop.DBus.NameOwnerChanged"); |
407 | 404 |
408 // Try getting the current name owner. It's not guaranteed that we can get | 405 // Try getting the current name owner. It's not guaranteed that we can get |
409 // the name owner at this moment, as the service may not yet be started. If | 406 // the name owner at this moment, as the service may not yet be started. If |
410 // that's the case, we'll get the name owner via NameOwnerChanged signal, | 407 // that's the case, we'll get the name owner via NameOwnerChanged signal, |
411 // as soon as the service is started. | 408 // as soon as the service is started. |
412 UpdateNameOwnerAndBlock(); | 409 UpdateNameOwnerAndBlock(); |
413 | 410 |
414 return success; | 411 return success; |
415 } | 412 } |
416 | 413 |
| 414 bool 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 |
| 435 void 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 |
417 DBusHandlerResult ObjectProxy::HandleMessage( | 457 DBusHandlerResult ObjectProxy::HandleMessage( |
418 DBusConnection* connection, | 458 DBusConnection* connection, |
419 DBusMessage* raw_message) { | 459 DBusMessage* raw_message) { |
420 bus_->AssertOnDBusThread(); | 460 bus_->AssertOnDBusThread(); |
421 | 461 |
422 if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_SIGNAL) | 462 if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_SIGNAL) |
423 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; | 463 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
424 | 464 |
425 // raw_message will be unrefed on exit of the function. Increment the | 465 // raw_message will be unrefed on exit of the function. Increment the |
426 // reference so we can use it in Signal. | 466 // reference so we can use it in Signal. |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 std::string name, old_owner, new_owner; | 658 std::string name, old_owner, new_owner; |
619 if (reader.PopString(&name) && | 659 if (reader.PopString(&name) && |
620 reader.PopString(&old_owner) && | 660 reader.PopString(&old_owner) && |
621 reader.PopString(&new_owner) && | 661 reader.PopString(&new_owner) && |
622 name == service_name_) { | 662 name == service_name_) { |
623 service_name_owner_ = new_owner; | 663 service_name_owner_ = new_owner; |
624 bus_->GetOriginTaskRunner()->PostTask( | 664 bus_->GetOriginTaskRunner()->PostTask( |
625 FROM_HERE, | 665 FROM_HERE, |
626 base::Bind(&ObjectProxy::RunNameOwnerChangedCallback, | 666 base::Bind(&ObjectProxy::RunNameOwnerChangedCallback, |
627 this, old_owner, new_owner)); | 667 this, old_owner, new_owner)); |
| 668 |
| 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)); |
| 675 } |
628 } | 676 } |
629 } | 677 } |
630 | 678 |
631 // Always return unhandled to let other object proxies handle the same | 679 // Always return unhandled to let other object proxies handle the same |
632 // signal. | 680 // signal. |
633 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; | 681 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
634 } | 682 } |
635 | 683 |
636 void ObjectProxy::RunNameOwnerChangedCallback(const std::string& old_owner, | 684 void ObjectProxy::RunNameOwnerChangedCallback(const std::string& old_owner, |
637 const std::string& new_owner) { | 685 const std::string& new_owner) { |
638 bus_->AssertOnOriginThread(); | 686 bus_->AssertOnOriginThread(); |
639 if (!name_owner_changed_callback_.is_null()) | 687 if (!name_owner_changed_callback_.is_null()) |
640 name_owner_changed_callback_.Run(old_owner, new_owner); | 688 name_owner_changed_callback_.Run(old_owner, new_owner); |
641 } | 689 } |
642 | 690 |
| 691 void ObjectProxy::RunWaitForServiceToBeAvailableCallbacks( |
| 692 bool service_is_available) { |
| 693 bus_->AssertOnOriginThread(); |
| 694 |
| 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); |
| 699 } |
| 700 |
643 } // namespace dbus | 701 } // namespace dbus |
OLD | NEW |