- add sources.
[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 <set>
8
9 #include "base/bind.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"
15 #include "dbus/bus.h"
16 #include "dbus/message.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
18
19 using chromeos::nfc_client_helpers::DBusObjectMap;
20
21 namespace chromeos {
22
23 NfcTagClient::Properties::Properties(
24     dbus::ObjectProxy* object_proxy,
25     const PropertyChangedCallback& callback)
26     : NfcPropertySet(object_proxy,
27                      nfc_tag::kNfcTagInterface,
28                      callback) {
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);
33 }
34
35 NfcTagClient::Properties::~Properties() {
36 }
37
38 // The NfcTagClient implementation used in production.
39 class NfcTagClientImpl : public NfcTagClient,
40                          public NfcAdapterClient::Observer,
41                          public nfc_client_helpers::DBusObjectMap::Delegate {
42  public:
43   explicit NfcTagClientImpl(NfcAdapterClient* adapter_client)
44       : bus_(NULL),
45         adapter_client_(adapter_client),
46         weak_ptr_factory_(this) {
47     DCHECK(adapter_client);
48   }
49
50   virtual ~NfcTagClientImpl() {
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 Properties* GetProperties(const dbus::ObjectPath& object_path)
68       OVERRIDE {
69     return static_cast<Properties*>(
70         object_map_->GetObjectProperties(object_path));
71   }
72
73   // NfcTagClient override.
74   virtual void Write(
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);
80     if (!object_proxy) {
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,
86                          error_message);
87       return;
88     }
89
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);
96       return;
97     }
98
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);
111     }
112     writer.CloseContainer(&array_writer);
113
114     object_proxy->CallMethodWithErrorCallback(
115         &method_call,
116         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
117         base::Bind(&nfc_client_helpers::OnSuccess, callback),
118         base::Bind(&nfc_client_helpers::OnError, error_callback));
119   }
120
121  protected:
122   // DBusClient override.
123   virtual void Init(dbus::Bus* bus) OVERRIDE {
124     VLOG(1) << "Creating NfcTagClientImpl";
125     DCHECK(bus);
126     bus_ = bus;
127     object_map_.reset(new nfc_client_helpers::DBusObjectMap(
128         nfc_tag::kNfcTagServiceName, this, bus));
129     DCHECK(adapter_client_);
130     adapter_client_->AddObserver(this);
131   }
132
133  private:
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);
142
143     // Ignore changes to properties other than "Tags".
144     if (property_name != adapter_properties->tags.name())
145       return;
146
147     VLOG(1) << "NFC tags changed.";
148
149     // Update the known tags.
150     const std::vector<dbus::ObjectPath>& received_tags =
151         adapter_properties->tags.value();
152     object_map_->UpdateObjects(received_tags);
153   }
154
155   // nfc_client_helpers::DBusObjectMap::Delegate override.
156   virtual NfcPropertySet* CreateProperties(
157       dbus::ObjectProxy* object_proxy) OVERRIDE {
158     return new Properties(
159         object_proxy,
160         base::Bind(&NfcTagClientImpl::OnPropertyChanged,
161                    weak_ptr_factory_.GetWeakPtr(),
162                    object_proxy->object_path()));
163   }
164
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));
169   }
170
171   virtual void ObjectRemoved(const dbus::ObjectPath& object_path) OVERRIDE {
172     FOR_EACH_OBSERVER(NfcTagClient::Observer, observers_,
173                       TagLost(object_path));
174   }
175
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));
184   }
185
186   // We maintain a pointer to the bus to be able to request proxies for
187   // new NFC tags that appear.
188   dbus::Bus* bus_;
189
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_;
193
194   // The manager client that we listen to events notifications from.
195   NfcAdapterClient* adapter_client_;
196
197   // List of observers interested in event notifications.
198   ObserverList<NfcTagClient::Observer> observers_;
199
200   // Weak pointer factory for generating 'this' pointers that might live longer
201   // than we do.
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_;
205
206   DISALLOW_COPY_AND_ASSIGN(NfcTagClientImpl);
207 };
208
209 NfcTagClient::NfcTagClient() {
210 }
211
212 NfcTagClient::~NfcTagClient() {
213 }
214
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();
221 }
222
223 }  // namespace chromeos