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