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 virtual ~NfcRecordClientImpl() {
56 DCHECK(device_client_
);
58 device_client_
->RemoveObserver(this);
59 tag_client_
->RemoveObserver(this);
62 // NfcRecordClient override.
63 virtual void AddObserver(NfcRecordClient::Observer
* observer
) OVERRIDE
{
65 observers_
.AddObserver(observer
);
68 // NfcRecordClient override.
69 virtual void RemoveObserver(NfcRecordClient::Observer
* observer
) OVERRIDE
{
71 observers_
.RemoveObserver(observer
);
74 virtual 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 virtual std::vector
<dbus::ObjectPath
> GetRecordsForTag(
84 const dbus::ObjectPath
& tag_path
) OVERRIDE
{
85 return GetRecordsForDevice(tag_path
);
88 // NfcRecordClient override.
89 virtual Properties
* GetProperties(
90 const dbus::ObjectPath
& object_path
) OVERRIDE
{
91 return static_cast<Properties
*>(
92 devices_and_tags_to_object_maps_
.FindObjectProperties(object_path
));
96 // DBusClient override.
97 virtual void Init(dbus::Bus
* bus
) OVERRIDE
{
98 VLOG(1) << "Creating NfcRecordClient impl";
101 DCHECK(device_client_
);
103 device_client_
->AddObserver(this);
104 tag_client_
->AddObserver(this);
108 // NfcDeviceClient::Observer override.
109 virtual 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_
);
116 // NfcDeviceClient::Observer override.
117 virtual 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
);
128 // NfcDeviceClient::Observer override.
129 virtual void DevicePropertyChanged(
130 const dbus::ObjectPath
& object_path
,
131 const std::string
& property_name
) OVERRIDE
{
132 // Update the record proxies using records from the device.
133 DCHECK(device_client_
);
134 NfcDeviceClient::Properties
* device_properties
=
135 device_client_
->GetProperties(object_path
);
137 // Ignore changes to properties other than "Records".
138 if (property_name
!= device_properties
->records
.name())
141 // Update known records.
142 VLOG(1) << "NFC records changed.";
143 const std::vector
<dbus::ObjectPath
>& received_records
=
144 device_properties
->records
.value();
145 DBusObjectMap
* object_map
=
146 devices_and_tags_to_object_maps_
.GetObjectMap(object_path
);
148 object_map
->UpdateObjects(received_records
);
151 // NfcTagClient::Observer override.
152 virtual void TagAdded(const dbus::ObjectPath
& object_path
) OVERRIDE
{
153 VLOG(1) << "Tag added. Creating map for record proxies belonging to "
154 << "tag: " << object_path
.value();
155 devices_and_tags_to_object_maps_
.CreateObjectMap(
156 object_path
, nfc_record::kNfcRecordServiceName
, this, bus_
);
159 // NfcTagClient::Observer override.
160 virtual void TagRemoved(const dbus::ObjectPath
& object_path
) OVERRIDE
{
161 // Neard doesn't send out property changed signals for the records that
162 // are removed when the tag they belong to is removed. Clean up the
163 // object proxies for records that belong to the removed tag.
164 // Note: DBusObjectMap guarantees that the Properties structure for the
165 // removed adapter will be valid before this method returns.
166 VLOG(1) << "Tag removed. Cleaning up record proxies belonging to "
167 << "tag: " << object_path
.value();
168 devices_and_tags_to_object_maps_
.RemoveObjectMap(object_path
);
171 // NfcTagClient::Observer override.
172 virtual void TagPropertyChanged(const dbus::ObjectPath
& object_path
,
173 const std::string
& property_name
) OVERRIDE
{
174 // Update the record proxies using records from the tag.
175 DCHECK(device_client_
);
176 NfcTagClient::Properties
* tag_properties
=
177 tag_client_
->GetProperties(object_path
);
179 // Ignore changes to properties other than "Records".
180 if (property_name
!= tag_properties
->records
.name())
183 // Update known records.
184 VLOG(1) << "NFC records changed.";
185 const std::vector
<dbus::ObjectPath
>& received_records
=
186 tag_properties
->records
.value();
187 DBusObjectMap
* object_map
=
188 devices_and_tags_to_object_maps_
.GetObjectMap(object_path
);
190 object_map
->UpdateObjects(received_records
);
192 // When rewriting the record to a tag, neard fires a property changed
193 // signal for the tags "Records" property, without creating a new object
194 // path. Sync the properties of all records here, in case Update objects
196 VLOG(1) << "Fetch properties for all records.";
197 object_map
->RefreshAllProperties();
200 // nfc_client_helpers::DBusObjectMap::Delegate override.
201 virtual NfcPropertySet
* CreateProperties(
202 dbus::ObjectProxy
* object_proxy
) OVERRIDE
{
203 Properties
* properties
= new Properties(
205 base::Bind(&NfcRecordClientImpl::OnPropertyChanged
,
206 weak_ptr_factory_
.GetWeakPtr(),
207 object_proxy
->object_path()));
208 properties
->SetAllPropertiesReceivedCallback(
209 base::Bind(&NfcRecordClientImpl::OnPropertiesReceived
,
210 weak_ptr_factory_
.GetWeakPtr(),
211 object_proxy
->object_path()));
215 // nfc_client_helpers::DBusObjectMap::Delegate override.
216 virtual void ObjectAdded(const dbus::ObjectPath
& object_path
) OVERRIDE
{
217 FOR_EACH_OBSERVER(NfcRecordClient::Observer
, observers_
,
218 RecordAdded(object_path
));
221 // nfc_client_helpers::DBusObjectMap::Delegate override.
222 virtual void ObjectRemoved(const dbus::ObjectPath
& object_path
) OVERRIDE
{
223 FOR_EACH_OBSERVER(NfcRecordClient::Observer
, observers_
,
224 RecordRemoved(object_path
));
227 // Called by NfcPropertySet when a property value is changed, either by
228 // result of a signal or response to a GetAll() or Get() call.
229 void OnPropertyChanged(const dbus::ObjectPath
& object_path
,
230 const std::string
& property_name
) {
231 VLOG(1) << "Record property changed; Path: " << object_path
.value()
232 << " Property: " << property_name
;
233 FOR_EACH_OBSERVER(NfcRecordClient::Observer
, observers_
,
234 RecordPropertyChanged(object_path
, property_name
));
237 // Called by NfcPropertySet when all properties have been processed as a
238 // result of a call to GetAll.
239 void OnPropertiesReceived(const dbus::ObjectPath
& object_path
) {
240 VLOG(1) << "All record properties received; Path: " << object_path
.value();
241 FOR_EACH_OBSERVER(NfcRecordClient::Observer
, observers_
,
242 RecordPropertiesReceived(object_path
));
245 // We maintain a pointer to the bus to be able to request proxies for
246 // new NFC records that appear.
249 // List of observers interested in event notifications.
250 ObserverList
<NfcRecordClient::Observer
> observers_
;
252 // Mapping from object paths to object proxies and properties structures that
253 // were already created by us. Record objects belong to either Tag or Device
254 // objects. This structure stores a different DBusObjectMap for each known
256 ObjectProxyTree devices_and_tags_to_object_maps_
;
258 // The device and tag clients that we listen to events notifications from.
259 NfcDeviceClient
* device_client_
;
260 NfcTagClient
* tag_client_
;
261 // Weak pointer factory for generating 'this' pointers that might live longer
263 // Note: This should remain the last member so it'll be destroyed and
264 // invalidate its weak pointers before any other members are destroyed.
265 base::WeakPtrFactory
<NfcRecordClientImpl
> weak_ptr_factory_
;
267 DISALLOW_COPY_AND_ASSIGN(NfcRecordClientImpl
);
270 NfcRecordClient::NfcRecordClient() {
273 NfcRecordClient::~NfcRecordClient() {
276 NfcRecordClient
* NfcRecordClient::Create(NfcDeviceClient
* device_client
,
277 NfcTagClient
* tag_client
) {
278 return new NfcRecordClientImpl(device_client
, tag_client
);
281 } // namespace chromeos