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"
10 #include "base/memory/weak_ptr.h"
11 #include "base/observer_list.h"
12 #include "base/strings/stringprintf.h"
13 #include "chromeos/dbus/fake_nfc_tag_client.h"
14 #include "chromeos/dbus/nfc_adapter_client.h"
16 #include "dbus/message.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
19 using chromeos::nfc_client_helpers::DBusObjectMap;
23 NfcTagClient::Properties::Properties(
24 dbus::ObjectProxy* object_proxy,
25 const PropertyChangedCallback& callback)
26 : NfcPropertySet(object_proxy,
27 nfc_tag::kNfcTagInterface,
29 RegisterProperty(nfc_tag::kTypeProperty, &type);
30 RegisterProperty(nfc_tag::kProtocolProperty, &protocol);
31 RegisterProperty(nfc_tag::kRecordsProperty, &records);
32 RegisterProperty(nfc_tag::kReadOnlyProperty, &read_only);
35 NfcTagClient::Properties::~Properties() {
38 // The NfcTagClient implementation used in production.
39 class NfcTagClientImpl : public NfcTagClient,
40 public NfcAdapterClient::Observer,
41 public nfc_client_helpers::DBusObjectMap::Delegate {
43 explicit NfcTagClientImpl(NfcAdapterClient* adapter_client)
45 adapter_client_(adapter_client),
46 weak_ptr_factory_(this) {
47 DCHECK(adapter_client);
50 virtual ~NfcTagClientImpl() {
51 adapter_client_->RemoveObserver(this);
54 // NfcTagClient override.
55 virtual void AddObserver(NfcTagClient::Observer* observer) OVERRIDE {
57 observers_.AddObserver(observer);
60 // NfcTagClient override.
61 virtual void RemoveObserver(NfcTagClient::Observer* observer) OVERRIDE {
63 observers_.RemoveObserver(observer);
66 // NfcTagClient override.
67 virtual Properties* GetProperties(const dbus::ObjectPath& object_path)
69 return static_cast<Properties*>(
70 object_map_->GetObjectProperties(object_path));
73 // NfcTagClient override.
75 const dbus::ObjectPath& object_path,
76 const RecordAttributes& attributes,
77 const base::Closure& callback,
78 const nfc_client_helpers::ErrorCallback& error_callback) OVERRIDE {
79 dbus::ObjectProxy* object_proxy = object_map_->GetObjectProxy(object_path);
81 std::string error_message =
82 base::StringPrintf("NFC tag with object path \"%s\" does not exist.",
83 object_path.value().c_str());
84 LOG(ERROR) << error_message;
85 error_callback.Run(nfc_client_helpers::kUnknownObjectError,
90 // |attributes| should not be empty.
91 if (attributes.empty()) {
92 std::string error_message =
93 "Cannot write data to tag with empty arguments.";
94 LOG(ERROR) << error_message;
95 error_callback.Run(nfc_error::kInvalidArguments, error_message);
99 // Create the arguments.
100 dbus::MethodCall method_call(nfc_tag::kNfcTagInterface, nfc_tag::kWrite);
101 dbus::MessageWriter writer(&method_call);
102 dbus::MessageWriter array_writer(NULL);
103 dbus::MessageWriter dict_entry_writer(NULL);
104 writer.OpenArray("{sv}", &array_writer);
105 for (RecordAttributes::const_iterator iter = attributes.begin();
106 iter != attributes.end(); ++iter) {
107 array_writer.OpenDictEntry(&dict_entry_writer);
108 dict_entry_writer.AppendString(iter->first);
109 dict_entry_writer.AppendVariantOfString(iter->second);
110 array_writer.CloseContainer(&dict_entry_writer);
112 writer.CloseContainer(&array_writer);
114 object_proxy->CallMethodWithErrorCallback(
116 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
117 base::Bind(&nfc_client_helpers::OnSuccess, callback),
118 base::Bind(&nfc_client_helpers::OnError, error_callback));
122 // DBusClient override.
123 virtual void Init(dbus::Bus* bus) OVERRIDE {
124 VLOG(1) << "Creating NfcTagClientImpl";
127 object_map_.reset(new nfc_client_helpers::DBusObjectMap(
128 nfc_tag::kNfcTagServiceName, this, bus));
129 DCHECK(adapter_client_);
130 adapter_client_->AddObserver(this);
134 // NfcAdapterClient::Observer override.
135 virtual void AdapterPropertyChanged(
136 const dbus::ObjectPath& object_path,
137 const std::string& property_name) OVERRIDE {
138 // Update the tag proxies.
139 DCHECK(adapter_client_);
140 NfcAdapterClient::Properties *adapter_properties =
141 adapter_client_->GetProperties(object_path);
143 // Ignore changes to properties other than "Tags".
144 if (property_name != adapter_properties->tags.name())
147 VLOG(1) << "NFC tags changed.";
149 // Update the known tags.
150 const std::vector<dbus::ObjectPath>& received_tags =
151 adapter_properties->tags.value();
152 object_map_->UpdateObjects(received_tags);
155 // nfc_client_helpers::DBusObjectMap::Delegate override.
156 virtual NfcPropertySet* CreateProperties(
157 dbus::ObjectProxy* object_proxy) OVERRIDE {
158 return new Properties(
160 base::Bind(&NfcTagClientImpl::OnPropertyChanged,
161 weak_ptr_factory_.GetWeakPtr(),
162 object_proxy->object_path()));
165 // nfc_client_helpers::DBusObjectMap::Delegate override.
166 virtual void ObjectAdded(const dbus::ObjectPath& object_path) OVERRIDE {
167 FOR_EACH_OBSERVER(NfcTagClient::Observer, observers_,
168 TagFound(object_path));
171 virtual void ObjectRemoved(const dbus::ObjectPath& object_path) OVERRIDE {
172 FOR_EACH_OBSERVER(NfcTagClient::Observer, observers_,
173 TagLost(object_path));
176 // Called by NfcPropertySet when a property value is changed, either by
177 // result of a signal or response to a GetAll() or Get() call.
178 void OnPropertyChanged(const dbus::ObjectPath& object_path,
179 const std::string& property_name) {
180 VLOG(1) << "Tag property changed; Path: " << object_path.value()
181 << " Property: " << property_name;
182 FOR_EACH_OBSERVER(NfcTagClient::Observer, observers_,
183 TagPropertyChanged(object_path, property_name));
186 // We maintain a pointer to the bus to be able to request proxies for
187 // new NFC tags that appear.
190 // Mapping from object paths to object proxies and properties structures that
191 // were already created by us.
192 scoped_ptr<nfc_client_helpers::DBusObjectMap> object_map_;
194 // The manager client that we listen to events notifications from.
195 NfcAdapterClient* adapter_client_;
197 // List of observers interested in event notifications.
198 ObserverList<NfcTagClient::Observer> observers_;
200 // Weak pointer factory for generating 'this' pointers that might live longer
202 // Note: This should remain the last member so it'll be destroyed and
203 // invalidate its weak pointers before any other members are destroyed.
204 base::WeakPtrFactory<NfcTagClientImpl> weak_ptr_factory_;
206 DISALLOW_COPY_AND_ASSIGN(NfcTagClientImpl);
209 NfcTagClient::NfcTagClient() {
212 NfcTagClient::~NfcTagClient() {
215 NfcTagClient* NfcTagClient::Create(DBusClientImplementationType type,
216 NfcAdapterClient* adapter_client) {
217 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
218 return new NfcTagClientImpl(adapter_client);
219 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
220 return new FakeNfcTagClient();
223 } // namespace chromeos