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_record_client.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/macros.h" | |
9 #include "base/memory/weak_ptr.h" | |
10 #include "base/observer_list.h" | |
11 #include "chromeos/dbus/nfc_device_client.h" | |
12 #include "chromeos/dbus/nfc_tag_client.h" | |
13 #include "dbus/bus.h" | |
14 #include "third_party/cros_system_api/dbus/service_constants.h" | |
15 | |
16 using chromeos::nfc_client_helpers::DBusObjectMap; | |
17 using chromeos::nfc_client_helpers::ObjectProxyTree; | |
18 | |
19 namespace chromeos { | |
20 | |
21 NfcRecordClient::Properties::Properties( | |
22 dbus::ObjectProxy* object_proxy, | |
23 const PropertyChangedCallback& callback) | |
24 : NfcPropertySet(object_proxy, | |
25 nfc_record::kNfcRecordInterface, | |
26 callback) { | |
27 RegisterProperty(nfc_record::kTypeProperty, &type); | |
28 RegisterProperty(nfc_record::kLanguageProperty, &language); | |
29 RegisterProperty(nfc_record::kEncodingProperty, &encoding); | |
30 RegisterProperty(nfc_record::kRepresentationProperty, &representation); | |
31 RegisterProperty(nfc_record::kUriProperty, &uri); | |
32 RegisterProperty(nfc_record::kMimeTypeProperty, &mime_type); | |
33 RegisterProperty(nfc_record::kSizeProperty, &size); | |
34 RegisterProperty(nfc_record::kActionProperty, &action); | |
35 } | |
36 | |
37 NfcRecordClient::Properties::~Properties() { | |
38 } | |
39 | |
40 // The NfcRecordClient implementation used in production. | |
41 class NfcRecordClientImpl : public NfcRecordClient, | |
42 public NfcDeviceClient::Observer, | |
43 public NfcTagClient::Observer, | |
44 public DBusObjectMap::Delegate { | |
45 public: | |
46 explicit NfcRecordClientImpl(NfcDeviceClient* device_client, | |
47 NfcTagClient* tag_client) | |
48 : bus_(NULL), | |
49 device_client_(device_client), | |
50 tag_client_(tag_client), | |
51 weak_ptr_factory_(this) { | |
52 DCHECK(device_client); | |
53 DCHECK(tag_client); | |
54 } | |
55 | |
56 ~NfcRecordClientImpl() override { | |
57 DCHECK(device_client_); | |
58 DCHECK(tag_client_); | |
59 device_client_->RemoveObserver(this); | |
60 tag_client_->RemoveObserver(this); | |
61 } | |
62 | |
63 // NfcRecordClient override. | |
64 void AddObserver(NfcRecordClient::Observer* observer) override { | |
65 DCHECK(observer); | |
66 observers_.AddObserver(observer); | |
67 } | |
68 | |
69 // NfcRecordClient override. | |
70 void RemoveObserver(NfcRecordClient::Observer* observer) override { | |
71 DCHECK(observer); | |
72 observers_.RemoveObserver(observer); | |
73 } | |
74 | |
75 std::vector<dbus::ObjectPath> GetRecordsForDevice( | |
76 const dbus::ObjectPath& device_path) override { | |
77 DBusObjectMap* object_map = | |
78 devices_and_tags_to_object_maps_.GetObjectMap(device_path); | |
79 if (!object_map) | |
80 return std::vector<dbus::ObjectPath>(); | |
81 return object_map->GetObjectPaths(); | |
82 } | |
83 | |
84 std::vector<dbus::ObjectPath> GetRecordsForTag( | |
85 const dbus::ObjectPath& tag_path) override { | |
86 return GetRecordsForDevice(tag_path); | |
87 } | |
88 | |
89 // NfcRecordClient override. | |
90 Properties* GetProperties(const dbus::ObjectPath& object_path) override { | |
91 return static_cast<Properties*>( | |
92 devices_and_tags_to_object_maps_.FindObjectProperties(object_path)); | |
93 } | |
94 | |
95 protected: | |
96 // DBusClient override. | |
97 void Init(dbus::Bus* bus) override { | |
98 VLOG(1) << "Creating NfcRecordClient impl"; | |
99 DCHECK(bus); | |
100 bus_ = bus; | |
101 DCHECK(device_client_); | |
102 DCHECK(tag_client_); | |
103 device_client_->AddObserver(this); | |
104 tag_client_->AddObserver(this); | |
105 } | |
106 | |
107 private: | |
108 // NfcDeviceClient::Observer override. | |
109 void DeviceAdded(const dbus::ObjectPath& object_path) override { | |
110 VLOG(1) << "Device added. Creating map for record proxies belonging to " | |
111 << "device: " << object_path.value(); | |
112 devices_and_tags_to_object_maps_.CreateObjectMap( | |
113 object_path, nfc_record::kNfcRecordServiceName, this, bus_); | |
114 } | |
115 | |
116 // NfcDeviceClient::Observer override. | |
117 void DeviceRemoved(const dbus::ObjectPath& object_path) override { | |
118 // Neard doesn't send out property changed signals for the records that | |
119 // are removed when the device they belong to is removed. Clean up the | |
120 // object proxies for records that belong to the removed device. | |
121 // Note: DBusObjectMap guarantees that the Properties structure for the | |
122 // removed adapter will be valid before this method returns. | |
123 VLOG(1) << "Device removed. Cleaning up record proxies belonging to " | |
124 << "device: " << object_path.value(); | |
125 devices_and_tags_to_object_maps_.RemoveObjectMap(object_path); | |
126 } | |
127 | |
128 // NfcDeviceClient::Observer override. | |
129 void DevicePropertyChanged(const dbus::ObjectPath& object_path, | |
130 const std::string& property_name) override { | |
131 // Update the record proxies using records from the device. | |
132 DCHECK(device_client_); | |
133 NfcDeviceClient::Properties* device_properties = | |
134 device_client_->GetProperties(object_path); | |
135 | |
136 // Ignore changes to properties other than "Records". | |
137 if (property_name != device_properties->records.name()) | |
138 return; | |
139 | |
140 // Update known records. | |
141 VLOG(1) << "NFC records changed."; | |
142 const std::vector<dbus::ObjectPath>& received_records = | |
143 device_properties->records.value(); | |
144 DBusObjectMap* object_map = | |
145 devices_and_tags_to_object_maps_.GetObjectMap(object_path); | |
146 DCHECK(object_map); | |
147 object_map->UpdateObjects(received_records); | |
148 } | |
149 | |
150 // NfcTagClient::Observer override. | |
151 void TagAdded(const dbus::ObjectPath& object_path) override { | |
152 VLOG(1) << "Tag added. Creating map for record proxies belonging to " | |
153 << "tag: " << object_path.value(); | |
154 devices_and_tags_to_object_maps_.CreateObjectMap( | |
155 object_path, nfc_record::kNfcRecordServiceName, this, bus_); | |
156 } | |
157 | |
158 // NfcTagClient::Observer override. | |
159 void TagRemoved(const dbus::ObjectPath& object_path) override { | |
160 // Neard doesn't send out property changed signals for the records that | |
161 // are removed when the tag they belong to is removed. Clean up the | |
162 // object proxies for records that belong to the removed tag. | |
163 // Note: DBusObjectMap guarantees that the Properties structure for the | |
164 // removed adapter will be valid before this method returns. | |
165 VLOG(1) << "Tag removed. Cleaning up record proxies belonging to " | |
166 << "tag: " << object_path.value(); | |
167 devices_and_tags_to_object_maps_.RemoveObjectMap(object_path); | |
168 } | |
169 | |
170 // NfcTagClient::Observer override. | |
171 void TagPropertyChanged(const dbus::ObjectPath& object_path, | |
172 const std::string& property_name) override { | |
173 // Update the record proxies using records from the tag. | |
174 DCHECK(device_client_); | |
175 NfcTagClient::Properties* tag_properties = | |
176 tag_client_->GetProperties(object_path); | |
177 | |
178 // Ignore changes to properties other than "Records". | |
179 if (property_name != tag_properties->records.name()) | |
180 return; | |
181 | |
182 // Update known records. | |
183 VLOG(1) << "NFC records changed."; | |
184 const std::vector<dbus::ObjectPath>& received_records = | |
185 tag_properties->records.value(); | |
186 DBusObjectMap* object_map = | |
187 devices_and_tags_to_object_maps_.GetObjectMap(object_path); | |
188 DCHECK(object_map); | |
189 object_map->UpdateObjects(received_records); | |
190 | |
191 // When rewriting the record to a tag, neard fires a property changed | |
192 // signal for the tags "Records" property, without creating a new object | |
193 // path. Sync the properties of all records here, in case Update objects | |
194 // doesn't do it. | |
195 VLOG(1) << "Fetch properties for all records."; | |
196 object_map->RefreshAllProperties(); | |
197 } | |
198 | |
199 // nfc_client_helpers::DBusObjectMap::Delegate override. | |
200 NfcPropertySet* CreateProperties(dbus::ObjectProxy* object_proxy) override { | |
201 Properties* properties = new Properties( | |
202 object_proxy, | |
203 base::Bind(&NfcRecordClientImpl::OnPropertyChanged, | |
204 weak_ptr_factory_.GetWeakPtr(), | |
205 object_proxy->object_path())); | |
206 properties->SetAllPropertiesReceivedCallback( | |
207 base::Bind(&NfcRecordClientImpl::OnPropertiesReceived, | |
208 weak_ptr_factory_.GetWeakPtr(), | |
209 object_proxy->object_path())); | |
210 return properties; | |
211 } | |
212 | |
213 // nfc_client_helpers::DBusObjectMap::Delegate override. | |
214 void ObjectAdded(const dbus::ObjectPath& object_path) override { | |
215 FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, | |
216 RecordAdded(object_path)); | |
217 } | |
218 | |
219 // nfc_client_helpers::DBusObjectMap::Delegate override. | |
220 void ObjectRemoved(const dbus::ObjectPath& object_path) override { | |
221 FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, | |
222 RecordRemoved(object_path)); | |
223 } | |
224 | |
225 // Called by NfcPropertySet when a property value is changed, either by | |
226 // result of a signal or response to a GetAll() or Get() call. | |
227 void OnPropertyChanged(const dbus::ObjectPath& object_path, | |
228 const std::string& property_name) { | |
229 VLOG(1) << "Record property changed; Path: " << object_path.value() | |
230 << " Property: " << property_name; | |
231 FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, | |
232 RecordPropertyChanged(object_path, property_name)); | |
233 } | |
234 | |
235 // Called by NfcPropertySet when all properties have been processed as a | |
236 // result of a call to GetAll. | |
237 void OnPropertiesReceived(const dbus::ObjectPath& object_path) { | |
238 VLOG(1) << "All record properties received; Path: " << object_path.value(); | |
239 FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, | |
240 RecordPropertiesReceived(object_path)); | |
241 } | |
242 | |
243 // We maintain a pointer to the bus to be able to request proxies for | |
244 // new NFC records that appear. | |
245 dbus::Bus* bus_; | |
246 | |
247 // List of observers interested in event notifications. | |
248 base::ObserverList<NfcRecordClient::Observer> observers_; | |
249 | |
250 // Mapping from object paths to object proxies and properties structures that | |
251 // were already created by us. Record objects belong to either Tag or Device | |
252 // objects. This structure stores a different DBusObjectMap for each known | |
253 // device and tag. | |
254 ObjectProxyTree devices_and_tags_to_object_maps_; | |
255 | |
256 // The device and tag clients that we listen to events notifications from. | |
257 NfcDeviceClient* device_client_; | |
258 NfcTagClient* tag_client_; | |
259 // Weak pointer factory for generating 'this' pointers that might live longer | |
260 // than we do. | |
261 // Note: This should remain the last member so it'll be destroyed and | |
262 // invalidate its weak pointers before any other members are destroyed. | |
263 base::WeakPtrFactory<NfcRecordClientImpl> weak_ptr_factory_; | |
264 | |
265 DISALLOW_COPY_AND_ASSIGN(NfcRecordClientImpl); | |
266 }; | |
267 | |
268 NfcRecordClient::NfcRecordClient() { | |
269 } | |
270 | |
271 NfcRecordClient::~NfcRecordClient() { | |
272 } | |
273 | |
274 NfcRecordClient* NfcRecordClient::Create(NfcDeviceClient* device_client, | |
275 NfcTagClient* tag_client) { | |
276 return new NfcRecordClientImpl(device_client, tag_client); | |
277 } | |
278 | |
279 } // namespace chromeos | |
OLD | NEW |