summaryrefslogtreecommitdiffstats
path: root/dbus
diff options
context:
space:
mode:
Diffstat (limited to 'dbus')
-rw-r--r--dbus/object_manager.cc34
-rw-r--r--dbus/object_manager.h6
-rw-r--r--dbus/object_manager_unittest.cc17
-rw-r--r--dbus/test_service.cc53
-rw-r--r--dbus/test_service.h23
5 files changed, 133 insertions, 0 deletions
diff --git a/dbus/object_manager.cc b/dbus/object_manager.cc
index 0386228..d8eb569 100644
--- a/dbus/object_manager.cc
+++ b/dbus/object_manager.cc
@@ -32,6 +32,9 @@ ObjectManager::ObjectManager(Bus* bus,
DCHECK(bus_);
object_proxy_ = bus_->GetObjectProxy(service_name_, object_path_);
+ object_proxy_->SetNameOwnerChangedCallback(
+ base::Bind(&ObjectManager::NameOwnerChanged,
+ weak_ptr_factory_.GetWeakPtr()));
object_proxy_->ConnectToSignal(
kObjectManagerInterface,
@@ -292,4 +295,35 @@ void ObjectManager::RemoveInterface(const ObjectPath& object_path,
}
}
+void ObjectManager::NameOwnerChanged(const std::string& old_owner,
+ const std::string& new_owner) {
+ if (!old_owner.empty()) {
+ ObjectMap::iterator iter = object_map_.begin();
+ while (iter != object_map_.end()) {
+ ObjectMap::iterator tmp = iter;
+ ++iter;
+
+ // PropertiesMap is mutated by RemoveInterface, and also Object is
+ // destroyed; easier to collect the object path and interface names
+ // and remove them safely.
+ const dbus::ObjectPath object_path = tmp->first;
+ Object* object = tmp->second;
+ std::vector<std::string> interfaces;
+
+ for (Object::PropertiesMap::iterator piter =
+ object->properties_map.begin();
+ piter != object->properties_map.end(); ++piter)
+ interfaces.push_back(piter->first);
+
+ for (std::vector<std::string>::iterator iiter = interfaces.begin();
+ iiter != interfaces.end(); ++iiter)
+ RemoveInterface(object_path, *iiter);
+ }
+
+ }
+
+ if (!new_owner.empty())
+ GetManagedObjects();
+}
+
} // namespace dbus
diff --git a/dbus/object_manager.h b/dbus/object_manager.h
index 333f69e..0d3ae5d0 100644
--- a/dbus/object_manager.h
+++ b/dbus/object_manager.h
@@ -273,6 +273,12 @@ public:
void RemoveInterface(const ObjectPath& object_path,
const std::string& interface_name);
+ // Removes all objects and interfaces from the object manager when
+ // |old_owner| is not the empty string and/or re-requests the set of managed
+ // objects when |new_owner| is not the empty string.
+ void NameOwnerChanged(const std::string& old_owner,
+ const std::string& new_owner);
+
Bus* bus_;
std::string service_name_;
ObjectPath object_path_;
diff --git a/dbus/object_manager_unittest.cc b/dbus/object_manager_unittest.cc
index 595489f..3e53095 100644
--- a/dbus/object_manager_unittest.cc
+++ b/dbus/object_manager_unittest.cc
@@ -333,4 +333,21 @@ TEST_F(ObjectManagerTest, RemoveSecondObject) {
EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
}
+TEST_F(ObjectManagerTest, OwnershipLost) {
+ PerformAction("ReleaseOwnership", ObjectPath("/org/chromium/TestService"));
+ WaitForRemoveObject();
+
+ std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
+ ASSERT_EQ(0U, object_paths.size());
+}
+
+TEST_F(ObjectManagerTest, OwnershipLostAndRegained) {
+ PerformAction("Ownership", ObjectPath("/org/chromium/TestService"));
+ WaitForRemoveObject();
+ WaitForObject();
+
+ std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
+ ASSERT_EQ(1U, object_paths.size());
+}
+
} // namespace dbus
diff --git a/dbus/test_service.cc b/dbus/test_service.cc
index 21a885d..064b91e 100644
--- a/dbus/test_service.cc
+++ b/dbus/test_service.cc
@@ -142,6 +142,24 @@ void TestService::OnOwnership(base::Callback<void(bool)> callback,
on_name_obtained_.Signal();
}
+void TestService::ReleaseOwnership(base::Closure callback) {
+ bus_->GetDBusTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&TestService::ReleaseOwnershipInternal,
+ base::Unretained(this),
+ callback));
+}
+
+void TestService::ReleaseOwnershipInternal(
+ base::Closure callback) {
+ bus_->ReleaseOwnership("org.chromium.TestService");
+ has_ownership_ = false;
+
+ bus_->GetOriginTaskRunner()->PostTask(
+ FROM_HERE,
+ callback);
+}
+
void TestService::OnExported(const std::string& interface_name,
const std::string& method_name,
bool success) {
@@ -443,11 +461,46 @@ void TestService::PerformAction(
AddObject(object_path);
else if (action == "RemoveObject")
RemoveObject(object_path);
+ else if (action == "ReleaseOwnership") {
+ ReleaseOwnership(base::Bind(&TestService::PerformActionResponse,
+ base::Unretained(this),
+ method_call, response_sender));
+ return;
+ } else if (action == "Ownership") {
+ ReleaseOwnership(base::Bind(&TestService::OwnershipReleased,
+ base::Unretained(this),
+ method_call, response_sender));
+ return;
+ }
scoped_ptr<Response> response = Response::FromMethodCall(method_call);
response_sender.Run(response.Pass());
}
+void TestService::PerformActionResponse(
+ MethodCall* method_call,
+ ExportedObject::ResponseSender response_sender) {
+ scoped_ptr<Response> response = Response::FromMethodCall(method_call);
+ response_sender.Run(response.Pass());
+}
+
+void TestService::OwnershipReleased(
+ MethodCall* method_call,
+ ExportedObject::ResponseSender response_sender) {
+ RequestOwnership(base::Bind(&TestService::OwnershipRegained,
+ base::Unretained(this),
+ method_call, response_sender));
+}
+
+
+void TestService::OwnershipRegained(
+ MethodCall* method_call,
+ ExportedObject::ResponseSender response_sender,
+ bool success) {
+ PerformActionResponse(method_call, response_sender);
+}
+
+
void TestService::GetManagedObjects(
MethodCall* method_call,
ExportedObject::ResponseSender response_sender) {
diff --git a/dbus/test_service.h b/dbus/test_service.h
index 197b8d2..523864c 100644
--- a/dbus/test_service.h
+++ b/dbus/test_service.h
@@ -74,6 +74,10 @@ class TestService : public base::Thread {
// completed.
void RequestOwnership(base::Callback<void(bool)> callback);
+ // Release the ownership of the well-known name "TestService".
+ // |callback| will be called when the ownership has been released.
+ void ReleaseOwnership(base::Closure callback);
+
// Returns whether this instance has the name ownership or not.
bool has_ownership() const { return has_ownership_; }
@@ -166,6 +170,25 @@ class TestService : public base::Thread {
// Helper function for RequestOwnership().
void RequestOwnershipInternal(base::Callback<void(bool)> callback);
+ // Helper function for ReleaseOwnership().
+ void ReleaseOwnershipInternal(base::Closure callback);
+
+ // Sends the response on completion of the performed action.
+ void PerformActionResponse(
+ MethodCall* method_call,
+ dbus::ExportedObject::ResponseSender response_sender);
+
+ // Re-requests ownership of the well-known name after releasing it.
+ void OwnershipReleased(
+ MethodCall* method_call,
+ dbus::ExportedObject::ResponseSender response_sender);
+
+ // Sends the action response after regaining the well-known name.
+ void OwnershipRegained(
+ MethodCall* method_call,
+ dbus::ExportedObject::ResponseSender response_sender,
+ bool success);
+
// Options to use when requesting service ownership.
Bus::ServiceOwnershipOptions request_ownership_options_;