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   object_proxy_->SetNameOwnerChangedCallback(
     36       base::Bind(&ObjectManager::NameOwnerChanged,
     37                  weak_ptr_factory_.GetWeakPtr()));
     38 
     39   object_proxy_->ConnectToSignal(
     40       kObjectManagerInterface,
     41       kObjectManagerInterfacesAdded,
     42       base::Bind(&ObjectManager::InterfacesAddedReceived,
     43                  weak_ptr_factory_.GetWeakPtr()),
     44       base::Bind(&ObjectManager::InterfacesAddedConnected,
     45                  weak_ptr_factory_.GetWeakPtr()));
     46 
     47   object_proxy_->ConnectToSignal(
     48       kObjectManagerInterface,
     49       kObjectManagerInterfacesRemoved,
     50       base::Bind(&ObjectManager::InterfacesRemovedReceived,
     51                  weak_ptr_factory_.GetWeakPtr()),
     52       base::Bind(&ObjectManager::InterfacesRemovedConnected,
     53                  weak_ptr_factory_.GetWeakPtr()));
     54 
     55   GetManagedObjects();
     56 }
     57 
     58 ObjectManager::~ObjectManager() {
     59   // Clean up Object structures
     60   for (ObjectMap::iterator iter = object_map_.begin();
     61        iter != object_map_.end(); ++iter) {
     62     Object* object = iter->second;
     63 
     64     for (Object::PropertiesMap::iterator piter = object->properties_map.begin();
     65          piter != object->properties_map.end(); ++piter) {
     66       PropertySet* properties = piter->second;
     67       delete properties;
     68     }
     69 
     70     delete object;
     71   }
     72 }
     73 
     74 void ObjectManager::RegisterInterface(const std::string& interface_name,
     75                                       Interface* interface) {
     76   interface_map_[interface_name] = interface;
     77 }
     78 
     79 void ObjectManager::UnregisterInterface(const std::string& interface_name) {
     80   InterfaceMap::iterator iter = interface_map_.find(interface_name);
     81   if (iter != interface_map_.end())
     82     interface_map_.erase(iter);
     83 }
     84 
     85 std::vector<ObjectPath> ObjectManager::GetObjects() {
     86   std::vector<ObjectPath> object_paths;
     87 
     88   for (ObjectMap::iterator iter = object_map_.begin();
     89        iter != object_map_.end(); ++iter)
     90     object_paths.push_back(iter->first);
     91 
     92   return object_paths;
     93 }
     94 
     95 std::vector<ObjectPath> ObjectManager::GetObjectsWithInterface(
     96       const std::string& interface_name) {
     97   std::vector<ObjectPath> object_paths;
     98 
     99   for (ObjectMap::iterator oiter = object_map_.begin();
    100        oiter != object_map_.end(); ++oiter) {
    101     Object* object = oiter->second;
    102 
    103     Object::PropertiesMap::iterator piter =
    104         object->properties_map.find(interface_name);
    105     if (piter != object->properties_map.end())
    106       object_paths.push_back(oiter->first);
    107   }
    108 
    109   return object_paths;
    110 }
    111 
    112 ObjectProxy* ObjectManager::GetObjectProxy(const ObjectPath& object_path) {
    113   ObjectMap::iterator iter = object_map_.find(object_path);
    114   if (iter == object_map_.end())
    115     return NULL;
    116 
    117   Object* object = iter->second;
    118   return object->object_proxy;
    119 }
    120 
    121 PropertySet* ObjectManager::GetProperties(const ObjectPath& object_path,
    122                                           const std::string& interface_name) {
    123   ObjectMap::iterator iter = object_map_.find(object_path);
    124   if (iter == object_map_.end())
    125     return NULL;
    126 
    127   Object* object = iter->second;
    128   Object::PropertiesMap::iterator piter =
    129       object->properties_map.find(interface_name);
    130   if (piter == object->properties_map.end())
    131     return NULL;
    132 
    133   return piter->second;
    134 }
    135 
    136 void ObjectManager::GetManagedObjects() {
    137   MethodCall method_call(kObjectManagerInterface,
    138                          kObjectManagerGetManagedObjects);
    139 
    140   object_proxy_->CallMethod(
    141       &method_call,
    142       ObjectProxy::TIMEOUT_USE_DEFAULT,
    143       base::Bind(&ObjectManager::OnGetManagedObjects,
    144                  weak_ptr_factory_.GetWeakPtr()));
    145 }
    146 
    147 void ObjectManager::OnGetManagedObjects(Response* response) {
    148   if (response != NULL) {
    149     MessageReader reader(response);
    150     MessageReader array_reader(NULL);
    151     if (!reader.PopArray(&array_reader))
    152       return;
    153 
    154     while (array_reader.HasMoreData()) {
    155       MessageReader dict_entry_reader(NULL);
    156       ObjectPath object_path;
    157       if (!array_reader.PopDictEntry(&dict_entry_reader) ||
    158           !dict_entry_reader.PopObjectPath(&object_path))
    159         continue;
    160 
    161       UpdateObject(object_path, &dict_entry_reader);
    162     }
    163 
    164   } else {
    165     LOG(WARNING) << service_name_ << " " << object_path_.value()
    166                  << ": Failed to get managed objects";
    167   }
    168 }
    169 
    170 void ObjectManager::InterfacesAddedReceived(Signal* signal) {
    171   DCHECK(signal);
    172   MessageReader reader(signal);
    173   ObjectPath object_path;
    174   if (!reader.PopObjectPath(&object_path)) {
    175     LOG(WARNING) << service_name_ << " " << object_path_.value()
    176                  << ": InterfacesAdded signal has incorrect parameters: "
    177                  << signal->ToString();
    178     return;
    179   }
    180 
    181   UpdateObject(object_path, &reader);
    182 }
    183 
    184 void ObjectManager::InterfacesAddedConnected(const std::string& interface_name,
    185                                              const std::string& signal_name,
    186                                              bool success) {
    187   LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
    188                             << ": Failed to connect to InterfacesAdded signal.";
    189 }
    190 
    191 void ObjectManager::InterfacesRemovedReceived(Signal* signal) {
    192   DCHECK(signal);
    193   MessageReader reader(signal);
    194   ObjectPath object_path;
    195   std::vector<std::string> interface_names;
    196   if (!reader.PopObjectPath(&object_path) ||
    197       !reader.PopArrayOfStrings(&interface_names)) {
    198     LOG(WARNING) << service_name_ << " " << object_path_.value()
    199                  << ": InterfacesRemoved signal has incorrect parameters: "
    200                  << signal->ToString();
    201     return;
    202   }
    203 
    204   for (size_t i = 0; i < interface_names.size(); ++i)
    205     RemoveInterface(object_path, interface_names[i]);
    206 }
    207 
    208 void ObjectManager::InterfacesRemovedConnected(
    209     const std::string& interface_name,
    210     const std::string& signal_name,
    211     bool success) {
    212   LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
    213                             << ": Failed to connect to "
    214                             << "InterfacesRemoved signal.";
    215 }
    216 
    217 void ObjectManager::UpdateObject(const ObjectPath& object_path,
    218                                  MessageReader* reader) {
    219   DCHECK(reader);
    220   MessageReader array_reader(NULL);
    221   if (!reader->PopArray(&array_reader))
    222     return;
    223 
    224   while (array_reader.HasMoreData()) {
    225     MessageReader dict_entry_reader(NULL);
    226     std::string interface_name;
    227     if (!array_reader.PopDictEntry(&dict_entry_reader) ||
    228         !dict_entry_reader.PopString(&interface_name))
    229       continue;
    230 
    231     AddInterface(object_path, interface_name, &dict_entry_reader);
    232   }
    233 }
    234 
    235 
    236 void ObjectManager::AddInterface(const ObjectPath& object_path,
    237                                  const std::string& interface_name,
    238                                  MessageReader* reader) {
    239   InterfaceMap::iterator iiter = interface_map_.find(interface_name);
    240   if (iiter == interface_map_.end())
    241     return;
    242   Interface* interface = iiter->second;
    243 
    244   ObjectMap::iterator oiter = object_map_.find(object_path);
    245   Object* object;
    246   if (oiter == object_map_.end()) {
    247     object = object_map_[object_path] = new Object;
    248     object->object_proxy = bus_->GetObjectProxy(service_name_, object_path);
    249   } else
    250     object = oiter->second;
    251 
    252   Object::PropertiesMap::iterator piter =
    253       object->properties_map.find(interface_name);
    254   PropertySet* property_set;
    255   const bool interface_added = (piter == object->properties_map.end());
    256   if (interface_added) {
    257     property_set = object->properties_map[interface_name] =
    258         interface->CreateProperties(object->object_proxy,
    259                                     object_path, interface_name);
    260     property_set->ConnectSignals();
    261   } else
    262     property_set = piter->second;
    263 
    264   property_set->UpdatePropertiesFromReader(reader);
    265 
    266   if (interface_added)
    267     interface->ObjectAdded(object_path, interface_name);
    268 }
    269 
    270 void ObjectManager::RemoveInterface(const ObjectPath& object_path,
    271                                     const std::string& interface_name) {
    272   ObjectMap::iterator oiter = object_map_.find(object_path);
    273   if (oiter == object_map_.end())
    274     return;
    275   Object* object = oiter->second;
    276 
    277   Object::PropertiesMap::iterator piter =
    278       object->properties_map.find(interface_name);
    279   if (piter == object->properties_map.end())
    280     return;
    281 
    282   // Inform the interface before removing the properties structure or object
    283   // in case it needs details from them to make its own decisions.
    284   InterfaceMap::iterator iiter = interface_map_.find(interface_name);
    285   if (iiter != interface_map_.end()) {
    286     Interface* interface = iiter->second;
    287     interface->ObjectRemoved(object_path, interface_name);
    288   }
    289 
    290   object->properties_map.erase(piter);
    291 
    292   if (object->properties_map.empty()) {
    293     object_map_.erase(oiter);
    294     delete object;
    295   }
    296 }
    297 
    298 void ObjectManager::NameOwnerChanged(const std::string& old_owner,
    299                                      const std::string& new_owner) {
    300   if (!old_owner.empty()) {
    301     ObjectMap::iterator iter = object_map_.begin();
    302     while (iter != object_map_.end()) {
    303       ObjectMap::iterator tmp = iter;
    304       ++iter;
    305 
    306       // PropertiesMap is mutated by RemoveInterface, and also Object is
    307       // destroyed; easier to collect the object path and interface names
    308       // and remove them safely.
    309       const dbus::ObjectPath object_path = tmp->first;
    310       Object* object = tmp->second;
    311       std::vector<std::string> interfaces;
    312 
    313       for (Object::PropertiesMap::iterator piter =
    314               object->properties_map.begin();
    315            piter != object->properties_map.end(); ++piter)
    316         interfaces.push_back(piter->first);
    317 
    318       for (std::vector<std::string>::iterator iiter = interfaces.begin();
    319            iiter != interfaces.end(); ++iiter)
    320         RemoveInterface(object_path, *iiter);
    321     }
    322 
    323   }
    324 
    325   if (!new_owner.empty())
    326     GetManagedObjects();
    327 }
    328 
    329 }  // namespace dbus
    330