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