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/fake_nfc_adapter_client.h"
6
7 #include "base/logging.h"
8 #include "chromeos/dbus/dbus_thread_manager.h"
9 #include "chromeos/dbus/fake_nfc_device_client.h"
10 #include "chromeos/dbus/fake_nfc_tag_client.h"
11 #include "chromeos/dbus/nfc_client_helpers.h"
12 #include "dbus/message.h"
13 #include "dbus/object_path.h"
14 #include "third_party/cros_system_api/dbus/service_constants.h"
15
16 namespace chromeos {
17
18 using nfc_client_helpers::ObjectPathVector;
19
20 const char FakeNfcAdapterClient::kAdapterPath0[] = "/fake/nfc0";
21 const char FakeNfcAdapterClient::kAdapterPath1[] = "/fake/nfc1";
22
Properties(const PropertyChangedCallback & callback)23 FakeNfcAdapterClient::Properties::Properties(
24 const PropertyChangedCallback& callback)
25 : NfcAdapterClient::Properties(NULL, callback) {
26 }
27
~Properties()28 FakeNfcAdapterClient::Properties::~Properties() {
29 }
30
Get(dbus::PropertyBase * property,dbus::PropertySet::GetCallback callback)31 void FakeNfcAdapterClient::Properties::Get(
32 dbus::PropertyBase* property,
33 dbus::PropertySet::GetCallback callback) {
34 VLOG(1) << "Get " << property->name();
35 callback.Run(false);
36 }
37
GetAll()38 void FakeNfcAdapterClient::Properties::GetAll() {
39 VLOG(1) << "GetAll";
40 }
41
Set(dbus::PropertyBase * property,dbus::PropertySet::SetCallback callback)42 void FakeNfcAdapterClient::Properties::Set(
43 dbus::PropertyBase* property,
44 dbus::PropertySet::SetCallback callback) {
45 VLOG(1) << "Set " << property->name();
46 if (property->name() != powered.name()) {
47 callback.Run(false);
48 return;
49 }
50
51 // Cannot set the power if currently polling.
52 if (polling.value()) {
53 LOG(ERROR) << "Cannot set power while polling.";
54 callback.Run(false);
55 return;
56 }
57
58 // Cannot set power if there is a device or a tag that is currently
59 // "paired".
60 if (!devices.value().empty() || !tags.value().empty()) {
61 LOG(ERROR) << "Cannot set power while the device is paired.";
62 callback.Run(false);
63 return;
64 }
65
66 // Obtain the cached "set value" and send a property changed signal only if
67 // its value is different from the current value of the property.
68 scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
69 dbus::MessageWriter writer(response.get());
70 property->AppendSetValueToWriter(&writer);
71 dbus::MessageReader reader(response.get());
72 bool set_value = false;
73 if (!reader.PopVariantOfBool(&set_value) || set_value == powered.value()) {
74 LOG(WARNING) << "Property has not changed.";
75 callback.Run(false);
76 return;
77 }
78 property->ReplaceValueWithSetValue();
79 callback.Run(true);
80 }
81
FakeNfcAdapterClient()82 FakeNfcAdapterClient::FakeNfcAdapterClient()
83 : present_(true),
84 second_present_(false),
85 start_pairing_on_poll_(true),
86 device_pairing_(false) {
87 VLOG(1) << "Creating FakeNfcAdapterClient";
88
89 std::vector<std::string> protocols;
90 protocols.push_back(nfc_common::kProtocolFelica);
91 protocols.push_back(nfc_common::kProtocolMifare);
92 protocols.push_back(nfc_common::kProtocolJewel);
93 protocols.push_back(nfc_common::kProtocolIsoDep);
94 protocols.push_back(nfc_common::kProtocolNfcDep);
95
96 properties_.reset(new Properties(base::Bind(
97 &FakeNfcAdapterClient::OnPropertyChanged,
98 base::Unretained(this),
99 dbus::ObjectPath(kAdapterPath0))));
100 properties_->protocols.ReplaceValue(protocols);
101
102 second_properties_.reset(new Properties(base::Bind(
103 &FakeNfcAdapterClient::OnPropertyChanged,
104 base::Unretained(this),
105 dbus::ObjectPath(kAdapterPath1))));
106 second_properties_->protocols.ReplaceValue(protocols);
107 }
108
~FakeNfcAdapterClient()109 FakeNfcAdapterClient::~FakeNfcAdapterClient() {
110 }
111
Init(dbus::Bus * bus)112 void FakeNfcAdapterClient::Init(dbus::Bus* bus) {
113 }
114
AddObserver(Observer * observer)115 void FakeNfcAdapterClient::AddObserver(Observer* observer) {
116 observers_.AddObserver(observer);
117 }
118
RemoveObserver(Observer * observer)119 void FakeNfcAdapterClient::RemoveObserver(Observer* observer) {
120 observers_.RemoveObserver(observer);
121 }
122
GetAdapters()123 std::vector<dbus::ObjectPath> FakeNfcAdapterClient::GetAdapters() {
124 std::vector<dbus::ObjectPath> object_paths;
125 if (present_)
126 object_paths.push_back(dbus::ObjectPath(kAdapterPath0));
127 if (second_present_)
128 object_paths.push_back(dbus::ObjectPath(kAdapterPath1));
129 return object_paths;
130 }
131
132 FakeNfcAdapterClient::Properties*
GetProperties(const dbus::ObjectPath & object_path)133 FakeNfcAdapterClient::GetProperties(const dbus::ObjectPath& object_path) {
134 if (object_path == dbus::ObjectPath(kAdapterPath0))
135 return properties_.get();
136 if (object_path == dbus::ObjectPath(kAdapterPath1))
137 return second_properties_.get();
138 return NULL;
139 }
140
StartPollLoop(const dbus::ObjectPath & object_path,const std::string & mode,const base::Closure & callback,const nfc_client_helpers::ErrorCallback & error_callback)141 void FakeNfcAdapterClient::StartPollLoop(
142 const dbus::ObjectPath& object_path,
143 const std::string& mode,
144 const base::Closure& callback,
145 const nfc_client_helpers::ErrorCallback& error_callback) {
146 VLOG(1) << "FakeNfcAdapterClient::StartPollLoop";
147 if (object_path != dbus::ObjectPath(kAdapterPath0)) {
148 error_callback.Run(nfc_client_helpers::kNoResponseError, "");
149 return;
150 }
151 if (!properties_->powered.value()) {
152 error_callback.Run(nfc_error::kFailed, "Adapter not powered.");
153 return;
154 }
155 if (properties_->polling.value()) {
156 error_callback.Run(nfc_error::kFailed, "Already polling.");
157 return;
158 }
159 if (!properties_->devices.value().empty() ||
160 !properties_->tags.value().empty()) {
161 error_callback.Run(nfc_error::kFailed, "Adapter busy.");
162 return;
163 }
164 properties_->polling.ReplaceValue(true);
165 properties_->mode.ReplaceValue(mode);
166 callback.Run();
167
168 if (!start_pairing_on_poll_)
169 return;
170
171 if (device_pairing_) {
172 FakeNfcDeviceClient* device_client =
173 static_cast<FakeNfcDeviceClient*>(
174 DBusThreadManager::Get()->GetNfcDeviceClient());
175 device_client->BeginPairingSimulation(3000, 2000);
176 } else {
177 FakeNfcTagClient* tag_client =
178 static_cast<FakeNfcTagClient*>(
179 DBusThreadManager::Get()->GetNfcTagClient());
180 tag_client->BeginPairingSimulation(2000);
181 }
182 device_pairing_ = !device_pairing_;
183 }
184
StopPollLoop(const dbus::ObjectPath & object_path,const base::Closure & callback,const nfc_client_helpers::ErrorCallback & error_callback)185 void FakeNfcAdapterClient::StopPollLoop(
186 const dbus::ObjectPath& object_path,
187 const base::Closure& callback,
188 const nfc_client_helpers::ErrorCallback& error_callback) {
189 VLOG(1) << "FakeNfcAdapterClient::StopPollLoop.";
190 if (object_path != dbus::ObjectPath(kAdapterPath0)) {
191 error_callback.Run(nfc_client_helpers::kNoResponseError, "");
192 return;
193 }
194 if (!properties_->polling.value()) {
195 error_callback.Run("org.neard.Error.Failed", "Not polling.");
196 return;
197 }
198 FakeNfcDeviceClient* device_client =
199 static_cast<FakeNfcDeviceClient*>(
200 DBusThreadManager::Get()->GetNfcDeviceClient());
201 device_client->EndPairingSimulation();
202 FakeNfcTagClient* tag_client =
203 static_cast<FakeNfcTagClient*>(
204 DBusThreadManager::Get()->GetNfcTagClient());
205 tag_client->EndPairingSimulation();
206 properties_->polling.ReplaceValue(false);
207 callback.Run();
208 }
209
SetAdapterPresent(bool present)210 void FakeNfcAdapterClient::SetAdapterPresent(bool present) {
211 if (present == present_)
212 return;
213 present_ = present;
214 if (present_) {
215 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
216 AdapterAdded(dbus::ObjectPath(kAdapterPath0)));
217 } else {
218 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
219 AdapterRemoved(dbus::ObjectPath(kAdapterPath0)));
220 }
221 }
222
SetSecondAdapterPresent(bool present)223 void FakeNfcAdapterClient::SetSecondAdapterPresent(bool present) {
224 if (present == second_present_)
225 return;
226 second_present_ = present;
227 if (present_) {
228 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
229 AdapterAdded(dbus::ObjectPath(kAdapterPath1)));
230 } else {
231 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
232 AdapterRemoved(dbus::ObjectPath(kAdapterPath1)));
233 }
234 }
235
SetDevice(const dbus::ObjectPath & device_path)236 void FakeNfcAdapterClient::SetDevice(const dbus::ObjectPath& device_path) {
237 LOG(INFO) << "Add device path to the fake adapter: " << device_path.value();
238 if (!properties_->polling.value()) {
239 LOG(ERROR) << "Adapter not polling, cannot set device.";
240 return;
241 }
242 const ObjectPathVector& devices(properties_->devices.value());
243 for (ObjectPathVector::const_iterator iter = devices.begin();
244 iter != devices.end(); ++iter) {
245 if (*iter == device_path) {
246 LOG(WARNING) << "Device path already in list of devices.";
247 return;
248 }
249 }
250 // Mark as not polling.
251 properties_->polling.ReplaceValue(false);
252
253 ObjectPathVector new_devices = devices;
254 new_devices.push_back(device_path);
255 properties_->devices.ReplaceValue(new_devices);
256 }
257
SetTag(const dbus::ObjectPath & tag_path)258 void FakeNfcAdapterClient::SetTag(const dbus::ObjectPath& tag_path) {
259 LOG(INFO) << "Add tag path to the fake adapter: " << tag_path.value();
260 if (!properties_->polling.value()) {
261 LOG(ERROR) << "Adapter not polling, cannot set tag.";
262 return;
263 }
264 const ObjectPathVector& tags(properties_->tags.value());
265 for (ObjectPathVector::const_iterator iter = tags.begin();
266 iter != tags.end(); ++iter) {
267 if (*iter == tag_path) {
268 LOG(WARNING) << "Tag path already in list of tags.";
269 return;
270 }
271 }
272 // Mark as not polling.
273 properties_->polling.ReplaceValue(false);
274
275 ObjectPathVector new_tags = tags;
276 new_tags.push_back(tag_path);
277 properties_->tags.ReplaceValue(new_tags);
278 }
279
UnsetDevice(const dbus::ObjectPath & device_path)280 void FakeNfcAdapterClient::UnsetDevice(const dbus::ObjectPath& device_path) {
281 LOG(INFO) << "Remove device path from the fake adapter: "
282 << device_path.value();
283 ObjectPathVector new_devices = properties_->devices.value();
284 for (ObjectPathVector::iterator iter = new_devices.begin();
285 iter != new_devices.end(); ++iter) {
286 if (*iter == device_path) {
287 new_devices.erase(iter);
288 properties_->devices.ReplaceValue(new_devices);
289
290 // Mark as polling.
291 DCHECK(!properties_->polling.value());
292 properties_->polling.ReplaceValue(true);
293 return;
294 }
295 }
296 LOG(WARNING) << "Device path not in list of devices.";
297 }
298
UnsetTag(const dbus::ObjectPath & tag_path)299 void FakeNfcAdapterClient::UnsetTag(const dbus::ObjectPath& tag_path) {
300 LOG(INFO) << "Remove tag path from the fake adapter: " << tag_path.value();
301 ObjectPathVector new_tags = properties_->tags.value();
302 for (ObjectPathVector::iterator iter = new_tags.begin();
303 iter != new_tags.end(); ++iter) {
304 if (*iter == tag_path) {
305 new_tags.erase(iter);
306 properties_->tags.ReplaceValue(new_tags);
307
308 // Mark as polling.
309 DCHECK(!properties_->polling.value());
310 properties_->polling.ReplaceValue(true);
311 return;
312 }
313 }
314 LOG(WARNING) << "Tag path not in list of tags.";
315 }
316
EnablePairingOnPoll(bool enabled)317 void FakeNfcAdapterClient::EnablePairingOnPoll(bool enabled) {
318 start_pairing_on_poll_ = enabled;
319 }
320
OnPropertyChanged(const dbus::ObjectPath & object_path,const std::string & property_name)321 void FakeNfcAdapterClient::OnPropertyChanged(
322 const dbus::ObjectPath& object_path,
323 const std::string& property_name) {
324 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_,
325 AdapterPropertyChanged(object_path, property_name));
326 }
327
328 } // namespace chromeos
329