OLD | NEW |
| (Empty) |
1 // Copyright 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 "chromeos/dbus/nfc_client_helpers.h" | |
6 | |
7 #include "base/stl_util.h" | |
8 #include "dbus/values_util.h" | |
9 | |
10 namespace chromeos { | |
11 namespace nfc_client_helpers { | |
12 | |
13 const char kNoResponseError[] = "org.chromium.Error.NoResponse"; | |
14 const char kUnknownObjectError[] = "org.chromium.Error.UnknownObject"; | |
15 | |
16 void OnSuccess(const base::Closure& callback, dbus::Response* response) { | |
17 DCHECK(response); | |
18 callback.Run(); | |
19 } | |
20 | |
21 void OnError(const ErrorCallback& error_callback, | |
22 dbus::ErrorResponse* response) { | |
23 // Error response has optional error message argument. | |
24 std::string error_name; | |
25 std::string error_message; | |
26 if (response) { | |
27 dbus::MessageReader reader(response); | |
28 error_name = response->GetErrorName(); | |
29 reader.PopString(&error_message); | |
30 } else { | |
31 error_name = kNoResponseError; | |
32 error_message = ""; | |
33 } | |
34 error_callback.Run(error_name, error_message); | |
35 } | |
36 | |
37 DBusObjectMap::DBusObjectMap(const std::string& service_name, | |
38 Delegate* delegate, | |
39 dbus::Bus* bus) | |
40 : bus_(bus), | |
41 service_name_(service_name), | |
42 delegate_(delegate) { | |
43 DCHECK(bus_); | |
44 DCHECK(delegate_); | |
45 } | |
46 | |
47 DBusObjectMap::~DBusObjectMap() { | |
48 // Clean up the Properties structures. We don't explicitly delete the object | |
49 // proxies, as they are owned by dbus::Bus. | |
50 for (ObjectMap::iterator iter = object_map_.begin(); | |
51 iter != object_map_.end(); ++iter) { | |
52 const dbus::ObjectPath& object_path = iter->first; | |
53 ObjectPropertyPair pair = iter->second; | |
54 delegate_->ObjectRemoved(object_path); | |
55 CleanUpObjectPropertyPair(pair); | |
56 } | |
57 } | |
58 | |
59 dbus::ObjectProxy* DBusObjectMap::GetObjectProxy( | |
60 const dbus::ObjectPath& object_path) { | |
61 return GetObjectPropertyPair(object_path).first; | |
62 } | |
63 | |
64 NfcPropertySet* DBusObjectMap::GetObjectProperties( | |
65 const dbus::ObjectPath& object_path) { | |
66 return GetObjectPropertyPair(object_path).second; | |
67 } | |
68 | |
69 void DBusObjectMap::UpdateObjects(const ObjectPathVector& object_paths) { | |
70 // This set is used to query if an object path was removed, while updating | |
71 // the removed paths below. The iterator is used as a hint to accelerate | |
72 // insertion. | |
73 std::set<dbus::ObjectPath> object_path_set; | |
74 std::set<dbus::ObjectPath>::iterator object_path_set_iter = | |
75 object_path_set.begin(); | |
76 | |
77 // Add all objects. | |
78 for (ObjectPathVector::const_iterator iter = object_paths.begin(); | |
79 iter != object_paths.end(); ++iter) { | |
80 const dbus::ObjectPath &object_path = *iter; | |
81 AddObject(object_path); | |
82 // Neard usually returns object paths in ascending order. Give a hint here | |
83 // to make insertion amortized constant. | |
84 object_path_set_iter = | |
85 object_path_set.insert(object_path_set_iter, object_path); | |
86 } | |
87 | |
88 // Remove all objects that are not in |object_paths|. | |
89 ObjectMap::const_iterator iter = object_map_.begin(); | |
90 while (iter != object_map_.end()) { | |
91 // It is safe to use a const reference here, as DBusObjectMap::RemoveObject | |
92 // won't access it after the iterator becomes invalidated. | |
93 const dbus::ObjectPath &object_path = iter->first; | |
94 ++iter; | |
95 if (!base::ContainsKey(object_path_set, object_path)) | |
96 RemoveObject(object_path); | |
97 } | |
98 } | |
99 | |
100 bool DBusObjectMap::AddObject(const dbus::ObjectPath& object_path) { | |
101 ObjectMap::iterator iter = object_map_.find(object_path); | |
102 if (iter != object_map_.end()) | |
103 return false; | |
104 | |
105 DCHECK(bus_); | |
106 DCHECK(delegate_); | |
107 dbus::ObjectProxy* object_proxy = bus_->GetObjectProxy(service_name_, | |
108 object_path); | |
109 | |
110 // Create the properties structure. | |
111 NfcPropertySet* properties = delegate_->CreateProperties(object_proxy); | |
112 properties->ConnectSignals(); | |
113 properties->GetAll(); | |
114 ObjectPropertyPair object = std::make_pair(object_proxy, properties); | |
115 object_map_[object_path] = object; | |
116 VLOG(1) << "Created proxy for object with Path: " << object_path.value() | |
117 << ", Service: " << service_name_; | |
118 delegate_->ObjectAdded(object_path); | |
119 return true; | |
120 } | |
121 | |
122 void DBusObjectMap::RemoveObject(const dbus::ObjectPath& object_path) { | |
123 DCHECK(bus_); | |
124 DCHECK(delegate_); | |
125 ObjectMap::iterator iter = object_map_.find(object_path); | |
126 if (iter == object_map_.end()) | |
127 return; | |
128 | |
129 // Notify the delegate, so that it can perform any clean up that is | |
130 // necessary. | |
131 delegate_->ObjectRemoved(object_path); | |
132 | |
133 // Clean up the object proxy and the properties structure. | |
134 ObjectPropertyPair pair = iter->second; | |
135 CleanUpObjectPropertyPair(pair); | |
136 object_map_.erase(iter); | |
137 VLOG(1) << "Object proxy removed for object path: " | |
138 << object_path.value(); | |
139 } | |
140 | |
141 void DBusObjectMap::RefreshProperties(const dbus::ObjectPath& object_path) { | |
142 NfcPropertySet* properties = GetObjectProperties(object_path); | |
143 if (properties) | |
144 properties->GetAll(); | |
145 } | |
146 | |
147 void DBusObjectMap::RefreshAllProperties() { | |
148 for (ObjectMap::const_iterator iter = object_map_.begin(); | |
149 iter != object_map_.end(); ++iter) { | |
150 const dbus::ObjectPath& object_path = iter->first; | |
151 RefreshProperties(object_path); | |
152 } | |
153 } | |
154 | |
155 ObjectPathVector DBusObjectMap::GetObjectPaths() { | |
156 std::vector<dbus::ObjectPath> object_paths; | |
157 for (ObjectMap::const_iterator iter = object_map_.begin(); | |
158 iter != object_map_.end(); ++iter) { | |
159 const dbus::ObjectPath& object_path = iter->first; | |
160 object_paths.push_back(object_path); | |
161 } | |
162 return object_paths; | |
163 } | |
164 | |
165 DBusObjectMap::ObjectPropertyPair DBusObjectMap::GetObjectPropertyPair( | |
166 const dbus::ObjectPath& object_path) { | |
167 ObjectMap::iterator iter = object_map_.find(object_path); | |
168 if (iter != object_map_.end()) | |
169 return iter->second; | |
170 return std::make_pair(static_cast<dbus::ObjectProxy*>(NULL), | |
171 static_cast<NfcPropertySet*>(NULL)); | |
172 } | |
173 | |
174 void DBusObjectMap::CleanUpObjectPropertyPair(const ObjectPropertyPair& pair) { | |
175 // Don't remove the object proxy. There is a bug in dbus::Bus that causes a | |
176 // crash when object proxies are removed, due to the proxy objects not being | |
177 // properly reference counted. (See crbug.com/170182 and crbug.com/328264). | |
178 NfcPropertySet* properties = pair.second; | |
179 delete properties; | |
180 } | |
181 | |
182 ObjectProxyTree::ObjectProxyTree() { | |
183 } | |
184 | |
185 ObjectProxyTree::~ObjectProxyTree() { | |
186 for (PathsToObjectMapsType::iterator iter = paths_to_object_maps_.begin(); | |
187 iter != paths_to_object_maps_.end(); ++iter) { | |
188 DBusObjectMap* object_map = iter->second; | |
189 delete object_map; | |
190 } | |
191 } | |
192 | |
193 bool ObjectProxyTree::CreateObjectMap(const dbus::ObjectPath& object_path, | |
194 const std::string& service_name, | |
195 DBusObjectMap::Delegate* delegate, | |
196 dbus::Bus* bus) { | |
197 if (base::ContainsKey(paths_to_object_maps_, object_path)) { | |
198 LOG(ERROR) << "Mapping already exists for object path: " | |
199 << object_path.value(); | |
200 return false; | |
201 } | |
202 paths_to_object_maps_[object_path] = | |
203 new DBusObjectMap(service_name, delegate, bus); | |
204 return true; | |
205 } | |
206 | |
207 void ObjectProxyTree::RemoveObjectMap(const dbus::ObjectPath& object_path) { | |
208 PathsToObjectMapsType::iterator iter = | |
209 paths_to_object_maps_.find(object_path); | |
210 if (iter == paths_to_object_maps_.end()) | |
211 return; | |
212 DBusObjectMap* object_map = iter->second; | |
213 paths_to_object_maps_.erase(iter); | |
214 delete object_map; | |
215 } | |
216 | |
217 DBusObjectMap* ObjectProxyTree::GetObjectMap( | |
218 const dbus::ObjectPath& object_path) { | |
219 PathsToObjectMapsType::iterator iter = | |
220 paths_to_object_maps_.find(object_path); | |
221 if (iter == paths_to_object_maps_.end()) | |
222 return NULL; | |
223 return iter->second; | |
224 } | |
225 | |
226 dbus::ObjectProxy* ObjectProxyTree::FindObjectProxy( | |
227 const dbus::ObjectPath& object_proxy_path) { | |
228 for (PathsToObjectMapsType::iterator iter = paths_to_object_maps_.begin(); | |
229 iter != paths_to_object_maps_.end(); ++iter) { | |
230 DBusObjectMap* object_map = iter->second; | |
231 dbus::ObjectProxy* object_proxy = | |
232 object_map->GetObjectProxy(object_proxy_path); | |
233 if (object_proxy) | |
234 return object_proxy; | |
235 } | |
236 return NULL; | |
237 } | |
238 | |
239 NfcPropertySet* ObjectProxyTree::FindObjectProperties( | |
240 const dbus::ObjectPath& object_proxy_path) { | |
241 for (PathsToObjectMapsType::iterator iter = paths_to_object_maps_.begin(); | |
242 iter != paths_to_object_maps_.end(); ++iter) { | |
243 DBusObjectMap* object_map = iter->second; | |
244 NfcPropertySet* properties = | |
245 object_map->GetObjectProperties(object_proxy_path); | |
246 if (properties) | |
247 return properties; | |
248 } | |
249 return NULL; | |
250 } | |
251 | |
252 } // namespace nfc_client_helpers | |
253 } // namespace chromeos | |
OLD | NEW |