Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: dbus/object_proxy.cc

Issue 25488002: dbus: Add ObjectProxy::WaitForServiceToBeAvailable() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Also test already-available case Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « dbus/object_proxy.h ('k') | dbus/object_proxy_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « dbus/object_proxy.h ('k') | dbus/object_proxy_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698