Home | History | Annotate | Download | only in dbus
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "dbus/object_manager.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "dbus/bus.h"
     10 #include "dbus/message.h"
     11 #include "dbus/object_proxy.h"
     12 #include "dbus/property.h"
     13 
     14 namespace dbus {
     15 
     16 ObjectManager::Object::Object()
     17   : object_proxy(NULL) {
     18 }
     19 
     20 ObjectManager::Object::~Object() {
     21 }
     22 
     23 ObjectManager::ObjectManager(Bus* bus,
     24                              const std::string& service_name,
     25                              const ObjectPath& object_path)
     26     : bus_(bus),
     27       service_name_(service_name),
     28       object_path_(object_path),
     29       weak_ptr_factory_(this) {
     30   DVLOG(1) << "Creating ObjectManager for " << service_name_
     31            << " " << object_path_.value();
     32 
     33   DCHECK(bus_);
     34   object_proxy_ = bus_->GetObjectProxy(service_name_, object_path_);
     35 
     36   object_proxy_->ConnectToSignal(
     37       kObjectManagerInterface,
     38       kObjectManagerInterfacesAdded,
     39       base::Bind(&ObjectManager::InterfacesAddedReceived,
     40                  weak_ptr_factory_.GetWeakPtr()),
     41       base::Bind(&ObjectManager::InterfacesAddedConnected,
     42                  weak_ptr_factory_.GetWeakPtr()));
     43 
     44   object_proxy_->ConnectToSignal(
     45       kObjectManagerInterface,
     46       kObjectManagerInterfacesRemoved,
     47       base::Bind(&ObjectManager::InterfacesRemovedReceived,
     48                  weak_ptr_factory_.GetWeakPtr()),
     49       base::Bind(&ObjectManager::InterfacesRemovedConnected,
     50                  weak_ptr_factory_.GetWeakPtr()));
     51 
     52   GetManagedObjects();
     53 }
     54 
     55 ObjectManager::~ObjectManager() {
     56   // Clean up Object structures
     57   for (ObjectMap::iterator iter = object_map_.begin();
     58        iter != object_map_.end(); ++iter) {
     59     Object* object = iter->second;
     60 
     61     for (Object::PropertiesMap::iterator piter = object->properties_map.begin();
     62          piter != object->properties_map.end(); ++piter) {
     63       PropertySet* properties = piter->second;
     64       delete properties;
     65     }
     66 
     67     delete object;
     68   }
     69 }
     70 
     71 void ObjectManager::RegisterInterface(const std::string& interface_name,
     72                                       Interface* interface) {
     73   interface_map_[interface_name] = interface;
     74 }
     75 
     76 void ObjectManager::UnregisterInterface(const std::string& interface_name) {
     77   InterfaceMap::iterator iter = interface_map_.find(interface_name);
     78   if (iter != interface_map_.end())
     79     interface_map_.erase(iter);
     80 }
     81 
     82 std::vector<ObjectPath> ObjectManager::GetObjects() {
     83   std::vector<ObjectPath> object_paths;
     84 
     85   for (ObjectMap::iterator iter = object_map_.begin();
     86        iter != object_map_.end(); ++iter)
     87     object_paths.push_back(iter->first);
     88 
     89   return object_paths;
     90 }
     91 
     92 std::vector<ObjectPath> ObjectManager::GetObjectsWithInterface(
     93       const std::string& interface_name) {
     94   std::vector<ObjectPath> object_paths;
     95 
     96   for (ObjectMap::iterator oiter = object_map_.begin();
     97        oiter != object_map_.end(); ++oiter) {
     98     Object* object = oiter->second;
     99 
    100     Object::PropertiesMap::iterator piter =
    101         object->properties_map.find(interface_name);
    102     if (piter != object->properties_map.end())
    103       object_paths.push_back(oiter->first);
    104   }
    105 
    106   return object_paths;
    107 }
    108 
    109 ObjectProxy* ObjectManager::GetObjectProxy(const ObjectPath& object_path) {
    110   ObjectMap::iterator iter = object_map_.find(object_path);
    111   if (iter == object_map_.end())
    112     return NULL;
    113 
    114   Object* object = iter->second;
    115   return object->object_proxy;
    116 }
    117 
    118 PropertySet* ObjectManager::GetProperties(const ObjectPath& object_path,
    119                                           const std::string& interface_name) {
    120   ObjectMap::iterator iter = object_map_.find(object_path);
    121   if (iter == object_map_.end())
    122     return NULL;
    123 
    124   Object* object = iter->second;
    125   Object::PropertiesMap::iterator piter =
    126       object->properties_map.find(interface_name);
    127   if (piter == object->properties_map.end())
    128     return NULL;
    129 
    130   return piter->second;
    131 }
    132 
    133 void ObjectManager::GetManagedObjects() {
    134   MethodCall method_call(kObjectManagerInterface,
    135                          kObjectManagerGetManagedObjects);
    136 
    137   object_proxy_->CallMethod(
    138       &method_call,
    139       ObjectProxy::TIMEOUT_USE_DEFAULT,
    140       base::Bind(&ObjectManager::OnGetManagedObjects,
    141                  weak_ptr_factory_.GetWeakPtr()));
    142 }
    143 
    144 void ObjectManager::OnGetManagedObjects(Response* response) {
    145   if (response != NULL) {
    146     MessageReader reader(response);
    147     MessageReader array_reader(NULL);
    148     if (!reader.PopArray(&array_reader))
    149       return;
    150 
    151     while (array_reader.HasMoreData()) {
    152       MessageReader dict_entry_reader(NULL);
    153       ObjectPath object_path;
    154       if (!array_reader.PopDictEntry(&dict_entry_reader) ||
    155           !dict_entry_reader.PopObjectPath(&object_path))
    156         continue;
    157 
    158       UpdateObject(object_path, &dict_entry_reader);
    159     }
    160 
    161   } else {
    162     LOG(WARNING) << service_name_ << " " << object_path_.value()
    163                  << ": Failed to get managed objects";
    164   }
    165 }
    166 
    167 void ObjectManager::InterfacesAddedReceived(Signal* signal) {
    168   DCHECK(signal);
    169   MessageReader reader(signal);
    170   ObjectPath object_path;
    171   if (!reader.PopObjectPath(&object_path)) {
    172     LOG(WARNING) << service_name_ << " " << object_path_.value()
    173                  << ": InterfacesAdded signal has incorrect parameters: "
    174                  << signal->ToString();
    175     return;
    176   }
    177 
    178   UpdateObject(object_path, &reader);
    179 }
    180 
    181 void ObjectManager::InterfacesAddedConnected(const std::string& interface_name,
    182                                              const std::string& signal_name,
    183                                              bool success) {
    184   LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
    185                             << ": Failed to connect to InterfacesAdded signal.";
    186 }
    187 
    188 void ObjectManager::InterfacesRemovedReceived(Signal* signal) {
    189   DCHECK(signal);
    190   MessageReader reader(signal);
    191   ObjectPath object_path;
    192   std::vector<std::string> interface_names;
    193   if (!reader.PopObjectPath(&object_path) ||
    194       !reader.PopArrayOfStrings(&interface_names)) {
    195     LOG(WARNING) << service_name_ << " " << object_path_.value()
    196                  << ": InterfacesRemoved signal has incorrect parameters: "
    197                  << signal->ToString();
    198     return;
    199   }
    200 
    201   for (size_t i = 0; i < interface_names.size(); ++i)
    202     RemoveInterface(object_path, interface_names[i]);
    203 }
    204 
    205 void ObjectManager::InterfacesRemovedConnected(
    206     const std::string& interface_name,
    207     const std::string& signal_name,
    208     bool success) {
    209   LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
    210                             << ": Failed to connect to "
    211                             << "InterfacesRemoved signal.";
    212 }
    213 
    214 void ObjectManager::UpdateObject(const ObjectPath& object_path,
    215                                  MessageReader* reader) {
    216   DCHECK(reader);
    217   MessageReader array_reader(NULL);
    218   if (!reader->PopArray(&array_reader))
    219     return;
    220 
    221   while (array_reader.HasMoreData()) {
    222     MessageReader dict_entry_reader(NULL);
    223     std::string interface_name;
    224     if (!array_reader.PopDictEntry(&dict_entry_reader) ||
    225         !dict_entry_reader.PopString(&interface_name))
    226       continue;
    227 
    228     AddInterface(object_path, interface_name, &dict_entry_reader);
    229   }
    230 }
    231 
    232 
    233 void ObjectManager::AddInterface(const ObjectPath& object_path,
    234                                  const std::string& interface_name,
    235                                  MessageReader* reader) {
    236   InterfaceMap::iterator iiter = interface_map_.find(interface_name);
    237   if (iiter == interface_map_.end())
    238     return;
    239   Interface* interface = iiter->second;
    240 
    241   ObjectMap::iterator oiter = object_map_.find(object_path);
    242   Object* object;
    243   if (oiter == object_map_.end()) {
    244     object = object_map_[object_path] = new Object;
    245     object->object_proxy = bus_->GetObjectProxy(service_name_, object_path);
    246   } else
    247     object = oiter->second;
    248 
    249   Object::PropertiesMap::iterator piter =
    250       object->properties_map.find(interface_name);
    251   PropertySet* property_set;
    252   const bool interface_added = (piter == object->properties_map.end());
    253   if (interface_added) {
    254     property_set = object->properties_map[interface_name] =
    255         interface->CreateProperties(object->object_proxy,
    256                                     object_path, interface_name);
    257     property_set->ConnectSignals();
    258   } else
    259     property_set = piter->second;
    260 
    261   property_set->UpdatePropertiesFromReader(reader);
    262 
    263   if (interface_added)
    264     interface->ObjectAdded(object_path, interface_name);
    265 }
    266 
    267 void ObjectManager::RemoveInterface(const ObjectPath& object_path,
    268                                     const std::string& interface_name) {
    269   ObjectMap::iterator oiter = object_map_.find(object_path);
    270   if (oiter == object_map_.end())
    271     return;
    272   Object* object = oiter->second;
    273 
    274   Object::PropertiesMap::iterator piter =
    275       object->properties_map.find(interface_name);
    276   if (piter == object->properties_map.end())
    277     return;
    278 
    279   // Inform the interface before removing the properties structure or object
    280   // in case it needs details from them to make its own decisions.
    281   InterfaceMap::iterator iiter = interface_map_.find(interface_name);
    282   if (iiter != interface_map_.end()) {
    283     Interface* interface = iiter->second;
    284     interface->ObjectRemoved(object_path, interface_name);
    285   }
    286 
    287   object->properties_map.erase(piter);
    288 
    289   if (object->properties_map.empty()) {
    290     object_map_.erase(oiter);
    291     delete object;
    292   }
    293 }
    294 
    295 }  // namespace dbus
    296