| Index: dbus/object_manager.cc
|
| diff --git a/dbus/object_manager.cc b/dbus/object_manager.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4b96d8317f9ca1cb440d391be42ccb8437348577
|
| --- /dev/null
|
| +++ b/dbus/object_manager.cc
|
| @@ -0,0 +1,288 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "dbus/object_manager.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/logging.h"
|
| +#include "dbus/bus.h"
|
| +#include "dbus/message.h"
|
| +#include "dbus/object_proxy.h"
|
| +#include "dbus/property.h"
|
| +
|
| +namespace dbus {
|
| +
|
| +ObjectManager::ObjectManager(Bus* bus,
|
| + const std::string& service_name,
|
| + const ObjectPath& object_path)
|
| + : bus_(bus),
|
| + service_name_(service_name),
|
| + object_path_(object_path),
|
| + weak_ptr_factory_(this) {
|
| + DVLOG(1) << "Creating ObjectManager for " << service_name_
|
| + << " " << object_path_.value();
|
| +
|
| + DCHECK(bus_);
|
| + object_proxy_ = bus_->GetObjectProxy(service_name_, object_path_);
|
| +
|
| + object_proxy_->ConnectToSignal(
|
| + kObjectManagerInterface,
|
| + kObjectManagerInterfacesAdded,
|
| + base::Bind(&ObjectManager::InterfacesAddedReceived,
|
| + weak_ptr_factory_.GetWeakPtr()),
|
| + base::Bind(&ObjectManager::InterfacesAddedConnected,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| +
|
| + object_proxy_->ConnectToSignal(
|
| + kObjectManagerInterface,
|
| + kObjectManagerInterfacesRemoved,
|
| + base::Bind(&ObjectManager::InterfacesRemovedReceived,
|
| + weak_ptr_factory_.GetWeakPtr()),
|
| + base::Bind(&ObjectManager::InterfacesRemovedConnected,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| +
|
| + GetManagedObjects();
|
| +}
|
| +
|
| +ObjectManager::~ObjectManager() {
|
| + // Clean up Object structures
|
| + for (ObjectMap::iterator iter = object_map_.begin();
|
| + iter != object_map_.end(); ++iter) {
|
| + Object* object = iter->second;
|
| +
|
| + for (Object::PropertiesMap::iterator piter = object->properties_map.begin();
|
| + piter != object->properties_map.end(); ++piter) {
|
| + PropertySet* properties = piter->second;
|
| + delete properties;
|
| + }
|
| +
|
| + delete object;
|
| + }
|
| +}
|
| +
|
| +void ObjectManager::RegisterInterface(const std::string& interface_name,
|
| + Interface* interface) {
|
| + interface_map_[interface_name] = interface;
|
| +}
|
| +
|
| +void ObjectManager::UnregisterInterface(const std::string& interface_name) {
|
| + InterfaceMap::iterator iter = interface_map_.find(interface_name);
|
| + if (iter != interface_map_.end())
|
| + interface_map_.erase(iter);
|
| +}
|
| +
|
| +std::vector<ObjectPath> ObjectManager::GetObjects() {
|
| + std::vector<ObjectPath> object_paths;
|
| +
|
| + for (ObjectMap::iterator iter = object_map_.begin();
|
| + iter != object_map_.end(); ++iter)
|
| + object_paths.push_back(iter->first);
|
| +
|
| + return object_paths;
|
| +}
|
| +
|
| +std::vector<ObjectPath> ObjectManager::GetObjectsWithInterface(
|
| + const std::string& interface_name) {
|
| + std::vector<ObjectPath> object_paths;
|
| +
|
| + for (ObjectMap::iterator oiter = object_map_.begin();
|
| + oiter != object_map_.end(); ++oiter) {
|
| + Object* object = oiter->second;
|
| +
|
| + Object::PropertiesMap::iterator piter =
|
| + object->properties_map.find(interface_name);
|
| + if (piter != object->properties_map.end())
|
| + object_paths.push_back(oiter->first);
|
| + }
|
| +
|
| + return object_paths;
|
| +}
|
| +
|
| +ObjectProxy* ObjectManager::GetObjectProxy(const ObjectPath& object_path) {
|
| + ObjectMap::iterator iter = object_map_.find(object_path);
|
| + if (iter == object_map_.end())
|
| + return NULL;
|
| +
|
| + Object* object = iter->second;
|
| + return object->object_proxy;
|
| +}
|
| +
|
| +PropertySet* ObjectManager::GetProperties(const ObjectPath& object_path,
|
| + const std::string& interface_name) {
|
| + ObjectMap::iterator iter = object_map_.find(object_path);
|
| + if (iter == object_map_.end())
|
| + return NULL;
|
| +
|
| + Object* object = iter->second;
|
| + Object::PropertiesMap::iterator piter =
|
| + object->properties_map.find(interface_name);
|
| + if (piter == object->properties_map.end())
|
| + return NULL;
|
| +
|
| + return piter->second;
|
| +}
|
| +
|
| +void ObjectManager::GetManagedObjects() {
|
| + MethodCall method_call(kObjectManagerInterface,
|
| + kObjectManagerGetManagedObjects);
|
| +
|
| + object_proxy_->CallMethod(
|
| + &method_call,
|
| + ObjectProxy::TIMEOUT_USE_DEFAULT,
|
| + base::Bind(&ObjectManager::OnGetManagedObjects,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void ObjectManager::OnGetManagedObjects(Response* response) {
|
| + if (response != NULL) {
|
| + MessageReader reader(response);
|
| + MessageReader array_reader(NULL);
|
| + if (!reader.PopArray(&array_reader))
|
| + return;
|
| +
|
| + while (array_reader.HasMoreData()) {
|
| + MessageReader dict_entry_reader(NULL);
|
| + ObjectPath object_path;
|
| + if (!array_reader.PopDictEntry(&dict_entry_reader) ||
|
| + !dict_entry_reader.PopObjectPath(&object_path))
|
| + continue;
|
| +
|
| + UpdateObject(object_path, &dict_entry_reader);
|
| + }
|
| +
|
| + } else {
|
| + LOG(WARNING) << service_name_ << " " << object_path_.value()
|
| + << ": Failed to get managed objects";
|
| + }
|
| +}
|
| +
|
| +void ObjectManager::InterfacesAddedReceived(Signal* signal) {
|
| + DCHECK(signal);
|
| + MessageReader reader(signal);
|
| + ObjectPath object_path;
|
| + if (!reader.PopObjectPath(&object_path)) {
|
| + LOG(WARNING) << service_name_ << " " << object_path_.value()
|
| + << ": InterfacesAdded signal has incorrect parameters: "
|
| + << signal->ToString();
|
| + return;
|
| + }
|
| +
|
| + UpdateObject(object_path, &reader);
|
| +}
|
| +
|
| +void ObjectManager::InterfacesAddedConnected(const std::string& interface_name,
|
| + const std::string& signal_name,
|
| + bool success) {
|
| + LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
|
| + << ": Failed to connect to InterfacesAdded signal.";
|
| +}
|
| +
|
| +void ObjectManager::InterfacesRemovedReceived(Signal* signal) {
|
| + DCHECK(signal);
|
| + MessageReader reader(signal);
|
| + ObjectPath object_path;
|
| + std::vector<std::string> interface_names;
|
| + if (!reader.PopObjectPath(&object_path) ||
|
| + !reader.PopArrayOfStrings(&interface_names)) {
|
| + LOG(WARNING) << service_name_ << " " << object_path_.value()
|
| + << ": InterfacesRemoved signal has incorrect parameters: "
|
| + << signal->ToString();
|
| + return;
|
| + }
|
| +
|
| + for (size_t i = 0; i < interface_names.size(); ++i)
|
| + RemoveInterface(object_path, interface_names[i]);
|
| +}
|
| +
|
| +void ObjectManager::InterfacesRemovedConnected(
|
| + const std::string& interface_name,
|
| + const std::string& signal_name,
|
| + bool success) {
|
| + LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
|
| + << ": Failed to connect to "
|
| + << "InterfacesRemoved signal.";
|
| +}
|
| +
|
| +void ObjectManager::UpdateObject(const ObjectPath& object_path,
|
| + MessageReader* reader) {
|
| + DCHECK(reader);
|
| + MessageReader array_reader(NULL);
|
| + if (!reader->PopArray(&array_reader))
|
| + return;
|
| +
|
| + while (array_reader.HasMoreData()) {
|
| + MessageReader dict_entry_reader(NULL);
|
| + std::string interface_name;
|
| + if (!array_reader.PopDictEntry(&dict_entry_reader) ||
|
| + !dict_entry_reader.PopString(&interface_name))
|
| + continue;
|
| +
|
| + AddInterface(object_path, interface_name, &dict_entry_reader);
|
| + }
|
| +}
|
| +
|
| +
|
| +void ObjectManager::AddInterface(const ObjectPath& object_path,
|
| + const std::string& interface_name,
|
| + MessageReader* reader) {
|
| + InterfaceMap::iterator iiter = interface_map_.find(interface_name);
|
| + if (iiter == interface_map_.end())
|
| + return;
|
| + Interface* interface = iiter->second;
|
| +
|
| + ObjectMap::iterator oiter = object_map_.find(object_path);
|
| + Object* object;
|
| + if (oiter == object_map_.end()) {
|
| + object = object_map_[object_path] = new Object;
|
| + object->object_proxy = bus_->GetObjectProxy(service_name_, object_path);
|
| + } else
|
| + object = oiter->second;
|
| +
|
| + Object::PropertiesMap::iterator piter =
|
| + object->properties_map.find(interface_name);
|
| + PropertySet* property_set;
|
| + const bool interface_added = (piter == object->properties_map.end());
|
| + if (interface_added) {
|
| + property_set = object->properties_map[interface_name] =
|
| + interface->CreateProperties(object->object_proxy,
|
| + object_path, interface_name);
|
| + property_set->ConnectSignals();
|
| + } else
|
| + property_set = piter->second;
|
| +
|
| + property_set->UpdatePropertiesFromReader(reader);
|
| +
|
| + if (interface_added)
|
| + interface->ObjectAdded(object_path, interface_name);
|
| +}
|
| +
|
| +void ObjectManager::RemoveInterface(const ObjectPath& object_path,
|
| + const std::string& interface_name) {
|
| + ObjectMap::iterator oiter = object_map_.find(object_path);
|
| + if (oiter == object_map_.end())
|
| + return;
|
| + Object* object = oiter->second;
|
| +
|
| + Object::PropertiesMap::iterator piter =
|
| + object->properties_map.find(interface_name);
|
| + if (piter == object->properties_map.end())
|
| + return;
|
| +
|
| + // Inform the interface before removing the properties structure or object
|
| + // in case it needs details from them to make its own decisions.
|
| + InterfaceMap::iterator iiter = interface_map_.find(interface_name);
|
| + if (iiter != interface_map_.end()) {
|
| + Interface* interface = iiter->second;
|
| + interface->ObjectRemoved(object_path, interface_name);
|
| + }
|
| +
|
| + object->properties_map.erase(piter);
|
| +
|
| + if (object->properties_map.empty()) {
|
| + object_map_.erase(oiter);
|
| + delete object;
|
| + }
|
| +}
|
| +
|
| +} // namespace dbus
|
|
|