• 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 
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 
~ObjectManager()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 
RegisterInterface(const std::string & interface_name,Interface * interface)71 void ObjectManager::RegisterInterface(const std::string& interface_name,
72                                       Interface* interface) {
73   interface_map_[interface_name] = interface;
74 }
75 
UnregisterInterface(const std::string & interface_name)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 
GetObjects()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 
GetObjectsWithInterface(const std::string & interface_name)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 
GetObjectProxy(const ObjectPath & object_path)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 
GetProperties(const ObjectPath & object_path,const std::string & interface_name)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 
GetManagedObjects()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 
OnGetManagedObjects(Response * response)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 
InterfacesAddedReceived(Signal * signal)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 
InterfacesAddedConnected(const std::string & interface_name,const std::string & signal_name,bool success)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 
InterfacesRemovedReceived(Signal * signal)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 
InterfacesRemovedConnected(const std::string & interface_name,const std::string & signal_name,bool success)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 
UpdateObject(const ObjectPath & object_path,MessageReader * reader)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 
AddInterface(const ObjectPath & object_path,const std::string & interface_name,MessageReader * reader)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 
RemoveInterface(const ObjectPath & object_path,const std::string & interface_name)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