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_tag_client.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/observer_list.h"
10 #include "base/strings/stringprintf.h"
11 #include "chromeos/dbus/nfc_adapter_client.h"
13 #include "dbus/message.h"
14 #include "dbus/values_util.h"
15 #include "third_party/cros_system_api/dbus/service_constants.h"
17 using chromeos::nfc_client_helpers::DBusObjectMap
;
18 using chromeos::nfc_client_helpers::ObjectProxyTree
;
22 NfcTagClient::Properties::Properties(
23 dbus::ObjectProxy
* object_proxy
,
24 const PropertyChangedCallback
& callback
)
25 : NfcPropertySet(object_proxy
,
26 nfc_tag::kNfcTagInterface
,
28 RegisterProperty(nfc_tag::kTypeProperty
, &type
);
29 RegisterProperty(nfc_tag::kProtocolProperty
, &protocol
);
30 RegisterProperty(nfc_tag::kRecordsProperty
, &records
);
31 RegisterProperty(nfc_tag::kReadOnlyProperty
, &read_only
);
34 NfcTagClient::Properties::~Properties() {
37 // The NfcTagClient implementation used in production.
38 class NfcTagClientImpl
: public NfcTagClient
,
39 public NfcAdapterClient::Observer
,
40 public DBusObjectMap::Delegate
{
42 explicit NfcTagClientImpl(NfcAdapterClient
* adapter_client
)
44 adapter_client_(adapter_client
),
45 weak_ptr_factory_(this) {
46 DCHECK(adapter_client
);
49 ~NfcTagClientImpl() override
{
50 DCHECK(adapter_client_
);
51 adapter_client_
->RemoveObserver(this);
54 // NfcTagClient override.
55 void AddObserver(NfcTagClient::Observer
* observer
) override
{
57 observers_
.AddObserver(observer
);
60 // NfcTagClient override.
61 void RemoveObserver(NfcTagClient::Observer
* observer
) override
{
63 observers_
.RemoveObserver(observer
);
66 // NfcTagClient override.
67 std::vector
<dbus::ObjectPath
> GetTagsForAdapter(
68 const dbus::ObjectPath
& adapter_path
) override
{
69 DBusObjectMap
* object_map
=
70 adapters_to_object_maps_
.GetObjectMap(adapter_path
);
72 return std::vector
<dbus::ObjectPath
>();
73 return object_map
->GetObjectPaths();
76 // NfcTagClient override.
77 Properties
* GetProperties(const dbus::ObjectPath
& object_path
) override
{
78 return static_cast<Properties
*>(
79 adapters_to_object_maps_
.FindObjectProperties(object_path
));
82 // NfcTagClient override.
83 void Write(const dbus::ObjectPath
& object_path
,
84 const base::DictionaryValue
& attributes
,
85 const base::Closure
& callback
,
86 const nfc_client_helpers::ErrorCallback
& error_callback
) override
{
87 dbus::ObjectProxy
* object_proxy
=
88 adapters_to_object_maps_
.FindObjectProxy(object_path
);
90 std::string error_message
=
91 base::StringPrintf("NFC tag with object path \"%s\" does not exist.",
92 object_path
.value().c_str());
93 LOG(ERROR
) << error_message
;
94 error_callback
.Run(nfc_client_helpers::kUnknownObjectError
,
99 // |attributes| should not be empty.
100 if (attributes
.empty()) {
101 std::string error_message
=
102 "Cannot write data to tag with empty arguments.";
103 LOG(ERROR
) << error_message
;
104 error_callback
.Run(nfc_error::kInvalidArguments
, error_message
);
108 // Create the arguments.
109 dbus::MethodCall
method_call(nfc_tag::kNfcTagInterface
, nfc_tag::kWrite
);
110 dbus::MessageWriter
writer(&method_call
);
111 dbus::AppendValueData(&writer
, attributes
);
113 object_proxy
->CallMethodWithErrorCallback(
115 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
116 base::Bind(&nfc_client_helpers::OnSuccess
, callback
),
117 base::Bind(&nfc_client_helpers::OnError
, error_callback
));
121 // DBusClient override.
122 void Init(dbus::Bus
* bus
) override
{
123 VLOG(1) << "Creating NfcTagClientImpl";
126 DCHECK(adapter_client_
);
127 adapter_client_
->AddObserver(this);
131 // NfcAdapterClient::Observer override.
132 void AdapterAdded(const dbus::ObjectPath
& object_path
) override
{
133 VLOG(1) << "Adapter added. Creating map for tag proxies belonging to "
134 << "adapter: " << object_path
.value();
135 adapters_to_object_maps_
.CreateObjectMap(
136 object_path
, nfc_tag::kNfcTagServiceName
, this, bus_
);
139 // NfcAdapterClient::Observer override.
140 void AdapterRemoved(const dbus::ObjectPath
& object_path
) override
{
141 // Neard doesn't send out property changed signals for the tags that
142 // are removed when the adapter they belong to is removed. Clean up the
143 // object proxies for devices that are managed by the removed adapter.
144 // Note: DBusObjectMap guarantees that the Properties structure for the
145 // removed adapter will be valid before this method returns.
146 VLOG(1) << "Adapter removed. Cleaning up tag proxies belonging to "
147 << "adapter: " << object_path
.value();
148 adapters_to_object_maps_
.RemoveObjectMap(object_path
);
151 // NfcAdapterClient::Observer override.
152 void AdapterPropertyChanged(const dbus::ObjectPath
& object_path
,
153 const std::string
& property_name
) override
{
154 // Update the tag proxies.
155 DCHECK(adapter_client_
);
156 NfcAdapterClient::Properties
*adapter_properties
=
157 adapter_client_
->GetProperties(object_path
);
158 DCHECK(adapter_properties
);
159 if (!adapter_properties
) {
160 LOG(ERROR
) << "No property structure found for adapter: "
161 << object_path
.value();
165 // Ignore changes to properties other than "Tags".
166 if (property_name
!= adapter_properties
->tags
.name())
169 // Update the known tags.
170 VLOG(1) << "NFC tags changed.";
171 const std::vector
<dbus::ObjectPath
>& received_tags
=
172 adapter_properties
->tags
.value();
173 DBusObjectMap
* object_map
=
174 adapters_to_object_maps_
.GetObjectMap(object_path
);
176 object_map
->UpdateObjects(received_tags
);
179 // nfc_client_helpers::DBusObjectMap::Delegate override.
180 NfcPropertySet
* CreateProperties(dbus::ObjectProxy
* object_proxy
) override
{
181 Properties
* properties
= new Properties(
183 base::Bind(&NfcTagClientImpl::OnPropertyChanged
,
184 weak_ptr_factory_
.GetWeakPtr(),
185 object_proxy
->object_path()));
186 properties
->SetAllPropertiesReceivedCallback(
187 base::Bind(&NfcTagClientImpl::OnPropertiesReceived
,
188 weak_ptr_factory_
.GetWeakPtr(),
189 object_proxy
->object_path()));
193 // nfc_client_helpers::DBusObjectMap::Delegate override.
194 void ObjectAdded(const dbus::ObjectPath
& object_path
) override
{
195 FOR_EACH_OBSERVER(NfcTagClient::Observer
, observers_
,
196 TagAdded(object_path
));
199 void ObjectRemoved(const dbus::ObjectPath
& object_path
) override
{
200 FOR_EACH_OBSERVER(NfcTagClient::Observer
, observers_
,
201 TagRemoved(object_path
));
204 // Called by NfcPropertySet when a property value is changed, either by
205 // result of a signal or response to a GetAll() or Get() call.
206 void OnPropertyChanged(const dbus::ObjectPath
& object_path
,
207 const std::string
& property_name
) {
208 VLOG(1) << "Tag property changed; Path: " << object_path
.value()
209 << " Property: " << property_name
;
210 FOR_EACH_OBSERVER(NfcTagClient::Observer
, observers_
,
211 TagPropertyChanged(object_path
, property_name
));
214 // Called by NfcPropertySet when all properties have been processed as a
215 // result of a call to GetAll.
216 void OnPropertiesReceived(const dbus::ObjectPath
& object_path
) {
217 VLOG(1) << "All tag properties received; Path: " << object_path
.value();
218 FOR_EACH_OBSERVER(NfcTagClient::Observer
, observers_
,
219 TagPropertiesReceived(object_path
));
222 // We maintain a pointer to the bus to be able to request proxies for
223 // new NFC tags that appear.
226 // List of observers interested in event notifications.
227 ObserverList
<NfcTagClient::Observer
> observers_
;
229 // Mapping from object paths to object proxies and properties structures that
230 // were already created by us. This stucture stores a different DBusObjectMap
231 // for each known NFC adapter object path.
232 ObjectProxyTree adapters_to_object_maps_
;
234 // The adapter client that we listen to events notifications from.
235 NfcAdapterClient
* adapter_client_
;
237 // Weak pointer factory for generating 'this' pointers that might live longer
239 // Note: This should remain the last member so it'll be destroyed and
240 // invalidate its weak pointers before any other members are destroyed.
241 base::WeakPtrFactory
<NfcTagClientImpl
> weak_ptr_factory_
;
243 DISALLOW_COPY_AND_ASSIGN(NfcTagClientImpl
);
246 NfcTagClient::NfcTagClient() {
249 NfcTagClient::~NfcTagClient() {
252 NfcTagClient
* NfcTagClient::Create(NfcAdapterClient
* adapter_client
) {
253 return new NfcTagClientImpl(adapter_client
);
256 } // namespace chromeos