• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Object()16 ObjectManager::Object::Object()
17   : object_proxy(NULL) {
18 }
19 
~Object()20 ObjectManager::Object::~Object() {
21 }
22 
ObjectManager(Bus * bus,const std::string & service_name,const ObjectPath & object_path)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 
~ObjectManager()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 
RegisterInterface(const std::string & interface_name,Interface * interface)74 void ObjectManager::RegisterInterface(const std::string& interface_name,
75                                       Interface* interface) {
76   interface_map_[interface_name] = interface;
77 }
78 
UnregisterInterface(const std::string & interface_name)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 
GetObjects()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 
GetObjectsWithInterface(const std::string & interface_name)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 
GetObjectProxy(const ObjectPath & object_path)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 
GetProperties(const ObjectPath & object_path,const std::string & interface_name)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 
GetManagedObjects()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 
OnGetManagedObjects(Response * response)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 
InterfacesAddedReceived(Signal * signal)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 
InterfacesAddedConnected(const std::string & interface_name,const std::string & signal_name,bool success)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 
InterfacesRemovedReceived(Signal * signal)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 
InterfacesRemovedConnected(const std::string & interface_name,const std::string & signal_name,bool success)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 
UpdateObject(const ObjectPath & object_path,MessageReader * reader)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 
AddInterface(const ObjectPath & object_path,const std::string & interface_name,MessageReader * reader)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 
RemoveInterface(const ObjectPath & object_path,const std::string & interface_name)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 
NameOwnerChanged(const std::string & old_owner,const std::string & new_owner)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