Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chromeos / dbus / nfc_tag_client.cc
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_tag_client.h"
6
7 #include "base/bind.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"
12 #include "dbus/bus.h"
13 #include "dbus/message.h"
14 #include "dbus/values_util.h"
15 #include "third_party/cros_system_api/dbus/service_constants.h"
16
17 using chromeos::nfc_client_helpers::DBusObjectMap;
18 using chromeos::nfc_client_helpers::ObjectProxyTree;
19
20 namespace chromeos {
21
22 NfcTagClient::Properties::Properties(
23     dbus::ObjectProxy* object_proxy,
24     const PropertyChangedCallback& callback)
25     : NfcPropertySet(object_proxy,
26                      nfc_tag::kNfcTagInterface,
27                      callback) {
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);
32 }
33
34 NfcTagClient::Properties::~Properties() {
35 }
36
37 // The NfcTagClient implementation used in production.
38 class NfcTagClientImpl : public NfcTagClient,
39                          public NfcAdapterClient::Observer,
40                          public DBusObjectMap::Delegate {
41  public:
42   explicit NfcTagClientImpl(NfcAdapterClient* adapter_client)
43       : bus_(NULL),
44         adapter_client_(adapter_client),
45         weak_ptr_factory_(this) {
46     DCHECK(adapter_client);
47   }
48
49   virtual ~NfcTagClientImpl() {
50     DCHECK(adapter_client_);
51     adapter_client_->RemoveObserver(this);
52   }
53
54   // NfcTagClient override.
55   virtual void AddObserver(NfcTagClient::Observer* observer) override {
56     DCHECK(observer);
57     observers_.AddObserver(observer);
58   }
59
60   // NfcTagClient override.
61   virtual void RemoveObserver(NfcTagClient::Observer* observer) override {
62     DCHECK(observer);
63     observers_.RemoveObserver(observer);
64   }
65
66   // NfcTagClient override.
67   virtual std::vector<dbus::ObjectPath> GetTagsForAdapter(
68       const dbus::ObjectPath& adapter_path) override {
69     DBusObjectMap* object_map =
70         adapters_to_object_maps_.GetObjectMap(adapter_path);
71     if (!object_map)
72       return std::vector<dbus::ObjectPath>();
73     return object_map->GetObjectPaths();
74   }
75
76   // NfcTagClient override.
77   virtual Properties* GetProperties(
78       const dbus::ObjectPath& object_path) override {
79     return static_cast<Properties*>(
80         adapters_to_object_maps_.FindObjectProperties(object_path));
81   }
82
83   // NfcTagClient override.
84   virtual void Write(
85       const dbus::ObjectPath& object_path,
86       const base::DictionaryValue& attributes,
87       const base::Closure& callback,
88       const nfc_client_helpers::ErrorCallback& error_callback) override {
89     dbus::ObjectProxy* object_proxy =
90         adapters_to_object_maps_.FindObjectProxy(object_path);
91     if (!object_proxy) {
92       std::string error_message =
93           base::StringPrintf("NFC tag with object path \"%s\" does not exist.",
94                              object_path.value().c_str());
95       LOG(ERROR) << error_message;
96       error_callback.Run(nfc_client_helpers::kUnknownObjectError,
97                          error_message);
98       return;
99     }
100
101     // |attributes| should not be empty.
102     if (attributes.empty()) {
103       std::string error_message =
104           "Cannot write data to tag with empty arguments.";
105       LOG(ERROR) << error_message;
106       error_callback.Run(nfc_error::kInvalidArguments, error_message);
107       return;
108     }
109
110     // Create the arguments.
111     dbus::MethodCall method_call(nfc_tag::kNfcTagInterface, nfc_tag::kWrite);
112     dbus::MessageWriter writer(&method_call);
113     dbus::AppendValueData(&writer, attributes);
114
115     object_proxy->CallMethodWithErrorCallback(
116         &method_call,
117         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
118         base::Bind(&nfc_client_helpers::OnSuccess, callback),
119         base::Bind(&nfc_client_helpers::OnError, error_callback));
120   }
121
122  protected:
123   // DBusClient override.
124   virtual void Init(dbus::Bus* bus) override {
125     VLOG(1) << "Creating NfcTagClientImpl";
126     DCHECK(bus);
127     bus_ = bus;
128     DCHECK(adapter_client_);
129     adapter_client_->AddObserver(this);
130   }
131
132  private:
133   // NfcAdapterClient::Observer override.
134   virtual void AdapterAdded(const dbus::ObjectPath& object_path) override {
135     VLOG(1) << "Adapter added. Creating map for tag proxies belonging to "
136             << "adapter: " << object_path.value();
137     adapters_to_object_maps_.CreateObjectMap(
138         object_path, nfc_tag::kNfcTagServiceName, this, bus_);
139   }
140
141   // NfcAdapterClient::Observer override.
142   virtual void AdapterRemoved(const dbus::ObjectPath& object_path) override {
143     // Neard doesn't send out property changed signals for the tags that
144     // are removed when the adapter they belong to is removed. Clean up the
145     // object proxies for devices that are managed by the removed adapter.
146     // Note: DBusObjectMap guarantees that the Properties structure for the
147     // removed adapter will be valid before this method returns.
148     VLOG(1) << "Adapter removed. Cleaning up tag proxies belonging to "
149             << "adapter: " << object_path.value();
150     adapters_to_object_maps_.RemoveObjectMap(object_path);
151   }
152
153   // NfcAdapterClient::Observer override.
154   virtual void AdapterPropertyChanged(
155       const dbus::ObjectPath& object_path,
156       const std::string& property_name) override {
157     // Update the tag proxies.
158     DCHECK(adapter_client_);
159     NfcAdapterClient::Properties *adapter_properties =
160         adapter_client_->GetProperties(object_path);
161     DCHECK(adapter_properties);
162     if (!adapter_properties) {
163       LOG(ERROR) << "No property structure found for adapter: "
164                  << object_path.value();
165       return;
166     }
167
168     // Ignore changes to properties other than "Tags".
169     if (property_name != adapter_properties->tags.name())
170       return;
171
172     // Update the known tags.
173     VLOG(1) << "NFC tags changed.";
174     const std::vector<dbus::ObjectPath>& received_tags =
175         adapter_properties->tags.value();
176     DBusObjectMap* object_map =
177         adapters_to_object_maps_.GetObjectMap(object_path);
178     DCHECK(object_map);
179     object_map->UpdateObjects(received_tags);
180   }
181
182   // nfc_client_helpers::DBusObjectMap::Delegate override.
183   virtual NfcPropertySet* CreateProperties(
184       dbus::ObjectProxy* object_proxy) override {
185     Properties* properties = new Properties(
186         object_proxy,
187         base::Bind(&NfcTagClientImpl::OnPropertyChanged,
188                    weak_ptr_factory_.GetWeakPtr(),
189                    object_proxy->object_path()));
190     properties->SetAllPropertiesReceivedCallback(
191         base::Bind(&NfcTagClientImpl::OnPropertiesReceived,
192                    weak_ptr_factory_.GetWeakPtr(),
193                    object_proxy->object_path()));
194     return properties;
195   }
196
197   // nfc_client_helpers::DBusObjectMap::Delegate override.
198   virtual void ObjectAdded(const dbus::ObjectPath& object_path) override {
199     FOR_EACH_OBSERVER(NfcTagClient::Observer, observers_,
200                       TagAdded(object_path));
201   }
202
203   virtual void ObjectRemoved(const dbus::ObjectPath& object_path) override {
204     FOR_EACH_OBSERVER(NfcTagClient::Observer, observers_,
205                       TagRemoved(object_path));
206   }
207
208   // Called by NfcPropertySet when a property value is changed, either by
209   // result of a signal or response to a GetAll() or Get() call.
210   void OnPropertyChanged(const dbus::ObjectPath& object_path,
211                          const std::string& property_name) {
212     VLOG(1) << "Tag property changed; Path: " << object_path.value()
213             << " Property: " << property_name;
214     FOR_EACH_OBSERVER(NfcTagClient::Observer, observers_,
215                       TagPropertyChanged(object_path, property_name));
216   }
217
218   // Called by NfcPropertySet when all properties have been processed as a
219   // result of a call to GetAll.
220   void OnPropertiesReceived(const dbus::ObjectPath& object_path) {
221     VLOG(1) << "All tag properties received; Path: " << object_path.value();
222     FOR_EACH_OBSERVER(NfcTagClient::Observer, observers_,
223                       TagPropertiesReceived(object_path));
224   }
225
226   // We maintain a pointer to the bus to be able to request proxies for
227   // new NFC tags that appear.
228   dbus::Bus* bus_;
229
230   // List of observers interested in event notifications.
231   ObserverList<NfcTagClient::Observer> observers_;
232
233   // Mapping from object paths to object proxies and properties structures that
234   // were already created by us. This stucture stores a different DBusObjectMap
235   // for each known NFC adapter object path.
236   ObjectProxyTree adapters_to_object_maps_;
237
238   // The adapter client that we listen to events notifications from.
239   NfcAdapterClient* adapter_client_;
240
241   // Weak pointer factory for generating 'this' pointers that might live longer
242   // than we do.
243   // Note: This should remain the last member so it'll be destroyed and
244   // invalidate its weak pointers before any other members are destroyed.
245   base::WeakPtrFactory<NfcTagClientImpl> weak_ptr_factory_;
246
247   DISALLOW_COPY_AND_ASSIGN(NfcTagClientImpl);
248 };
249
250 NfcTagClient::NfcTagClient() {
251 }
252
253 NfcTagClient::~NfcTagClient() {
254 }
255
256 NfcTagClient* NfcTagClient::Create(NfcAdapterClient* adapter_client) {
257   return new NfcTagClientImpl(adapter_client);
258 }
259
260 }  // namespace chromeos