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