diff options
-rw-r--r-- | dbus/object_manager.cc | 34 | ||||
-rw-r--r-- | dbus/object_manager.h | 6 | ||||
-rw-r--r-- | dbus/object_manager_unittest.cc | 17 | ||||
-rw-r--r-- | dbus/test_service.cc | 53 | ||||
-rw-r--r-- | dbus/test_service.h | 23 |
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_; |