| 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 |