| 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" |
| 11 #include "base/strings/string_piece.h" | 11 #include "base/strings/string_piece.h" |
| 12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "base/task_runner_util.h" |
| 13 #include "base/threading/thread.h" | 14 #include "base/threading/thread.h" |
| 14 #include "base/threading/thread_restrictions.h" | 15 #include "base/threading/thread_restrictions.h" |
| 15 #include "dbus/dbus_statistics.h" | 16 #include "dbus/dbus_statistics.h" |
| 16 #include "dbus/message.h" | 17 #include "dbus/message.h" |
| 17 #include "dbus/object_path.h" | 18 #include "dbus/object_path.h" |
| 18 #include "dbus/object_proxy.h" | 19 #include "dbus/object_proxy.h" |
| 19 #include "dbus/scoped_dbus_error.h" | 20 #include "dbus/scoped_dbus_error.h" |
| 20 | 21 |
| 21 namespace dbus { | 22 namespace dbus { |
| 22 | 23 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 // Wait for the response in the D-Bus thread. | 165 // Wait for the response in the D-Bus thread. |
| 165 bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task); | 166 bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task); |
| 166 } | 167 } |
| 167 | 168 |
| 168 void ObjectProxy::ConnectToSignal(const std::string& interface_name, | 169 void ObjectProxy::ConnectToSignal(const std::string& interface_name, |
| 169 const std::string& signal_name, | 170 const std::string& signal_name, |
| 170 SignalCallback signal_callback, | 171 SignalCallback signal_callback, |
| 171 OnConnectedCallback on_connected_callback) { | 172 OnConnectedCallback on_connected_callback) { |
| 172 bus_->AssertOnOriginThread(); | 173 bus_->AssertOnOriginThread(); |
| 173 | 174 |
| 174 bus_->GetDBusTaskRunner()->PostTask( | 175 base::PostTaskAndReplyWithResult( |
| 176 bus_->GetDBusTaskRunner(), |
| 175 FROM_HERE, | 177 FROM_HERE, |
| 176 base::Bind(&ObjectProxy::ConnectToSignalInternal, | 178 base::Bind(&ObjectProxy::ConnectToSignalInternal, |
| 177 this, | 179 this, |
| 178 interface_name, | 180 interface_name, |
| 179 signal_name, | 181 signal_name, |
| 180 signal_callback, | 182 signal_callback), |
| 181 on_connected_callback)); | 183 base::Bind(on_connected_callback, |
| 184 interface_name, |
| 185 signal_name)); |
| 182 } | 186 } |
| 183 | 187 |
| 184 void ObjectProxy::Detach() { | 188 void ObjectProxy::Detach() { |
| 185 bus_->AssertOnDBusThread(); | 189 bus_->AssertOnDBusThread(); |
| 186 | 190 |
| 187 if (filter_added_) { | 191 if (filter_added_) { |
| 188 if (!bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this)) { | 192 if (!bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this)) { |
| 189 LOG(ERROR) << "Failed to remove filter function"; | 193 LOG(ERROR) << "Failed to remove filter function"; |
| 190 } | 194 } |
| 191 } | 195 } |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 OnPendingCallIsCompleteData* data = | 350 OnPendingCallIsCompleteData* data = |
| 347 reinterpret_cast<OnPendingCallIsCompleteData*>(user_data); | 351 reinterpret_cast<OnPendingCallIsCompleteData*>(user_data); |
| 348 ObjectProxy* self = data->object_proxy; | 352 ObjectProxy* self = data->object_proxy; |
| 349 self->OnPendingCallIsComplete(pending_call, | 353 self->OnPendingCallIsComplete(pending_call, |
| 350 data->response_callback, | 354 data->response_callback, |
| 351 data->error_callback, | 355 data->error_callback, |
| 352 data->start_time); | 356 data->start_time); |
| 353 delete data; | 357 delete data; |
| 354 } | 358 } |
| 355 | 359 |
| 356 void ObjectProxy::ConnectToSignalInternal( | 360 bool ObjectProxy::ConnectToSignalInternal(const std::string& interface_name, |
| 357 const std::string& interface_name, | 361 const std::string& signal_name, |
| 358 const std::string& signal_name, | 362 SignalCallback signal_callback) { |
| 359 SignalCallback signal_callback, | |
| 360 OnConnectedCallback on_connected_callback) { | |
| 361 bus_->AssertOnDBusThread(); | 363 bus_->AssertOnDBusThread(); |
| 362 | 364 |
| 363 const std::string absolute_signal_name = | 365 const std::string absolute_signal_name = |
| 364 GetAbsoluteSignalName(interface_name, signal_name); | 366 GetAbsoluteSignalName(interface_name, signal_name); |
| 365 | 367 |
| 366 // Will become true, if everything is successful. | 368 if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) |
| 367 bool success = false; | 369 return false; |
| 368 | 370 |
| 369 if (bus_->Connect() && bus_->SetUpAsyncOperations()) { | 371 // We should add the filter only once. Otherwise, HandleMessage() will |
| 370 // We should add the filter only once. Otherwise, HandleMessage() will | 372 // be called more than once. |
| 371 // be called more than once. | 373 if (!filter_added_) { |
| 372 if (!filter_added_) { | 374 if (bus_->AddFilterFunction(&ObjectProxy::HandleMessageThunk, this)) { |
| 373 if (bus_->AddFilterFunction(&ObjectProxy::HandleMessageThunk, this)) { | 375 filter_added_ = true; |
| 374 filter_added_ = true; | 376 } else { |
| 375 } else { | 377 LOG(ERROR) << "Failed to add filter function"; |
| 376 LOG(ERROR) << "Failed to add filter function"; | |
| 377 } | |
| 378 } | 378 } |
| 379 // Add a match rule so the signal goes through HandleMessage(). | 379 } |
| 380 const std::string match_rule = | 380 // Add a match rule so the signal goes through HandleMessage(). |
| 381 base::StringPrintf("type='signal', interface='%s', path='%s'", | 381 const std::string match_rule = |
| 382 interface_name.c_str(), | 382 base::StringPrintf("type='signal', interface='%s', path='%s'", |
| 383 object_path_.value().c_str()); | 383 interface_name.c_str(), |
| 384 // Add a match_rule listening NameOwnerChanged for the well-known name | 384 object_path_.value().c_str()); |
| 385 // |service_name_|. | 385 // Add a match_rule listening NameOwnerChanged for the well-known name |
| 386 const std::string name_owner_changed_match_rule = | 386 // |service_name_|. |
| 387 base::StringPrintf( | 387 const std::string name_owner_changed_match_rule = |
| 388 "type='signal',interface='org.freedesktop.DBus'," | 388 base::StringPrintf( |
| 389 "member='NameOwnerChanged',path='/org/freedesktop/DBus'," | 389 "type='signal',interface='org.freedesktop.DBus'," |
| 390 "sender='org.freedesktop.DBus',arg0='%s'", | 390 "member='NameOwnerChanged',path='/org/freedesktop/DBus'," |
| 391 service_name_.c_str()); | 391 "sender='org.freedesktop.DBus',arg0='%s'", |
| 392 if (AddMatchRuleWithCallback(match_rule, | 392 service_name_.c_str()); |
| 393 absolute_signal_name, | |
| 394 signal_callback) && | |
| 395 AddMatchRuleWithoutCallback(name_owner_changed_match_rule, | |
| 396 "org.freedesktop.DBus.NameOwnerChanged")) { | |
| 397 success = true; | |
| 398 } | |
| 399 | 393 |
| 400 // Try getting the current name owner. It's not guaranteed that we can get | 394 const bool success = |
| 401 // the name owner at this moment, as the service may not yet be started. If | 395 AddMatchRuleWithCallback(match_rule, |
| 402 // that's the case, we'll get the name owner via NameOwnerChanged signal, | 396 absolute_signal_name, |
| 403 // as soon as the service is started. | 397 signal_callback) && |
| 404 UpdateNameOwnerAndBlock(); | 398 AddMatchRuleWithoutCallback(name_owner_changed_match_rule, |
| 405 } | 399 "org.freedesktop.DBus.NameOwnerChanged"); |
| 406 | 400 |
| 407 // Run on_connected_callback in the origin thread. | 401 // Try getting the current name owner. It's not guaranteed that we can get |
| 408 bus_->GetOriginTaskRunner()->PostTask( | 402 // the name owner at this moment, as the service may not yet be started. If |
| 409 FROM_HERE, | 403 // that's the case, we'll get the name owner via NameOwnerChanged signal, |
| 410 base::Bind(&ObjectProxy::OnConnected, | 404 // as soon as the service is started. |
| 411 this, | 405 UpdateNameOwnerAndBlock(); |
| 412 on_connected_callback, | |
| 413 interface_name, | |
| 414 signal_name, | |
| 415 success)); | |
| 416 } | |
| 417 | 406 |
| 418 void ObjectProxy::OnConnected(OnConnectedCallback on_connected_callback, | 407 return success; |
| 419 const std::string& interface_name, | |
| 420 const std::string& signal_name, | |
| 421 bool success) { | |
| 422 bus_->AssertOnOriginThread(); | |
| 423 | |
| 424 on_connected_callback.Run(interface_name, signal_name, success); | |
| 425 } | 408 } |
| 426 | 409 |
| 427 void ObjectProxy::SetNameOwnerChangedCallback(SignalCallback callback) { | 410 void ObjectProxy::SetNameOwnerChangedCallback(SignalCallback callback) { |
| 428 bus_->AssertOnOriginThread(); | 411 bus_->AssertOnOriginThread(); |
| 429 | 412 |
| 430 name_owner_changed_callback_ = callback; | 413 name_owner_changed_callback_ = callback; |
| 431 } | 414 } |
| 432 | 415 |
| 433 DBusHandlerResult ObjectProxy::HandleMessage( | 416 DBusHandlerResult ObjectProxy::HandleMessage( |
| 434 DBusConnection* connection, | 417 DBusConnection* connection, |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 } | 635 } |
| 653 } | 636 } |
| 654 } | 637 } |
| 655 | 638 |
| 656 // Always return unhandled to let other object proxies handle the same | 639 // Always return unhandled to let other object proxies handle the same |
| 657 // signal. | 640 // signal. |
| 658 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; | 641 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
| 659 } | 642 } |
| 660 | 643 |
| 661 } // namespace dbus | 644 } // namespace dbus |
| OLD | NEW |